From de8fb2a9f6cde176ecccccf56e65010c8897bae1 Mon Sep 17 00:00:00 2001 From: Om Gate Date: Thu, 22 Jan 2026 17:01:27 +0530 Subject: [PATCH 1/6] feat: AI SDK sync --- .github/workflows/generate-from-python.yml | 203 +++++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 .github/workflows/generate-from-python.yml diff --git a/.github/workflows/generate-from-python.yml b/.github/workflows/generate-from-python.yml new file mode 100644 index 0000000..ad74d38 --- /dev/null +++ b/.github/workflows/generate-from-python.yml @@ -0,0 +1,203 @@ +name: Generate Node SDK from Python + +on: + repository_dispatch: + types: [python-updated] + + # Manual trigger for testing + workflow_dispatch: + inputs: + before_sha: + description: 'Before commit SHA in Python SDK' + required: false + after_sha: + description: 'After commit SHA in Python SDK' + required: false + +jobs: + generate: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + + steps: + - name: Checkout Node SDK + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Set commit SHAs + id: shas + run: | + if [[ "${{ github.event_name }}" == "repository_dispatch" ]]; then + echo "before_sha=${{ github.event.client_payload.before_sha }}" >> $GITHUB_OUTPUT + echo "after_sha=${{ github.event.client_payload.after_sha }}" >> $GITHUB_OUTPUT + echo "source_repo=${{ github.event.client_payload.source_repo }}" >> $GITHUB_OUTPUT + echo "commit_message=${{ github.event.client_payload.commit_message }}" >> $GITHUB_OUTPUT + echo "changed_files=${{ github.event.client_payload.changed_files }}" >> $GITHUB_OUTPUT + else + # Manual trigger + SOURCE_REPO="${{ github.repository_owner }}/videodb-python" + echo "source_repo=$SOURCE_REPO" >> $GITHUB_OUTPUT + echo "commit_message=Manual trigger" >> $GITHUB_OUTPUT + echo "changed_files=" >> $GITHUB_OUTPUT + + if [[ -n "${{ inputs.before_sha }}" ]]; then + echo "before_sha=${{ inputs.before_sha }}" >> $GITHUB_OUTPUT + else + echo "before_sha=" >> $GITHUB_OUTPUT + fi + + if [[ -n "${{ inputs.after_sha }}" ]]; then + echo "after_sha=${{ inputs.after_sha }}" >> $GITHUB_OUTPUT + else + echo "after_sha=main" >> $GITHUB_OUTPUT + fi + fi + + - name: Fetch Python SDK diff + id: diff + env: + GH_TOKEN: ${{ secrets.SDK_SYNC_PAT }} + run: | + SOURCE_REPO="${{ steps.shas.outputs.source_repo }}" + BEFORE_SHA="${{ steps.shas.outputs.before_sha }}" + AFTER_SHA="${{ steps.shas.outputs.after_sha }}" + + echo "Fetching diff from $SOURCE_REPO" + echo "Before: $BEFORE_SHA" + echo "After: $AFTER_SHA" + + # Fetch the diff + if [[ -n "$BEFORE_SHA" ]]; then + gh api \ + -H "Accept: application/vnd.github.v3.diff" \ + "/repos/$SOURCE_REPO/compare/${BEFORE_SHA}...${AFTER_SHA}" \ + > python.diff 2>/dev/null || echo "Could not fetch diff" + else + echo "No before SHA available" + touch python.diff + fi + + echo "Diff size: $(wc -l < python.diff) lines" + + - name: Run Codex + uses: openai/codex-action@v1 + with: + openai-api-key: ${{ secrets.OPENAI_API_KEY }} + sandbox: workspace-write + prompt: | + You are updating the VideoDB Node SDK to match changes made to the Python SDK. + + ## Git Diff of Python SDK Changes + + The following diff shows what changed in the Python SDK: + + ```diff + $(cat python.diff) + ``` + + ## Your Task + + 1. First, read the existing Node SDK structure in `src/` to understand: + - Client structure and patterns + - Type definitions + - How methods are implemented + + 2. Translate the Python changes to TypeScript equivalents: + + ## Translation Rules + + | Python | TypeScript | + |--------|------------| + | `str` | `string` | + | `int`, `float` | `number` | + | `bool` | `boolean` | + | `None` | `null` or `undefined` | + | `Optional[X]` | `X \| undefined` or `X?` | + | `List[X]` | `X[]` | + | `Dict[str, X]` | `Record` | + | `def method(self, ...)` | `async method(...): Promise<...>` | + | `@dataclass class Foo` | `interface Foo { ... }` | + | snake_case | camelCase | + + 3. Match the existing TypeScript patterns exactly: + - Import style + - Async/await usage + - Error handling + - JSDoc format (if used) + + ## Important + + - Do NOT modify `package.json` or version numbers + - Do NOT change existing exports unless adding new ones + - Do NOT refactor unrelated code + - Only implement what the diff indicates was added/changed + - Convert snake_case to camelCase for all identifiers + + - name: Check for changes and create PR + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + # Configure git + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + # Check if there are changes + if git diff --quiet && git diff --staged --quiet; then + echo "No changes generated by Codex" + exit 0 + fi + + # Create branch + BRANCH="auto/python-sync-$(date +%Y%m%d-%H%M%S)" + git checkout -b "$BRANCH" + git add -A + + # Commit + COMMIT_MSG="${{ steps.shas.outputs.commit_message }}" + git commit -m "feat: sync with Python SDK + + Source: ${{ steps.shas.outputs.source_repo }}@${{ steps.shas.outputs.after_sha }} + Original commit: ${COMMIT_MSG} + + Generated by OpenAI Codex" + + # Push + git push origin "$BRANCH" + + # Create PR + gh pr create \ + --title "feat: sync with Python SDK" \ + --body "## Summary + + Automated SDK update to match Python SDK changes. + + **Source**: \`${{ steps.shas.outputs.source_repo }}\` + **Commit**: \`${{ steps.shas.outputs.after_sha }}\` + **Original message**: ${{ steps.shas.outputs.commit_message }} + + ## Changes + + This PR was automatically generated by Codex based on the following Python SDK diff: + +
+ Python SDK Diff + + \`\`\`diff + $(head -200 python.diff) + \`\`\` + +
+ + ## Review Checklist + + - [ ] TypeScript types are correct + - [ ] Async/await patterns match existing code + - [ ] camelCase naming convention followed + - [ ] No breaking changes introduced + - [ ] Tests pass locally + + --- + *Generated by [OpenAI Codex](https://github.com/openai/codex)*" From ff7a97f62a331321201c89010b2001fda24f23a6 Mon Sep 17 00:00:00 2001 From: Om Gate Date: Thu, 22 Jan 2026 17:13:19 +0530 Subject: [PATCH 2/6] feat: model change --- .github/workflows/generate-from-python.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/generate-from-python.yml b/.github/workflows/generate-from-python.yml index ad74d38..29762c9 100644 --- a/.github/workflows/generate-from-python.yml +++ b/.github/workflows/generate-from-python.yml @@ -86,6 +86,7 @@ jobs: uses: openai/codex-action@v1 with: openai-api-key: ${{ secrets.OPENAI_API_KEY }} + model: o4-mini sandbox: workspace-write prompt: | You are updating the VideoDB Node SDK to match changes made to the Python SDK. From 5ebf385f008e1e51104158049d970a5aa77e26f5 Mon Sep 17 00:00:00 2001 From: Om Gate Date: Thu, 22 Jan 2026 17:16:01 +0530 Subject: [PATCH 3/6] feat: docs node --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 7c04d54..11d5c9b 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -2,7 +2,7 @@ name: Deploy Docs to GitHub Pages on: push: - branches: [main] + branches: [feat/0.4.0] workflow_dispatch: permissions: From e7102bf11f4976544481784a49f6cc7313d60504 Mon Sep 17 00:00:00 2001 From: Om Gate Date: Thu, 22 Jan 2026 17:49:01 +0530 Subject: [PATCH 4/6] feat: workflow prompt --- .github/workflows/generate-from-python.yml | 62 ++++++++++++++++------ 1 file changed, 46 insertions(+), 16 deletions(-) diff --git a/.github/workflows/generate-from-python.yml b/.github/workflows/generate-from-python.yml index 29762c9..9e63af0 100644 --- a/.github/workflows/generate-from-python.yml +++ b/.github/workflows/generate-from-python.yml @@ -99,14 +99,35 @@ jobs: $(cat python.diff) ``` - ## Your Task + ## File Mapping: Python SDK → Node SDK + + The Python SDK files map to Node SDK files as follows: + + | Python File | Node File | Description | + |-------------|-----------|-------------| + | `videodb/client.py` | `src/core/connection.ts` | Main client/connection class | + | `videodb/collection.py` | `src/core/collection.ts` | Collection operations | + | `videodb/video.py` | `src/core/video.ts` | Video class and methods | + | `videodb/audio.py` | `src/core/audio.ts` | Audio class and methods | + | `videodb/image.py` | `src/core/image.ts` | Image class and methods | + | `videodb/scene.py` | `src/core/scene.ts` | Scene class | + | `videodb/shot.py` | `src/core/shot.ts` | Shot class | + | `videodb/timeline.py` | `src/core/timeline.ts` | Timeline class | + | `videodb/search.py` | `src/core/search/` | Search functionality | + | `videodb/_constants.py` | `src/constants.ts` | Constants and enums | + | `videodb/_utils/` | `src/utils/` | Utility functions | + | Type definitions | `src/types/` | TypeScript interfaces | - 1. First, read the existing Node SDK structure in `src/` to understand: - - Client structure and patterns - - Type definitions - - How methods are implemented + ## Your Task - 2. Translate the Python changes to TypeScript equivalents: + 1. **Identify which Python files changed** in the diff above + 2. **Find the corresponding Node SDK file** using the mapping table + 3. **Read both files** to understand the current implementation + 4. **Replicate the exact same changes** in the Node SDK file: + - If a new method was added in Python, add the equivalent method in Node + - If a constant was added, add it to constants.ts + - If a new class was added, create the corresponding TypeScript class + - If parameters were added/changed, update the Node version accordingly ## Translation Rules @@ -121,26 +142,35 @@ jobs: | `Dict[str, X]` | `Record` | | `def method(self, ...)` | `async method(...): Promise<...>` | | `@dataclass class Foo` | `interface Foo { ... }` | - | snake_case | camelCase | + | `snake_case` | `camelCase` | + | `UPPER_SNAKE_CASE` | `UPPER_SNAKE_CASE` (keep same for constants) | + + ## Node SDK Patterns - 3. Match the existing TypeScript patterns exactly: - - Import style - - Async/await usage - - Error handling - - JSDoc format (if used) + - Methods that call the API should be `async` and return `Promise` + - Use the existing `this.connection.post()` / `this.connection.get()` patterns + - Types go in `src/types/` directory + - Exports are managed in `src/index.ts` ## Important - - Do NOT modify `package.json` or version numbers + - Do NOT modify `package.json`, `version.ts`, or version numbers - Do NOT change existing exports unless adding new ones - Do NOT refactor unrelated code - - Only implement what the diff indicates was added/changed - - Convert snake_case to camelCase for all identifiers + - ONLY implement what the diff indicates was added/changed + - Convert `snake_case` to `camelCase` for methods and variables + - Keep `UPPER_SNAKE_CASE` for constants - name: Check for changes and create PR env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | + # Save diff content for PR body before cleanup + DIFF_CONTENT=$(head -200 python.diff 2>/dev/null || echo "No diff available") + + # Clean up temporary files - DO NOT commit these + rm -f python.diff + # Configure git git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" @@ -187,7 +217,7 @@ jobs: Python SDK Diff \`\`\`diff - $(head -200 python.diff) + ${DIFF_CONTENT} \`\`\` From 42d563fc3986655c75ec327ccb191f1cfa40d9d3 Mon Sep 17 00:00:00 2001 From: Om Gate Date: Thu, 22 Jan 2026 17:57:15 +0530 Subject: [PATCH 5/6] feat: python SDK context --- .github/workflows/generate-from-python.yml | 52 ++++++++++++++++++++-- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/.github/workflows/generate-from-python.yml b/.github/workflows/generate-from-python.yml index 9e63af0..6666521 100644 --- a/.github/workflows/generate-from-python.yml +++ b/.github/workflows/generate-from-python.yml @@ -56,6 +56,32 @@ jobs: fi fi + - name: Clone Python SDK + env: + GH_TOKEN: ${{ secrets.SDK_SYNC_PAT }} + run: | + SOURCE_REPO="${{ steps.shas.outputs.source_repo }}" + AFTER_SHA="${{ steps.shas.outputs.after_sha }}" + + echo "Cloning Python SDK from $SOURCE_REPO at $AFTER_SHA" + + # Clone the Python SDK into a subdirectory + git clone --depth 1 "https://x-access-token:${GH_TOKEN}@github.com/${SOURCE_REPO}.git" python-sdk + + # Checkout the specific commit if provided + if [[ -n "$AFTER_SHA" && "$AFTER_SHA" != "main" ]]; then + cd python-sdk + git fetch --depth 1 origin "$AFTER_SHA" + git checkout "$AFTER_SHA" + cd .. + fi + + # Remove .git directory - makes it READ-ONLY reference, impossible to push + rm -rf python-sdk/.git + + echo "Python SDK cloned as read-only reference" + ls -la python-sdk/videodb/ + - name: Fetch Python SDK diff id: diff env: @@ -91,6 +117,17 @@ jobs: prompt: | You are updating the VideoDB Node SDK to match changes made to the Python SDK. + ## Python SDK Available (READ-ONLY) + + The complete Python SDK is available at `./python-sdk/videodb/` for you to read. + You have FULL ACCESS to read any Python file to understand the complete context. + + ⚠️ IMPORTANT: The `python-sdk/` directory is READ-ONLY for reference. + - DO NOT write, modify, or create any files in `python-sdk/` + - DO NOT attempt to commit or push changes to the Python SDK + - ONLY read from `python-sdk/` to understand the source code + - ONLY write to the Node SDK files in `src/` + ## Git Diff of Python SDK Changes The following diff shows what changed in the Python SDK: @@ -121,14 +158,20 @@ jobs: ## Your Task 1. **Identify which Python files changed** in the diff above - 2. **Find the corresponding Node SDK file** using the mapping table - 3. **Read both files** to understand the current implementation - 4. **Replicate the exact same changes** in the Node SDK file: + 2. **Read the FULL Python file** from `./python-sdk/videodb/` to understand: + - The complete context of the change + - What class/enum/function the change belongs to + - The surrounding code structure + 3. **Find the corresponding Node SDK file** using the mapping table + 4. **Read the Node SDK file** to understand current patterns + 5. **Replicate the exact same changes** in the Node SDK file: - If a new method was added in Python, add the equivalent method in Node - - If a constant was added, add it to constants.ts + - If a constant was added, add it to the same location in constants.ts - If a new class was added, create the corresponding TypeScript class - If parameters were added/changed, update the Node version accordingly + IMPORTANT: Always read the full Python source file, not just the diff, to understand WHERE and HOW to add the code. + ## Translation Rules | Python | TypeScript | @@ -170,6 +213,7 @@ jobs: # Clean up temporary files - DO NOT commit these rm -f python.diff + rm -rf python-sdk # Configure git git config user.name "github-actions[bot]" From f2073db0a9479afec69760a30d0c1d937fef4174 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 22 Jan 2026 13:16:07 +0000 Subject: [PATCH 6/6] feat: sync with Python SDK Source: omgate234/videodb-python@bfffed541bce11c998437a7bf7b0d4abb4430866 Original commit: Merge pull request #3 from omgate234/auto/spec-sync-20260122-125746 feat: sync with OpenAPI spec Generated by OpenAI Codex --- src/constants.ts | 2 ++ src/core/collection.ts | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/constants.ts b/src/constants.ts index a54fed9..0527d5d 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -36,6 +36,8 @@ export const ApiPath = { scenes: 'scenes', timeline: 'timeline', frame: 'frame', + /** Test assets */ + test_assets: 'test-assets', } as const; export const ResponseStatus = { diff --git a/src/core/collection.ts b/src/core/collection.ts index 49cb4ec..0b42a89 100644 --- a/src/core/collection.ts +++ b/src/core/collection.ts @@ -183,6 +183,22 @@ export class Collection implements ICollection { }); }; + /** + * Delete the test asset. + * @param testAssetId - ID of the test asset to delete + * @returns A promise that resolves when delete is successful + * @throws an error if the request fails + */ + public deleteTestAsset = async (testAssetId: string) => { + if (!testAssetId.trim()) { + throw new VideodbError('Test asset ID cannot be empty'); + } + return await this.#vhttp.delete>( + [ApiPath.test_assets, testAssetId], + { params: { collection_id: this.meta.id } } + ); + }; + /** * @param filePath - absolute path to a file * @param callbackUrl- [optional] A url that will be called once upload is finished