mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-07-25 01:15:26 +10:00
feat: add AI agent workspace (#3062)
* chore(ai): remove local AI store now that providers live server-side
The Zustand-based useAIStore has been replaced by the server-side
aiProviders oRPC router (encrypted credentials persisted in DB).
Delete the dead store + tests, drop the ./store export, and remove
zustand/immer deps which are no longer referenced anywhere in
packages/ai/src/.
* feat(agent): archive/delete actions and read-only state for agent threads
- Backend: mark archived threads as read-only in threads.get and reject
messages.send with CONFLICT when the thread is archived.
- Frontend: render archived threads in the sidebar with muted styling and
an Archived badge; add a per-thread dropdown menu in the chat header
with Archive (non-destructive) and Delete (with confirmation); show a
read-only banner above the message list that disambiguates archived
vs. missing-resource causes; suppress the Retry and Stop buttons in
read-only mode.
- Tests: new packages/api/src/services/agent.test.ts covering the
archived-thread isReadOnly flag and the archived-thread send refusal.
* fix(agent): abort run on archive and verify ownership before deleting thread
- threads.archive: before flipping status, abort any in-flight run controller
and clear the active-run state on the thread; cleanup failures are logged
but do not block the status update.
- threads.delete: assert thread ownership via getThread before destructive
work so an authenticated user cannot wipe another user's attachment rows
by passing a foreign threadId.
Adds focused tests for both behaviors.
* feat(agent): display patch diffs and surface revert conflicts
Render apply_resume_patch tool messages with a status-aware card (applied/
reverted/conflicted), expandable operation list, and a Revert button that
correctly handles RESUME_VERSION_CONFLICT responses. Adds unit tests for
the inverse-patch builder and the agentService.actions.revert flow.
* chore(agent): remove out-of-scope attachment tests accidentally added in Task 6
The Task 6 commit (73ef1acca) accidentally re-introduced three attachment-
related tests that belong to a separate task:
- `buildAttachmentModelParts > converts text, image, supported binary, and
unsupported attachments into model parts`
- `agentService.messages.send > persists the user message with file UI parts
and links selected attachments to it` (was failing — the `ToolLoopAgent`
mock is not callable as a constructor)
- `agentService.messages.send > rejects attachments that are missing, foreign,
or already linked before persisting a message`
These were likely re-added during a stash recovery and were not requested
for Task 6, whose scope was limited to the `agentService.actions.revert`
flow. Remove them along with the helpers/fixtures (`buildAttachment`,
`buildActiveThread`, `selectWhereResult`, `selectOrderByResult`) that they
were the only consumers of. `selectLimitResult` is preserved because it is
used by the revert tests.
* chore(agent): configure runtime dependencies
* feat(db): add agent workspace schema
* feat(api): add agent backend services
* feat(web): add agent workspace UI
* chore(agent): remove legacy builder assistant
* test(agent): make agent stream mocks constructible
* chore(web): remove unused resume replacement hook
* feat(api): add unsafe AI base URL flag
* chore(dev): expose local services in compose
* fix(web): normalize resume preview gaps
* feat(api): improve agent tool handling
* feat(web): polish agent workspace UI
* chore: update dependencies
* fix(api,web): address PR review feedback for agent workspace
Security/correctness:
- Restrict AI provider URLs to http/https even in unsafe mode
- Stop exposing Redis on host network by default
- Make .env.local optional and drop app profile in compose.dev.yml
- Store agent attachments with private ACL on S3
- Reset provider test status when provider/model/baseURL changes
- Decouple non-agent AI endpoints from REDIS_URL requirement
- Fix JSON Patch add inverse for existing object members
- Wrap resume patch + agent action insert in db transaction
- Validate partialMessage at runtime and rate-limit attachment uploads
- Add unique index on agent_messages (thread_id, sequence)
UX/bugs:
- Mark agent thread route as ssr: false and guard SSE chunk parsing
- Show config-specific banner only on known configuration error
- Gate AI provider checks behind loading state in resume import
- Fix relative-time formatter blank gap between 45-59 seconds
- Clarify thread delete confirmation message
Polish:
- Raise ENCRYPTION_SECRET minimum to 32 characters
- Bucket AI rate limits by resumeId/threadId/messageId
- Trim form values before submitting AI provider config
- Use single key identifier and nullish-coalesce baseURL display
* fix: address ai agent review feedback
* fix: preserve mobile agent chat state
* docs: add ai agent workspace guides
* feat: introduce design system for Reactive Resume
This commit is contained in:
@@ -90,7 +90,6 @@ OAUTH_SCOPES=""
|
||||
# BETTER_AUTH_URL="https://auth.example.com"
|
||||
# BETTER_AUTH_SECRET=""
|
||||
|
||||
|
||||
# --- Email (optional) ---
|
||||
# If all keys are disabled, the app logs the email to be sent to the console instead.
|
||||
SMTP_HOST=""
|
||||
@@ -112,10 +111,21 @@ S3_BUCKET=""
|
||||
# Set to "false" for virtual-hosted-style URLs (https://bucket.endpoint), common with AWS S3, Cloudflare R2, etc.
|
||||
S3_FORCE_PATH_STYLE="false"
|
||||
|
||||
# --- AI features (optional) ---
|
||||
# ENCRYPTION_SECRET is required for saved AI providers. REDIS_URL is also required for the AI Agent workspace.
|
||||
# The rest of Reactive Resume can run without these.
|
||||
REDIS_URL=""
|
||||
# Generated using `openssl rand -hex 32`
|
||||
ENCRYPTION_SECRET=""
|
||||
# Optional fallback for URL extraction. Not required for normal agent operation.
|
||||
CLOUDFLARE_ACCOUNT_ID=""
|
||||
CLOUDFLARE_API_TOKEN=""
|
||||
|
||||
# --- Feature Flags ---
|
||||
FLAG_DISABLE_SIGNUPS="false"
|
||||
FLAG_DISABLE_EMAIL_AUTH="false"
|
||||
FLAG_DISABLE_IMAGE_PROCESSING="false"
|
||||
# Allows unsafe/private/non-public AI provider base URLs. Keep false unless this is a trusted self-hosted deployment.
|
||||
FLAG_ALLOW_UNSAFE_AI_BASE_URL="false"
|
||||
```
|
||||
|
||||
@@ -251,6 +261,9 @@ docker compose logs -f reactive-resume
|
||||
<li>
|
||||
S3 storage (<code>S3_*</code>)
|
||||
</li>
|
||||
<li>
|
||||
AI providers and AI Agent workspace (<code>ENCRYPTION_SECRET</code>, <code>REDIS_URL</code>)
|
||||
</li>
|
||||
<li>
|
||||
Feature flags (<code>FLAG_*</code>)
|
||||
</li>
|
||||
@@ -326,17 +339,28 @@ openssl rand -hex 32
|
||||
- **`LOCAL_STORAGE_PATH`** (optional): Overrides the local data directory. Defaults to `/app/data` in the official Docker image and `<workspace>/data` in development. The container validates this path is writable at startup and refuses to start otherwise.
|
||||
- **Rootless Docker**: `/app/data` remains the container path. Prefer the named volume from the example Compose file, or make sure a bind-mounted host directory is writable by the container's `node` user mapping.
|
||||
- **S3/S3-compatible**: Configure `S3_ACCESS_KEY_ID`, `S3_SECRET_ACCESS_KEY`, `S3_REGION`, `S3_ENDPOINT`, and `S3_BUCKET`.
|
||||
- **Agent attachments/private objects**: The AI Agent workspace requires S3-compatible storage for private objects. Local storage rejects private objects.
|
||||
- **`S3_FORCE_PATH_STYLE`** controls bucket addressing (defaults to `"false"`):
|
||||
- `"true"` for path-style URLs (`https://endpoint/bucket`) common with MinIO/SeaweedFS.
|
||||
- `"false"` for virtual-hosted-style URLs (`https://bucket.endpoint`) common with AWS S3 / Cloudflare R2.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="AI features (optional)">
|
||||
Saved AI provider management is usable only when **`ENCRYPTION_SECRET`** is configured. The AI Agent workspace also requires **`REDIS_URL`**. The rest of Reactive Resume can run without them.
|
||||
|
||||
- **`REDIS_URL`**: Redis connection string used by the AI Agent workspace.
|
||||
- **`ENCRYPTION_SECRET`**: Secret used to encrypt saved AI provider credentials. Generate with `openssl rand -hex 32`.
|
||||
- **`CLOUDFLARE_ACCOUNT_ID`** / **`CLOUDFLARE_API_TOKEN`** (optional): Enables the Cloudflare URL extraction fallback. Cloudflare is not required for normal agent operation.
|
||||
|
||||
If you use the Postgres-only Compose example above and want the AI Agent workspace, add a Redis service or use managed Redis, then set `REDIS_URL`.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Feature Flags">
|
||||
- **`FLAG_DISABLE_SIGNUPS`**: Disables new signups (web app and server). Useful for private instances.
|
||||
- **`FLAG_DISABLE_EMAIL_AUTH`**: Disables email/password login entirely. Also disables email verification, forgot password, and reset password flows. Users can still sign up via social auth (Google/GitHub/LinkedIn/Custom OAuth), unless FLAG_DISABLE_SIGNUPS is also set to true. Useful when only SSO is required.
|
||||
- **`FLAG_DISABLE_IMAGE_PROCESSING`**: Disables image processing. This is useful if you are using a machine with limited resources, like a Raspberry Pi.
|
||||
- **`FLAG_ALLOW_UNSAFE_AI_BASE_URL`**: Allows AI providers to be configured with `http://` URLs and private/loopback addresses (e.g. a local Ollama instance at `http://192.168.1.10:11434`). **Warning: enabling this on a multi-tenant deployment is an SSRF risk.** Only enable on a trusted, single-tenant self-hosted instance.
|
||||
</Accordion>
|
||||
- **`FLAG_DISABLE_SIGNUPS`**: Disables new signups (web app and server). Useful for private instances.
|
||||
- **`FLAG_DISABLE_EMAIL_AUTH`**: Disables email/password login entirely. Also disables email verification, forgot password, and reset password flows. Users can still sign up via social auth (Google/GitHub/LinkedIn/Custom OAuth), unless FLAG_DISABLE_SIGNUPS is also set to true. Useful when only SSO is required.
|
||||
- **`FLAG_DISABLE_IMAGE_PROCESSING`**: Disables image processing. This is useful if you are using a machine with limited resources, like a Raspberry Pi.
|
||||
- **`FLAG_ALLOW_UNSAFE_AI_BASE_URL`**: Allows AI providers to be configured with unsafe, private, or non-public base URLs, including `http://` and private/loopback addresses (for example, a local Ollama instance at `http://192.168.1.10:11434`). Public HTTPS provider URLs remain the safe default. **Warning: enabling this on a multi-tenant deployment is an SSRF risk.** Only enable on trusted, self-hosted deployments.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Updating your installation
|
||||
|
||||
Reference in New Issue
Block a user