Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions .claude/logs/agent-2-planning-velt-py-0.1.10.md
Original file line number Diff line number Diff line change
@@ -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`
40 changes: 40 additions & 0 deletions .claude/logs/agent-7-qa-velt-py-0.1.10.md
Original file line number Diff line number Diff line change
@@ -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
91 changes: 91 additions & 0 deletions backend-sdks/python.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 6 additions & 0 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -1002,6 +1002,12 @@
"pages": [
"release-notes/version-5/crdt-core-changelog"
]
},
{
"group": "Backend SDKs",
"pages": [
"release-notes/version-5/velt-py-changelog"
]
}
]
},
Expand Down
20 changes: 0 additions & 20 deletions release-notes/version-5/sdk-changelog.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ description: Release Notes of changes added to the core Velt SDK
- `@veltdev/react`
- `@veltdev/client`
- `@veltdev/sdk`
- `velt-py`

<Update label="5.0.2-beta.22" description="April 28, 2026">

Expand Down Expand Up @@ -82,25 +81,6 @@ commentElement.on('addCommentDraft').subscribe((event) => {

</Update>

<Update label="Python SDK (velt-py) v0.1.9" description="April 20, 2026">

### 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.

</Update>

<Update label="5.0.2-beta.19" description="April 20, 2026">

Expand Down
47 changes: 47 additions & 0 deletions release-notes/version-5/velt-py-changelog.mdx
Original file line number Diff line number Diff line change
@@ -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`

<Update label="Python SDK (velt-py) v0.1.10" description="May 19, 2026">

### 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.

</Update>

<Update label="Python SDK (velt-py) v0.1.9" description="April 20, 2026">

### 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.

</Update>