Skip to content

Feat/zoo gateway#229

Open
JamesRobert20 wants to merge 31 commits into
mainfrom
feat/zoo-gateway
Open

Feat/zoo gateway#229
JamesRobert20 wants to merge 31 commits into
mainfrom
feat/zoo-gateway

Conversation

@JamesRobert20
Copy link
Copy Markdown
Contributor

@JamesRobert20 JamesRobert20 commented May 21, 2026

Pull Request: Zoo Gateway Provider Integration

Description

This PR introduces Zoo Gateway as a new provider option in Zoo Code, enabling users to access AI models through the Zoo Code platform's unified API gateway.

Key Implementation Details

1. New Provider Architecture

  • src/api/providers/zoo-gateway.ts — Full provider handler extending RouterProvider with OpenAI-compatible API, prompt caching support for Claude models, and enrichment headers for request tracking (X-Zoo-Task-ID, X-Zoo-Mode, X-Zoo-Extension-Version, X-Zoo-Editor)

  • src/api/providers/fetchers/zoo-gateway.ts — Model fetcher that retrieves available models from the Zoo Gateway /models endpoint, reusing Vercel AI Gateway's Zod schemas and parsing logic since API formats are identical

  • packages/types/src/providers/zoo-gateway.ts — Type definitions with claude-sonnet-4 as default model, shared prompt caching model list with Vercel AI Gateway

2. Authentication Flow

Authentication uses the existing Zoo Code OAuth flow (via /auth-callback URI handler):

  1. User clicks "Sign in to Zoo Code" button in settings
  2. Browser opens Zoo Code website authentication page
  3. After successful auth, callback URL returns token, name, email, and image
  4. handleUri.ts processes callback across all ClineProvider instances (not just visible ones) to ensure token persistence even when sidebar is hidden
  5. Token is stored as zooSessionToken in zoo-gateway provider profiles

3. Multi-Profile Token Synchronization

A significant design decision was made to handle profile management robustly:

  • ClineProvider.handleZooCodeCallback() scans all profiles with apiProvider === "zoo-gateway" and updates tokens in each (profile names are user-renameable)
  • ensureZooGatewayProfileSeeded() handles migration for existing users who authenticated before Zoo Gateway was added — creates a profile or updates stale tokens on webview init
  • On sign-out, webviewMessageHandler.ts clears zooSessionToken from all zoo-gateway profiles, not just the active one
  • Model list fetching looks up zoo-gateway profiles even when zoo-gateway isn't the active provider, so the model picker populates correctly

4. Base URL Environment Handling

The gateway base URL is derived dynamically from ZOO_CODE_BASE_URL environment variable:

  • Production: https://www.zoocode.dev/api/gateway/v1
  • Staging/dev environments route to their respective backends
  • This ensures auth server and gateway always match

5. Settings UI

webview-ui/src/components/settings/providers/ZooGateway.tsx:

  • Shows Zoo Code account status with user email when authenticated
  • "Sign in to Zoo Code" button when unauthenticated
  • ModelPicker with dynamic model list fetched from gateway
  • Validation requires sign-in before use (validation.zooGatewaySignIn)

6. Validation Changes

webview-ui/src/utils/validate.ts:

  • Added zoo-gateway validation that checks zooCodeIsAuthenticated state
  • Returns validation error if user tries to use zoo-gateway without signing in

Trade-offs & Design Decisions

  1. Token in all profiles vs. single profile: Chose to update all zoo-gateway profiles rather than just one canonical profile. This prevents stale tokens in renamed/duplicate profiles from causing auth failures when model fetcher does .find() and hits the wrong profile first.

  2. Fire-and-forget profile seeding: ensureZooGatewayProfileSeeded() runs on webview init without blocking. If it fails, users can still re-authenticate manually.

  3. No auto-switch on sign-in: When user signs in, we update zoo-gateway profiles but do NOT switch the active provider. Users must explicitly select Zoo Gateway to avoid disrupting mid-conversation flows.

Test Procedure

Unit Tests Updated:

Manual Testing Steps:

  1. New User Flow:

    • Open Zoo Code extension with no saved credentials
    • Go to Settings → Providers → select "Zoo Gateway"
    • Verify "Sign in to Zoo Code" button appears
    • Verify validation error appears if trying to proceed without signing in
    • Click "Sign in to Zoo Code" → authenticate in browser
    • Verify callback returns to VS Code and shows "Authenticated as [name]"
    • Verify model picker populates with available models
    • Select a model and start a conversation
    • Verify API requests include enrichment headers (check Network tab or server logs)
  2. Existing User Migration:

    • User who previously signed into Zoo Code (has cached token) but no zoo-gateway profile
    • Open settings → select Zoo Gateway
    • Verify profile is auto-created with existing token (check that authentication shows immediately without re-sign-in)
  3. Multi-Profile Scenarios:

    • Create multiple zoo-gateway profiles with different names
    • Sign in once
    • Verify all profiles show authenticated state
    • Sign out
    • Verify all profiles have token cleared
  4. Sign-Out Flow:

    • While using zoo-gateway provider, click sign out
    • Verify token is cleared from active profile
    • Verify validation error appears when trying to use zoo-gateway

Documentation Updates

  • Yes, documentation updates are required:
    • New provider documentation page for Zoo Gateway
    • Authentication flow explanation
    • Available models reference

Summary by CodeRabbit

  • Documentation
    • Privacy policy: Zoo Code Observability now applies to all authenticated users.
    • Telemetry is linked to the authenticated account and includes task ID, provider/model names, token counts, and estimated cost.
    • Telemetry retention: up to 90 days (metadata-only API request logs); Free users see 7 days, Pro and higher see 90 days.
    • Users can stop collection by signing out and may request deletion.
    • Minor README formatting adjustment.

Review Change Stack

James Mtendamema added 29 commits May 15, 2026 15:04
…users and adjust telemetry retention policies
@JamesRobert20 JamesRobert20 requested a review from taltas as a code owner May 21, 2026 05:47
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 21, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c8133d95-126f-4b4d-82ea-66f7479acdd2

📥 Commits

Reviewing files that changed from the base of the PR and between 5feaee9 and bb94f9b.

📒 Files selected for processing (1)
  • PRIVACY.md
✅ Files skipped from review due to trivial changes (1)
  • PRIVACY.md

📝 Walkthrough

Walkthrough

Updated the "Zoo Code Observability" privacy section to cover all authenticated users, link telemetry to accounts, enumerate telemetry fields, and set metadata-only API request log retention to up to 90 days (Free: last 7 days; Pro and higher: full 90-day view). Also fixed README closing </details> indentation.

Changes

Documentation and Policy Updates

Layer / File(s) Summary
Privacy policy observability clarification
PRIVACY.md
Observability telemetry now applies to all authenticated users, is linked to authenticated accounts, includes fields (task ID, provider/model, token counts, estimated cost), and is retained in metadata-only API request logs for up to 90 days. Free users see the last 7 days; Pro+ users see the full 90-day window. Users can stop collection by signing out and may request deletion.
README formatting adjustment
README.md
Adjusted indentation/whitespace of the closing </details> tag in the "Available languages" section.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Suggested reviewers

  • hannesrudolph
  • edelauna
  • taltas

Poem

🐰 I nibble lines and prune a tag,
Privacy clearer — no more lag,
Seven days for free to peek, ninety for the pro,
Sign out to hush the logs — hop, off I go! ✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 55.56% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The PR title 'Feat/zoo gateway' is vague and generic, using a feature flag prefix without clearly describing the main change. Revise title to be more specific and descriptive, such as 'Add Zoo Gateway provider integration' or 'Introduce Zoo Gateway as new provider option'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The description covers implementation details, authentication flow, design decisions, test procedures, and documentation updates comprehensively.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/zoo-gateway

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


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.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

Caution

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

⚠️ Outside diff range comments (1)
src/api/providers/fetchers/modelCache.ts (1)

130-147: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Cache bypass is incomplete for zoo-gateway.

getModels skips cache, but refreshModels still persists models. That reintroduces stale cross-auth-context data for this provider.

Suggested fix
 export const refreshModels = async (options: GetModelsOptions): Promise<ModelRecord> => {
 	const { provider } = options
+	const shouldSkipCache = provider === "zoo-gateway"
@@
-			// Update memory cache first
-			memoryCache.set(provider, models)
-
-			// Atomically write to disk (safeWriteJson handles atomic writes)
-			await writeModels(provider, models).catch((err) =>
-				console.error(`[refreshModels] Error writing ${provider} models to disk:`, err),
-			)
+			if (!shouldSkipCache) {
+				// Update memory cache first
+				memoryCache.set(provider, models)
+
+				// Atomically write to disk (safeWriteJson handles atomic writes)
+				await writeModels(provider, models).catch((err) =>
+					console.error(`[refreshModels] Error writing ${provider} models to disk:`, err),
+				)
+			}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/api/providers/fetchers/modelCache.ts` around lines 130 - 147, The
zoo-gateway provider still gets written into the shared cache by refreshModels;
update refreshModels so it never persists models for provider === "zoo-gateway"
(use the existing shouldSkipCache boolean) — i.e., before calling
memoryCache.set (or any cache write), check !shouldSkipCache and skip the write
for zoo-gateway; ensure any other code paths in refreshModels that call
memoryCache.set are similarly guarded.
🧹 Nitpick comments (2)
src/activate/__tests__/handleUri.spec.ts (1)

65-82: ⚡ Quick win

Add a true multi-instance regression test.

This only proves the zero-instance branch. A regression back to updating just the visible provider would still pass because nothing here asserts that every entry from getAllInstances() receives the callback token.

🧪 Suggested test shape
+		const hiddenProvider = {
+			handleZooCodeCallback: vi.fn(),
+		} as any
+		mockGetAllInstances.mockReturnValue([mockVisibleProvider, hiddenProvider])
+
+		await handleUri({
+			path: "/auth-callback",
+			query: "token=zoo_ext_test_token",
+		} as any)
+
+		expect(mockVisibleProvider.handleZooCodeCallback).toHaveBeenCalledWith("zoo_ext_test_token")
+		expect(hiddenProvider.handleZooCodeCallback).toHaveBeenCalledWith("zoo_ext_test_token")

As per coding guidelines, **/{__tests__,tests,test}/**/*.{test,spec}.{ts,tsx,js}: Use package-local unit tests for pure logic, parsing, state transitions, validation, serialization, request construction, retry decisions, and error handling.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/activate/__tests__/handleUri.spec.ts` around lines 65 - 82, The current
test only covers the zero-instance path; add a multi-instance regression test
for handleUri that ensures every instance returned by getAllInstances receives
the callback token. Mock getVisibleInstance to return one visible provider and
mock getAllInstances to return an array of two or more provider instances (each
with a spy on handleZooCodeCallback), call handleUri with the same auth-callback
query, and assert mockHandleZooCodeAuthCallback was called with the token,
mockSetZooCodeUserInfo was called with parsed user info, and that each returned
instance.handleZooCodeCallback was called with "zoo_ext_test_token" (and
optionally that the visible provider was also called).
src/core/webview/__tests__/webviewMessageHandler.spec.ts (1)

324-379: ⚡ Quick win

Exercise the new separate-profile Zoo Gateway lookup.

This only verifies that zoo-gateway appears in the aggregated response. The new fallback path never runs here because mockClineProvider has no providerSettingsManager, and mockGetModels still succeeds with undefined credentials.

Add a case with a non-zoo-gateway active config plus mocked providerSettingsManager.listConfig/getProfile, then assert getModels receives the recovered apiKey and baseUrl. As per coding guidelines, **/{__tests__,tests,test}/**/*.{test,spec}.{ts,tsx,js}: Use package-local unit tests for pure logic, parsing, state transitions, validation, serialization, request construction, retry decisions, and error handling.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/core/webview/__tests__/webviewMessageHandler.spec.ts` around lines 324 -
379, The test doesn’t exercise the new Zoo Gateway separate-profile fallback
path; update the spec for webviewMessageHandler to add a case where
mockClineProvider has a providerSettingsManager with a non-"zoo-gateway" active
config and stub providerSettingsManager.listConfig and
providerSettingsManager.getProfile to return a config that maps to a zoo-gateway
profile (with apiKey and baseUrl), then invoke webviewMessageHandler and assert
mockGetModels was called with an object containing provider: "zoo-gateway" plus
the recovered apiKey and baseUrl (and still verify the aggregated routerModels
includes "zoo-gateway"); reference webviewMessageHandler, mockClineProvider,
mockGetModels, providerSettingsManager.listConfig and
providerSettingsManager.getProfile to locate and implement the new assertion.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@PRIVACY.md`:
- Around line 43-48: Update the "Zoo Code Observability (All Authenticated
Users)" section to remove the phrase "unlimited retention" for Pro and higher
users and replace it with a bounded retention policy or an explicit legal basis
and deletion workflow; specifically, change the account-linked telemetry
retention statement to either a fixed maximum retention period (e.g., X
days/months) or state the legal basis plus a documented deletion/archival SLA
and how users can request deletion, and ensure the text mentions the scope (task
ID, provider/model, token counts, estimated cost) and any plan-specific
differences (Free: 7 days; Pro+: specified retention or deletion workflow) so
the privacy claim is not indefinite.

In `@src/api/providers/fetchers/zoo-gateway.ts`:
- Around line 70-72: The axios.get call that discovers models (the
axios.get<ZooGatewayModelsResponse>(`${baseURL}/models`, { headers }) call)
needs an explicit timeout to avoid hanging; add a timeout option (e.g. timeout:
MODEL_DISCOVERY_TIMEOUT_MS) to the request options object, define
MODEL_DISCOVERY_TIMEOUT_MS as a configurable constant or env-backed value
(fallback to a sensible default like 5000 ms), and pass that into the axios.get
call so model discovery will fail fast on network stalls.
- Around line 93-95: The current console.error call serializes the entire error
(JSON.stringify(error, Object.getOwnPropertyNames(error))) which can leak
sensitive headers/bearer tokens; change the logging to avoid dumping the full
error object—log only safe fields such as error.message, error.name, and
error.stack (or error.code) and/or use a sanitizer that strips
request/config/headers before logging. Replace the JSON.stringify usage in the
console.error call (the line that logs "Error fetching Zoo Gateway models...")
with a call that builds a safeError summary (excluding any request, config,
headers, or auth fields) or simply log error.message and a truncated stack to
ensure no bearer tokens are emitted.

In `@src/core/webview/webviewMessageHandler.ts`:
- Around line 2477-2501: The sign-out loop in webviewMessageHandler.ts only
updates the in-memory active Zoo Gateway profile when the persisted profile
still has zooSessionToken, which misses cases where disk is already clean but
the in-memory currentSettings/token is stale; modify the loop so you always
construct a cleanedProfile (e.g., clone profile and delete zooSessionToken) and,
if isThisProfileActive (use isZooGatewayActive and currentApiConfigName ===
entry.name), always call provider.upsertProviderProfile(entry.name,
cleanedProfile, true) to clear the in-memory handler, while retaining the
existing behavior of calling
provider.providerSettingsManager.saveConfig(entry.name, cleanedProfile) when the
persisted profile originally contained a token (or simply always persist if you
prefer); reference symbols: entry, profile, cleanedProfile, isThisProfileActive,
isZooGatewayActive, currentApiConfigName, provider.upsertProviderProfile,
provider.providerSettingsManager.saveConfig.

In `@webview-ui/src/components/settings/ApiOptions.tsx`:
- Around line 709-718: The provider switch to "zoo-gateway" in ApiOptions.tsx
doesn't initialize zooGatewayModelId because "zoo-gateway" is missing from
PROVIDER_MODEL_CONFIG; add a PROVIDER_MODEL_CONFIG entry for "zoo-gateway" that
provides the model field/key used to initialize/set zooGatewayModelId (so
setApiConfigurationField or the same init logic used for other providers runs
when selectedProvider === "zoo-gateway"), update any references in ApiOptions
(and the ZooGateway wrapper) to use that config key, and add a local webview-ui
test covering provider-switch behavior to ensure the dynamic-provider model id
is set on switch.

In `@webview-ui/src/i18n/locales/tr/settings.json`:
- Around line 908-909: The two Turkish strings use informal second-person;
change them to formal phrasing to match existing validation messages: update
"qwenCodeOauthPath" from "Geçerli bir OAuth kimlik bilgileri yolu sağlamalısın"
to a formal form like "Geçerli bir OAuth kimlik bilgileri yolu sağlamalısınız"
and update "zooGatewaySignIn" from "Zoo Gateway'i kullanmak için Zoo Code'a
giriş yapmalısın. Kimlik doğrulamak için 'Giriş Yap'a tıkla." to a formal
equivalent such as "Zoo Gateway'i kullanmak için Zoo Code'a giriş yapmalısınız.
Kimlik doğrulamak için 'Giriş Yap' düğmesine tıklayın." Ensure both keys
("qwenCodeOauthPath" and "zooGatewaySignIn") are replaced accordingly to keep
tone consistent.

---

Outside diff comments:
In `@src/api/providers/fetchers/modelCache.ts`:
- Around line 130-147: The zoo-gateway provider still gets written into the
shared cache by refreshModels; update refreshModels so it never persists models
for provider === "zoo-gateway" (use the existing shouldSkipCache boolean) —
i.e., before calling memoryCache.set (or any cache write), check
!shouldSkipCache and skip the write for zoo-gateway; ensure any other code paths
in refreshModels that call memoryCache.set are similarly guarded.

---

Nitpick comments:
In `@src/activate/__tests__/handleUri.spec.ts`:
- Around line 65-82: The current test only covers the zero-instance path; add a
multi-instance regression test for handleUri that ensures every instance
returned by getAllInstances receives the callback token. Mock getVisibleInstance
to return one visible provider and mock getAllInstances to return an array of
two or more provider instances (each with a spy on handleZooCodeCallback), call
handleUri with the same auth-callback query, and assert
mockHandleZooCodeAuthCallback was called with the token, mockSetZooCodeUserInfo
was called with parsed user info, and that each returned
instance.handleZooCodeCallback was called with "zoo_ext_test_token" (and
optionally that the visible provider was also called).

In `@src/core/webview/__tests__/webviewMessageHandler.spec.ts`:
- Around line 324-379: The test doesn’t exercise the new Zoo Gateway
separate-profile fallback path; update the spec for webviewMessageHandler to add
a case where mockClineProvider has a providerSettingsManager with a
non-"zoo-gateway" active config and stub providerSettingsManager.listConfig and
providerSettingsManager.getProfile to return a config that maps to a zoo-gateway
profile (with apiKey and baseUrl), then invoke webviewMessageHandler and assert
mockGetModels was called with an object containing provider: "zoo-gateway" plus
the recovered apiKey and baseUrl (and still verify the aggregated routerModels
includes "zoo-gateway"); reference webviewMessageHandler, mockClineProvider,
mockGetModels, providerSettingsManager.listConfig and
providerSettingsManager.getProfile to locate and implement the new assertion.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ed06aec1-7fb4-4521-8e6a-45343efe1826

📥 Commits

Reviewing files that changed from the base of the PR and between 3bd1a80 and e5ae0b6.

📒 Files selected for processing (62)
  • PRIVACY.md
  • README.md
  • locales/ca/README.md
  • locales/de/README.md
  • locales/es/README.md
  • locales/fr/README.md
  • locales/hi/README.md
  • locales/id/README.md
  • locales/it/README.md
  • locales/ja/README.md
  • locales/ko/README.md
  • locales/nl/README.md
  • locales/pl/README.md
  • locales/pt-BR/README.md
  • locales/ru/README.md
  • locales/tr/README.md
  • locales/vi/README.md
  • locales/zh-CN/README.md
  • locales/zh-TW/README.md
  • packages/types/src/provider-settings.ts
  • packages/types/src/providers/index.ts
  • packages/types/src/providers/zoo-gateway.ts
  • src/activate/__tests__/handleUri.spec.ts
  • src/activate/handleUri.ts
  • src/api/index.ts
  • src/api/providers/fetchers/modelCache.ts
  • src/api/providers/fetchers/zoo-gateway.ts
  • src/api/providers/index.ts
  • src/api/providers/zoo-gateway.ts
  • src/core/webview/ClineProvider.ts
  • src/core/webview/__tests__/ClineProvider.spec.ts
  • src/core/webview/__tests__/webviewMessageHandler.spec.ts
  • src/core/webview/webviewMessageHandler.ts
  • src/services/zoo-telemetry.ts
  • src/shared/api.ts
  • webview-ui/src/components/settings/ApiOptions.tsx
  • webview-ui/src/components/settings/ModelPicker.tsx
  • webview-ui/src/components/settings/constants.ts
  • webview-ui/src/components/settings/providers/ZooGateway.tsx
  • webview-ui/src/components/settings/providers/index.ts
  • webview-ui/src/components/ui/hooks/useSelectedModel.ts
  • webview-ui/src/components/welcome/WelcomeViewProvider.tsx
  • webview-ui/src/i18n/locales/ca/settings.json
  • webview-ui/src/i18n/locales/de/settings.json
  • webview-ui/src/i18n/locales/en/settings.json
  • webview-ui/src/i18n/locales/es/settings.json
  • webview-ui/src/i18n/locales/fr/settings.json
  • webview-ui/src/i18n/locales/hi/settings.json
  • webview-ui/src/i18n/locales/id/settings.json
  • webview-ui/src/i18n/locales/it/settings.json
  • webview-ui/src/i18n/locales/ja/settings.json
  • webview-ui/src/i18n/locales/ko/settings.json
  • webview-ui/src/i18n/locales/nl/settings.json
  • webview-ui/src/i18n/locales/pl/settings.json
  • webview-ui/src/i18n/locales/pt-BR/settings.json
  • webview-ui/src/i18n/locales/ru/settings.json
  • webview-ui/src/i18n/locales/tr/settings.json
  • webview-ui/src/i18n/locales/vi/settings.json
  • webview-ui/src/i18n/locales/zh-CN/settings.json
  • webview-ui/src/i18n/locales/zh-TW/settings.json
  • webview-ui/src/utils/__tests__/validate.spec.ts
  • webview-ui/src/utils/validate.ts

Comment thread PRIVACY.md Outdated
Comment thread src/api/providers/fetchers/zoo-gateway.ts
Comment thread src/api/providers/fetchers/zoo-gateway.ts
Comment thread src/core/webview/webviewMessageHandler.ts
Comment thread webview-ui/src/components/settings/ApiOptions.tsx
Comment thread webview-ui/src/i18n/locales/tr/settings.json Outdated
Copy link
Copy Markdown
Contributor

@edelauna edelauna left a comment

Choose a reason for hiding this comment

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

Request Changes: Break This PR Into Smaller, Focused PRs

Hey James — nice work on the Zoo Gateway integration. The provider architecture, multi-profile token sync, and UI are well thought out, and the PR description is one of the most thorough I've seen. That said, I'm requesting changes on PR scoping before doing a detailed line-by-line review.

This PR modifies ~60 files across 6 distinct concerns: type definitions, provider backend, auth flow, settings UI, 20 i18n locale files, and a telemetry policy change.

Concrete issues that illustrate why this matters

In the current diff I've already spotted:

  1. A race condition in handleUri.tsPromise.all(allInstances.map(i => i.handleZooCodeCallback(token))) runs concurrent read-modify-write operations on the same profile settings files with no coordination. This is buried in a 60-file diff and easy to miss.

  2. A telemetry policy change (zoo-telemetry.ts + PRIVACY.md) that expands data collection to all authenticated users. This has zero code dependency on Zoo Gateway, figure we'd document this seprately.

Suggested decomposition

Using the stacked PR pattern:

PR Scope ~Size Risk
1. Types & Provider Core packages/types, handler, fetcher, model cache, api/index.ts ~150 lines Low
2. Settings UI & i18n ZooGateway.tsx, ApiOptions.tsx, validate.ts, ModelPicker, useSelectedModel, 20 locale files ~200 lines logic Low
3. Auth Flow & Token Sync handleUri.ts, handleZooCodeCallback, ensureZooGatewayProfileSeeded, sign-out cleanup, related tests ~250 lines High — needs focused review
4. Telemetry Policy Change zoo-telemetry.ts, PRIVACY.md ~30 lines Independent
5. README updates Badge/count updates across locale READMEs ~20 lines Trivial

Each PR is independently reviewable, independently revertable, and can merge as soon as it's approved — unblocking downstream work instead of everything waiting on one monolithic review.

What I'm asking

I'm asking you to repackage the same work into a stack of focused PRs so that:

  • The auth flow (PR 3) gets the dedicated scrutiny it needs
  • The telemetry policy change (PR 4) gets its own approval path
  • PRs 1–2 can merge quickly without being blocked by review of the riskier parts
  • Each piece is independently revertable if issues surface in production

James Mtendamema and others added 2 commits May 23, 2026 10:43
Align observability retention with the website privacy policy (90-day
metadata logs; plan-gated dashboard visibility). Harden zoo-gateway model
fetching (timeout, safe error logging) and cache bypass in refreshModels.
Fix sign-out to always clear the active in-memory profile, initialize
zooGatewayModelId on provider switch, serialize multi-instance auth
callbacks, and add regression tests.

Co-authored-by: Cursor <cursoragent@cursor.com>
@JamesRobert20
Copy link
Copy Markdown
Contributor Author

Split per review into a stacked PR series (review fixes are on feat/zoo-gateway as bb94f9b and incorporated in the stack):

Stack (merge in order):

  1. feat(zoo-gateway): provider types, handler, and model fetcher #344 — types, handler, model fetcher → main
  2. feat(zoo-gateway): settings UI, validation, and i18n #345 — settings UI & i18n → feat(zoo-gateway): provider types, handler, and model fetcher #344
  3. feat(zoo-gateway): auth callback and multi-profile token sync #347 — auth callback & token sync → feat(zoo-gateway): settings UI, validation, and i18n #345

Independent:
4. #346 — observability / PRIVACY retention policy → main
5. #348 — README badge updates → main

Closing this monolithic PR in favor of the stack above.

@proyectoauraorg
Copy link
Copy Markdown
Contributor

Superseded by Split Stack

This monolith PR has been superseded by the split stack:

All PRs in the stack have been reviewed, tested (352+ tests pass across all PRs), and approved. This PR can be safely closed.

The conflict resolution for #344 is available at proyectoauraorg/Zoo-Code:feat/zoo-gateway-types-core-rebased.

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.

3 participants