mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-14 13:49:18 +02:00
* fix(views): surface backend error messages on mutation failures (MUL-2317)
Mutation toasts across the views package were swallowing the backend
`error` string and showing only a generic i18n fallback. This made it
impossible for users to see why an operation failed (most visibly:
creating an issue with a duplicate title produced a vague "Failed to
create issue" toast).
The fix has three pieces:
1. Create-issue duplicate branch (A段)
- New schema `DuplicateIssueErrorBodySchema` in core/api/schemas.ts.
- `create-issue.tsx` parses `ApiError.body` via `parseWithFallback`
and renders a dedicated amber-toned toast with a "view existing"
link when the server returns `{ code: "active_duplicate_issue",
issue: {...} }`. Schema drift downgrades to the normal error toast.
- Schema intentionally omits `issue.status` so the toast does not
depend on `StatusIcon`, which has no fallback for unknown enums.
2. User-facing mutation failure toasts (B段)
- 47 sites converted to `err instanceof Error && err.message ?
err.message : <existing fallback>` — preserves all existing
code-specific branches (slug conflict, agent_unavailable,
daemon_version_unsupported) and i18n keys.
- Covers Type 1 (onError) and Type 2 (catch block) patterns across
issues, projects, autopilots, inbox, runtimes, squads, comments,
batch actions, workspace create, and agent config tabs.
3. Autopilot partial-success (Type 3)
- New i18n keys `toast_create_partial_with_reason` /
`toast_update_partial_with_reason` (double-brace `{{reason}}`).
- `autopilot-dialog.tsx` captures `err.message` in the schedule
`catch` and routes to the `_with_reason` variant when present,
preserving the partial-success semantic (autopilot saved, schedule
failed) while exposing the actual reason.
Explicitly out of scope:
- `packages/core/` mutation hooks (no global onError, no UI dependency)
- No `toastApiError` helper (matches existing 14+ correct sites)
- Sub-issue link aggregate `Promise.allSettled` keeps count-based toast
(N independent requests cannot collapse to one err.message); only
added a dev-side `console.error` per rejection.
- Clipboard catches and `useUpdateChatSession` (not API mutation toasts)
Tests:
- `packages/core/api/schemas.test.ts` — schema contract (valid body,
forward-compat fields, rename rejection, missing issue, wrong types).
- `packages/views/modals/create-issue.test.tsx` — duplicate toast +
view link, schema-drift fallback, err.message surfacing, non-Error
fallback (4 new cases).
- `packages/views/autopilots/components/autopilot-dialog-i18n.test.ts`
— real i18next, asserts rendered text contains the reason verbatim
(guards against `{reason}` vs `{{reason}}` regression).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
* fix(autopilots): unify rotate-token catch + cover dialog partial-success render
Address reviewer feedback on PR #2772:
1. webhook-token rotate (`autopilot-detail-page.tsx`) now follows the
`err.message ?? fallback` ternary used by the sibling trigger
delete/add paths, instead of swallowing the error.
2. Extract `formatSchedulePartialFailureToast` so the dialog's
partial-success branches and the i18n test exercise the same
helper. The test now drives the actual format function, so a
variable-name typo at the call site (e.g. `{ msg }` instead of
`{ reason }`) fails the substring assertion.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
* test(modals): drop user.type for title in success path to dodge CI 5s timeout
The success-path test typed the 42-character title via userEvent which
triggers a controlled re-render per keystroke. On the slower CI runner
the whole test crept up to ~5s and intermittently tripped the default
vitest timeout. Setting the value in one shot via fireEvent.change cuts
the cost while leaving the submit + toast interactions on userEvent.
Co-authored-by: multica-agent <github@multica.ai>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
121 lines
4.7 KiB
JSON
121 lines
4.7 KiB
JSON
{
|
|
"name": "@multica/core",
|
|
"version": "0.0.0",
|
|
"private": true,
|
|
"type": "module",
|
|
"scripts": {
|
|
"typecheck": "tsc --noEmit",
|
|
"lint": "eslint .",
|
|
"test": "vitest run"
|
|
},
|
|
"exports": {
|
|
".": "./index.ts",
|
|
"./types": "./types/index.ts",
|
|
"./types/*": "./types/*.ts",
|
|
"./api": "./api/index.ts",
|
|
"./api/client": "./api/client.ts",
|
|
"./api/schema": "./api/schema.ts",
|
|
"./api/schemas": "./api/schemas.ts",
|
|
"./api/ws-client": "./api/ws-client.ts",
|
|
"./config": "./config/index.ts",
|
|
"./auth": "./auth/index.ts",
|
|
"./workspace": "./workspace/index.ts",
|
|
"./workspace/queries": "./workspace/queries.ts",
|
|
"./workspace/mutations": "./workspace/mutations.ts",
|
|
"./workspace/hooks": "./workspace/hooks.ts",
|
|
"./issues": "./issues/index.ts",
|
|
"./issues/queries": "./issues/queries.ts",
|
|
"./issues/mutations": "./issues/mutations.ts",
|
|
"./issues/ws-updaters": "./issues/ws-updaters.ts",
|
|
"./issues/config": "./issues/config/index.ts",
|
|
"./issues/config/status": "./issues/config/status.ts",
|
|
"./issues/config/priority": "./issues/config/priority.ts",
|
|
"./issues/stores": "./issues/stores/index.ts",
|
|
"./issues/stores/view-store-context": "./issues/stores/view-store-context.tsx",
|
|
"./issues/stores/*": "./issues/stores/*.ts",
|
|
"./inbox": "./inbox/index.ts",
|
|
"./inbox/queries": "./inbox/queries.ts",
|
|
"./inbox/mutations": "./inbox/mutations.ts",
|
|
"./inbox/ws-updaters": "./inbox/ws-updaters.ts",
|
|
"./notification-preferences": "./notification-preferences/index.ts",
|
|
"./notification-preferences/queries": "./notification-preferences/queries.ts",
|
|
"./notification-preferences/mutations": "./notification-preferences/mutations.ts",
|
|
"./chat": "./chat/index.ts",
|
|
"./chat/queries": "./chat/queries.ts",
|
|
"./chat/mutations": "./chat/mutations.ts",
|
|
"./runtimes": "./runtimes/index.ts",
|
|
"./runtimes/queries": "./runtimes/queries.ts",
|
|
"./runtimes/mutations": "./runtimes/mutations.ts",
|
|
"./runtimes/hooks": "./runtimes/hooks.ts",
|
|
"./runtimes/custom-pricing-store": "./runtimes/custom-pricing-store.ts",
|
|
"./dashboard": "./dashboard/index.ts",
|
|
"./dashboard/queries": "./dashboard/queries.ts",
|
|
"./agents": "./agents/index.ts",
|
|
"./agents/queries": "./agents/queries.ts",
|
|
"./agents/derive-presence": "./agents/derive-presence.ts",
|
|
"./agents/use-agent-presence": "./agents/use-agent-presence.ts",
|
|
"./agents/visibility-label": "./agents/visibility-label.ts",
|
|
"./agents/stores": "./agents/stores/index.ts",
|
|
"./squads": "./squads/index.ts",
|
|
"./squads/stores": "./squads/stores/index.ts",
|
|
"./permissions": "./permissions/index.ts",
|
|
"./projects": "./projects/index.ts",
|
|
"./projects/queries": "./projects/queries.ts",
|
|
"./projects/mutations": "./projects/mutations.ts",
|
|
"./projects/config": "./projects/config.ts",
|
|
"./labels": "./labels/index.ts",
|
|
"./labels/queries": "./labels/queries.ts",
|
|
"./labels/mutations": "./labels/mutations.ts",
|
|
"./autopilots": "./autopilots/index.ts",
|
|
"./autopilots/queries": "./autopilots/queries.ts",
|
|
"./autopilots/mutations": "./autopilots/mutations.ts",
|
|
"./pins": "./pins/index.ts",
|
|
"./pins/queries": "./pins/queries.ts",
|
|
"./pins/mutations": "./pins/mutations.ts",
|
|
"./github": "./github/index.ts",
|
|
"./github/queries": "./github/queries.ts",
|
|
"./feedback": "./feedback/index.ts",
|
|
"./feedback/mutations": "./feedback/mutations.ts",
|
|
"./realtime": "./realtime/index.ts",
|
|
"./navigation": "./navigation/index.ts",
|
|
"./modals": "./modals/index.ts",
|
|
"./onboarding": "./onboarding/index.ts",
|
|
"./paths": "./paths/index.ts",
|
|
"./hooks": "./hooks.tsx",
|
|
"./hooks/*": "./hooks/*.ts",
|
|
"./query-client": "./query-client.ts",
|
|
"./provider": "./provider.tsx",
|
|
"./logger": "./logger.ts",
|
|
"./utils": "./utils.ts",
|
|
"./constants/*": "./constants/*.ts",
|
|
"./platform": "./platform/index.ts",
|
|
"./analytics": "./analytics/index.ts",
|
|
"./i18n": "./i18n/index.ts",
|
|
"./i18n/react": "./i18n/react.ts",
|
|
"./i18n/browser": "./i18n/browser.ts"
|
|
},
|
|
"dependencies": {
|
|
"@formatjs/intl-localematcher": "catalog:",
|
|
"@tanstack/react-query": "catalog:",
|
|
"@tanstack/react-query-devtools": "^5.96.2",
|
|
"i18next": "catalog:",
|
|
"posthog-js": "catalog:",
|
|
"react-i18next": "catalog:",
|
|
"zod": "catalog:",
|
|
"zustand": "catalog:"
|
|
},
|
|
"peerDependencies": {
|
|
"react": "catalog:"
|
|
},
|
|
"devDependencies": {
|
|
"@multica/tsconfig": "workspace:*",
|
|
"@testing-library/react": "catalog:",
|
|
"@types/react": "catalog:",
|
|
"jsdom": "catalog:",
|
|
"react": "catalog:",
|
|
"react-dom": "catalog:",
|
|
"typescript": "catalog:",
|
|
"vitest": "catalog:"
|
|
}
|
|
}
|