From 710e40870962f624745758af3e643f59a9e3b766 Mon Sep 17 00:00:00 2001 From: "opencode-agent[bot]" Date: Thu, 11 Jun 2026 06:32:44 +0000 Subject: [PATCH] chore: generate --- .../20260611035744_credential/snapshot.json | 187 +- packages/core/src/catalog.ts | 4 +- packages/core/src/connector.ts | 16 +- packages/core/src/credential.ts | 44 +- packages/core/src/credential/sql.ts | 4 +- .../migration/20260611035744_credential.ts | 4 +- .../plugin/provider/cloudflare-workers-ai.ts | 5 +- .../core/src/plugin/provider/openai-auth.ts | 3 +- packages/core/test/connector.test.ts | 10 +- packages/core/test/credential.test.ts | 1 - packages/core/test/plugin/models-dev.test.ts | 9 +- .../provider-cloudflare-workers-ai.test.ts | 10 +- packages/sdk/openapi.json | 1606 ++++++++++++++--- packages/server/src/handlers/connector.ts | 23 +- packages/tui/src/context/data.tsx | 5 +- packages/tui/test/fixture/tui-sdk.ts | 6 +- 16 files changed, 1523 insertions(+), 414 deletions(-) diff --git a/packages/core/migration/20260611035744_credential/snapshot.json b/packages/core/migration/20260611035744_credential/snapshot.json index 13cc247abf..6a18732d95 100644 --- a/packages/core/migration/20260611035744_credential/snapshot.json +++ b/packages/core/migration/20260611035744_credential/snapshot.json @@ -2,9 +2,7 @@ "version": "7", "dialect": "sqlite", "id": "f25f9126-c7dc-4882-9ff4-af27e11d2da1", - "prevIds": [ - "d1bfa125-b81e-4c61-9b6e-e74abf6e488f" - ], + "prevIds": ["d1bfa125-b81e-4c61-9b6e-e74abf6e488f"], "ddl": [ { "name": "workspace", @@ -1493,13 +1491,9 @@ "table": "session_share" }, { - "columns": [ - "project_id" - ], + "columns": ["project_id"], "tableTo": "project", - "columnsTo": [ - "id" - ], + "columnsTo": ["id"], "onUpdate": "NO ACTION", "onDelete": "CASCADE", "nameExplicit": false, @@ -1508,13 +1502,9 @@ "table": "workspace" }, { - "columns": [ - "active_account_id" - ], + "columns": ["active_account_id"], "tableTo": "account", - "columnsTo": [ - "id" - ], + "columnsTo": ["id"], "onUpdate": "NO ACTION", "onDelete": "SET NULL", "nameExplicit": false, @@ -1523,13 +1513,9 @@ "table": "account_state" }, { - "columns": [ - "aggregate_id" - ], + "columns": ["aggregate_id"], "tableTo": "event_sequence", - "columnsTo": [ - "aggregate_id" - ], + "columnsTo": ["aggregate_id"], "onUpdate": "NO ACTION", "onDelete": "CASCADE", "nameExplicit": false, @@ -1538,13 +1524,9 @@ "table": "event" }, { - "columns": [ - "project_id" - ], + "columns": ["project_id"], "tableTo": "project", - "columnsTo": [ - "id" - ], + "columnsTo": ["id"], "onUpdate": "NO ACTION", "onDelete": "CASCADE", "nameExplicit": false, @@ -1553,13 +1535,9 @@ "table": "permission" }, { - "columns": [ - "project_id" - ], + "columns": ["project_id"], "tableTo": "project", - "columnsTo": [ - "id" - ], + "columnsTo": ["id"], "onUpdate": "NO ACTION", "onDelete": "CASCADE", "nameExplicit": false, @@ -1568,13 +1546,9 @@ "table": "project_directory" }, { - "columns": [ - "session_id" - ], + "columns": ["session_id"], "tableTo": "session", - "columnsTo": [ - "id" - ], + "columnsTo": ["id"], "onUpdate": "NO ACTION", "onDelete": "CASCADE", "nameExplicit": false, @@ -1583,13 +1557,9 @@ "table": "message" }, { - "columns": [ - "message_id" - ], + "columns": ["message_id"], "tableTo": "message", - "columnsTo": [ - "id" - ], + "columnsTo": ["id"], "onUpdate": "NO ACTION", "onDelete": "CASCADE", "nameExplicit": false, @@ -1598,13 +1568,9 @@ "table": "part" }, { - "columns": [ - "session_id" - ], + "columns": ["session_id"], "tableTo": "session", - "columnsTo": [ - "id" - ], + "columnsTo": ["id"], "onUpdate": "NO ACTION", "onDelete": "CASCADE", "nameExplicit": false, @@ -1613,13 +1579,9 @@ "table": "session_context_epoch" }, { - "columns": [ - "session_id" - ], + "columns": ["session_id"], "tableTo": "session", - "columnsTo": [ - "id" - ], + "columnsTo": ["id"], "onUpdate": "NO ACTION", "onDelete": "CASCADE", "nameExplicit": false, @@ -1628,13 +1590,9 @@ "table": "session_input" }, { - "columns": [ - "session_id" - ], + "columns": ["session_id"], "tableTo": "session", - "columnsTo": [ - "id" - ], + "columnsTo": ["id"], "onUpdate": "NO ACTION", "onDelete": "CASCADE", "nameExplicit": false, @@ -1643,13 +1601,9 @@ "table": "session_message" }, { - "columns": [ - "project_id" - ], + "columns": ["project_id"], "tableTo": "project", - "columnsTo": [ - "id" - ], + "columnsTo": ["id"], "onUpdate": "NO ACTION", "onDelete": "CASCADE", "nameExplicit": false, @@ -1658,13 +1612,9 @@ "table": "session" }, { - "columns": [ - "session_id" - ], + "columns": ["session_id"], "tableTo": "session", - "columnsTo": [ - "id" - ], + "columnsTo": ["id"], "onUpdate": "NO ACTION", "onDelete": "CASCADE", "nameExplicit": false, @@ -1673,13 +1623,9 @@ "table": "todo" }, { - "columns": [ - "session_id" - ], + "columns": ["session_id"], "tableTo": "session", - "columnsTo": [ - "id" - ], + "columnsTo": ["id"], "onUpdate": "NO ACTION", "onDelete": "CASCADE", "nameExplicit": false, @@ -1688,174 +1634,133 @@ "table": "session_share" }, { - "columns": [ - "email", - "url" - ], + "columns": ["email", "url"], "nameExplicit": false, "name": "control_account_pk", "entityType": "pks", "table": "control_account" }, { - "columns": [ - "project_id", - "directory" - ], + "columns": ["project_id", "directory"], "nameExplicit": false, "name": "project_directory_pk", "entityType": "pks", "table": "project_directory" }, { - "columns": [ - "session_id", - "position" - ], + "columns": ["session_id", "position"], "nameExplicit": false, "name": "todo_pk", "entityType": "pks", "table": "todo" }, { - "columns": [ - "id" - ], + "columns": ["id"], "nameExplicit": false, "name": "workspace_pk", "table": "workspace", "entityType": "pks" }, { - "columns": [ - "name" - ], + "columns": ["name"], "nameExplicit": false, "name": "data_migration_pk", "table": "data_migration", "entityType": "pks" }, { - "columns": [ - "id" - ], + "columns": ["id"], "nameExplicit": false, "name": "account_state_pk", "table": "account_state", "entityType": "pks" }, { - "columns": [ - "id" - ], + "columns": ["id"], "nameExplicit": false, "name": "account_pk", "table": "account", "entityType": "pks" }, { - "columns": [ - "id" - ], + "columns": ["id"], "nameExplicit": false, "name": "credential_pk", "table": "credential", "entityType": "pks" }, { - "columns": [ - "aggregate_id" - ], + "columns": ["aggregate_id"], "nameExplicit": false, "name": "event_sequence_pk", "table": "event_sequence", "entityType": "pks" }, { - "columns": [ - "id" - ], + "columns": ["id"], "nameExplicit": false, "name": "event_pk", "table": "event", "entityType": "pks" }, { - "columns": [ - "id" - ], + "columns": ["id"], "nameExplicit": false, "name": "permission_pk", "table": "permission", "entityType": "pks" }, { - "columns": [ - "id" - ], + "columns": ["id"], "nameExplicit": false, "name": "project_pk", "table": "project", "entityType": "pks" }, { - "columns": [ - "id" - ], + "columns": ["id"], "nameExplicit": false, "name": "message_pk", "table": "message", "entityType": "pks" }, { - "columns": [ - "id" - ], + "columns": ["id"], "nameExplicit": false, "name": "part_pk", "table": "part", "entityType": "pks" }, { - "columns": [ - "session_id" - ], + "columns": ["session_id"], "nameExplicit": false, "name": "session_context_epoch_pk", "table": "session_context_epoch", "entityType": "pks" }, { - "columns": [ - "id" - ], + "columns": ["id"], "nameExplicit": false, "name": "session_input_pk", "table": "session_input", "entityType": "pks" }, { - "columns": [ - "id" - ], + "columns": ["id"], "nameExplicit": false, "name": "session_message_pk", "table": "session_message", "entityType": "pks" }, { - "columns": [ - "id" - ], + "columns": ["id"], "nameExplicit": false, "name": "session_pk", "table": "session", "entityType": "pks" }, { - "columns": [ - "session_id" - ], + "columns": ["session_id"], "nameExplicit": false, "name": "session_share_pk", "table": "session_share", diff --git a/packages/core/src/catalog.ts b/packages/core/src/catalog.ts index 6d41dd2a65..7df56e75ba 100644 --- a/packages/core/src/catalog.ts +++ b/packages/core/src/catalog.ts @@ -236,7 +236,9 @@ export const layer = Layer.effect( all: Effect.fn("CatalogV2.provider.all")(function* () { const credentials = yield* active() - return Array.fromIterable(state.get().providers.values()).map((record) => project(record.provider, credentials)) + return Array.fromIterable(state.get().providers.values()).map((record) => + project(record.provider, credentials), + ) }), available: Effect.fn("CatalogV2.provider.available")(function* () { diff --git a/packages/core/src/connector.ts b/packages/core/src/connector.ts index f17dbbd339..141c374f12 100644 --- a/packages/core/src/connector.ts +++ b/packages/core/src/connector.ts @@ -213,10 +213,7 @@ export interface Interface { readonly inputs: Inputs /** User-facing label for the credential created on completion. */ readonly label?: string - }) => Effect.Effect< - Attempt, - AuthorizationError - > + }) => Effect.Effect /** Returns the current state of an OAuth attempt. */ readonly status: (attemptID: AttemptID) => Effect.Effect /** Completes the attempt and stores its credential. */ @@ -273,7 +270,8 @@ export const locationLayer = Layer.effect( list: () => Array.from(draft.connectors.values(), (entry) => entry.connector) as Info[], get: (id) => draft.connectors.get(id)?.connector as Info | undefined, update: (id, update) => { - const current = draft.connectors.get(id) ?? + const current = + draft.connectors.get(id) ?? castDraft({ connector: new Info({ id, name: id, methods: [] }), implementations: new Map() }) if (!draft.connectors.has(id)) draft.connectors.set(id, current) update(current.connector) @@ -282,7 +280,8 @@ export const locationLayer = Layer.effect( remove: (id) => draft.connectors.delete(id), method: { update: (implementation) => { - const current = draft.connectors.get(implementation.connectorID) ?? + const current = + draft.connectors.get(implementation.connectorID) ?? castDraft({ connector: new Info({ id: implementation.connectorID, name: implementation.connectorID, methods: [] }), implementations: new Map(), @@ -318,10 +317,7 @@ export const locationLayer = Layer.effect( return error instanceof Error ? error.message : String(error) } - const settle = Effect.fnUntraced(function* ( - attemptID: AttemptID, - exit: Exit.Exit, - ) { + const settle = Effect.fnUntraced(function* (attemptID: AttemptID, exit: Exit.Exit) { const now = yield* Clock.currentTimeMillis const result = yield* SynchronizedRef.modify(attempts, (current) => { const attempt = current.get(attemptID) diff --git a/packages/core/src/credential.ts b/packages/core/src/credential.ts index 8c39756746..1a64284202 100644 --- a/packages/core/src/credential.ts +++ b/packages/core/src/credential.ts @@ -118,7 +118,11 @@ export const legacyImportLayer = Layer.effectDiscard( const id = ID.create() const connector = ConnectorSchema.ID.make(connectorID.replace(/\/+$/, "")) const methodID = ConnectorSchema.MethodID.make( - credential.type === "api" ? "api-key" : connector === ConnectorSchema.ID.make("openai") ? "chatgpt-browser" : "oauth", + credential.type === "api" + ? "api-key" + : connector === ConnectorSchema.ID.make("openai") + ? "chatgpt-browser" + : "oauth", ) const next: Value = credential.type === "api" @@ -206,9 +210,12 @@ export const layer = Layer.effect( return row ? info(row) : undefined }), all: Effect.fn("Credential.all")(function* () { - return (yield* db.select().from(CredentialTable).orderBy(asc(CredentialTable.time_created)).all().pipe(Effect.orDie)).map( - info, - ) + return (yield* db + .select() + .from(CredentialTable) + .orderBy(asc(CredentialTable.time_created)) + .all() + .pipe(Effect.orDie)).map(info) }), active: Effect.fn("Credential.active")(function* (connectorID) { const row = yield* db @@ -220,19 +227,22 @@ export const layer = Layer.effect( return row ? info(row) : undefined }), activeAll: Effect.fn("Credential.activeAll")(function* () { - const rows = yield* db.select().from(CredentialTable).where(eq(CredentialTable.active, true)).all().pipe(Effect.orDie) + const rows = yield* db + .select() + .from(CredentialTable) + .where(eq(CredentialTable.active, true)) + .all() + .pipe(Effect.orDie) return new Map(rows.map((row) => [row.connector_id, info(row)])) }), forConnector: Effect.fn("Credential.forConnector")(function* (connectorID) { - return ( - yield* db - .select() - .from(CredentialTable) - .where(eq(CredentialTable.connector_id, connectorID)) - .orderBy(asc(CredentialTable.time_created)) - .all() - .pipe(Effect.orDie) - ).map(info) + return (yield* db + .select() + .from(CredentialTable) + .where(eq(CredentialTable.connector_id, connectorID)) + .orderBy(asc(CredentialTable.time_created)) + .all() + .pipe(Effect.orDie)).map(info) }), create: Effect.fn("Credential.create")(function* (input) { const credential = new Info({ @@ -298,7 +308,11 @@ export const layer = Layer.effect( .orderBy(asc(CredentialTable.time_created)) .get() if (replacement) { - yield* tx.update(CredentialTable).set({ active: true }).where(eq(CredentialTable.id, replacement.id)).run() + yield* tx + .update(CredentialTable) + .set({ active: true }) + .where(eq(CredentialTable.id, replacement.id)) + .run() } return { credential: info(row), diff --git a/packages/core/src/credential/sql.ts b/packages/core/src/credential/sql.ts index c67ff67b1b..ff2c50fb08 100644 --- a/packages/core/src/credential/sql.ts +++ b/packages/core/src/credential/sql.ts @@ -16,6 +16,8 @@ export const CredentialTable = sqliteTable( ...Timestamps, }, (table) => [ - uniqueIndex("credential_connector_active_idx").on(table.connector_id).where(sql`${table.active} = 1`), + uniqueIndex("credential_connector_active_idx") + .on(table.connector_id) + .where(sql`${table.active} = 1`), ], ) diff --git a/packages/core/src/database/migration/20260611035744_credential.ts b/packages/core/src/database/migration/20260611035744_credential.ts index 71660cb463..80df43cdf5 100644 --- a/packages/core/src/database/migration/20260611035744_credential.ts +++ b/packages/core/src/database/migration/20260611035744_credential.ts @@ -17,7 +17,9 @@ export default { \`time_updated\` integer NOT NULL ); `) - yield* tx.run(`CREATE UNIQUE INDEX \`credential_connector_active_idx\` ON \`credential\` (\`connector_id\`) WHERE "credential"."active" = 1;`) + yield* tx.run( + `CREATE UNIQUE INDEX \`credential_connector_active_idx\` ON \`credential\` (\`connector_id\`) WHERE "credential"."active" = 1;`, + ) }) }, } satisfies DatabaseMigration.Migration diff --git a/packages/core/src/plugin/provider/cloudflare-workers-ai.ts b/packages/core/src/plugin/provider/cloudflare-workers-ai.ts index 9bcd2684b1..10f3f5200a 100644 --- a/packages/core/src/plugin/provider/cloudflare-workers-ai.ts +++ b/packages/core/src/plugin/provider/cloudflare-workers-ai.ts @@ -28,7 +28,10 @@ export const CloudflareWorkersAIPlugin = PluginV2.define({ if (!hasWorkersEndpoint(evt.model.api) && !accountId) return const mod = yield* Effect.promise(() => import("@ai-sdk/openai-compatible")) evt.sdk = mod.createOpenAICompatible( - sdkOptions({ ...evt.options, baseURL: evt.options.baseURL ?? (accountId ? workersEndpoint(accountId) : undefined) }) as any, + sdkOptions({ + ...evt.options, + baseURL: evt.options.baseURL ?? (accountId ? workersEndpoint(accountId) : undefined), + }) as any, ) }), "aisdk.language": Effect.fn(function* (evt) { diff --git a/packages/core/src/plugin/provider/openai-auth.ts b/packages/core/src/plugin/provider/openai-auth.ts index ef43174aaf..c760664bc1 100644 --- a/packages/core/src/plugin/provider/openai-auth.ts +++ b/packages/core/src/plugin/provider/openai-auth.ts @@ -246,6 +246,7 @@ function claim(token: string) { } } -const successPage = "OpenCode

Authorization successful

You can close this window.

" +const successPage = + "OpenCode

Authorization successful

You can close this window.

" const errorPage = (message: string) => `OpenCode

Authorization failed

${message.replace(/[&<>"']/g, "")}

` diff --git a/packages/core/test/connector.test.ts b/packages/core/test/connector.test.ts index 205de295f6..83c365e22a 100644 --- a/packages/core/test/connector.test.ts +++ b/packages/core/test/connector.test.ts @@ -47,9 +47,7 @@ describe("Connector", () => { yield* connectors .update((editor) => editor.update(openai, (connector) => (connector.name = "OpenAI"))) .pipe(Scope.provide(scope)) - expect(yield* connectors.get(openai)).toEqual( - new Connector.Info({ id: openai, name: "OpenAI", methods: [] }), - ) + expect(yield* connectors.get(openai)).toEqual(new Connector.Info({ id: openai, name: "OpenAI", methods: [] })) yield* Scope.close(scope, Exit.void) expect(yield* connectors.get(openai)).toBeUndefined() @@ -313,9 +311,9 @@ describe("Connector", () => { ) const attempt = yield* connectors.connect.oauth.begin({ connectorID, methodID, inputs: {} }) - expect(yield* connectors.connect.oauth.complete({ attemptID: attempt.attemptID }).pipe(Effect.flip)).toBeInstanceOf( - Connector.CodeRequiredError, - ) + expect( + yield* connectors.connect.oauth.complete({ attemptID: attempt.attemptID }).pipe(Effect.flip), + ).toBeInstanceOf(Connector.CodeRequiredError) expect(closed).toBe(false) yield* connectors.connect.oauth.cancel(attempt.attemptID) expect(closed).toBe(true) diff --git a/packages/core/test/credential.test.ts b/packages/core/test/credential.test.ts index 5edac2a0de..0227ca318b 100644 --- a/packages/core/test/credential.test.ts +++ b/packages/core/test/credential.test.ts @@ -203,5 +203,4 @@ describe("Credential", () => { ), ), ) - }) diff --git a/packages/core/test/plugin/models-dev.test.ts b/packages/core/test/plugin/models-dev.test.ts index 5bf290c694..7de776c98d 100644 --- a/packages/core/test/plugin/models-dev.test.ts +++ b/packages/core/test/plugin/models-dev.test.ts @@ -23,13 +23,8 @@ const locationLayer = Layer.succeed( ) const plugins = PluginV2.layer.pipe(Layer.provide(events)) const policy = Policy.layer.pipe(Layer.provide(locationLayer)) -const credentials = Credential.layer.pipe( - Layer.provide(Database.layerFromPath(":memory:")), - Layer.provide(events), -) -const catalog = Catalog.layer.pipe( - Layer.provide(Layer.mergeAll(events, locationLayer, plugins, policy, credentials)), -) +const credentials = Credential.layer.pipe(Layer.provide(Database.layerFromPath(":memory:")), Layer.provide(events)) +const catalog = Catalog.layer.pipe(Layer.provide(Layer.mergeAll(events, locationLayer, plugins, policy, credentials))) const connectors = Connector.locationLayer.pipe(Layer.provide(credentials), Layer.provide(events)) const layer = Layer.mergeAll(catalog, connectors, credentials, events, locationLayer, plugins) const it = testEffect(layer) diff --git a/packages/core/test/plugin/provider-cloudflare-workers-ai.test.ts b/packages/core/test/plugin/provider-cloudflare-workers-ai.test.ts index 6195a2cc16..235f76d039 100644 --- a/packages/core/test/plugin/provider-cloudflare-workers-ai.test.ts +++ b/packages/core/test/plugin/provider-cloudflare-workers-ai.test.ts @@ -152,10 +152,12 @@ describe("CloudflareWorkersAIPlugin", () => { provider.api = { type: "aisdk", package: "test-provider" } }), ) - expect((yield* catalog.provider.get(ProviderV2.ID.make("cloudflare-workers-ai"))).request.body).toMatchObject({ - apiKey: "account-key", - accountId: "account-acct", - }) + expect((yield* catalog.provider.get(ProviderV2.ID.make("cloudflare-workers-ai"))).request.body).toMatchObject( + { + apiKey: "account-key", + accountId: "account-acct", + }, + ) }), ), ) diff --git a/packages/sdk/openapi.json b/packages/sdk/openapi.json index b4d425e24e..bf8b8e131a 100644 --- a/packages/sdk/openapi.json +++ b/packages/sdk/openapi.json @@ -11184,6 +11184,902 @@ ] } }, + "/api/connector": { + "get": { + "tags": ["connectors"], + "operationId": "v2.connector.list", + "parameters": [ + { + "name": "location", + "in": "query", + "schema": { + "type": "object", + "properties": { + "directory": { + "type": "string" + }, + "workspace": { + "type": "string" + } + }, + "additionalProperties": false + }, + "required": false, + "style": "deepObject", + "explode": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "location": { + "$ref": "#/components/schemas/LocationInfo" + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ConnectorInfo" + } + } + }, + "required": ["location", "data"], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "InvalidRequestError", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InvalidRequestError" + } + } + } + }, + "401": { + "description": "UnauthorizedError", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnauthorizedError" + } + } + } + } + }, + "description": "Retrieve available connectors and their authentication methods.", + "summary": "List connectors", + "x-codeSamples": [ + { + "lang": "js", + "source": "import { createOpencodeClient } from \"@opencode-ai/sdk\n\nconst client = createOpencodeClient()\nawait client.v2.connector.list({\n ...\n})" + } + ] + } + }, + "/api/connector/{connectorID}": { + "get": { + "tags": ["connectors"], + "operationId": "v2.connector.get", + "parameters": [ + { + "name": "connectorID", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "location", + "in": "query", + "schema": { + "type": "object", + "properties": { + "directory": { + "type": "string" + }, + "workspace": { + "type": "string" + } + }, + "additionalProperties": false + }, + "required": false, + "style": "deepObject", + "explode": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "location": { + "$ref": "#/components/schemas/LocationInfo" + }, + "data": { + "$ref": "#/components/schemas/ConnectorInfo" + } + }, + "required": ["location", "data"], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "InvalidRequestError", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InvalidRequestError" + } + } + } + }, + "401": { + "description": "UnauthorizedError", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnauthorizedError" + } + } + } + } + }, + "description": "Retrieve one connector and its authentication methods.", + "summary": "Get connector", + "x-codeSamples": [ + { + "lang": "js", + "source": "import { createOpencodeClient } from \"@opencode-ai/sdk\n\nconst client = createOpencodeClient()\nawait client.v2.connector.get({\n ...\n})" + } + ] + } + }, + "/api/connector/{connectorID}/connect/key": { + "post": { + "tags": ["connectors"], + "operationId": "v2.connector.connect.key", + "parameters": [ + { + "name": "connectorID", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "location", + "in": "query", + "schema": { + "type": "object", + "properties": { + "directory": { + "type": "string" + }, + "workspace": { + "type": "string" + } + }, + "additionalProperties": false + }, + "required": false, + "style": "deepObject", + "explode": true + } + ], + "security": [], + "responses": { + "204": { + "description": "" + }, + "400": { + "description": "InvalidRequestError", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/InvalidRequestError" + }, + { + "$ref": "#/components/schemas/InvalidRequestError" + } + ] + } + } + } + }, + "401": { + "description": "UnauthorizedError", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnauthorizedError" + } + } + } + } + }, + "description": "Run a key authentication method and store the resulting credential.", + "summary": "Connect with key", + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "methodID": { + "type": "string" + }, + "key": { + "type": "string" + }, + "inputs": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "label": { + "type": "string" + } + }, + "required": ["methodID", "key", "inputs"], + "additionalProperties": false + } + } + }, + "required": true + }, + "x-codeSamples": [ + { + "lang": "js", + "source": "import { createOpencodeClient } from \"@opencode-ai/sdk\n\nconst client = createOpencodeClient()\nawait client.v2.connector.connect.key({\n ...\n})" + } + ] + } + }, + "/api/connector/{connectorID}/connect/oauth": { + "post": { + "tags": ["connectors"], + "operationId": "v2.connector.connect.oauth.begin", + "parameters": [ + { + "name": "connectorID", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "location", + "in": "query", + "schema": { + "type": "object", + "properties": { + "directory": { + "type": "string" + }, + "workspace": { + "type": "string" + } + }, + "additionalProperties": false + }, + "required": false, + "style": "deepObject", + "explode": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "location": { + "$ref": "#/components/schemas/LocationInfo" + }, + "data": { + "$ref": "#/components/schemas/ConnectorAttempt" + } + }, + "required": ["location", "data"], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "InvalidRequestError", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/InvalidRequestError" + }, + { + "$ref": "#/components/schemas/InvalidRequestError" + } + ] + } + } + } + }, + "401": { + "description": "UnauthorizedError", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnauthorizedError" + } + } + } + } + }, + "description": "Start an OAuth attempt and return the authorization details.", + "summary": "Begin OAuth connection", + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "methodID": { + "type": "string" + }, + "inputs": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "label": { + "type": "string" + } + }, + "required": ["methodID", "inputs"], + "additionalProperties": false + } + } + }, + "required": true + }, + "x-codeSamples": [ + { + "lang": "js", + "source": "import { createOpencodeClient } from \"@opencode-ai/sdk\n\nconst client = createOpencodeClient()\nawait client.v2.connector.connect.oauth.begin({\n ...\n})" + } + ] + } + }, + "/api/connector/oauth/{attemptID}": { + "get": { + "tags": ["connectors"], + "operationId": "v2.connector.connect.oauth.status", + "parameters": [ + { + "name": "attemptID", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "location", + "in": "query", + "schema": { + "type": "object", + "properties": { + "directory": { + "type": "string" + }, + "workspace": { + "type": "string" + } + }, + "additionalProperties": false + }, + "required": false, + "style": "deepObject", + "explode": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "location": { + "$ref": "#/components/schemas/LocationInfo" + }, + "data": { + "anyOf": [ + { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": ["pending"] + }, + "time": { + "type": "object", + "properties": { + "created": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string", + "enum": ["NaN"] + }, + { + "type": "string", + "enum": ["Infinity"] + }, + { + "type": "string", + "enum": ["-Infinity"] + }, + { + "type": "string", + "enum": ["Infinity", "-Infinity", "NaN"] + } + ] + }, + "expires": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string", + "enum": ["NaN"] + }, + { + "type": "string", + "enum": ["Infinity"] + }, + { + "type": "string", + "enum": ["-Infinity"] + }, + { + "type": "string", + "enum": ["Infinity", "-Infinity", "NaN"] + } + ] + } + }, + "required": ["created", "expires"], + "additionalProperties": false + } + }, + "required": ["status", "time"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": ["complete"] + }, + "time": { + "type": "object", + "properties": { + "created": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string", + "enum": ["NaN"] + }, + { + "type": "string", + "enum": ["Infinity"] + }, + { + "type": "string", + "enum": ["-Infinity"] + }, + { + "type": "string", + "enum": ["Infinity", "-Infinity", "NaN"] + } + ] + }, + "expires": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string", + "enum": ["NaN"] + }, + { + "type": "string", + "enum": ["Infinity"] + }, + { + "type": "string", + "enum": ["-Infinity"] + }, + { + "type": "string", + "enum": ["Infinity", "-Infinity", "NaN"] + } + ] + } + }, + "required": ["created", "expires"], + "additionalProperties": false + } + }, + "required": ["status", "time"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": ["failed"] + }, + "message": { + "type": "string" + }, + "time": { + "type": "object", + "properties": { + "created": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string", + "enum": ["NaN"] + }, + { + "type": "string", + "enum": ["Infinity"] + }, + { + "type": "string", + "enum": ["-Infinity"] + }, + { + "type": "string", + "enum": ["Infinity", "-Infinity", "NaN"] + } + ] + }, + "expires": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string", + "enum": ["NaN"] + }, + { + "type": "string", + "enum": ["Infinity"] + }, + { + "type": "string", + "enum": ["-Infinity"] + }, + { + "type": "string", + "enum": ["Infinity", "-Infinity", "NaN"] + } + ] + } + }, + "required": ["created", "expires"], + "additionalProperties": false + } + }, + "required": ["status", "message", "time"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": ["expired"] + }, + "time": { + "type": "object", + "properties": { + "created": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string", + "enum": ["NaN"] + }, + { + "type": "string", + "enum": ["Infinity"] + }, + { + "type": "string", + "enum": ["-Infinity"] + }, + { + "type": "string", + "enum": ["Infinity", "-Infinity", "NaN"] + } + ] + }, + "expires": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string", + "enum": ["NaN"] + }, + { + "type": "string", + "enum": ["Infinity"] + }, + { + "type": "string", + "enum": ["-Infinity"] + }, + { + "type": "string", + "enum": ["Infinity", "-Infinity", "NaN"] + } + ] + } + }, + "required": ["created", "expires"], + "additionalProperties": false + } + }, + "required": ["status", "time"], + "additionalProperties": false + } + ] + } + }, + "required": ["location", "data"], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "InvalidRequestError", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InvalidRequestError" + } + } + } + }, + "401": { + "description": "UnauthorizedError", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnauthorizedError" + } + } + } + } + }, + "description": "Poll the current status of an OAuth attempt.", + "summary": "Get OAuth attempt status", + "x-codeSamples": [ + { + "lang": "js", + "source": "import { createOpencodeClient } from \"@opencode-ai/sdk\n\nconst client = createOpencodeClient()\nawait client.v2.connector.connect.oauth.status({\n ...\n})" + } + ] + }, + "delete": { + "tags": ["connectors"], + "operationId": "v2.connector.connect.oauth.cancel", + "parameters": [ + { + "name": "attemptID", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "location", + "in": "query", + "schema": { + "type": "object", + "properties": { + "directory": { + "type": "string" + }, + "workspace": { + "type": "string" + } + }, + "additionalProperties": false + }, + "required": false, + "style": "deepObject", + "explode": true + } + ], + "security": [], + "responses": { + "204": { + "description": "" + }, + "400": { + "description": "InvalidRequestError", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InvalidRequestError" + } + } + } + }, + "401": { + "description": "UnauthorizedError", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnauthorizedError" + } + } + } + } + }, + "description": "Cancel an OAuth attempt and release its resources.", + "summary": "Cancel OAuth connection", + "x-codeSamples": [ + { + "lang": "js", + "source": "import { createOpencodeClient } from \"@opencode-ai/sdk\n\nconst client = createOpencodeClient()\nawait client.v2.connector.connect.oauth.cancel({\n ...\n})" + } + ] + } + }, + "/api/connector/oauth/{attemptID}/complete": { + "post": { + "tags": ["connectors"], + "operationId": "v2.connector.connect.oauth.complete", + "parameters": [ + { + "name": "attemptID", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "location", + "in": "query", + "schema": { + "type": "object", + "properties": { + "directory": { + "type": "string" + }, + "workspace": { + "type": "string" + } + }, + "additionalProperties": false + }, + "required": false, + "style": "deepObject", + "explode": true + } + ], + "security": [], + "responses": { + "204": { + "description": "" + }, + "400": { + "description": "InvalidRequestError", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/InvalidRequestError" + }, + { + "$ref": "#/components/schemas/InvalidRequestError" + } + ] + } + } + } + }, + "401": { + "description": "UnauthorizedError", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnauthorizedError" + } + } + } + } + }, + "description": "Complete a code-based OAuth attempt and store the resulting credential.", + "summary": "Complete OAuth connection", + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + } + }, + "additionalProperties": false + } + } + }, + "required": true + }, + "x-codeSamples": [ + { + "lang": "js", + "source": "import { createOpencodeClient } from \"@opencode-ai/sdk\n\nconst client = createOpencodeClient()\nawait client.v2.connector.connect.oauth.complete({\n ...\n})" + } + ] + } + }, "/api/permission/request": { "get": { "tags": ["permissions"], @@ -12589,6 +13485,15 @@ { "$ref": "#/components/schemas/EventModels-devRefreshed" }, + { + "$ref": "#/components/schemas/EventCredentialAdded" + }, + { + "$ref": "#/components/schemas/EventCredentialRemoved" + }, + { + "$ref": "#/components/schemas/EventCredentialSwitched" + }, { "$ref": "#/components/schemas/EventPluginAdded" }, @@ -12728,13 +13633,7 @@ "$ref": "#/components/schemas/EventFileEdited" }, { - "$ref": "#/components/schemas/EventAccountAdded" - }, - { - "$ref": "#/components/schemas/EventAccountRemoved" - }, - { - "$ref": "#/components/schemas/EventAccountSwitched" + "$ref": "#/components/schemas/EventConnectorUpdated" }, { "$ref": "#/components/schemas/EventPermissionV2Asked" @@ -14731,6 +15630,87 @@ "required": ["id", "type", "properties"], "additionalProperties": false }, + { + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "^evt_" + }, + "type": { + "type": "string", + "enum": ["credential.added"] + }, + "properties": { + "type": "object", + "properties": { + "credential": { + "$ref": "#/components/schemas/CredentialInfo" + } + }, + "required": ["credential"], + "additionalProperties": false + } + }, + "required": ["id", "type", "properties"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "^evt_" + }, + "type": { + "type": "string", + "enum": ["credential.removed"] + }, + "properties": { + "type": "object", + "properties": { + "credential": { + "$ref": "#/components/schemas/CredentialInfo" + } + }, + "required": ["credential"], + "additionalProperties": false + } + }, + "required": ["id", "type", "properties"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "^evt_" + }, + "type": { + "type": "string", + "enum": ["credential.switched"] + }, + "properties": { + "type": "object", + "properties": { + "connectorID": { + "type": "string" + }, + "from": { + "type": "string" + }, + "to": { + "type": "string" + } + }, + "required": ["connectorID"], + "additionalProperties": false + } + }, + "required": ["id", "type", "properties"], + "additionalProperties": false + }, { "type": "object", "properties": { @@ -16532,73 +17512,11 @@ }, "type": { "type": "string", - "enum": ["account.added"] + "enum": ["connector.updated"] }, "properties": { "type": "object", - "properties": { - "account": { - "$ref": "#/components/schemas/AuthInfo" - } - }, - "required": ["account"], - "additionalProperties": false - } - }, - "required": ["id", "type", "properties"], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "id": { - "type": "string", - "pattern": "^evt_" - }, - "type": { - "type": "string", - "enum": ["account.removed"] - }, - "properties": { - "type": "object", - "properties": { - "account": { - "$ref": "#/components/schemas/AuthInfo" - } - }, - "required": ["account"], - "additionalProperties": false - } - }, - "required": ["id", "type", "properties"], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "id": { - "type": "string", - "pattern": "^evt_" - }, - "type": { - "type": "string", - "enum": ["account.switched"] - }, - "properties": { - "type": "object", - "properties": { - "serviceID": { - "type": "string" - }, - "from": { - "type": "string" - }, - "to": { - "type": "string" - } - }, - "required": ["serviceID"], - "additionalProperties": false + "properties": {} } }, "required": ["id", "type", "properties"], @@ -21219,6 +22137,85 @@ "required": ["directory"], "additionalProperties": false }, + "CredentialOAuth": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["oauth"] + }, + "refresh": { + "type": "string" + }, + "access": { + "type": "string" + }, + "expires": { + "type": "integer", + "minimum": 0 + }, + "metadata": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "required": ["type", "refresh", "access", "expires"], + "additionalProperties": false + }, + "CredentialKey": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["key"] + }, + "key": { + "type": "string" + }, + "metadata": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "required": ["type", "key"], + "additionalProperties": false + }, + "CredentialValue": { + "anyOf": [ + { + "$ref": "#/components/schemas/CredentialOAuth" + }, + { + "$ref": "#/components/schemas/CredentialKey" + } + ] + }, + "CredentialInfo": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "connectorID": { + "type": "string" + }, + "methodID": { + "type": "string" + }, + "label": { + "type": "string" + }, + "value": { + "$ref": "#/components/schemas/CredentialValue" + } + }, + "required": ["id", "connectorID", "methodID", "label", "value"], + "additionalProperties": false + }, "ModelV2Info": { "type": "object", "properties": { @@ -21953,76 +22950,6 @@ "required": ["message", "isRetryable"], "additionalProperties": false }, - "AuthOAuthCredential": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": ["oauth"] - }, - "refresh": { - "type": "string" - }, - "access": { - "type": "string" - }, - "expires": { - "type": "integer", - "minimum": 0 - } - }, - "required": ["type", "refresh", "access", "expires"], - "additionalProperties": false - }, - "AuthApiKeyCredential": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": ["api"] - }, - "key": { - "type": "string" - }, - "metadata": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "required": ["type", "key"], - "additionalProperties": false - }, - "AuthCredential": { - "anyOf": [ - { - "$ref": "#/components/schemas/AuthOAuthCredential" - }, - { - "$ref": "#/components/schemas/AuthApiKeyCredential" - } - ] - }, - "AuthInfo": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "serviceID": { - "type": "string" - }, - "description": { - "type": "string" - }, - "credential": { - "$ref": "#/components/schemas/AuthCredential" - } - }, - "required": ["id", "serviceID", "description", "credential"], - "additionalProperties": false - }, "PermissionV2Source": { "type": "object", "properties": { @@ -25248,13 +26175,13 @@ "properties": { "via": { "type": "string", - "enum": ["account"] + "enum": ["credential"] }, - "service": { + "credentialID": { "type": "string" } }, - "required": ["via", "service"], + "required": ["via", "credentialID"], "additionalProperties": false }, { @@ -25340,6 +26267,244 @@ "required": ["id", "name", "enabled", "env", "api", "request"], "additionalProperties": false }, + "ConnectorWhen": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "op": { + "type": "string", + "enum": ["eq", "neq"] + }, + "value": { + "type": "string" + } + }, + "required": ["key", "op", "value"], + "additionalProperties": false + }, + "ConnectorTextPrompt": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["text"] + }, + "key": { + "type": "string" + }, + "message": { + "type": "string" + }, + "placeholder": { + "type": "string" + }, + "when": { + "$ref": "#/components/schemas/ConnectorWhen" + } + }, + "required": ["type", "key", "message"], + "additionalProperties": false + }, + "ConnectorSelectPrompt": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["select"] + }, + "key": { + "type": "string" + }, + "message": { + "type": "string" + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "value": { + "type": "string" + }, + "hint": { + "type": "string" + } + }, + "required": ["label", "value"], + "additionalProperties": false + } + }, + "when": { + "$ref": "#/components/schemas/ConnectorWhen" + } + }, + "required": ["type", "key", "message", "options"], + "additionalProperties": false + }, + "ConnectorOAuthMethod": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": ["oauth"] + }, + "label": { + "type": "string" + }, + "prompts": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/ConnectorTextPrompt" + }, + { + "$ref": "#/components/schemas/ConnectorSelectPrompt" + } + ] + } + } + }, + "required": ["id", "type", "label"], + "additionalProperties": false + }, + "ConnectorKeyMethod": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": ["key"] + }, + "label": { + "type": "string" + }, + "prompts": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/ConnectorTextPrompt" + }, + { + "$ref": "#/components/schemas/ConnectorSelectPrompt" + } + ] + } + } + }, + "required": ["id", "type", "label"], + "additionalProperties": false + }, + "ConnectorInfo": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "methods": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/ConnectorOAuthMethod" + }, + { + "$ref": "#/components/schemas/ConnectorKeyMethod" + } + ] + } + } + }, + "required": ["id", "name", "methods"], + "additionalProperties": false + }, + "ConnectorAttempt": { + "type": "object", + "properties": { + "attemptID": { + "type": "string" + }, + "url": { + "type": "string" + }, + "instructions": { + "type": "string" + }, + "mode": { + "type": "string", + "enum": ["auto", "code"] + }, + "time": { + "type": "object", + "properties": { + "created": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string", + "enum": ["NaN"] + }, + { + "type": "string", + "enum": ["Infinity"] + }, + { + "type": "string", + "enum": ["-Infinity"] + }, + { + "type": "string", + "enum": ["Infinity", "-Infinity", "NaN"] + } + ] + }, + "expires": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string", + "enum": ["NaN"] + }, + { + "type": "string", + "enum": ["Infinity"] + }, + { + "type": "string", + "enum": ["-Infinity"] + }, + { + "type": "string", + "enum": ["Infinity", "-Infinity", "NaN"] + } + ] + } + }, + "required": ["created", "expires"], + "additionalProperties": false + } + }, + "required": ["attemptID", "url", "instructions", "mode", "time"], + "additionalProperties": false + }, "PermissionV2Request": { "type": "object", "properties": { @@ -25625,6 +26790,87 @@ "required": ["id", "type", "properties"], "additionalProperties": false }, + "EventCredentialAdded": { + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "^evt_" + }, + "type": { + "type": "string", + "enum": ["credential.added"] + }, + "properties": { + "type": "object", + "properties": { + "credential": { + "$ref": "#/components/schemas/CredentialInfo" + } + }, + "required": ["credential"], + "additionalProperties": false + } + }, + "required": ["id", "type", "properties"], + "additionalProperties": false + }, + "EventCredentialRemoved": { + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "^evt_" + }, + "type": { + "type": "string", + "enum": ["credential.removed"] + }, + "properties": { + "type": "object", + "properties": { + "credential": { + "$ref": "#/components/schemas/CredentialInfo" + } + }, + "required": ["credential"], + "additionalProperties": false + } + }, + "required": ["id", "type", "properties"], + "additionalProperties": false + }, + "EventCredentialSwitched": { + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "^evt_" + }, + "type": { + "type": "string", + "enum": ["credential.switched"] + }, + "properties": { + "type": "object", + "properties": { + "connectorID": { + "type": "string" + }, + "from": { + "type": "string" + }, + "to": { + "type": "string" + } + }, + "required": ["connectorID"], + "additionalProperties": false + } + }, + "required": ["id", "type", "properties"], + "additionalProperties": false + }, "EventPluginAdded": { "type": "object", "properties": { @@ -27939,7 +29185,7 @@ "required": ["id", "type", "properties"], "additionalProperties": false }, - "EventAccountAdded": { + "EventConnectorUpdated": { "type": "object", "properties": { "id": { @@ -27948,73 +29194,11 @@ }, "type": { "type": "string", - "enum": ["account.added"] + "enum": ["connector.updated"] }, "properties": { "type": "object", - "properties": { - "account": { - "$ref": "#/components/schemas/AuthInfo" - } - }, - "required": ["account"], - "additionalProperties": false - } - }, - "required": ["id", "type", "properties"], - "additionalProperties": false - }, - "EventAccountRemoved": { - "type": "object", - "properties": { - "id": { - "type": "string", - "pattern": "^evt_" - }, - "type": { - "type": "string", - "enum": ["account.removed"] - }, - "properties": { - "type": "object", - "properties": { - "account": { - "$ref": "#/components/schemas/AuthInfo" - } - }, - "required": ["account"], - "additionalProperties": false - } - }, - "required": ["id", "type", "properties"], - "additionalProperties": false - }, - "EventAccountSwitched": { - "type": "object", - "properties": { - "id": { - "type": "string", - "pattern": "^evt_" - }, - "type": { - "type": "string", - "enum": ["account.switched"] - }, - "properties": { - "type": "object", - "properties": { - "serviceID": { - "type": "string" - }, - "from": { - "type": "string" - }, - "to": { - "type": "string" - } - }, - "required": ["serviceID"], - "additionalProperties": false + "properties": {} } }, "required": ["id", "type", "properties"], @@ -29222,6 +30406,10 @@ "name": "providers", "description": "Experimental provider routes." }, + { + "name": "connectors", + "description": "Connector discovery and authentication routes." + }, { "name": "permissions", "description": "Experimental permission routes." diff --git a/packages/server/src/handlers/connector.ts b/packages/server/src/handlers/connector.ts index 41f8d36c4d..7938b05a7b 100644 --- a/packages/server/src/handlers/connector.ts +++ b/packages/server/src/handlers/connector.ts @@ -76,17 +76,18 @@ export const ConnectorHandler = HttpApiBuilder.group(Api, "server.connector", (h "connector.connect.oauth.complete", Effect.fn(function* (ctx) { const service = yield* Connector.Service - yield* service.connect.oauth - .complete({ attemptID: ctx.params.attemptID, code: ctx.payload.code }) - .pipe( - Effect.mapError( - (error) => - new InvalidRequestError({ - message: error._tag === "Connector.CodeRequired" ? "Authorization code is required" : "Authentication failed", - kind: error._tag === "Connector.CodeRequired" ? "connector_code_required" : "connector_authorization", - }), - ), - ) + yield* service.connect.oauth.complete({ attemptID: ctx.params.attemptID, code: ctx.payload.code }).pipe( + Effect.mapError( + (error) => + new InvalidRequestError({ + message: + error._tag === "Connector.CodeRequired" + ? "Authorization code is required" + : "Authentication failed", + kind: error._tag === "Connector.CodeRequired" ? "connector_code_required" : "connector_authorization", + }), + ), + ) return HttpApiSchema.NoContent.make() }), ) diff --git a/packages/tui/src/context/data.tsx b/packages/tui/src/context/data.tsx index 74457fb832..d6b10699a4 100644 --- a/packages/tui/src/context/data.tsx +++ b/packages/tui/src/context/data.tsx @@ -425,10 +425,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({ break case "credential.switched": { const location = { directory: metadata.directory, workspaceID: metadata.workspace } - void Promise.allSettled([ - result.location.model.refresh(location), - result.location.provider.refresh(location), - ]) + void Promise.allSettled([result.location.model.refresh(location), result.location.provider.refresh(location)]) break } case "connector.updated": diff --git a/packages/tui/test/fixture/tui-sdk.ts b/packages/tui/test/fixture/tui-sdk.ts index a781291898..fb6226215c 100644 --- a/packages/tui/test/fixture/tui-sdk.ts +++ b/packages/tui/test/fixture/tui-sdk.ts @@ -60,7 +60,11 @@ export function createFetch(override?: FetchHandler) { if (url.pathname === "/experimental/console") return json({ consoleManagedProviders: [], switchableOrgCount: 0 }) if (url.pathname === "/path") return json({ home: "", state: "", config: "", worktree, directory }) if (url.pathname === "/api/location") return json({ directory, project: { id: "proj_test", directory: worktree } }) - if (["/api/agent", "/api/model", "/api/provider", "/api/connector", "/api/command", "/api/skill"].includes(url.pathname)) + if ( + ["/api/agent", "/api/model", "/api/provider", "/api/connector", "/api/command", "/api/skill"].includes( + url.pathname, + ) + ) return json({ location: { directory, project: { id: "proj_test", directory: worktree } }, data: [],