Repository navigation
Internal cleanup - #33852
Internal cleanup#33852
Conversation
…ma to what the cloud sends
…blank question text and labels
…ginal never undoes newer state
…ccount with relay-style connector tokens
…the next sign-in, dropped events resync, failed receipts settle
…ign-out, and watching from start
…and acks belong to a hello
…jinwoo/connector-desktop-poll
…w, quit fence, network-ready connect; acks name their hello
…jinwoo/connector-desktop-poll
…ons persist across clients and restarts
…top-poll # Conflicts: # cloud/pnpm-lock.yaml # config/scripts/check-test-file-runners.mjs # src/shared/connector-cloud-contract.ts
…g work Items leave only when a 204 lands while the hello it named is still accepted; senders read the outbox head under that hello and do nothing without one.
…pshot turn ids in the contract
…hes, exact success shapes, snapshot turn ids Pairs with #33821. A failed poll says hello again so unsettled deliveries are listed again.
…shot restores the same turn to working
Snapshots list recently active conversations, newest first, up to 200; hellos list the most recently used projects, up to 500, trimmed to the request cap. Each logs once when it leaves something out.
… hello only replaces the accepted one
… or Linear; a posted reply names its messageId
…ze the snapshot test's clock
…r touch a stored Slack thread
…chine ignores it once that turn is over
…s' into jinwoo/connector-desktop-poll
… handoff; no watch, no open turn
…, like its turn events
…' into jinwoo/connector-desktop-poll
…ract-sources # Conflicts: # cloud/apps/connector/src/connector-inbox.ts
… contract The cloud picks a machine for a Slack conversation only among those whose hello lists slack, so a newer source never lands on a machine that would refuse it. The turn-bound cancel (turnId on cancel, the turnCancel feature) goes with Stop, which is not in the first release.
…ck thread with the same id Events are narrowed to stored (Slack) conversations once, before both the thread state and the Slack posts read them, and a reply for another source is refused like one for a thread the machine doesn't own.
…s' into jinwoo/connector-desktop-poll # Conflicts: # cloud/apps/connector/src/connector-inbox.test.ts # cloud/packages/connector-contract/src/hello-messages.ts
Walkthrough
Priority: Pre-merge checks:
|
Walkthrough
Priority: Merge Risk:
|
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments: 1
src/main/connector-cloud/connector-turn-events.ts: 1
223-230:Trivial · Performance & Scalability · Quick win Write the turn-end file only when the set of turn ends changes.
onChangeruns on every outbox change. That includes everyprompt,linkedandturn-startedpush, and every accepted ack-free batch. Each call re-serializes and synchronously rewrites the full turn-end list withwriteSecureJsonFileon the main process.During an outage or a 503 backoff, the outbox can hold up to 200 turn ends. Each one can carry an 8 KB
lastAssistantMessage. Every live agent event then does a ~1.6 MB synchronous write on the Electron main thread, even though no turn end changed.Skip the write when the kept turn ends are the same objects as the last stored set.
♻️ Proposed change
- private store(events: readonly ConnectorEvent[]): void { - const turnEnds = events.filter(isTurnEnded) - if (turnEnds.length === 0) { + private store(events: readonly ConnectorEvent[]): void { + const turnEnds = events.filter(isTurnEnded) + const last = this.storedTurnEnds + if (last && last.length === turnEnds.length && turnEnds.every((event, i) => event === last[i])) { + return + } + this.storedTurnEnds = turnEnds + if (turnEnds.length === 0) { rmSync(this.filePath, { force: true }) } else { writeSecureJsonFile(this.filePath, { account: this.account, turnEnds }) } }Declare
private storedTurnEnds: TurnEnded[] | null = nullon the class. The first call still writes, because the field starts asnull.

Review info
-
Run configuration-
- Source mode: Auto
- Repository: Unavailable
- Branch: Unavailable
- File: No configuration file from this repository applied
- Commit: Unavailable
- Layers: Repository UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
15ea262d-b588-4a6c-b211-89bfcc435267
Files selected for processing: 44-
src/main/connector-cloud/connector-cloud-install.tssrc/main/connector-cloud/connector-cloud-request.tssrc/main/connector-cloud/connector-cloud.test.tssrc/main/connector-cloud/connector-cloud.tssrc/main/connector-cloud/connector-deliveries.tssrc/main/connector-cloud/connector-hello.test.tssrc/main/connector-cloud/connector-hello.tssrc/main/connector-cloud/connector-machine.tssrc/main/connector-cloud/connector-origin.tssrc/main/connector-cloud/connector-outbox.test.tssrc/main/connector-cloud/connector-outbox.tssrc/main/connector-cloud/connector-places.test.tssrc/main/connector-cloud/connector-places.tssrc/main/connector-cloud/connector-poll-client.test.tssrc/main/connector-cloud/connector-poll-client.tssrc/main/connector-cloud/connector-snapshot.test.tssrc/main/connector-cloud/connector-snapshot.tssrc/main/connector-cloud/connector-token-mint.test.tssrc/main/connector-cloud/connector-token-mint.tssrc/main/connector-cloud/connector-transport.tssrc/main/connector-cloud/connector-turn-events.test.tssrc/main/connector-cloud/connector-turn-events.tssrc/main/connector-cloud/fake-connector-cloud.test-fixture.tssrc/main/connector-cloud/fake-connector-seam.test-fixture.tssrc/main/external-conversations/external-conversation-delivery-receipts.test.tssrc/main/external-conversations/external-conversation-delivery-receipts.tssrc/main/external-conversations/external-conversation-events.tssrc/main/external-conversations/external-conversation-prompts.test.tssrc/main/external-conversations/external-conversation-seam.tssrc/main/ipc/orca-profile-id-arg.tssrc/main/ipc/orca-profiles.tssrc/main/ipc/register-core-handlers/register-core-handlers.tssrc/main/orca-profiles/profile-cloud-auth-config.test.tssrc/main/orca-profiles/profile-cloud-auth-config.tssrc/main/orca-profiles/profile-cloud-client.test.tssrc/main/orca-profiles/profile-cloud-org-members-client.test.tssrc/main/orca-profiles/profile-cloud-pkce.test.tssrc/main/startup/main-process-connector-startup.tssrc/main/startup/main-process-quit.tssrc/main/startup/main-process-runtime-launch-activation.test.tssrc/main/startup/main-process-runtime-launch.tssrc/main/startup/main-process-state.tssrc/main/startup/main-window-core-services.tssrc/shared/connector-cloud-contract.ts
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 5 remain after this review.
-
| signOutStarted(): void { | ||
| this.signingOut = true | ||
| this.stopClient() | ||
| if (this.events) { | ||
| this.events.clear() | ||
| this.events = null | ||
| } else { | ||
| ConnectorTurnEvents.clearStored(this.options.userDataPath) | ||
| } | ||
| } |
There was a problem hiding this comment.
Isolate outbox cleanup failures so they cannot abort the sign-out.
signOutStarted() runs from onBeforeSignOut, before signOutCurrentOrcaProfile. this.events.clear() and ConnectorTurnEvents.clearStored() do file I/O: rmSync and writeSecureJsonFile in store(). On Windows these can throw EBUSY or EPERM when antivirus or another process holds the file.
If either call throws, three things follow:
- The exception propagates out of the
orcaProfiles:signOutCurrenthandler. - The sign-out never starts.
signingOutstaystrue.onAfterSignOutruns only in thefinallyof thesignOutCurrentOrcaProfilecall, which never executes. The connector then stays stopped until restart.
The outbox file is tagged with its account, and readStored ignores a file that belongs to another account. A failed cleanup therefore does not expose turn ends to another account. Log the failure and continue.
Proposed fix
-
--- "a/src/main/connector-cloud/connector-cloud.ts" +++ "b/src/main/connector-cloud/connector-cloud.ts" @@ -43,16 +43,20 @@ } /** Just before the desktop signs out: stop now, and drop turn ends no other account can report. */ signOutStarted(): void { this.signingOut = true this.stopClient() - if (this.events) { - this.events.clear() - this.events = null - } else { - ConnectorTurnEvents.clearStored(this.options.userDataPath) - } + try { + if (this.events) { + this.events.clear() + } else { + ConnectorTurnEvents.clearStored(this.options.userDataPath) + } + } catch (error) { + console.warn('[connector] could not clear pending turn ends before sign-out', error) + } + this.events = null } /** Quit or relaunch: stop now; pending turn ends stay on disk for the next launch of this account. */ fence(): void {
Committable suggestion
-
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.Suggested changesignOutStarted(): void { this.signingOut = true this.stopClient() if (this.events) { this.events.clear() this.events = null } else { ConnectorTurnEvents.clearStored(this.options.userDataPath) } } signOutStarted(): void { this.signingOut = true this.stopClient() try { if (this.events) { this.events.clear() } else { ConnectorTurnEvents.clearStored(this.options.userDataPath) } } catch (error) { console.warn('[connector] could not clear pending turn ends before sign-out', error) } this.events = null }
| if (connectorAccount(userDataPath) !== account) { | ||
| return SIGNED_OUT | ||
| } | ||
| const active = ensureActiveOrcaProfile(userDataPath) |
There was a problem hiding this comment.
🔎 Supported by static analysis
-
Script executed:
set -o pipefail printf '%s\n' '--- token mint ---' nl -ba src/main/connector-cloud/connector-token-mint.ts printf '%s\n' '--- bound symbols and transport callers ---' rg -n -F --glob '*.ts' -e 'function connectorAccount' -e 'ensureActiveOrcaProfile' -e 'class ConnectorAccountTransport' -e 'ConnectorAccountTransport' src || test "$?" -eq 1 printf '%s\n' '--- transport definitions/callers ---' rg -n -F --glob '*.ts' -e 'class ConnectorAccountTransport' -e 'ensure(' -e '.call(' src/main/connector-cloud src/main | head -200
Repository: stablyai/orca
Length of output: 38126
Script executed:
printf '%s\n' '--- profile index store ---' nl -ba src/main/orca-profiles/profile-index-store.ts | sed -n '1,270p' printf '%s\n' '--- connector transport ---' nl -ba src/main/connector-cloud/connector-transport.ts printf '%s\n' '--- connector cloud construction ---' nl -ba src/main/connector-cloud/connector-cloud.ts | sed -n '55,105p'
Repository: stablyai/orca
Length of output: 16040
Move the profile reads inside the try block.
desktopConnectorTokenMint should return a ConnectorResult instead of rejecting. Both profile reads can perform synchronous filesystem operations and throw before the current try block. Move them inside the block so the existing catch converts those errors into ConnectorFailure.
🛡️ Suggested fix
-
--- "a/src/main/connector-cloud/connector-token-mint.ts" +++ "b/src/main/connector-cloud/connector-token-mint.ts" @@ -35,13 +35,13 @@ account: string, fetchImpl: typeof globalThis.fetch = globalThis.fetch ): ConnectorTokenMint { return async () => { - if (connectorAccount(userDataPath) !== account) { - return SIGNED_OUT - } - const active = ensureActiveOrcaProfile(userDataPath) try { + if (connectorAccount(userDataPath) !== account) { + return SIGNED_OUT + } + const active = ensureActiveOrcaProfile(userDataPath) // The per-install id the host descriptor already keeps; the cloud keys this machine on it. const machineId = await loadOrCreateHostInstallationId(userDataPath) const minted = await runWithFreshOrcaCloudSession( authConfig,
| recorded(key: ConversationKey, deliveryId: string): Promise<Delivery | null> { | ||
| const requestId = JSON.stringify([key.externalId, deliveryId]) | ||
| const fingerprint = callerFingerprint(key.source) | ||
| const running = this.inFlight.get(JSON.stringify([fingerprint, requestId])) | ||
| if (running) { | ||
| return running | ||
| } | ||
| const row = this.settledDb().getMutationReceipt(fingerprint, requestId) | ||
| if (row?.state !== 'completed') { | ||
| return Promise.resolve(null) | ||
| } | ||
| const recorded = RecordedDelivery.safeParse(JSON.parse(row.receipt ?? 'null')) | ||
| return Promise.resolve(recorded.success ? recorded.data : LOST) | ||
| } |
There was a problem hiding this comment.
Return a rejected promise from recorded instead of throwing synchronously.
recorded returns Promise<Delivery | null>, but it can throw synchronously in two places:
this.settledDb(), ifthis.db()orsettlePendingMutationReceiptsthrows.JSON.parse(row.receipt ?? 'null'), if the receipt is corrupt.
ConnectorPollClient.reconcile (src/main/connector-cloud/connector-poll-client.ts Line 251-259) adds the delivery ID to active first. Then it calls this.seam.recorded(...).then(..., onError). A synchronous throw skips onError, so the void this.reconcile(...) promise rejects unhandled. The delivery ID stays in active. Later hellos list the delivery as unsettled again, and reconcile returns early because of the active.has guard. The cloud never receives a done for that delivery until the process restarts.
Make the method async so every failure becomes a rejection. reconcile already maps a rejection to unknown.
🐛 Proposed fix
-
--- "a/src/main/external-conversations/external-conversation-delivery-receipts.ts" +++ "b/src/main/external-conversations/external-conversation-delivery-receipts.ts" @@ -95,20 +95,20 @@ } /** Read-only: what a received delivery came to, or null when nothing was recorded (refusals and answers leave none). */ - recorded(key: ConversationKey, deliveryId: string): Promise<Delivery | null> { + async recorded(key: ConversationKey, deliveryId: string): Promise<Delivery | null> { const requestId = JSON.stringify([key.externalId, deliveryId]) const fingerprint = callerFingerprint(key.source) const running = this.inFlight.get(JSON.stringify([fingerprint, requestId])) if (running) { return running } const row = this.settledDb().getMutationReceipt(fingerprint, requestId) if (row?.state !== 'completed') { - return Promise.resolve(null) + return null } const recorded = RecordedDelivery.safeParse(JSON.parse(row.receipt ?? 'null')) - return Promise.resolve(recorded.success ? recorded.data : LOST) + return recorded.success ? recorded.data : LOST } private settledDb(): DeliveryReceiptDb { const db = this.db()
Committable suggestion
-
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.Suggested changerecorded(key: ConversationKey, deliveryId: string): Promise<Delivery | null> { const requestId = JSON.stringify([key.externalId, deliveryId]) const fingerprint = callerFingerprint(key.source) const running = this.inFlight.get(JSON.stringify([fingerprint, requestId])) if (running) { return running } const row = this.settledDb().getMutationReceipt(fingerprint, requestId) if (row?.state !== 'completed') { return Promise.resolve(null) } const recorded = RecordedDelivery.safeParse(JSON.parse(row.receipt ?? 'null')) return Promise.resolve(recorded.success ? recorded.data : LOST) } async recorded(key: ConversationKey, deliveryId: string): Promise<Delivery | null> { const requestId = JSON.stringify([key.externalId, deliveryId]) const fingerprint = callerFingerprint(key.source) const running = this.inFlight.get(JSON.stringify([fingerprint, requestId])) if (running) { return running } const row = this.settledDb().getMutationReceipt(fingerprint, requestId) if (row?.state !== 'completed') { return null } const recorded = RecordedDelivery.safeParse(JSON.parse(row.receipt ?? 'null')) return recorded.success ? recorded.data : LOST }
| unsettled: z | ||
| .array(z.object({ deliveryId: z.string().min(1), conversation: ConnectorConversation })) | ||
| .optional(), |
There was a problem hiding this comment.
🔎 Supported by static analysis
-
Script executed:
set -eu printf '%s\n' '--- contract diff and current definitions ---' git diff --no-ext-diff 22fd6f505f7cde2a05cf58b5bf342276d4eaad32 d0f89c33f0d28bdb02a61e4b1766068f1623e702 -- src/shared/connector-cloud-contract.ts nl -ba src/shared/connector-cloud-contract.ts | sed -n '1,180p' printf '%s\n' '--- references ---' rg -n -F --glob '*.{ts,tsx}' -e 'requestConnector' -e 'unsettled' -e 'ConnectorPollResponse' -e 'ConnectorConversation' src test tests 2>/dev/null || true printf '%s\n' '--- poll client candidates ---' rg -n -F --glob '*.{ts,tsx}' -e 'class ConnectorPollClient' -e 'cycle(' -e 'safeParse' src/main src/shared 2>/dev/null || true
Repository: stablyai/orca
Length of output: 40843
Script executed:
set -eu printf '%s\n' '--- connector-cloud-request ---' nl -ba src/main/connector-cloud/connector-cloud-request.ts | sed -n '1,150p' printf '%s\n' '--- connector-poll-client cycle and reconciliation ---' nl -ba src/main/connector-cloud/connector-poll-client.ts | sed -n '130,310p' printf '%s\n' '--- delivery parsing ---' nl -ba src/main/connector-cloud/connector-deliveries.ts | sed -n '1,130p' printf '%s\n' '--- poll client tests around unsettled and failures ---' nl -ba src/main/connector-cloud/connector-poll-client.test.ts | sed -n '170,235p' nl -ba src/main/connector-cloud/connector-poll-client.test.ts | sed -n '450,625p'
Repository: stablyai/orca
Length of output: 25004
Script executed:
set -eu printf '%s\n' '--- connector files and source discriminants ---' rg -n -F --glob '*.{ts,tsx,js,json,md}' -e 'connector-cloud' -e 'CONNECTOR_PATHS' -e 'source: '\''slack'\''' -e 'source: "slack"' -e 'source: '\''discord'\''' -e 'source: "discord"' -e 'ConnectorConversation' -e '/v1/connector/poll' . 2>/dev/null || true printf '%s\n' '--- connector directory ---' find src/main/connector-cloud src/shared -maxdepth 3 -type f \( -iname '*connector*' -o -iname '*conversation*' \) -print | sort printf '%s\n' '--- repository top-level and cloud-like paths ---' find . -maxdepth 3 -type d \( -iname '*cloud*' -o -iname '*connector*' \) -print | sort
Repository: stablyai/orca
Length of output: 22453
Script executed:
set -eu printf '%s\n' '--- cloud connector contract ---' nl -ba cloud/packages/connector-contract/src/connector-wire-scalars.ts | sed -n '1,80p' nl -ba cloud/packages/connector-contract/src/delivery-messages.ts | sed -n '1,100p' printf '%s\n' '--- cloud inbox implementation ---' nl -ba cloud/apps/connector/src/connector-inbox.ts | sed -n '1,280p' printf '%s\n' '--- cloud poll route ---' nl -ba cloud/apps/connector/src/machine-routes.ts | sed -n '45,115p' printf '%s\n' '--- relevant cloud tests ---' nl -ba cloud/apps/connector/src/connector-inbox.test.ts | sed -n '145,245p' nl -ba cloud/apps/connector/src/connector-events.test.ts | sed -n '170,205p'
Repository: stablyai/orca
Length of output: 28916
Make unsettled forward-compatible.
The cloud contract accepts slack, discord, and linear conversations. The desktop contract accepts only slack. A non-Slack unsettled entry can therefore make the complete poll response unreadable. Parse unsettled entries independently. A valid delivery ID with an unsupported conversation should receive an unsupported completion acknowledgment; skip only entries that have no usable ID.
♻️ Suggested fix
-
const ConnectorConversation = z.object({ source: z.literal('slack'), externalId: z.string().min(1) }) export type ConnectorConversation = z.infer<typeof ConnectorConversation> +export const ConnectorUnsettled = z.object({ + deliveryId: z.string().min(1), + conversation: ConnectorConversation +}) + ... - unsettled: z - .array(z.object({ deliveryId: z.string().min(1), conversation: ConnectorConversation })) - .optional(), + unsettled: z.array(z.unknown()).optional(),Call
ConnectorUnsettled.safeParsefor each entry inConnectorPollClient.cycle. Send{ outcome: 'unsupported' }for entries with a validdeliveryIdthat fail the per-entry parse.
Source: Coding guidelines
No description provided.