diff --git a/.claude/logs/agent-2-planning-velt-py-0.1.10.md b/.claude/logs/agent-2-planning-velt-py-0.1.10.md new file mode 100644 index 00000000..9e1828c7 --- /dev/null +++ b/.claude/logs/agent-2-planning-velt-py-0.1.10.md @@ -0,0 +1,45 @@ +# Release Update Plan for velt-py v0.1.10 + +## Overview +- Release Type: Patch (typed field additions + sentinel value; no breaking changes) +- Key Changes: `PartialCommentAnnotation` gains 4 first-class typed fields; new `PartialTargetTextRange` dataclass; `BaseMetadata` now preserves `sdkVersion`/`documentMetadata`; `UNSET` sentinel on `resolvedByUserId` +- Breaking Changes: No — `extra_fields` pass-through is removed but the promoted fields are now typed; existing call sites that read `extra_fields` will need to switch to named attributes (document as a behavioral note, not a migration step) + +## Areas Requiring Updates + +### 1. Data Models — SKIP +Per the v0.1.9 precedent, Python dataclasses must NOT be added to `/api-reference/sdk/models/data-models.mdx`. Document all new types inline on the Python SDK page only. + +### 2. API Methods — SKIP +`/api-reference/sdk/` covers the Web/React SDK. Python-only types must NOT be added there. + +### 3. Primary Documentation: `/Users/yoenzhang/Downloads/docs/backend-sdks/python.mdx` +- File: `/Users/yoenzhang/Downloads/docs/backend-sdks/python.mdx` +- Changes: + - Locate the existing `PartialCommentAnnotation` reference section (imported from `velt_py` in the self-hosting handlers at lines ~270–274). Add or extend a dataclass reference block covering: + - `PartialCommentAnnotation` — table of typed fields: `annotationId`, `metadata`, `comments`, plus the four newly promoted fields: `from_` (aliased from `from`; type `dict`), `assignedTo` (`dict | None`), `targetTextRange` (`PartialTargetTextRange | None`), `resolvedByUserId` (`str | None | UNSET`). Note the `UNSET` sentinel meaning vs explicit `None`. + - `PartialTargetTextRange` — new dataclass, export path `from velt_py.models import PartialTargetTextRange`. Fields: document whatever the PyPI source exposes (minimally: `startIndex`, `endIndex`, `text` — note to Agent-3: verify exact fields against PyPI 0.1.10 source before publishing; use `str` for all if uncertain). + - In the `BaseMetadata` reference block (if one exists on python.mdx — check; if not, add it): note that `sdkVersion` (`str | None`) and `documentMetadata` (`dict | None`) are now preserved in Mongo writes. They were previously silently dropped. + - Add a short note under the `resolvedByUserId` field entry explaining the `UNSET` sentinel: "If absent from the incoming payload, `resolvedByUserId` is `UNSET` and Velt skips the Mongo write for that field. An explicit `null` from the frontend (unresolve action) arrives as `None` and writes `null` to Mongo." + - Add an import snippet: `from velt_py.models import PartialTargetTextRange, UNSET` +- Priority: High + +### 4. UI Customization / Wireframes / Primitives — N/A +Backend-only release. No frontend components affected. + +### 5. Upgrade Guide — N/A +No breaking changes requiring migration steps. The `extra_fields` removal is behavioral — access promoted fields by name instead. No separate upgrade-guide.mdx entry needed. + +## Implementation Sequence +1. Update `python.mdx` — add/extend `PartialCommentAnnotation` dataclass reference with 4 new fields, add `PartialTargetTextRange` dataclass reference, update `BaseMetadata` note for `sdkVersion`/`documentMetadata`, add `UNSET` sentinel explanation. +2. Verify `PartialTargetTextRange` field names against PyPI 0.1.10 before finalizing field table. + +## Quality Checklist +- [ ] `PartialCommentAnnotation` table lists all 7 fields including `from_`, `assignedTo`, `targetTextRange`, `resolvedByUserId` +- [ ] `PartialTargetTextRange` dataclass documented with export path `from velt_py.models import PartialTargetTextRange` +- [ ] `UNSET` sentinel explained: absent → no Mongo write; `None` → writes null +- [ ] `BaseMetadata` note added: `sdkVersion` and `documentMetadata` now preserved +- [ ] Import snippet `from velt_py.models import PartialTargetTextRange, UNSET` included +- [ ] No Python types added to `/api-reference/sdk/models/data-models.mdx` +- [ ] No breaking changes in upgrade-guide.mdx +- [ ] Log written to `.claude/logs/agent-2-planning-velt-py-0.1.10.md` diff --git a/.claude/logs/agent-7-qa-velt-py-0.1.10.md b/.claude/logs/agent-7-qa-velt-py-0.1.10.md new file mode 100644 index 00000000..74db3cbe --- /dev/null +++ b/.claude/logs/agent-7-qa-velt-py-0.1.10.md @@ -0,0 +1,40 @@ +## QA Summary for velt-py v0.1.10 + +### Issues Found: 0 + +No corrective changes were required. All touched files are consistent and correct. + +### Verification Coverage + +**release-notes/version-5/velt-py-changelog.mdx** +- Section order confirmed: New Features → Improvements → Bug Fixes (no Breaking Changes section) +- v0.1.10 and v0.1.9 entries both present; v0.1.9 correctly retained as historical record +- All `[Learn more →]` links resolve to `/backend-sdks/python` (valid path) +- `from` vs `from_` in changelog prose: accurate — changelog describes the JSON/Mongo key name (`from`); python.mdx clarifies `from_` is the Python alias. Not an inconsistency. +- "Bug Fixes: None." is unique formatting; acceptable — communicates intent clearly + +**release-notes/version-5/sdk-changelog.mdx** +- No velt-py content present (confirmed clean — v0.1.9 entry correctly removed to velt-py-changelog.mdx) + +**docs.json** +- Python SDK Changelog group nested correctly under Version 5.0.0 alongside sdk-changelog and crdt-core-changelog +- Page path `release-notes/version-5/velt-py-changelog` confirmed valid + +**backend-sdks/python.mdx — Data Models section (lines 3674–3749)** +- `PartialCommentAnnotation`, `PartialTargetTextRange`, `UNSET`, `BaseMetadata` all documented +- `#unset-sentinel` anchor: heading "UNSET Sentinel" → slug `unset-sentinel`; cross-reference on line 3698 matches +- `from_` field note accurately explains Python alias for reserved keyword `from` +- No `extra_fields` stale terminology present anywhere in the file +- `BaseMetadata` import note correctly states no import change required +- JS/TS `PartialCommentAnnotation` in `api-reference/sdk/models/data-models.mdx` is the TypeScript interface — distinct from Python dataclass, no naming conflict + +**Repo-wide stale terminology scan (release-notes/, backend-sdks/)** +- No "Cloud Functions", "Recorder / Player", "Comments / Wireframes", "Added group support" in touched files +- No `extra_fields` or `pass-through` stale terms surviving in any documentation path +- `PartialCommentAnnotation` references in `self-host-data/comments.mdx` and `data-models.mdx` refer to the JS/TS type only — correct, no update needed + +### Summary +- Files corrected: 0 +- Critical issues: 0 +- Terminology alignments: 0 +- Agent-6 assessment confirmed: alignment is clean, no propagation needed diff --git a/backend-sdks/python.mdx b/backend-sdks/python.mdx index 1c6326c1..ff48faca 100644 --- a/backend-sdks/python.mdx +++ b/backend-sdks/python.mdx @@ -3671,6 +3671,97 @@ Common self-hosting error codes returned in the response `errorCode` field: - `INTERNAL_ERROR` — Server-side error during processing - `NOT_FOUND` — Requested resource was not found +## Data Models + +Python-SDK-specific dataclasses used by the self-hosting backend. These are not in the shared API reference because they are only relevant to `sdk.selfHosting.*` implementations. + +### `PartialCommentAnnotation` + +Represents a partial update payload for a comment annotation. Starting in **v0.1.10**, `from`, `assignedTo`, `targetTextRange`, and `resolvedByUserId` are first-class typed fields (previously silent pass-through via `extra_fields`). + +```python +from velt_py.models import ( + PartialCommentAnnotation, + PartialTargetTextRange, + PartialUser, + PartialComment, + BaseMetadata, +) +from velt_py.models.comment import UNSET + +@dataclass +class PartialCommentAnnotation: + annotationId: str + metadata: Optional[BaseMetadata] = None + comments: Optional[Dict[str, PartialComment]] = None + from_: Optional[PartialUser] = None # 'from' on the wire; from_ avoids Python keyword. + assignedTo: Optional[PartialUser] = None + targetTextRange: Optional[PartialTargetTextRange] = None + resolvedByUserId: Any = UNSET # Tri-state: UNSET | None | str. See below. + extra_fields: Optional[Dict[str, Any]] = None # Catch-all for customer-configured custom keys. +``` + +**Field notes** + +- `from_` — Python alias for the JSON key `from` (reserved keyword). Serialized as `from` in the Mongo document. +- `assignedTo` — Typed as `PartialUser`. Omit to leave unchanged; the Mongo write skips the field when `None`. +- `targetTextRange` — Typed `PartialTargetTextRange` for the selected text snippet a comment is anchored to. +- `resolvedByUserId` — See [UNSET sentinel](#unset-sentinel) for the difference between absent (`UNSET`) and explicit `None`. +- `extra_fields` — Retained as a catch-all because the frontend contract includes `[key: string]: any` for customer-configured `fieldsToRemove` and `additionalFields`. + +### `PartialTargetTextRange` + +Anchors a comment to a selected text snippet. + +```python +from velt_py.models import PartialTargetTextRange + +@dataclass +class PartialTargetTextRange: + text: str = '' # The selected text content. +``` + +### UNSET Sentinel + +`UNSET` is a sentinel value exported from `velt_py.models.comment`. It signals that a field was not included in the incoming request payload and should be skipped entirely during the MongoDB write. + +```python +from velt_py.models.comment import UNSET + +# Field absent from payload → UNSET → field is NOT written to Mongo +annotation = PartialCommentAnnotation() +# annotation.resolvedByUserId is UNSET → Mongo $set will not include this field + +# Field explicitly set to None → None → field IS written as null to Mongo +annotation = PartialCommentAnnotation(resolvedByUserId=None) +# annotation.resolvedByUserId is None → Mongo $set writes null (frontend unresolve action) +``` + +| Value | Payload | Mongo write | +|-------|---------|-------------| +| `UNSET` | Field absent | Field skipped — no change | +| `None` | Field present, value `null` | Field written as `null` | + +### `BaseMetadata` + +Base metadata attached to every comment annotation. Starting in **v0.1.10**, `sdkVersion` and `documentMetadata` are fully modeled and preserved in MongoDB writes. These fields were previously sent by the frontend on every annotation save but silently dropped. + +```python +@dataclass +class BaseMetadata: + apiKey: Optional[str] = None + documentId: Optional[str] = None + clientDocumentId: Optional[str] = None + organizationId: Optional[str] = None + clientOrganizationId: Optional[str] = None + folderId: Optional[str] = None + veltFolderId: Optional[str] = None + documentMetadata: Optional[Dict[str, Any]] = None # New in v0.1.10. + sdkVersion: Optional[str] = None # New in v0.1.10. +``` + +No import change is required — `BaseMetadata` is populated automatically from the incoming request payload. The fix applies transparently to all `saveComments` calls. + ## Resources - [Velt-Py PyPI Package](https://pypi.org/project/velt-py) diff --git a/docs.json b/docs.json index ad72d0b2..96884b91 100644 --- a/docs.json +++ b/docs.json @@ -1002,6 +1002,12 @@ "pages": [ "release-notes/version-5/crdt-core-changelog" ] + }, + { + "group": "Backend SDKs", + "pages": [ + "release-notes/version-5/velt-py-changelog" + ] } ] }, diff --git a/release-notes/version-5/sdk-changelog.mdx b/release-notes/version-5/sdk-changelog.mdx index 6727bdab..31c96c4d 100644 --- a/release-notes/version-5/sdk-changelog.mdx +++ b/release-notes/version-5/sdk-changelog.mdx @@ -8,7 +8,6 @@ description: Release Notes of changes added to the core Velt SDK - `@veltdev/react` - `@veltdev/client` - `@veltdev/sdk` -- `velt-py` @@ -82,25 +81,6 @@ commentElement.on('addCommentDraft').subscribe((event) => { - - -### New Features - -- [**REST API Backend**]: The `sdk.api.*` namespace is now available, introducing a REST API backend for the Python SDK with feature parity with the Velt Node SDK. [Learn more →](/backend-sdks/python) - -- [**REST API Services**]: 17 services are included: `organizations`, `folders`, `documents`, `users`, `userGroups`, `notifications`, `commentAnnotations`, `activities`, `accessControl`, `crdt`, `presence`, `livestate`, `recordings`, `rewriter`, `gdpr`, `workspace`, and `token`. - -- [**Typed Request Dataclasses**]: Every `sdk.api.*` method accepts a typed `@dataclass` request object (e.g., `AddOrganizationsRequest`) and returns the raw Velt API response without local reshaping or validation. - -- [**camelCase Method Names**]: All `sdk.api.*` method names are camelCase and match the JavaScript/Node SDK one-to-one. - -- [**Custom Error Classes**]: Three new error classes are available: `VeltValidationError`, `VeltTokenError`, and `VeltApiError`, all extending the base `VeltSDKError`. - -- [**Environment Variable Support**]: The SDK reads `VELT_API_KEY`, `VELT_AUTH_TOKEN`, `VELT_WORKSPACE_ID`, and `VELT_WORKSPACE_AUTH_TOKEN` from the environment for credential configuration. - -- [**PyPI Distribution**]: The package is published to PyPI as `velt-py`. Requires Python 3.8+; the `requests` library is installed automatically as a dependency. - - diff --git a/release-notes/version-5/velt-py-changelog.mdx b/release-notes/version-5/velt-py-changelog.mdx new file mode 100644 index 00000000..6722eaaf --- /dev/null +++ b/release-notes/version-5/velt-py-changelog.mdx @@ -0,0 +1,47 @@ +--- +title: "Python SDK (velt-py) Changelog" +description: Release notes for the velt-py Python SDK for self-hosting +--- + +### Libraries +- `velt-py` + + + +### New Features + +- [**Self Hosting**]: `PartialCommentAnnotation` now exposes `from` (comment author), `assignedTo`, `targetTextRange`, and `resolvedByUserId` as first-class typed fields. These four keys previously fell through silently via `extra_fields`. [Learn more →](/backend-sdks/python) + +- [**Self Hosting**]: New `PartialTargetTextRange` dataclass (exported from `velt_py.models`) represents the selected text snippet a comment annotation is anchored to. [Learn more →](/backend-sdks/python) + +### Improvements + +- [**Self Hosting**]: `BaseMetadata` now models `sdkVersion` and `documentMetadata`, which were previously dropped silently; self-hosted Mongo writes now preserve both fields. + +- [**Self Hosting**]: Introduced an `UNSET` sentinel on `resolvedByUserId` to distinguish "field absent from payload" (no Mongo write) from "explicit null" (the frontend's unresolve action — writes null to Mongo). + +### Bug Fixes + +None. + + + + + +### New Features + +- [**REST API Backend**]: The `sdk.api.*` namespace is now available, introducing a REST API backend for the Python SDK with feature parity with the Velt Node SDK. [Learn more →](/backend-sdks/python) + +- [**REST API Services**]: 17 services are included: `organizations`, `folders`, `documents`, `users`, `userGroups`, `notifications`, `commentAnnotations`, `activities`, `accessControl`, `crdt`, `presence`, `livestate`, `recordings`, `rewriter`, `gdpr`, `workspace`, and `token`. + +- [**Typed Request Dataclasses**]: Every `sdk.api.*` method accepts a typed `@dataclass` request object (e.g., `AddOrganizationsRequest`) and returns the raw Velt API response without local reshaping or validation. + +- [**camelCase Method Names**]: All `sdk.api.*` method names are camelCase and match the JavaScript/Node SDK one-to-one. + +- [**Custom Error Classes**]: Three new error classes are available: `VeltValidationError`, `VeltTokenError`, and `VeltApiError`, all extending the base `VeltSDKError`. + +- [**Environment Variable Support**]: The SDK reads `VELT_API_KEY`, `VELT_AUTH_TOKEN`, `VELT_WORKSPACE_ID`, and `VELT_WORKSPACE_AUTH_TOKEN` from the environment for credential configuration. + +- [**PyPI Distribution**]: The package is published to PyPI as `velt-py`. Requires Python 3.8+; the `requests` library is installed automatically as a dependency. + +