Imported from huabeitech/agent-desk (
AGENTS.md). Install upstream withnpx skills add huabeitech/agent-desk. Copyright stays with the author.
AGENTS.md
This file defines the mandatory working agreement for AI agents in this repository. It is intentionally based on the current codebase rather than historical conventions.
1. Scope and Priorities
- These rules apply to the repository root and every subdirectory.
- Explicit user instructions take precedence over this file. Mention any deliberate deviation in the final summary.
- Inspect the relevant implementation before editing. Reuse current helpers, component APIs, generated-code workflows, and neighboring patterns instead of relying on memory.
- Keep changes narrowly scoped. Preserve unrelated and user-owned worktree changes, including staged changes.
- A review, investigation, or diagnosis request is read-only unless the user also asks for implementation.
2. Current Architecture
The repository contains three application areas:
- Go server:
cmd/serverandinternal/* - Next.js application:
web/* - Embedded workflow editor:
flowgram-editor/*, built intoweb/public/flowgram-editor
The main stack is:
- Go 1.26, Gin, GORM,
github.com/mlogclub/simple - SQLite and MySQL
- Next.js 16 App Router, React 19, TypeScript, Tailwind CSS, shadcn/Base UI
pnpmfor both frontend projects- Optional LanceDB builds through CGO; Qdrant is also supported by the application
Important entry points:
- Server assembly and middleware:
internal/bootstrap/server.go - Explicit API routes:
internal/bootstrap/routes.go - Model registration:
internal/models/models.go - Schema/data migration startup:
internal/bootstrap/migration.go - CRUD generator:
cmd/generator/generator.go - Frontend enum generator:
cmd/enums/generator.go - Frontend API client:
web/lib/api/client.ts - Frontend i18n:
web/i18n/*andweb/messages/* - Dashboard shared components:
web/components/dashboard/* - Project commands:
Taskfile.yml
3. General Change Rules
- Read the actual type, function, or component signature before using it.
- Prefer the highest-level existing abstraction that fits the requirement. Do not duplicate query state, pagination, auth refresh, localization, or dashboard CRUD behavior.
- Do not edit generated artifacts by hand. Change their source and run the corresponding generator/build command.
- Do not add a second implementation style when the repository already has a shared path for the same concern.
- Use
log/slogfor new Go logging and structured key-value fields for relevant context. - New Go code uses
any, notinterface{}. Existing generated or legacy code does not need unrelated cleanup. - Secrets, tokens, credentials, and private customer data must never be committed or printed in logs/tests.
4. Go Backend
4.1 Layer Ownership
The normal dependency and data flow is:
models -> repositories -> services -> handlers -> builders/response DTOs
internal/models: entity fields, GORM mappings, associations, and schema metadata only.internal/repositories: GORM/SQL access, conditions, ordering, pagination, locks, and persistence details.internal/services: business validation, state changes, authorization-independent domain rules, aggregation, transactions, and event orchestration.internal/handlers/{api,dashboard,third}: HTTP parameter parsing, authentication/permission checks, service calls, and response writing.internal/builders: pure model/aggregate-to-response mapping. Builders must not query the database.internal/pkg/dto/requestandinternal/pkg/dto/response: external request/response contracts.
Mandatory boundaries:
- Handlers must not call repositories or issue GORM queries directly.
- Models and repositories must not contain HTTP, permission, or cross-resource workflow logic.
- GORM models must not be returned directly from an API. Map them to response DTOs/builders.
- A service may return models internally, but public response shape remains owned by builders/DTOs.
- Put reusable SQL in repositories. A genuinely one-off aggregate query may stay near its domain service only when extraction would make ownership less clear.
4.2 Database and Transactions
- Repository methods that participate in transactions accept
db *gorm.DB; call them withsqls.DB()outside a transaction andctx.Txinside one. - Services own transaction boundaries through
sqls.WithTransaction. - Use a transaction for atomic multi-write workflows and consistency-sensitive read-modify-write operations.
- Do not add a transaction around a single independent SQL write.
- Every database operation inside a transaction must use the same
ctx.Tx; never escape tosqls.DB()mid-transaction. - Use
sqls.Cnd/sqls.NewCnd()and repository methods for ordinary filtering and pagination. - Preserve SQLite and MySQL compatibility. Avoid dialect-specific SQL unless both dialects are explicitly implemented and tested.
- Use portable column types and
int64primary/foreign identifiers. Keep time handling compatible with MySQLparseTime=True.
4.3 Models, Generation, and Migrations
- Register persistent models in
internal/models/models.goso startupAutoMigrate(models.Models...)includes them. - New tables, columns, indexes, and compatible constraints are normally applied by GORM
AutoMigrateininternal/bootstrap/migration.go. - Use
internal/migration/*only for versioned, idempotent data migration/backfill/repair work. Its version must increase monotonically. - When a model uses the standard generated repository/service surface, register it in
cmd/generator/generator.goand runtask generator. - Treat generator output as mechanical infrastructure. Put business-specific methods in handwritten files and do not manually patch generated CRUD output.
- Backend/frontend shared enums are defined in
internal/pkg/enums, annotated using the existing enum pattern, and generated withtask enumsintoweb/lib/generated/enums.ts. - Never create a handwritten frontend duplicate of a generated backend enum.
4.4 HTTP APIs
- All routes are explicit in
internal/bootstrap/routes.go; handler names do not create endpoints. - Public/product APIs live under
/api/*, authenticated management APIs under/api/dashboard/*, callbacks under/api/third/*, and WebSockets under/api/ws/*. - Add a resource-specific
register...Routesfunction or extend the existing one, then mount it fromaddRouterunder the correct group. - Follow the existing resource contract: detail commonly uses
GET /:id, list uses/list, writes use explicit POST actions such as/create,/update,/delete, and domain actions retain their established snake_case path names. - Do not introduce
/api/v1, automatic routing assumptions, or unnecessary deeply nested resource paths. - Handler names mirror the registered method and path, for example
XxxGetBy,XxxAnyList, andXxxPostCreate. - Parse JSON/form/query/path values with
internal/pkg/httpx/paramsandinternal/pkg/httpxhelpers. - Dashboard permission checks use
services.AuthService.RequirePermissionor the established permission helper before domain work. - Write responses through
httpx.WriteJSON; preserve the sharedJsonResultcontract. - Paginated responses use
web.PageResultwithdata.resultsanddata.page. - Convert not-found, validation, permission, and persistence failures into stable application errors. Never expose raw SQL errors to clients.
4.5 Backend Internationalization
- Any new or changed user-visible backend error must support every backend locale, currently
zh-CNanden-US. - Add matching keys to both
internal/pkg/i18nx/locales/zh-CN.ymlandinternal/pkg/i18nx/locales/en-US.ymlin the same change. - Services should return localized application errors through the
errorsx.*I18nhelpers. - Handlers that need an immediate localized response use
httpx.JsonErrorMsg(ctx, key, args...); other request-context translation usesi18nx.T. - Do not hard-code Chinese or English error sentences in handlers/services when the text can reach a user.
- Keep format arguments equivalent across locales and cover new reusable/error-format behavior with focused tests.
5. Frontend
5.1 Component and Data Boundaries
- Application routes live under
web/app; reusable business components live underweb/components; route-private components live in the route's_componentsdirectory. - Reuse
web/components/ui/*primitives. Do not edit these shadcn base components for a feature-specific requirement. - Use the current Base UI/shadcn component API as implemented in the repository; do not assume APIs such as Radix
asChildexist. - Use
@/*imports for code withinweb. - Client components must declare
"use client"when they use state, effects, browser APIs, or client-only hooks. - Keep resource APIs in
web/lib/api/*and route all normal requests throughweb/lib/api/client.ts. - Pages, business components, and stores must not implement their own
JsonResultparsing, auth header handling, token refresh, or login-expiry cleanup. - Direct
fetchis reserved for unsupported transports such as third-party calls, binary transfers, SSE, and WebSocket handshakes; explain the exception in code. - Prefer
OptionComboboxfor standard dropdowns rather than adding shadcn Select-based business controls. - Format displayed timestamps with
formatDateTimefromweb/lib/utils.tsunless the product explicitly requires a different representation.
5.2 Dashboard Pages
Before building a dashboard page, inspect web/components/dashboard/crud, web/components/dashboard/list, and web/components/dashboard-page.tsx.
Use this order of preference:
DashboardCrudPagefor standard create/read/update/delete resources.DashboardListPagefor read-only or custom-content paginated resources.useDashboardPagedListwhen layout is bespoke but list query/filter/pagination lifecycle is standard.DashboardPage,DashboardToolbar,DashboardTableShell, and related low-level primitives only for interactions that cannot fit the higher-level components.
Rules:
- Do not copy a resource page to recreate standard filters, query/reset/refresh actions, pagination, loading/empty states, confirmations, row actions, or dialogs.
- Configure
DashboardCrudPagethrough its filters, columns, labels, service callbacks, row actions, sorting, and form/dialog extension points before adding page-local infrastructure. - Use its schema-driven
DashboardCrudFormDialogwhen supported. A genuinely custom form may live in_componentsand should normally usereact-hook-form,zod, andField. - Configure
DashboardListPagewith columns orrenderContent, and userenderToolbarActionsfor resource-specific actions. - Business API knowledge stays in the page/service module; generic dashboard components must not import a resource-specific API.
- A change to
web/components/dashboard/*must be generic, backward-compatible, and useful beyond one page. Otherwise keep it local to the feature.
5.3 Frontend Internationalization
- Every frontend feature and modification must work in all
SUPPORTED_LOCALES, currentlyzh-CNanden-US. - Add every new key to both
web/messages/zh-CN.jsonandweb/messages/en-US.jsonin the same change, preserving matching structure. - React pages/components use
useI18n(); locale-aware formatting/mapping may also useuseAppLocale(). - Non-React code uses
translateCurrentMessage()ortranslateMessage()fromweb/i18n/messages.ts. - Do not hard-code user-visible copy in JSX/TSX, toast messages, dialogs, confirmations, placeholders, validation, empty/loading/error states, tooltips, accessibility labels, or client-side fallback errors.
- Product names, protocol literals, user content, and raw business data do not need translation unless the UI already provides a display-name mapping.
- Dashboard labels supplied to shared CRUD/list components must come from translation keys.
- Centralize localized display names for backend identifiers/enums in a reusable
web/lib/*-i18n.tshelper instead of duplicating locale switches across pages. - Preserve the same placeholders in every locale and interpolate with
t(key, values); do not assemble sentences by concatenating translated fragments. - Locale configuration belongs to
AppI18nProviderandweb/i18n/config.ts; features must not introduce separate locale detection or state.
5.4 Commercial-Grade UI and Interaction
This is a commercial product, not a prototype or component demo. UI work is complete only when it is visually coherent, interaction-complete, responsive, localized, and credible with real production data.
Visual Quality
- Follow the existing design language, spacing scale, typography, radius, color tokens, and component variants. A new feature must look native to the product rather than like a pasted template.
- In support platform UI, if rounded corners are needed, use
rounded-mdconsistently. - Support platform components should not add
shadow. - Establish a clear hierarchy: page title/primary action, filters or context, main content, and secondary information. Do not make every region a card or every action visually prominent.
- Prefer restrained, purposeful styling. Avoid decorative gradients, oversized hero text, excessive shadows, glass effects, emoji icons, random accent colors, and ornamental copy unless the product context explicitly calls for them.
- Use Lucide icons consistently. Choose icons by meaning, keep icon size and stroke weight aligned with neighboring controls, and never use icons as decoration without communicative value.
- Keep spacing and alignment deliberate at every breakpoint. Labels, inputs, table columns, action groups, dialog footers, and empty states must align cleanly without ad hoc offsets.
- Design for realistic content, not ideal sample text. Verify long names, multiline content, large counts, missing optional fields, and mixed Chinese/English values. Use wrapping, truncation, tooltips, or scroll containers intentionally.
- Preserve information density appropriate to an operations dashboard. Do not waste large areas on decoration, but do not compress controls until scanning and clicking become difficult.
Interaction Completeness
- Every asynchronous action must have an immediate and unambiguous state: pending/loading, success, failure, and retry or recovery when appropriate.
- Prevent duplicate submissions. Disable or lock the initiating control while a mutation is pending and show action-specific progress text or a spinner without causing layout shift.
- Keep feedback close to the action. Use inline validation for field problems, contextual error states for failed content, and toast notifications for completed background or page-level actions.
- Never silently discard user input. Warn before closing, navigating away, resetting, or switching context when there are meaningful unsaved changes.
- Destructive, irreversible, security-sensitive, or broad-impact operations require confirmation that clearly names the object and consequence. Do not use a generic “Are you sure?” message.
- Confirmation is not a substitute for good defaults: routine reversible actions should remain efficient and should not be interrupted by unnecessary modal prompts.
- After create/update/delete operations, keep list state coherent: refresh affected data, preserve useful filters/page position when possible, close dialogs only on success, and prevent stale selections or detail panels.
- Buttons and menu items must use precise verbs describing the result. Avoid vague labels such as “OK”, “Submit”, or “Process” when a specific action name is available.
- Preserve keyboard behavior and focus flow: Enter submits only where expected, Escape closes dismissible overlays, focus moves into dialogs and returns to the trigger, and destructive actions are not the accidental default.
- Interactive rows, icons, badges, and text links must look interactive only when they are interactive. Do not rely on hover-only discoverability for essential actions.
Forms and Dialogs
- Use the smallest suitable interaction container: inline editing for simple local changes, a dialog for focused tasks, and a full page/workbench for complex or multi-step workflows.
- Dialogs need a clear title, concise context when necessary, stable body layout, and a consistent footer with secondary action before primary action. Long content must scroll inside the dialog without pushing actions off-screen.
- Forms must have visible labels, appropriate controls, useful defaults, required/optional semantics, and examples or help text only where they reduce ambiguity.
- Validate at the right time: do not show errors before the user has interacted, clear stale errors after correction, and map backend validation failures to the relevant field when possible.
- Preserve entered values after failed submission. Do not reset or close a form until the server confirms success.
- Dependent fields must clearly reflect disabled/loading/empty states. When one field invalidates another, update it predictably and explain the dependency when it is not obvious.
- Configuration and high-impact forms should not expose a permanently editable surface when a deliberate edit mode improves safety. Saving sensitive configuration requires explicit user intent and appropriate confirmation.
Lists, Tables, and Operational Screens
- Use the shared Dashboard CRUD/list system and maintain consistent toolbar, filter, pagination, loading, empty, and action placement across resources.
- Filters must distinguish draft values from applied query state. Query, reset, refresh, pagination, and URL/state behavior should be predictable and must not unexpectedly erase one another.
- Tables must remain scannable: align comparable values, keep action columns stable, use badges sparingly for status, avoid dense multiline cells when a detail view is more appropriate, and provide horizontal overflow on narrow screens.
- Empty states must distinguish “no data exists” from “no results match the current filters” and offer the most relevant next action when the user can resolve the state.
- Loading states should preserve layout. Prefer skeletons for content whose shape is known and compact spinners for localized actions; avoid replacing an entire stable page with a centered spinner.
- Error states must explain what failed in user terms and provide retry when retry is meaningful. Never leave a blank table or empty panel after a request failure.
- Bulk actions must show selection count, affected scope, eligibility, and partial-failure results. Clear selection when it is no longer valid.
Responsive and Accessibility Requirements
- Every changed screen must work at desktop and narrow/mobile widths. Do not treat horizontal clipping, overlapping controls, wrapped action chaos, or off-screen dialog buttons as acceptable.
- Responsive behavior must preserve task priority: primary actions remain reachable, secondary actions may move into menus, filters may stack or collapse, and tables may scroll without hiding row identity/actions.
- Use semantic controls and accessible names. Icon-only buttons require localized accessible labels and tooltips where the meaning is not universally obvious.
- Maintain visible focus states, logical tab order, sufficient target sizes, and adequate text/background contrast. Do not encode status or errors using color alone.
- Respect reduced-motion preferences. Animations should explain state or continuity, remain subtle, and never delay work.
Product Copy and Data Credibility
- Copy must sound like a finished product: concise, specific, consistent, and action-oriented. Do not expose implementation jargon, placeholder prose, “TODO”, mock labels, debug wording, or developer instructions to users.
- Do not ship fake statistics, sample records, disabled-looking placeholder buttons, decorative charts without meaning, or interactions that only log to the console.
- Distinguish unavailable features from empty data. If a capability is not implemented, do not render a control that pretends it is functional.
- User-visible names, statuses, permissions, dates, and errors must use the established formatting and i18n mappings rather than raw backend identifiers.
UI Verification
- For meaningful UI changes, inspect the finished screen in a real browser at representative desktop and narrow widths. Source review and typecheck alone are not sufficient visual validation.
- Exercise the complete interaction, including initial load, populated state, empty/filtered state, validation failure, server failure when practical, pending/disabled behavior, success, cancel/close, and refresh.
- Check both
zh-CNanden-US; verify that translated copy does not overflow, truncate critical meaning, or break control alignment. - Before handoff, remove temporary data, debug UI, console output, test-only shortcuts, and visual artifacts introduced during verification.
- When browser verification cannot be performed, state that limitation explicitly; do not describe the UI as visually verified.
5.5 Generated and Embedded Frontend Assets
web/lib/generated/enums.tsis generated bytask enums; do not edit it manually.web/public/sdk/agent-desk-sdk.min.jsis generated from the SDK source. When SDK source changes, runcd web && pnpm build:sdkand its focused SDK tests.web/public/flowgram-editoris produced fromflowgram-editor; edit the source project, not the generated public output.- When changing
flowgram-editor, use its ownpnpmscripts and ensure the embedding build still succeeds. - The Next.js application is statically exported/embedded into the Go binary. Avoid runtime-only Next.js features that conflict with the current export and embedding model.
6. Testing and Validation
Validation must match the changed surface. Do not claim checks that were not run.
- Go formatting: run
gofmton every changed.gofile. - Go behavior: add focused tests for changed business rules, transactions, security boundaries, parsing, and reusable helpers; run the narrow package tests first, then
go test ./...when practical. - Frontend TypeScript: run
cd web && pnpm typecheckfor frontend changes. - Frontend lint: run
cd web && pnpm lintfor broader component/page changes or when lint-sensitive code changed. - Frontend logic: run relevant
node --test ...files when changing utilities, i18n mappings, generated SDK behavior, or other modules with focused tests. - Workflow editor: run the relevant
flowgram-editorlint/build commands for changes in that project. - Generation: after model CRUD or shared enum changes, run the corresponding
task generatorortask enumsand review generated diffs. - Build: use
task buildwhen changes affect frontend embedding, build configuration, generated public assets, or release assembly. - Browser verification is expected for meaningful visual or interaction changes when a runnable environment is available; state explicitly when it was not performed.
- Documentation-only changes require at least
git diff --checkand verification that every referenced path/command exists.
7. Completion Checklist
Before handing off a change, confirm the applicable items:
- The implementation follows current layer/component ownership and does not create reverse dependencies.
- Transactions cover exactly the operations that must be atomic, and all transactional DB calls use the same
ctx.Tx. - API routes are explicitly registered and responses preserve
JsonResult/PageResultcontracts. - Models, migrations, queries, and tests remain compatible with SQLite and MySQL.
- Backend and frontend user-visible text is complete in both Chinese and English.
- Dashboard pages reuse the highest-level suitable component under
web/components/dashboard/*. - UI changes meet the commercial-grade standard: complete states, precise feedback, safe mutations, responsive layout, accessible controls, credible copy/data, and no demo-only behavior.
- Generated files were regenerated from their source and were not manually edited.
- Relevant tests/typechecks/lint/build/browser checks were run, and any validation limitation is reported.
git diff --checkpasses and unrelated worktree changes remain untouched.
