* feat(knowledge): add upsert document operation to Knowledge block
Add a "Create or Update" (upsert) document capability that finds an
existing document by ID or filename, deletes it if found, then creates
a new document and queues re-processing. Includes new tool, API route,
block wiring, and typed interfaces.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(knowledge): address review comments on upsert document
- Reorder create-then-delete to prevent data loss if creation fails
- Move Zod validation before workflow authorization for validated input
- Fix btoa stack overflow for large content using loop-based encoding
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(knowledge): guard against empty createDocumentRecords result
Add safety check before accessing firstDocument to prevent TypeError
and data loss if createDocumentRecords unexpectedly returns empty.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(knowledge): prevent documentId fallthrough and use byte-count limit
- Use if/else so filename lookup only runs when no documentId is provided,
preventing stale IDs from silently replacing unrelated documents
- Check utf8 byte length instead of character count for 1MB size limit,
correctly handling multi-byte characters (CJK, emoji)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(knowledge): rollback on delete failure, deduplicate sub-block IDs
- Add compensating rollback: if deleteDocument throws after create
succeeds, clean up the new record to prevent orphaned pending docs
- Merge duplicate name/content sub-blocks into single entries with
array conditions, matching the documentTags pattern
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* lint
* lint
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(admin): add user search by email and ID, remove table border
- Replace Load Users button with a live search input; query fires on any input
- Email search uses listUsers with contains operator
- User ID search (UUID format) uses admin.getUser directly for exact lookup
- Remove outer border on user table that rendered white in dark mode
- Reset pagination to page 0 on new search
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(admin): replace live search with explicit search button
- Split searchInput (controlled input) from searchQuery (committed value)
so the hook only fires on Search click or Enter, not every keystroke
- Gate table render on searchQuery.length > 0 to prevent stale results
showing after input is cleared
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(logs): persist execution diagnostics markers
Store last-started and last-completed block markers with finalization metadata so later read surfaces can explain how a run ended without reconstructing executor state.
* fix(executor): preserve durable diagnostics ordering
Await only the persistence needed to keep diagnostics durable before terminal completion while keeping callback failures from changing execution behavior.
* fix(logs): preserve fallback diagnostics semantics
Keep successful fallback output and accumulated cost intact while tightening progress-write draining and deduplicating trace span counting for diagnostics helpers.
* fix(api): restore async execute route test mock
Add the missing AuthType export to the hybrid auth mock so the async execution route test exercises the 202 queueing path instead of crashing with a 500 in CI.
* fix(executor): align async block error handling
* fix(logs): tighten marker ordering scope
Allow same-millisecond marker writes to replace prior markers and drop the unused diagnostics read helper so this PR stays focused on persistence rather than unread foundation code.
* fix(logs): remove unused finalization type guard
Drop the unused helper so this PR only ships the persistence-side status types it actually uses.
* fix(executor): await subflow diagnostics callbacks
Ensure empty-subflow and subflow-error lifecycle callbacks participate in progress-write draining before terminal finalization while still swallowing callback failures.
---------
Co-authored-by: test <test@example.com>
Co-authored-by: Vikhyath Mondreti <vikhyath@simstudio.ai>
* feat(csp): allow chat UI to be embedded in iframes
Mirror the existing form embed CSP pattern for chat pages: add
getChatEmbedCSPPolicy() with frame-ancestors *, configure /chat/:path*
headers in next.config.ts without X-Frame-Options, and early-return in
proxy.ts so chat routes skip the strict runtime CSP.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor(csp): extract shared getEmbedCSPPolicy helper
Deduplicate getChatEmbedCSPPolicy and getFormEmbedCSPPolicy into a
shared private helper to prevent future divergence.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(auth): migrate to better-auth admin plugin
* feat(settings): add unified Admin tab with user management
Consolidate superuser features into a single Admin settings tab:
- Super admin mode toggle (moved from General)
- Workflow import (moved from Debug)
- User management via better-auth admin (list, set role, ban/unban)
Replace Debug tab with Admin tab gated by requiresAdminRole.
Add React Query hooks for admin user operations.
* fix(db): backfill existing super users to admin role in migration
Add UPDATE statement to promote is_super_user=true rows to role='admin'
before dropping the is_super_user column, preventing silent demotion.
* fix(admin): resolve type errors in admin tab
- Fix cn import path to @/lib/core/utils/cn
- Use valid Badge variants (blue/gray/red/green instead of secondary/destructive)
- Type setRole param as 'user' | 'admin' union
* improvement(auth): remove /api/user/super-user route, use session role
Include user.role in customSession so it's available client-side.
Replace all useSuperUserStatus() calls with session.user.role === 'admin'.
Delete the now-redundant /api/user/super-user endpoint.
* chore(auth): remove redundant role override in customSession
The admin plugin already includes role on the user object.
No need to manually spread it in customSession.
* improvement(queries): clean up admin-users hooks per React Query best practices
- Remove unsafe unknown/Record casting, use better-auth typed response
- Add placeholderData: keepPreviousData for paginated variable-key query
- Remove nullable types where defaults are always applied
* fix(admin): address review feedback on admin tab
- Fix superUserModeEnabled default to false (matches sidebar behavior)
- Reset banReason when switching ban target to prevent state bleed
- Guard admin section render with session role check for direct URL access
* fix(settings): align superUserModeEnabled default to false everywhere
Three places defaulted to true while admin tab and sidebar used false.
Align all to false so new admins see consistent behavior.
* fix(admin): fix stale pendingUserId, add isPending guard and error feedback
- Only read mutation.variables when mutation isPending (prevents stale ID)
- Add isPending guard to super user mode toggle (prevents concurrent mutations)
- Show inline error message when setRole/ban/unban mutations fail
* fix(admin): concurrent pending users Set, session loading guard, domain blocking
- Replace pendingUserId scalar with pendingUserIds Set (useMemo) so concurrent
mutations across different users each disable their own row correctly
- Add sessionLoading guard to admin section redirect to prevent flash on direct
/settings/admin navigation before session resolves
- Add BLOCKED_SIGNUP_DOMAINS env var and before-hook for email domain denylist,
parsed once at module init as a Set for O(1) per-request lookups
- Add trailing newline to migration file
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(admin): close OAuth domain bypass, fix stale errors, deduplicate icon
- Add databaseHooks.user.create.before to enforce BLOCKED_SIGNUP_DOMAINS at
the model level, covering all signup vectors (email, OAuth, social) not just
/sign-up paths
- Call .reset() on each mutation before firing to clear stale error state from
previous operations
- Change Admin nav icon from ShieldCheck to Lock to avoid duplicate with
Access Control tab
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* improvement(mothership): tool display titles, html sanitization, and ui fixes
- Use TOOL_UI_METADATA as fallback for tool display titles (fast_edit shows "Editing workflow" instead of "Fast Edit")
- Harden HTML-to-text extraction with replaceUntilStable to prevent nested tag injection
- Decode HTML entities in a single pass to avoid double-unescaping
- Fix Google Drive/Docs query escaping for backslashes in folder IDs
- Replace regex with indexOf for email sender/display name parsing
- Update embedded workflow run tooltip to "Run workflow"
* fix(security): decode entities before tag stripping and cap loop iterations
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Include notification view in embedded workflow view
* fix(ui) fix workflow not showing up when mothership calls run
* Wire up fix in mothership
* Refresh events after workflow run
* Fix so run workflow switches tabs as well
---------
Co-authored-by: Theodore Li <theo@sim.ai>
Tools with requiresConfirmation (e.g. user_table) blocked indefinitely
in mothership because the frontend has no approval UI. Added a new
promptForToolApproval orchestrator option so mothership auto-executes
these tools while copilot continues to prompt for user approval.
Made-with: Cursor
Co-authored-by: Theodore Li <theo@sim.ai>
* Fix deploy subagent
* fix(stream) handle task switching (#3609)
* Fix task switching causing stream to abort
* Process all task streams all the time
* Process task streams that are in the background
---------
Co-authored-by: Theodore Li <theo@sim.ai>
* Always return isDeployed for undeploy chat
* Fix lint
---------
Co-authored-by: Siddharth Ganesan <siddharthganesan@gmail.com>
Co-authored-by: Theodore Li <theo@sim.ai>
* fix(deploy): consolidate deployment detection into single source of truth
* fix(deploy): address PR review feedback
- Remove redundant isLoading check (subset of isPending in RQ v5)
- Make deployedState prop nullable to avoid non-null assertion
- Destructure mutateAsync to eliminate ESLint suppression
- Guard debounced invalidation against stale workflowId on switch
* fix(deploy): clean up self-explanatory comments and fix unstable mutation dep
- Remove self-explanatory comments in deploy.tsx, tool-input.tsx, use-child-workflow.ts
- Tighten non-obvious comments in use-change-detection.ts
- Destructure mutate/isPending in WorkflowToolDeployBadge to avoid unstable
mutation object in useCallback deps (TanStack Query no-unstable-deps pattern)
* lint
* fix(deploy): skip expensive state merge when deployedState is null
Avoid running mergeSubblockStateWithValues on every render for
non-deployed workflows where changeDetected always returns false.
* fix(deploy): add missing workflow table import in deploy route
Pre-existing type error — workflow table was used but not imported.
* fix(deploy): forward AbortSignal in fetchDeployedWorkflowState
Match the pattern used by all other fetch helpers in the file so
in-flight requests are cancelled on component unmount or query re-trigger.
* perf(deploy): parallelize all DB queries in checkNeedsRedeployment
All three queries (active version, normalized data, workflow variables)
now run concurrently via Promise.all, saving one DB round trip on the
common path.
* fix(deploy): use sequential-then-parallel pattern in checkNeedsRedeployment
* fix(deploy): use client-side comparison for editor header, remove server polling
The lastSaved-based server polling was triggering API calls on every
local store mutation (before socket persistence), wasting requests and
checking stale DB state. Revert the editor header to pure client-side
hasWorkflowChanged comparison — zero network during editing, instant
badge updates. Child workflow badges still use server-side
useDeploymentInfo (they don't have Zustand state).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(deploy): suppress transient Update flash during deployed state refetch
Guard change detection on isFetching (not just isLoading) so the
comparison is suppressed during background refetches after mutations,
preventing a brief Update→Live badge flicker.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* improvement(connectors): audit and harden all 30 knowledge base connectors
* fix(oauth): update Notion test to match Basic Auth + JSON body config
* fix(connectors): address PR review comments for hubspot, jira, salesforce
- HubSpot: revert to Search API (POST /search) to restore lastmodifieddate DESCENDING sorting
- Salesforce: restore ArticleBody field and add it to HTML_FIELDS for proper stripping
- Jira: add zero-remaining guard to prevent requesting 0 maxResults
* fix(salesforce): revert ArticleBody — not a standard KnowledgeArticleVersion field
ArticleBody is not a standard field on KnowledgeArticleVersion per Salesforce
API docs. Article body content lives in custom fields on org-specific __kav
objects. Including ArticleBody in the SOQL query would cause runtime errors.
* fix(connectors): address second round of PR review comments
- OneDrive: use Buffer.subarray for byte-accurate truncation instead of
character-count slice
- Reddit: deduplicate comment extraction — fetchPostComments now calls
extractComments instead of duplicating the logic
- Webflow: replace crude value.includes('<') with regex /<[a-z][^>]*>/i
to avoid false positives on plain text containing '<'
- Jira: add response.ok check in getJiraCloudId before parsing JSON to
surface real HTTP errors instead of misleading "No Jira resources found"
* fix(jira,outlook): replace raw fetch in downloadJiraAttachments, fix Outlook URL encoding
- Jira: replace bare fetch() with fetchWithRetry in downloadJiraAttachments
for retry logic on transient errors and rate limits
- Outlook: use URLSearchParams in validateConfig $search URL construction
to match buildInitialUrl and produce RFC 3986 compliant encoding
* fix(tools): support stringified HTTP request tables
Accept stored header and query tables after they are reloaded from UI JSON so HTTP requests keep their query strings and URL-encoded body handling intact.
* test: mock AuthType in async execute route
* test(tools): cover invalid stringified HTTP inputs
---------
Co-authored-by: test <test@example.com>
* fix(cancel): report cancellation durability truthfully
Return explicit durability results for execution cancellation so success only reflects persisted cancellation state instead of best-effort Redis availability.
* fix: hoist cancellation test mocks
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix(sim): harden execution cancel durability
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix(sim): fallback manual cancel without redis
Abort active manual SSE executions locally when Redis cannot durably record the cancellation marker so the run still finalizes as cancelled instead of completing normally.
* test: mock AuthType in async execute route
Keep the rebased async execute route test aligned with the current hybrid auth module exports so it exercises the queueing path instead of failing at import time.
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: test <test@example.com>