Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(codegen): Adds special cases for AuthStatus to re-enable codegen #5854

Merged
merged 10 commits into from
Oct 10, 2024
38 changes: 38 additions & 0 deletions .github/workflows/agent-bindings.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Please post in #team-cody-clients if you need help getting this CI check to pass.
# Worst-case: feel free to disable this workflow here https://github.com/sourcegraph/cody/actions/workflows/agent-bindings.yml
name: agent-bindings
on:

pull_request:
paths:
- '**.ts'
- '**.tsx'
- '**.js'

jobs:
kotlin:
if: github.repository == 'sourcegraph/cody'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # SECURITY: pin third-party action hashes
id: pnpm-install
with:
version: 8.6.7
run_install: false
- name: Get pnpm store directory
id: pnpm-cache
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
- uses: actions/cache@v3
name: Setup pnpm cache
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- run: pnpm install --frozen-lockfile
- run: pnpm generate-agent-kotlin-bindings
- run: ./agent/scripts/error-if-diff.sh
- run: ./agent/scripts/compile-bindings-if-diff.sh
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,12 @@ interface CodyAgentServer {
fun testing_autocomplete_awaitPendingVisibilityTimeout(params: Null?): CompletableFuture<CompletionItemID?>
@JsonRequest("testing/autocomplete/setCompletionVisibilityDelay")
fun testing_autocomplete_setCompletionVisibilityDelay(params: Testing_Autocomplete_SetCompletionVisibilityDelayParams): CompletableFuture<Null?>
@JsonRequest("testing/autocomplete/providerConfig")
fun testing_autocomplete_providerConfig(params: Null?): CompletableFuture<Testing_Autocomplete_ProviderConfigResult>
@JsonRequest("extensionConfiguration/change")
fun extensionConfiguration_change(params: ExtensionConfiguration): CompletableFuture<AuthStatus?>
fun extensionConfiguration_change(params: ExtensionConfiguration): CompletableFuture<ProtocolAuthStatus?>
@JsonRequest("extensionConfiguration/status")
fun extensionConfiguration_status(params: Null?): CompletableFuture<AuthStatus?>
fun extensionConfiguration_status(params: Null?): CompletableFuture<ProtocolAuthStatus?>
@JsonRequest("extensionConfiguration/getSettingsSchema")
fun extensionConfiguration_getSettingsSchema(params: Null?): CompletableFuture<String>
@JsonRequest("textDocument/change")
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ object Constants {
const val agentic = "agentic"
const val ask = "ask"
const val assistant = "assistant"
const val authenticated = "authenticated"
const val autocomplete = "autocomplete"
const val balanced = "balanced"
const val byok = "byok"
Expand All @@ -41,7 +42,6 @@ object Constants {
const val function = "function"
const val gateway = "gateway"
const val history = "history"
const val `https-example-com` = "https://example.com"
const val human = "human"
const val ignore = "ignore"
const val indentation = "indentation"
Expand Down Expand Up @@ -84,6 +84,7 @@ object Constants {
const val terminal = "terminal"
const val tree = "tree"
const val `tree-sitter` = "tree-sitter"
const val unauthenticated = "unauthenticated"
const val unified = "unified"
const val use = "use"
const val user = "user"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
@file:Suppress("FunctionName", "ClassName", "unused", "EnumEntryName", "UnusedImport")
package com.sourcegraph.cody.agent.protocol_generated;

data class Chat_RestoreParams(
val modelID: String? = null,
val messages: List<SerializedChatMessage>,
val chatID: String,
data class OrganizationsParams(
val name: String,
val id: String,
)

Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,23 @@ import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import java.lang.reflect.Type;

sealed class AuthStatus {
sealed class ProtocolAuthStatus {
companion object {
val deserializer: JsonDeserializer<AuthStatus> =
val deserializer: JsonDeserializer<ProtocolAuthStatus> =
JsonDeserializer { element: JsonElement, _: Type, context: JsonDeserializationContext ->
if (element.getAsJsonObject().get("username") == null) {
context.deserialize<UnauthenticatedAuthStatus>(element, UnauthenticatedAuthStatus::class.java)
} else {
context.deserialize<AuthenticatedAuthStatus>(element, AuthenticatedAuthStatus::class.java)
}
when (element.getAsJsonObject().get("status").getAsString()) {
"authenticated" -> context.deserialize<ProtocolAuthenticatedAuthStatus>(element, ProtocolAuthenticatedAuthStatus::class.java)
"unauthenticated" -> context.deserialize<ProtocolUnauthenticatedAuthStatus>(element, ProtocolUnauthenticatedAuthStatus::class.java)
else -> throw Exception("Unknown discriminator ${element}")
}
}
}
}

data class UnauthenticatedAuthStatus(
val endpoint: String,
data class ProtocolAuthenticatedAuthStatus(
val status: StatusEnum, // Oneof: authenticated
val authenticated: Boolean,
val showNetworkError: Boolean? = null,
val showInvalidAccessTokenError: Boolean? = null,
val pendingValidation: Boolean,
) : AuthStatus() {
}

data class AuthenticatedAuthStatus(
val endpoint: String,
val authenticated: Boolean,
val username: String,
val isFireworksTracingEnabled: Boolean? = null,
val hasVerifiedEmail: Boolean? = null,
Expand All @@ -41,6 +33,25 @@ data class AuthenticatedAuthStatus(
val displayName: String? = null,
val avatarURL: String? = null,
val pendingValidation: Boolean,
) : AuthStatus() {
val organizations: List<OrganizationsParams>? = null,
) : ProtocolAuthStatus() {

enum class StatusEnum {
@SerializedName("authenticated") Authenticated,
}
}

data class ProtocolUnauthenticatedAuthStatus(
val status: StatusEnum, // Oneof: unauthenticated
val authenticated: Boolean,
val endpoint: String,
val showNetworkError: Boolean? = null,
val showInvalidAccessTokenError: Boolean? = null,
val pendingValidation: Boolean,
) : ProtocolAuthStatus() {

enum class StatusEnum {
@SerializedName("unauthenticated") Unauthenticated,
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package com.sourcegraph.cody.agent.protocol_generated;

object ProtocolTypeAdapters {
fun register(gson: com.google.gson.GsonBuilder) {
gson.registerTypeAdapter(AuthStatus::class.java, AuthStatus.deserializer)
gson.registerTypeAdapter(ContextItem::class.java, ContextItem.deserializer)
gson.registerTypeAdapter(CustomCommandResult::class.java, CustomCommandResult.deserializer)
gson.registerTypeAdapter(ProtocolAuthStatus::class.java, ProtocolAuthStatus.deserializer)
gson.registerTypeAdapter(TextEdit::class.java, TextEdit.deserializer)
gson.registerTypeAdapter(WorkspaceEditOperation::class.java, WorkspaceEditOperation.deserializer)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,18 @@ data class SerializedChatMessage(
val speaker: SpeakerEnum, // Oneof: human, assistant, system
val text: String? = null,
val model: String? = null,
val intent: IntentEnum? = null, // Oneof: search, chat
) {

enum class SpeakerEnum {
@SerializedName("human") Human,
@SerializedName("assistant") Assistant,
@SerializedName("system") System,
}

enum class IntentEnum {
@SerializedName("search") Search,
@SerializedName("chat") Chat,
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ package com.sourcegraph.cody.agent.protocol_generated;
data class ServerInfo(
val name: String,
val authenticated: Boolean? = null,
val authStatus: AuthStatus? = null,
val authStatus: ProtocolAuthStatus? = null,
)

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@file:Suppress("FunctionName", "ClassName", "unused", "EnumEntryName", "UnusedImport")
package com.sourcegraph.cody.agent.protocol_generated;

data class Testing_Autocomplete_ProviderConfigResult(
val id: String,
val legacyModel: String,
val configSource: String,
)

10 changes: 5 additions & 5 deletions agent/scripts/generate-agent-kotlin-bindings.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
set -eux
INDEXER_DIR=${SCIP_TYPESCRIPT_DIR:-../scip-typescript-cody-bindings}

if [ ! -d $INDEXER_DIR ]; then
git clone https://github.com/sourcegraph/scip-typescript.git $INDEXER_DIR
if [ ! -d "$INDEXER_DIR" ]; then
git clone https://github.com/sourcegraph/scip-typescript.git "$INDEXER_DIR"
fi

pushd $INDEXER_DIR
pushd "$INDEXER_DIR"
git fetch origin
git checkout olafurpg/signatures-rebase1
git pull origin olafurpg/signatures-rebase1
Expand All @@ -16,5 +16,5 @@ popd
pnpm install --prefer-offline
pnpm build
# TODO: invoke @sourcegraph/scip-typescript npm package instead
pnpm exec ts-node $INDEXER_DIR/src/main.ts index --emit-signatures --emit-external-symbols
pnpm exec ts-node agent/src/cli/scip-codegen/command.ts --output agent/bindings/kotlin/lib/src/main/kotlin/com/sourcegraph/cody/agent/protocol_generated
pnpm exec ts-node "$INDEXER_DIR"/src/main.ts index --emit-signatures --emit-external-symbols
pnpm exec ts-node agent/src/cli/scip-codegen/command.ts --output agent/bindings/kotlin/lib/src/main/kotlin/com/sourcegraph/cody/agent/protocol_generated
2 changes: 1 addition & 1 deletion agent/scripts/test-agent-binary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ async function main() {
customHeaders: {},
})

if (!valid?.authenticated) {
if (valid?.status !== 'authenticated') {
throw new Error('Failed to authenticate')
}

Expand Down
13 changes: 8 additions & 5 deletions agent/src/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
ModelUsage,
currentAuthStatus,
currentAuthStatusAuthed,
currentAuthStatusOrNotReadyYet,
firstResultFromOperation,
telemetryRecorder,
waitUntilComplete,
Expand Down Expand Up @@ -78,6 +77,10 @@ import { AgentWorkspaceDocuments } from './AgentWorkspaceDocuments'
import { registerNativeWebviewHandlers, resolveWebviewView } from './NativeWebview'
import type { PollyRequestError } from './cli/command-jsonrpc-stdio'
import { codyPaths } from './codyPaths'
import {
currentProtocolAuthStatus,
currentProtocolAuthStatusOrNotReadyYet,
} from './currentProtocolAuthStatus'
import { AgentGlobalState } from './global-state/AgentGlobalState'
import {
MessageHandler,
Expand Down Expand Up @@ -473,7 +476,7 @@ export class Agent extends MessageHandler implements ExtensionClient {
this.registerWebviewHandlers()
}

const authStatus = currentAuthStatusOrNotReadyYet()
const authStatus = currentProtocolAuthStatusOrNotReadyYet()
return {
name: 'cody-agent',
authenticated: authStatus?.authenticated ?? false,
Expand Down Expand Up @@ -571,12 +574,12 @@ export class Agent extends MessageHandler implements ExtensionClient {
this.registerRequest('extensionConfiguration/change', async config => {
this.authenticationPromise = this.handleConfigChanges(config)
await this.authenticationPromise
return currentAuthStatus()
return currentProtocolAuthStatus()
})

this.registerRequest('extensionConfiguration/status', async () => {
await this.authenticationPromise
return currentAuthStatus()
return currentProtocolAuthStatus()
})

this.registerRequest('extensionConfiguration/getSettingsSchema', async () => {
Expand Down Expand Up @@ -994,7 +997,7 @@ export class Agent extends MessageHandler implements ExtensionClient {

this.registerAuthenticatedRequest('testing/autocomplete/providerConfig', async () => {
const provider = await vscode_shim.completionProvider()
return provider.config
return provider.config.provider
})

this.registerAuthenticatedRequest('graphql/getRepoIds', async ({ names, first }) => {
Expand Down
19 changes: 15 additions & 4 deletions agent/src/cli/scip-codegen/BaseCodegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,18 @@ export interface ProtocolSymbol {
kind: ProtocolMethodKind
}

export type ConstantType = string | boolean | number
export type ConstantTypeType = 'string' | 'boolean' | 'number'

export function typeOfUnion(union: DiscriminatedUnion): ConstantTypeType {
if (union.members.length === 0) {
throw new TypeError(`Union ${JSON.stringify(union, null, 2)} has no members`)
}
return typeof union.members[0].value as ConstantTypeType
}

export interface DiscriminatedUnionMember {
value: string
value: ConstantType
type: scip.Type
}
export interface DiscriminatedUnion {
Expand Down Expand Up @@ -212,6 +222,9 @@ export abstract class BaseCodegen {
for (const sibling of this.siblingDiscriminatedUnionProperties.get(info.symbol) ?? []) {
visitInfo(this.symtab.info(sibling))
}
if (!info.has_signature) {
return
}
if (info.signature.has_value_signature) {
visitType(info.signature.value_signature.tpe)
return
Expand Down Expand Up @@ -290,8 +303,6 @@ export abstract class BaseCodegen {
// literals. If you're hitting on this error with types like string
// literals it means you are not guarding against it higher up in the
// call stack.
// throw new TypeError(`type has no properties: ${this.debug(type)}`)
this.reporter.error('', `type has no properties: ${this.debug(type)}`)
return []
throw new TypeError(`type has no properties: ${this.debug(type)}`)
}
}
Loading
Loading