Skip to content

Add Deep Search API, data connector files, and describe updates for v0.6.7#98

Merged
kdr merged 3 commits into
mainfrom
kdr-067
Mar 16, 2026
Merged

Add Deep Search API, data connector files, and describe updates for v0.6.7#98
kdr merged 3 commits into
mainfrom
kdr-067

Conversation

@kdr

@kdr kdr commented Mar 16, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Deep Search API: New client.deepSearch namespace with sync, streaming (SSE), and background processing modes. Includes createDeepSearch, createStreamingDeepSearch, listDeepSearches, getDeepSearch, deleteDeepSearch, cancelDeepSearch, and waitForReady polling.
  • Data Connector File Browsing: New client.dataConnectors.listFiles(connectorId, params) for browsing files in connected data sources (S3, GCS, Google Drive, Dropbox, Zoom) with provider-specific filtering and pagination.
  • Describe Job Updates: New client.describe.updateDescribe(jobId, params) to toggle use_in_default_index, and use_in_default_index option on createDescribe.
  • Response API Enhancements: knowledge_base now supports multiple source types (collections, files, default), added tools for function calling, and max_output_tokens parameter. knowledge_base is now optional.
  • Code Generation Fixes: Updated generate.js to handle nullable Partial<{}> type mismatches and z.discriminatedUnion with optional discriminators.

Summary by CodeRabbit

  • New Features
    • Deep Search API with streaming (SSE) support, real-time events, and readiness polling
    • Data Connectors: browse connector files with filtering, pagination, and path/bucket options
    • Describe API: toggle searchable-in-default-index and an updateDescribe method to modify jobs
    • Client: exposes Deep Search on the main client
  • Response API
    • Optional knowledge base targeting, tool definitions for function-calling, and max output token limit
  • Types
    • New public types for Deep Search, Data Connector files, and Response knowledge bases/tools
  • Chores
    • Package version bump and submodule pointer update

…es for API spec v0.6.7

- New Deep Search API with sync, streaming (SSE), and background modes
- Data connector file browsing endpoint with provider-specific filtering
- Describe job update endpoint (PATCH) for use_in_default_index flag
- Response API: flexible knowledge base (collections/files/default), tools, max_output_tokens
- Updated generate.js to handle nullable Partial types and discriminatedUnion fixes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Mar 16, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds Deep Search streaming and non‑streaming APIs, data‑connector file listing, Response API knowledge‑base/tool types, client wiring for Deep Search, and extensive post‑generation TypeScript/Zod postprocessing including File import aliasing and nullability fixes.

Changes

Cohort / File(s) Summary
Generation & Versioning
generate.js, package.json, spec
Extensive post-generation transforms to: propagate nullability (append `
Deep Search API
src/api/deep-search.api.ts
Added EnhancedDeepSearchApi with non‑streaming and streaming create, list/get/delete/cancel/wait helpers; SSE/fetch streaming support, SSE parsing (processLines, parseSSEStream), streaming event types and readiness polling.
Client Integration
src/client.ts
Wired Deep Search API client into shared Axios config and exposed public readonly deepSearch: EnhancedDeepSearchApi on Cloudglue.
Data Connectors
src/api/data-connectors.api.ts, src/types.ts
Added ListDataConnectorFilesParams and EnhancedDataConnectorsApi.listFiles(connectorId, params); introduced DataConnectorFile and DataConnectorFileList types and re-exports.
Describe API
src/api/describe.api.ts
Added optional use_in_default_index to createDescribe params and new updateDescribe(jobId, params) method to update that flag.
Response API & Types
src/api/response.api.ts, src/types.ts
Added ResponseKnowledgeBase* types and union ResponseKnowledgeBaseParam, ResponseToolDefinition; made knowledge_base optional in CreateResponseParams, added tools and max_output_tokens; updated exports and EntityBackedKnowledgeConfig.
Types & Re-exports
src/types.ts
Added Deep Search types (DeepSearch, DeepSearchResult, usage/list types), re-exported Deep Search API types and ListDataConnectorFilesParams, and extended Response/KnowledgeBase related public types.

Sequence Diagram

sequenceDiagram
    participant Client
    participant EnhancedAPI as EnhancedDeepSearchApi
    participant Fetch as fetch/SSE
    participant Backend as BackendService
    participant Consumer as EventConsumer

    Client->>EnhancedAPI: createStreamingDeepSearch(params)
    activate EnhancedAPI
    EnhancedAPI->>Fetch: POST /api/v1/deep-searches (stream=true)
    activate Fetch
    Fetch->>Backend: HTTP request with SSE headers
    activate Backend
    Backend-->>Fetch: ReadableStream<Uint8Array> (SSE)
    deactivate Backend
    Fetch-->>EnhancedAPI: Stream opened
    deactivate Fetch

    EnhancedAPI->>EnhancedAPI: parseSSEStream(stream)
    loop stream processing
        EnhancedAPI->>EnhancedAPI: processLines(buffer)
        EnhancedAPI->>Consumer: yield events (Created / TextDelta / ResultAdded / Completed / Error)
    end
    EnhancedAPI->>Consumer: final event / close
    deactivate EnhancedAPI

    Client-->>Consumer: consumes AsyncIterable events
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • amyxst

Poem

🐇 I hopped through schemas, nudged a nullable sign,

Streams now sing, files and types align,
Imports renamed with a tidy prance,
Deep searches stream and code can dance,
A rabbit cheers for every merging line.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title comprehensively covers the main changes: Deep Search API, data connector files, and describe updates, aligning well with the substantial additions across multiple API surfaces and client features.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch kdr-067
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
package.json (1)

36-36: ⚠️ Potential issue | 🔴 Critical

Upgrade axios to ^1.13.5 to address CVE-2026-25639.

axios 1.12.0 is affected by CVE-2026-25639, a DoS vulnerability in the mergeConfig function when processing objects with __proto__. Upgrade to version 1.13.5 or higher to patch this issue.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package.json` at line 36, Update the axios dependency in package.json from
"axios": "^1.12.0" to "axios": "^1.13.5" to remediate CVE-2026-25639; after
changing the version string, run your package manager to update node_modules and
the lockfile (npm install / pnpm install / yarn install), regenerate the
lockfile commit, and run tests and a dependency audit (npm audit / pnpm audit)
to verify no regressions.
🧹 Nitpick comments (2)
src/api/deep-search.api.ts (1)

283-290: Non-null assertion on status may mask issues if the API response is malformed.

The code uses deepSearch.status! with a non-null assertion. If the API returns a response without a status field (e.g., due to a schema mismatch or unexpected error), this could lead to unexpected behavior where the polling loop continues indefinitely.

Consider adding a defensive check:

🛡️ Suggested defensive check
      const deepSearch = await this.getDeepSearch(deepSearchId);
+     
+     if (!deepSearch.status) {
+       throw new CloudglueError(
+         `Deep search ${deepSearchId} returned invalid response without status`,
+       );
+     }

-     if (['completed', 'failed', 'cancelled'].includes(deepSearch.status!)) {
+     if (['completed', 'failed', 'cancelled'].includes(deepSearch.status)) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/api/deep-search.api.ts` around lines 283 - 290, The code uses a non-null
assertion on deepSearch.status which can hide missing/undefined statuses and
cause the poll to hang; update the logic in the function that handles the poll
response (referencing deepSearch.status, deepSearchId, and CloudglueError) to
explicitly check whether deepSearch.status is null/undefined before using it,
and if it is missing throw a CloudglueError (including deepSearchId and any
available response/error info) so the polling loop fails fast instead of
continuing indefinitely; remove the `!` assertion and replace it with a
defensive null/undefined guard that either throws or returns an appropriate
error result.
package.json (1)

3-3: Consider a minor version bump instead of a patch for new features.

The PR adds new API surfaces (Deep Search API, data connector file browsing) and new functionality (describe updates, response API enhancements). According to semantic versioning, new features typically warrant a minor version bump (e.g., 0.8.0) rather than a patch bump (0.7.4), which is typically reserved for backward-compatible bug fixes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package.json` at line 3, The package.json currently sets "version": "0.7.4"
but new features were added; update the version field to a minor bump (e.g.,
"0.8.0") to reflect added APIs (Deep Search, data connector browsing, response
API enhancements) and ensure any release notes/changelog entries reflect the new
minor release; update package.json's "version" value and verify any CI/release
scripts that read the version are in sync.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@package.json`:
- Line 3: The package.json "version" field currently reads "0.7.4" but the PR
title references v0.6.7; reconcile this by deciding the correct release version
and updating the mismatch: either change the package.json "version" value to
"0.6.7" or update the PR title to v0.7.4 so they match, and ensure any
accompanying changelog/release notes reflect the chosen version.

In `@spec`:
- Line 1: The PR references a submodule commit for the spec that doesn't exist,
breaking generate.js which relies on spec/spec/openapi.json; fix by either (A)
creating and pushing the missing commit in the cloudglue-api-spec repository so
its object ID matches b522b9959ddf32bedeba525d7afd0cbb7e517169 and ensure
spec/spec/openapi.json is present in that commit, or (B) update the spec
submodule pointer in this repo to a valid, public commit in cloudglue-api-spec
that contains spec/spec/openapi.json and commit the updated submodule reference
(and update .gitmodules if needed) so generate.js can run. Ensure the chosen
commit is publicly accessible before merging.

---

Outside diff comments:
In `@package.json`:
- Line 36: Update the axios dependency in package.json from "axios": "^1.12.0"
to "axios": "^1.13.5" to remediate CVE-2026-25639; after changing the version
string, run your package manager to update node_modules and the lockfile (npm
install / pnpm install / yarn install), regenerate the lockfile commit, and run
tests and a dependency audit (npm audit / pnpm audit) to verify no regressions.

---

Nitpick comments:
In `@package.json`:
- Line 3: The package.json currently sets "version": "0.7.4" but new features
were added; update the version field to a minor bump (e.g., "0.8.0") to reflect
added APIs (Deep Search, data connector browsing, response API enhancements) and
ensure any release notes/changelog entries reflect the new minor release; update
package.json's "version" value and verify any CI/release scripts that read the
version are in sync.

In `@src/api/deep-search.api.ts`:
- Around line 283-290: The code uses a non-null assertion on deepSearch.status
which can hide missing/undefined statuses and cause the poll to hang; update the
logic in the function that handles the poll response (referencing
deepSearch.status, deepSearchId, and CloudglueError) to explicitly check whether
deepSearch.status is null/undefined before using it, and if it is missing throw
a CloudglueError (including deepSearchId and any available response/error info)
so the polling loop fails fast instead of continuing indefinitely; remove the
`!` assertion and replace it with a defensive null/undefined guard that either
throws or returns an appropriate error result.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d89fe696-d042-4c94-8b45-0b38f15c397e

📥 Commits

Reviewing files that changed from the base of the PR and between a36821f and 54d3f13.

⛔ Files ignored due to path filters (7)
  • generated/Data_Connectors.ts is excluded by !**/generated/**
  • generated/Deep_Search.ts is excluded by !**/generated/**
  • generated/Describe.ts is excluded by !**/generated/**
  • generated/Response.ts is excluded by !**/generated/**
  • generated/common.ts is excluded by !**/generated/**
  • generated/index.ts is excluded by !**/generated/**
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (9)
  • generate.js
  • package.json
  • spec
  • src/api/data-connectors.api.ts
  • src/api/deep-search.api.ts
  • src/api/describe.api.ts
  • src/api/response.api.ts
  • src/client.ts
  • src/types.ts

Comment thread package.json
{
"name": "@cloudglue/cloudglue-js",
"version": "0.7.3",
"version": "0.7.4",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Version mismatch: PR title references v0.6.7 but package.json shows 0.7.4.

The PR title mentions "v0.6.7" but the version field shows "0.7.4". Please verify which version number is correct and update either the PR title or the package.json to ensure consistency.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package.json` at line 3, The package.json "version" field currently reads
"0.7.4" but the PR title references v0.6.7; reconcile this by deciding the
correct release version and updating the mismatch: either change the
package.json "version" value to "0.6.7" or update the PR title to v0.7.4 so they
match, and ensure any accompanying changelog/release notes reflect the chosen
version.

Comment thread spec
@@ -1 +1 @@
Subproject commit 1f9df1729b97053112d2caac753545f5e4858e75
Subproject commit b522b9959ddf32bedeba525d7afd0cbb7e517169

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Verify the spec submodule commit exists and show the changes

# Check if submodule directory exists and show commit details
if [ -d "spec" ]; then
  cd spec
  
  # Verify the new commit exists
  echo "=== Verifying new commit exists ==="
  git cat-file -t b522b9959ddf32bedeba525d7afd0cbb7e517169 2>/dev/null && echo "✓ Commit exists" || echo "✗ Commit not found"
  
  # Show commit message
  echo -e "\n=== New commit details ==="
  git log -1 --oneline b522b9959ddf32bedeba525d7afd0cbb7e517169
  
  # Show what changed between old and new commit (if old commit is known)
  echo -e "\n=== Files changed in submodule ==="
  git diff --name-status 1f9df1729b97053112d2caac753545f5e4858e75..b522b9959ddf32bedeba525d7afd0cbb7e517169
  
  cd ..
else
  echo "Submodule directory 'spec' not found"
fi

Repository: cloudglue/cloudglue-js

Length of output: 545


🏁 Script executed:

#!/bin/bash
# Description: Examine submodule configuration and status

echo "=== Checking .gitmodules file ==="
cat .gitmodules 2>/dev/null || echo "No .gitmodules file found"

echo -e "\n=== Checking git submodule status ==="
git config --file=.gitmodules --get-all submodule.spec.url 2>/dev/null || echo "No spec submodule found in config"

echo -e "\n=== Checking spec directory ==="
ls -la spec 2>/dev/null | head -20

echo -e "\n=== Checking git index for spec submodule ==="
git ls-files --stage spec | head -10

echo -e "\n=== Checking if spec is a gitlink ==="
git cat-file -p HEAD:spec 2>/dev/null || echo "spec not found in HEAD"

echo -e "\n=== Checking git log for spec file/module ==="
git log --oneline -- spec 2>/dev/null | head -5

Repository: cloudglue/cloudglue-js

Length of output: 726


🏁 Script executed:

#!/bin/bash
# Description: Check recent commits and understand the submodule update context

echo "=== Recent commits in cloudglue-js ==="
git log --oneline -10

echo -e "\n=== Commit that updated spec submodule (if recent) ==="
git log --oneline --all -- spec | head -5

echo -e "\n=== Check if new commit b522b99... is in any branch ==="
git branch -r --contains b522b9959ddf32bedeba525d7afd0cbb7e517169 2>/dev/null | head -5 || echo "Commit not found in any remote branch"

echo -e "\n=== Show the spec submodule change in current commit ==="
git diff HEAD^ HEAD -- spec 2>/dev/null | head -20

echo -e "\n=== Check .gitmodules changes ==="
git log --oneline -p -- .gitmodules | head -50

Repository: cloudglue/cloudglue-js

Length of output: 1120


🏁 Script executed:

#!/bin/bash
# Description: Get more context about the spec submodule update

echo "=== Current working directory and HEAD ==="
pwd
git rev-parse HEAD
git describe --always

echo -e "\n=== Check if spec directory has any git history ==="
cd spec && git log --oneline 2>&1 | head -10
cd ..

echo -e "\n=== List all files that were changed in the PR commit ==="
git show --name-only 54d3f13 | head -30

echo -e "\n=== Check if there are generated files that might depend on spec ==="
find . -name "*.ts" -o -name "*.js" | head -20 | xargs ls -la 2>/dev/null | head -30

Repository: cloudglue/cloudglue-js

Length of output: 2901


🏁 Script executed:

#!/bin/bash
# Description: Check generate.js to understand spec dependency

echo "=== Head of generate.js to understand spec path ==="
head -50 generate.js

echo -e "\n=== Search for 'spec' references in generate.js ==="
grep -n "spec" generate.js | head -20

echo -e "\n=== Check package.json scripts ==="
cat package.json | grep -A 5 "\"scripts\""

echo -e "\n=== Check if spec is in .gitignore ==="
grep -i "spec" .gitignore

Repository: cloudglue/cloudglue-js

Length of output: 3338


The submodule commit does not exist in the cloudglue-api-spec repository.

The spec submodule is configured to reference commit b522b9959ddf32bedeba525d7afd0cbb7e517169, but this commit does not exist in git@github.com:cloudglue/cloudglue-api-spec.git. The PR's generate.js script depends on spec/spec/openapi.json from this submodule to generate the API client code. Without the submodule commit being available, the project cannot be cloned and built, and the generated code cannot be regenerated or verified.

Ensure the corresponding commit in the cloudglue-api-spec repository is created, pushed, and publicly accessible before this PR can be merged.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@spec` at line 1, The PR references a submodule commit for the spec that
doesn't exist, breaking generate.js which relies on spec/spec/openapi.json; fix
by either (A) creating and pushing the missing commit in the cloudglue-api-spec
repository so its object ID matches b522b9959ddf32bedeba525d7afd0cbb7e517169 and
ensure spec/spec/openapi.json is present in that commit, or (B) update the spec
submodule pointer in this repo to a valid, public commit in cloudglue-api-spec
that contains spec/spec/openapi.json and commit the updated submodule reference
(and update .gitmodules if needed) so generate.js can run. Ensure the chosen
commit is publicly accessible before merging.

@kdr kdr requested a review from amyxst March 16, 2026 02:04
…lity

Ensures unknown SSE event types from the server aren't silently dropped.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/api/deep-search.api.ts`:
- Around line 189-199: The fetch call builds headers from
this.api.axios.defaults.headers and directly uses h['Authorization'],
h['x-sdk-client'], h['x-sdk-version'], which may be undefined; change the header
construction used in the fetch call to build a headers object dynamically (e.g.,
start with required static headers 'Content-Type' and 'Accept' then add
Authorization, x-sdk-client, x-sdk-version only if truthy) so undefined values
are not passed to fetch; locate the header read in the method that calls fetch
(the lines using const h = this.api.axios.defaults.headers and the subsequent
fetch(... headers: { ... })) and update it to conditionally include or filter
out undefined header entries.
- Around line 286-296: The loop that polls getDeepSearch uses a non-null
assertion on deepSearch.status and lets undefined fall through, which can cause
infinite polling; update the logic in the polling loop (where getDeepSearch is
called and deepSearch.status is inspected) to explicitly check for the presence
of deepSearch.status and fail fast if it's missing (for example: if status is
undefined/null throw a CloudglueError referencing deepSearchId and any
deepSearch.error), remove the non-null assertion usage, and ensure the existing
failure branch (deepSearch.status === 'failed') and the completed/cancelled
branch still work as intended.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 46c6a4d3-d7dc-4489-bd25-8b60dcee8508

📥 Commits

Reviewing files that changed from the base of the PR and between 54d3f13 and 162c679.

📒 Files selected for processing (1)
  • src/api/deep-search.api.ts

Comment thread src/api/deep-search.api.ts
Comment thread src/api/deep-search.api.ts
…p search

- Add null check on deepSearch.status in waitForReady to fail fast instead
  of polling indefinitely if the API returns a malformed response
- Build fetch headers dynamically to avoid passing undefined values

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/api/deep-search.api.ts (1)

42-88: DeepSearchStreamEventType is not actually discriminated.

Including DeepSearchGenericEvent { type: string } in the public union prevents useful narrowing on event.type, and the Record<string, any> payloads throw away the concrete DeepSearch/DeepSearchResult shapes. If you need an unknown-event fallback, normalize it to a separate 'unknown' variant instead of unioning in type: string.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/api/deep-search.api.ts` around lines 42 - 88, The union is not
discriminated because DeepSearchGenericEvent uses type: string and the payloads
use broad Record<string, any>; update the specific event interfaces
(DeepSearchCreatedEvent, DeepSearchResultAddedEvent, DeepSearchCompletedEvent)
to reference concrete types (e.g., DeepSearch and DeepSearchResult) instead of
Record<string, any>, and change DeepSearchGenericEvent to a single fallback with
type: 'unknown' and a generic payload field (e.g., payload: Record<string, any>)
so narrowing on event.type works; then keep DeepSearchStreamEventType as the
union of those concrete event interfaces plus the new
DeepSearchGenericEvent('unknown') fallback.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/api/deep-search.api.ts`:
- Around line 13-30: The exported CreateDeepSearchParams type currently includes
the stream?: boolean property which allows callers of createDeepSearch() (and
client.deepSearch.createDeepSearch) to compile with streaming enabled even
though only createStreamingDeepSearch() can handle SSE; remove the stream
property from CreateDeepSearchParams and any other non-streaming request types
(also update the duplicate definitions referenced around the other occurrence)
so that createDeepSearch()’s signature cannot accept stream: true, leaving
streaming behavior only to createStreamingDeepSearch() and its corresponding
request type.
- Around line 186-223: The fetch call and subsequent stream consumption in the
deep-search endpoint can throw transport-level errors that currently escape;
wrap the entire network interaction (the fetch(...) call and any downstream
stream-reading logic) in a try/catch and, on any thrown error, rethrow a
CloudglueError so transport failures are normalized with HTTP errors.
Specifically, catch errors around the fetch invocation and stream processing in
the method containing the fetch, build a CloudglueError using a sensible status
(e.g., 0 or undefined), include JSON.stringify(body) as the request payload,
include headers (or an empty object) from response.headers if available, and
attach the original error object/string as the error payload/responseData;
ensure you still preserve existing behavior for non-ok HTTP responses handled by
the existing response.ok branch.

---

Nitpick comments:
In `@src/api/deep-search.api.ts`:
- Around line 42-88: The union is not discriminated because
DeepSearchGenericEvent uses type: string and the payloads use broad
Record<string, any>; update the specific event interfaces
(DeepSearchCreatedEvent, DeepSearchResultAddedEvent, DeepSearchCompletedEvent)
to reference concrete types (e.g., DeepSearch and DeepSearchResult) instead of
Record<string, any>, and change DeepSearchGenericEvent to a single fallback with
type: 'unknown' and a generic payload field (e.g., payload: Record<string, any>)
so narrowing on event.type works; then keep DeepSearchStreamEventType as the
union of those concrete event interfaces plus the new
DeepSearchGenericEvent('unknown') fallback.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 966400e0-cbb2-486a-9382-43f2b7ad8218

📥 Commits

Reviewing files that changed from the base of the PR and between 162c679 and 52202ef.

📒 Files selected for processing (1)
  • src/api/deep-search.api.ts

Comment on lines +13 to +30
export interface CreateDeepSearchParams {
/** Knowledge base configuration specifying what content to search */
knowledge_base: DeepSearchKnowledgeBase;
/** The search query */
query: string;
/** Search scope - segment-level or file-level */
scope?: 'segment' | 'file';
/** Maximum number of results to return (1-500) */
limit?: number;
/** Whether to exclude weak results */
exclude_weak_results?: boolean;
/** Include additional data in results */
include?: Array<'search_queries'>;
/** Enable server-sent events streaming */
stream?: boolean;
/** Run the deep search in background (async) */
background?: boolean;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Remove stream from the createDeepSearch() contract.

createDeepSearch() forwards to the generated JSON client, so client.deepSearch.createDeepSearch({ ..., stream: true }) compiles even though only createStreamingDeepSearch() can consume an SSE response. Tighten the exported params/signature so the non-streaming entry point cannot be called in streaming mode.

Also applies to: 166-168

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/api/deep-search.api.ts` around lines 13 - 30, The exported
CreateDeepSearchParams type currently includes the stream?: boolean property
which allows callers of createDeepSearch() (and
client.deepSearch.createDeepSearch) to compile with streaming enabled even
though only createStreamingDeepSearch() can handle SSE; remove the stream
property from CreateDeepSearchParams and any other non-streaming request types
(also update the duplicate definitions referenced around the other occurrence)
so that createDeepSearch()’s signature cannot accept stream: true, leaving
streaming behavior only to createStreamingDeepSearch() and its corresponding
request type.

Comment on lines +186 to +223
const baseURL = this.api.axios.defaults.baseURL;
const url = `${baseURL}/deepSearch`;

const h = this.api.axios.defaults.headers as Record<string, any>;
const headers: Record<string, string> = {
'Content-Type': 'application/json',
Accept: 'text/event-stream',
};
if (h['Authorization']) headers['Authorization'] = h['Authorization'];
if (h['x-sdk-client']) headers['x-sdk-client'] = h['x-sdk-client'];
if (h['x-sdk-version']) headers['x-sdk-version'] = h['x-sdk-version'];

const response = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify(body),
});

if (!response.ok) {
let errorMessage = `Request failed with status ${response.status}`;
let responseData: any;
try {
responseData = await response.json();
if (typeof responseData?.error === 'string') {
errorMessage = responseData.error;
} else if (responseData?.error?.message) {
errorMessage = responseData.error.message;
}
} catch {
// Could not parse error body
}
throw new CloudglueError(
errorMessage,
response.status,
JSON.stringify(body),
Object.fromEntries(response.headers.entries()),
responseData,
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, let's examine the full context of the createStreamingDeepSearch method
head -230 src/api/deep-search.api.ts | tail -60

Repository: cloudglue/cloudglue-js

Length of output: 2097


🏁 Script executed:

# Check the full file structure
wc -l src/api/deep-search.api.ts

Repository: cloudglue/cloudglue-js

Length of output: 96


🏁 Script executed:

# Search for streaming patterns in the codebase
rg -i "streaming|event-stream|sse" --type ts src/ -A 3 -B 1

Repository: cloudglue/cloudglue-js

Length of output: 10083


🏁 Script executed:

# Check if there are other fetch() calls in src/api
rg "fetch\(" src/api --type ts -B 2 -A 2

Repository: cloudglue/cloudglue-js

Length of output: 715


🏁 Script executed:

# Check the Zodios usage in the codebase to understand how it's configured
rg "zodios" src/api --type ts -B 2 -A 2 | head -40

Repository: cloudglue/cloudglue-js

Length of output: 48


🏁 Script executed:

# Look for any comments or documentation about streaming and transport choices
rg -i "zodios.*stream|stream.*zodios|sse.*zodios" src/ --type ts -B 2 -A 2

Repository: cloudglue/cloudglue-js

Length of output: 48


🏁 Script executed:

# Check if there's any configuration or setup guidance in README or similar
fd -t f "README|CLAUDE|\.md" . -exec grep -l "stream\|sse\|fetch" {} \;

Repository: cloudglue/cloudglue-js

Length of output: 278


🏁 Script executed:

# Verify header coverage - check what other headers might be in axios.defaults.headers
rg "axios\.defaults\.headers|headers\s*=" src/client.ts -A 5 -B 2

Repository: cloudglue/cloudglue-js

Length of output: 48


🏁 Script executed:

# Find documentation files
find . -maxdepth 2 -type f \( -name "README*" -o -name "CLAUDE*" -o -name "*.md" \)

Repository: cloudglue/cloudglue-js

Length of output: 102


🏁 Script executed:

# Check client.ts for header setup
grep -n "headers\|Authorization\|x-sdk" src/client.ts | head -30

Repository: cloudglue/cloudglue-js

Length of output: 369


🏁 Script executed:

# Look for any comments or documentation about why fetch is used for streaming
rg "fetch\(|stream\(" src/api/deep-search.api.ts -B 3 -A 1

Repository: cloudglue/cloudglue-js

Length of output: 275


🏁 Script executed:

# Check if there are any TODOs or FIXMEs related to streaming or transport
rg -i "todo|fixme" src/api/deep-search.api.ts

Repository: cloudglue/cloudglue-js

Length of output: 48


🏁 Script executed:

# Check CLAUDE.md for guidance on streaming or fetch usage
cat CLAUDE.md

Repository: cloudglue/cloudglue-js

Length of output: 3111


🏁 Script executed:

# Check README for any streaming or architecture guidance
cat README.md | head -100

Repository: cloudglue/cloudglue-js

Length of output: 2732


Network-level errors during streaming are not wrapped in CloudglueError.

While HTTP response errors (non-ok status) are properly wrapped, connection failures, timeout errors, and stream-reading errors from fetch() will escape as raw errors instead of CloudglueError. For consistency with non-streaming endpoints, consider wrapping transport-level failures (e.g., around the fetch() call and stream consumption).

Note: SSE streaming requires a persistent connection incompatible with Zodios/Axios request-response design, so direct fetch() usage is appropriate here (similar to the documented exception for file uploads). The header extraction is adequate.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/api/deep-search.api.ts` around lines 186 - 223, The fetch call and
subsequent stream consumption in the deep-search endpoint can throw
transport-level errors that currently escape; wrap the entire network
interaction (the fetch(...) call and any downstream stream-reading logic) in a
try/catch and, on any thrown error, rethrow a CloudglueError so transport
failures are normalized with HTTP errors. Specifically, catch errors around the
fetch invocation and stream processing in the method containing the fetch, build
a CloudglueError using a sensible status (e.g., 0 or undefined), include
JSON.stringify(body) as the request payload, include headers (or an empty
object) from response.headers if available, and attach the original error
object/string as the error payload/responseData; ensure you still preserve
existing behavior for non-ok HTTP responses handled by the existing response.ok
branch.

@kdr kdr merged commit 4bb4605 into main Mar 16, 2026
1 check passed
@kdr kdr deleted the kdr-067 branch March 16, 2026 03:07
kdr added a commit that referenced this pull request Jun 8, 2026
## Summary

- Bumps the `cloudglue-api-spec` submodule to **v0.7.4** ([api-spec
#98](cloudglue/cloudglue-api-spec#98)), which
marks the include-gated Grain `source_metadata` fields as nullable.
- Regenerates the client. The only generated change is in
`GrainSourceMetadata` (`generated/common.ts`): `participants`,
`highlights`, `ai_summary`, `ai_action_items`, `ai_template_sections`,
and `calendar_event` move from `.optional()` → `.nullish()`, with
matching `| null` TS types produced by the existing `generate.js`
nullish/nullable transforms.
- Bumps SDK version `0.7.12` → `0.7.13`.

## Verification

- `npm run generate` is reproducible — re-running yields byte-identical
output (only `common.ts` changes).
- `npm run build` (tsc) passes.
- Ran `getSourceMetadata()` against a live Grain connector: fetch + Zod
parse both succeed with the new nullable schema.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
  * Version updated to 0.7.13
  * Submodule reference updated

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants