Skip to content

Commit 255a7d2

Browse files
authored
✨ Support full thread management (#3917)
* 📃 Merge cursor rules into universal AGENTS.md and skills * ✨ Support full thread management * ✨ Support full thread management phase2 * 🧪 Add test files * 🧪 Add test files * 🧪 Add test files * ✨ Thread management fulfilling platform constraint * 🧪 Add test files * 🧪 Add thread interface * 🧪 Add test files
1 parent 4987e14 commit 255a7d2

159 files changed

Lines changed: 12785 additions & 4735 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
name: nexent-backend
3+
description: Use when designing, implementing, debugging, or reviewing Nexent relational schemas, FastAPI endpoints, backend services, database access, SQL migrations, or backend/SDK configuration. Includes table/field naming, types, JSONB boundaries, audit fields, keys, and indexes even before code paths exist. Skip frontend-only work and unrelated SDK algorithms.
4+
---
5+
6+
# Nexent backend changes
7+
8+
Repository paths below are relative to the root; reference links resolve from this skill directory.
9+
10+
1. Identify the affected boundary and inspect existing callers and contracts. Apps handle HTTP, services orchestrate business logic, and database modules own persistence.
11+
2. Read only the references matching the work. For end-to-end changes, read each affected layer before editing.
12+
13+
| Work | Reference |
14+
| --- | --- |
15+
| HTTP routes, validation, identity, response/error mapping | [HTTP layer](references/http.md) |
16+
| Business orchestration and domain errors | [Services](references/services.md) |
17+
| Relational schema design, models, keys/indexes, queries, transactions, SQL migrations | [Database](references/database.md) |
18+
| Environment configuration and SDK configuration parameters | [Configuration](references/configuration.md) |
19+
| Threads, worker pools, blocking calls, background loops, streaming resource lifetime | [Thread lifecycle](references/thread-lifecycle.md) |
20+
21+
3. Preserve public contracts. Apply conventions to the changed scope; do not refactor unrelated legacy behavior merely to satisfy a rule.
22+
4. Verify affected success and failure behavior. For Python unit tests, use `nexent-python-tests` linked from root `AGENTS.md`. Unit-test mocks do not establish live-integration acceptance.
23+
5. Report references consulted, affected contracts, and verification results. Resolve material contract conflicts using concrete evidence; routine implementation choices do not require additional permission.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Backend and SDK configuration
2+
3+
Applies to backend/SDK Python configuration changes.
4+
5+
- Define environment reads and defaults only in `backend/consts/const.py`.
6+
- Backend apps and services import values from `consts.const` or accept explicit parameters. Apps pass configuration through to services.
7+
- SDK code accepts configuration through constructor/function parameters. Do not add environment reads or `from_env()` methods.
8+
- Update `deploy/env/.env.example` or the relevant component's tracked example when adding/changing a variable. Do not overwrite local `.env` files.
9+
- Update affected constructors/callers to pass values to the SDK. Remove superseded direct reads within the changed path.
10+
- Verify defaults and explicit configuration; inspect affected backend/SDK code for stray `os.getenv()` / `os.environ.get()` outside `const.py`.
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# Database design, access, and migrations
2+
3+
Use for relational schema design, `backend/database/**/*.py`, related service-level integrity checks, and schema work under `deploy/sql/`.
4+
5+
## Design workflow
6+
7+
1. Identify business entities and relationships before deciding tables and fields. An E-R diagram is optional; describe relationships clearly in the design even when no diagram is produced.
8+
2. Gather query scenarios, including filters, joins, sorting, pagination, updates, and version/history needs. Use these to choose columns, JSONB, tables, and indexes together.
9+
3. Specify field names, business definitions, types/lengths, nullability/defaults, audit behavior, references, and application-enforced integrity. Record JSONB boundaries and index rationale alongside DDL.
10+
4. Compare with existing models, callers, and migrations. Apply new design requirements to new schema; explicitly resolve legacy compatibility before implementing a schema change.
11+
12+
## Table and field naming
13+
14+
- Use lowercase snake_case. Business tables follow `<module>_<business_noun_phrase>_t`; backend-only log tables follow `<module>_<business_noun_phrase>_log`; archive tables follow `<table_name>_<archive_date>_bak` when archiving is needed.
15+
- Use one to three meaningful nouns or a noun phrase. Prefer module-consistent abbreviations; avoid a lone ambiguous verb. For example, `conversation_share_record_t` identifies a sharing record more clearly than `conversation_share_t`.
16+
- Name fields for business meaning and specific usage. Include units for measured values, such as `latency_ms` or `amount_usd`. Keep reference-field names consistent with the identifiers they reference.
17+
- Qualify broad names such as `data`, `info`, or `metadata`; use names such as `provider_metadata` with a defined purpose.
18+
- Every field needs an English database column comment describing its business meaning and applicable scenario. For example, a credential used only for speech-model authentication must state that limitation.
19+
- Carry comments into generated DDL/database metadata. Inspect whether the ORM declaration emits a database comment; Python-only documentation is not sufficient evidence that the column is commented.
20+
21+
## Field types and boundaries
22+
23+
Treat length/type choices as part of the specification and align input validation with them.
24+
25+
| Meaning | Recommended default | Design requirement |
26+
| --- | --- | --- |
27+
| Name/title | `VARCHAR(100)` | Adjust to an explicit business limit |
28+
| Enum/status code | `VARCHAR(30)` | Keep the vocabulary and length consistent |
29+
| General integer | `INT4` | Confirm the required range |
30+
| Primary/reference identifier | `INT4` | Match the referenced identifier's type; document capacity or legacy exceptions |
31+
| Dictionary/variable structured value | `JSONB` | Define purpose, accepted keys/structure, value types, and validation boundaries |
32+
33+
- Avoid unbounded `TEXT`/`VARCHAR` for values with meaningful business limits. Use them for bodies, error stacks, or raw text when no stable upper bound exists.
34+
- Do not copy an illustrative limit such as 1,000 characters for every message body. Derive limits from the actual contract and verify boundary/rejection behavior.
35+
36+
## Columns, JSONB, or tables
37+
38+
| Situation | Preferred representation |
39+
| --- | --- |
40+
| Attribute meaningful for all rows, queried/sorted/aggregated, or frequently updated | Explicit column |
41+
| Row-specific supplemental data, variable structures, or a value primarily read as a whole | Purpose-specific JSONB, such as a snapshot or raw provider output |
42+
| New business entity/relationship with many attributes | Separate table |
43+
| Small entity/relationship wholly subordinate to another entity | A few columns or bounded JSONB, chosen from the access patterns |
44+
45+
Document JSONB ownership and validation, including allowed/required keys or an explicitly opaque provider payload, null/default semantics, and applicable size limits. Do not hide stable queryable business attributes in an unrestricted metadata bag.
46+
47+
## Audit fields
48+
49+
The new design standard requires all five audit fields on every new table, including log/archive designs. Existing exceptions must be identified rather than copied silently.
50+
51+
| Field | Type | Meaning |
52+
| --- | --- | --- |
53+
| `created_by` | `VARCHAR(100)` | Creating user or system actor |
54+
| `create_time` | `TIMESTAMP` | Creation time |
55+
| `updated_by` | `VARCHAR(100)` | Last updating user or system actor |
56+
| `update_time` | `TIMESTAMP` | Last update time |
57+
| `delete_flag` | `VARCHAR(1)` | Soft-delete marker, default `N` |
58+
59+
- Inherit the five audit fields from `backend/database/db_models.py::TableBase`, which uses the names and types above. Do not redeclare inherited audit columns.
60+
- Define how all write paths maintain timestamps, including raw SQL and SQLAlchemy Core operations; do not assume an ORM `onupdate` setting proves database-wide behavior.
61+
62+
## Keys, references, and business uniqueness
63+
64+
- Every business table has a single technical primary key. If business identity is composite, add a separate record identifier instead of making that business combination the primary key.
65+
- For versioned resources, distinguish stable entity identity from a version-specific row ID. The supplied example uses `agent_no` across versions and `agent_id` for a concrete version; this is a design example, not authorization to rename existing columns.
66+
- New business-table designs do not declare database foreign-key constraints or non-primary unique constraints. Do not circumvent this policy with a unique index. Primary-key uniqueness and appropriate structural constraints such as `NOT NULL` remain allowed.
67+
- Keep logical reference names consistent and implement relationship checks and business uniqueness in the service layer. Document these contracts in field comments and identify the responsible service/write paths.
68+
- Specify the uniqueness scope, including tenant, version, and active/deleted rows where relevant. Verify missing references, duplicates, and concurrent writes. A check followed by an insert alone is not evidence of race-safe uniqueness; define transaction/serialization or another application-level coordination strategy where required.
69+
- Existing foreign keys and unique constraints/indexes are compatibility concerns. Do not remove them during unrelated work. Any removal needs an explicit migration and replacement integrity behavior, including all writers.
70+
71+
## Index design
72+
73+
- Design indexes together with tables using actual filtering, joining, ordering, and pagination scenarios. Describe which query each index supports and why its column order/predicate is appropriate.
74+
- Consider common active-row filtering and query combinations; avoid indexing every field by default. Business indexes remain non-unique under the policy above.
75+
- Include index DDL in the migration and validate representative query plans when an execution environment is available. Report unverified performance assumptions explicitly.
76+
77+
## Models and CRUD
78+
79+
- Define models in `backend/database/db_models.py`, inheriting `TableBase` and reusing its shared audit fields.
80+
- Prefer SQLAlchemy Core `insert`/`update`/`select` with `session.execute()` / `session.scalars()`. ORM `session.add()` remains allowed.
81+
- Creation sets the creating/updating actor and `delete_flag='N'`; populate timestamps through the designed defaults. Updates normally overwrite the row, refresh the updating actor/time, and preserve creation fields.
82+
- Business tables use soft deletion. Set `delete_flag='Y'`, the updating actor/time, and soft-delete dependent rows in the same transaction when required by the relationship contract.
83+
- Normal reads filter `delete_flag='N'`, including relevant joins. Reuse a shared active-row filter when available; do not assume the current data layer already injects it automatically. History/deleted-row access must be explicit.
84+
- If a resource requires retained versions, consider inserting a new version and soft-deleting the previous one in one transaction. Specify stable/version-specific references and which record reads should return; do not impose versioning on every update.
85+
86+
## Transaction ownership and errors
87+
88+
- Use `with get_db_session() as session:` from `backend/database/client.py`, or its supported shared-session form for a caller-owned transaction.
89+
- CRUD functions never call `commit()`, `rollback()`, or `close()`. The session owner handles lifecycle; the current context manager leaves explicitly supplied sessions to their caller.
90+
- Let exceptions propagate from CRUD modules. Central session management rolls back, logs, re-raises, and closes sessions it owns.
91+
- Define a shared database exception in `backend/consts/exceptions.py` if needed and verify its raising boundary. The current client re-raises original exceptions; it does not automatically create `DatabaseOperationError`.
92+
93+
## SQL
94+
95+
- Every file named `init.sql` or with `merged_migrations` in its name is already merged into the target branch, which is immutable. Never modify, rename, or delete one.
96+
- Add a versioned migration under `deploy/sql/migrations/`, following current naming/version conventions. Application version is `APP_VERSION` in `backend/consts/const.py`.
97+
- Verify naming/comments, type limits, JSONB validation, audit maintenance, reference/uniqueness behavior, soft deletion/versioning, query indexes, transaction ownership, and migration compatibility as applicable. External database execution requires authorization for that action.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# HTTP layer
2+
3+
Applies to `backend/apps/**/*.py`.
4+
5+
## Boundary and compatibility
6+
7+
- Parse/validate inputs, invoke services, translate domain errors to HTTP, and return responses. Keep business logic out of apps.
8+
- Read configuration from `consts.const` or pass explicit parameters. Preserve existing routes, payloads, and response structures.
9+
- New collections use plural nouns and snake_case path segments; parameters use singular semantic names such as `{agent_id}`. Keep legacy prefixes such as `/agent`.
10+
- Prefer resource-oriented CRUD routes; use action routes for non-CRUD behavior or compatibility.
11+
- GET reads/lists; preserve legacy GET actions but introduce no new side-effecting GETs. POST creates, searches, or triggers actions. DELETE is idempotent. Prefer PUT for full updates and PATCH for partial updates while retaining legacy POST update routes.
12+
13+
## Requests and identity
14+
15+
- Inject authorization with `authorization: Optional[str] = Header(None)` where this is the endpoint convention. Use `utils.auth_utils` helpers such as `get_current_user_id` / `get_current_user_info`; pass `user_id` / `tenant_id` to services. Do not implement token parsing in routes.
16+
- Prefer Pydantic models in `consts.model` for complex bodies; use `Body(..., embed=True)` for atomic named fields. Use `Query`, `Path`, and `Header` for the corresponding input locations.
17+
- Recommended new list pagination is page 1, page size 20, and page-size bounds 1 through 100. Return `items` / `total` or an established response shape; support ordering/filters where appropriate.
18+
19+
## Responses and failures
20+
21+
- Ordinary JSON success uses `JSONResponse(status_code=HTTPStatus.OK, content=payload)` unless an established standard model or other response mode applies. Preserve streaming contracts.
22+
- New responses use structured dictionaries consistent with nearby endpoints. Do not force a new envelope onto existing contracts.
23+
- Map exceptions from `backend/consts/exceptions.py`: `UnauthorizedError` to 401, `LimitExceededError` to 429, domain parameter errors to 400 or established 406 behavior, and unexpected failures to 500. Log internal details without exposing them to users.
24+
- Use a module-level `logging.getLogger(__name__)`; log useful events without sensitive data.
25+
- Match module async/sync conventions. Await async services directly; do not create new event loops to invoke services.
26+
27+
Verify validation, identity propagation, response shape, and changed exception mappings.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Service layer
2+
3+
Applies to `backend/services/**/*.py`.
4+
5+
- Orchestrate business behavior and coordinate database/SDK collaborators.
6+
- Return plain domain values; do not return web framework responses, raise `HTTPException`, or translate failures into HTTP status codes.
7+
- Reuse domain exceptions in `backend/consts/exceptions.py`; declare new domain classes there when needed. Wrap lower-level failures at the appropriate boundary with `raise DomainError(...) from exc`.
8+
- Existing exceptions include `AgentRunException`, `LimitExceededError`, `UnauthorizedError`, `SignatureValidationError`, and `MemoryPreparationException`. Inspect current definitions before use.
9+
- Import configuration from `consts.const` or accept parameters, then pass configuration into SDK calls. Do not read environment variables here.
10+
- A service explicitly allowed to continue after database failure may catch an appropriate shared exception. Inspect what the database client actually raises; do not assume it wraps failures in a named custom exception.
11+
12+
Verify orchestration, return values, and domain failure propagation independently of HTTP mapping.

0 commit comments

Comments
 (0)