mirror of
https://github.com/anomalyco/opencode.git
synced 2026-08-09 10:59:49 -04:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d7c183e988 |
@@ -561,7 +561,13 @@ function ProviderConnection(props: {
|
|||||||
if (!alive.value) return
|
if (!alive.value) return
|
||||||
dispatch({ type: "auth.error", error: formatError(e, language.t("common.requestFailed")) })
|
dispatch({ type: "auth.error", error: formatError(e, language.t("common.requestFailed")) })
|
||||||
})
|
})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
if (method.prompts?.length && !inputs) {
|
||||||
|
dispatch({ type: "auth.prompt" })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dispatch({ type: "auth.inputs", inputs: inputs ?? {} })
|
||||||
}
|
}
|
||||||
|
|
||||||
function AuthPromptsView() {
|
function AuthPromptsView() {
|
||||||
@@ -572,7 +578,7 @@ function ProviderConnection(props: {
|
|||||||
|
|
||||||
const prompts = createMemo(() => {
|
const prompts = createMemo(() => {
|
||||||
const value = method()
|
const value = method()
|
||||||
return value?.type === "oauth" ? (value.prompts ?? []) : []
|
return value?.prompts ?? []
|
||||||
})
|
})
|
||||||
const matches = (prompt: NonNullable<ReturnType<typeof prompts>[number]>, value: Record<string, string>) => {
|
const matches = (prompt: NonNullable<ReturnType<typeof prompts>[number]>, value: Record<string, string>) => {
|
||||||
if (!prompt.when) return true
|
if (!prompt.when) return true
|
||||||
@@ -820,6 +826,7 @@ function ProviderConnection(props: {
|
|||||||
integrationID: props.provider,
|
integrationID: props.provider,
|
||||||
location: location(),
|
location: location(),
|
||||||
key: apiKey,
|
key: apiKey,
|
||||||
|
inputs: store.promptInputs ?? {},
|
||||||
})
|
})
|
||||||
await complete()
|
await complete()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -992,6 +992,7 @@ export type Endpoint10_3Input = {
|
|||||||
readonly integrationID: Integration.ID
|
readonly integrationID: Integration.ID
|
||||||
readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined
|
readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined
|
||||||
readonly key: string
|
readonly key: string
|
||||||
|
readonly inputs?: { readonly [x: string]: string } | undefined
|
||||||
readonly label?: string | undefined
|
readonly label?: string | undefined
|
||||||
}
|
}
|
||||||
export type Endpoint10_3Output = void
|
export type Endpoint10_3Output = void
|
||||||
|
|||||||
@@ -664,7 +664,7 @@ const Endpoint10_3 = (raw: RawClient["server.integration"]) => (input: Endpoint1
|
|||||||
raw["integration.connect.key"]({
|
raw["integration.connect.key"]({
|
||||||
params: { integrationID: input["integrationID"] },
|
params: { integrationID: input["integrationID"] },
|
||||||
query: { location: input["location"] },
|
query: { location: input["location"] },
|
||||||
payload: { key: input["key"], label: input["label"] },
|
payload: { key: input["key"], inputs: input["inputs"], label: input["label"] },
|
||||||
}).pipe(Effect.mapError(mapClientError)),
|
}).pipe(Effect.mapError(mapClientError)),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -963,7 +963,7 @@ export function make(options: ClientOptions) {
|
|||||||
method: "POST",
|
method: "POST",
|
||||||
path: `/api/integration/${encodeURIComponent(input.integrationID)}/connect/key`,
|
path: `/api/integration/${encodeURIComponent(input.integrationID)}/connect/key`,
|
||||||
query: { location: input["location"] },
|
query: { location: input["location"] },
|
||||||
body: { key: input["key"], label: input["label"] },
|
body: { key: input["key"], inputs: input["inputs"], label: input["label"] },
|
||||||
successStatus: 204,
|
successStatus: 204,
|
||||||
declaredStatuses: [400, 401],
|
declaredStatuses: [400, 401],
|
||||||
empty: true,
|
empty: true,
|
||||||
|
|||||||
@@ -197,8 +197,6 @@ export type IntegrationWhen = { key: string; op: "eq" | "neq"; value: string }
|
|||||||
|
|
||||||
export type IntegrationCommandMethod = { id: string; type: "command"; label: string; command: Array<string> }
|
export type IntegrationCommandMethod = { id: string; type: "command"; label: string; command: Array<string> }
|
||||||
|
|
||||||
export type IntegrationKeyMethod = { type: "key"; label?: string }
|
|
||||||
|
|
||||||
export type IntegrationEnvMethod = { type: "env"; names: Array<string> }
|
export type IntegrationEnvMethod = { type: "env"; names: Array<string> }
|
||||||
|
|
||||||
export type ConnectionCredentialInfo = { type: "credential"; id: string; label: string }
|
export type ConnectionCredentialInfo = { type: "credential"; id: string; label: string }
|
||||||
@@ -1638,6 +1636,12 @@ export type IntegrationOAuthMethod = {
|
|||||||
prompts?: Array<IntegrationTextPrompt | IntegrationSelectPrompt>
|
prompts?: Array<IntegrationTextPrompt | IntegrationSelectPrompt>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type IntegrationKeyMethod = {
|
||||||
|
type: "key"
|
||||||
|
label?: string
|
||||||
|
prompts?: Array<IntegrationTextPrompt | IntegrationSelectPrompt>
|
||||||
|
}
|
||||||
|
|
||||||
export type FormField =
|
export type FormField =
|
||||||
| FormStringField
|
| FormStringField
|
||||||
| FormNumberField
|
| FormNumberField
|
||||||
@@ -3119,8 +3123,21 @@ export type IntegrationConnectKeyInput = {
|
|||||||
readonly location?: {
|
readonly location?: {
|
||||||
readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined
|
readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined
|
||||||
}["location"]
|
}["location"]
|
||||||
readonly key: { readonly key: string; readonly label?: string | undefined }["key"]
|
readonly key: {
|
||||||
readonly label?: { readonly key: string; readonly label?: string | undefined }["label"]
|
readonly key: string
|
||||||
|
readonly inputs?: { readonly [x: string]: string } | undefined
|
||||||
|
readonly label?: string | undefined
|
||||||
|
}["key"]
|
||||||
|
readonly inputs?: {
|
||||||
|
readonly key: string
|
||||||
|
readonly inputs?: { readonly [x: string]: string } | undefined
|
||||||
|
readonly label?: string | undefined
|
||||||
|
}["inputs"]
|
||||||
|
readonly label?: {
|
||||||
|
readonly key: string
|
||||||
|
readonly inputs?: { readonly [x: string]: string } | undefined
|
||||||
|
readonly label?: string | undefined
|
||||||
|
}["label"]
|
||||||
}
|
}
|
||||||
|
|
||||||
export type IntegrationConnectKeyOutput = void
|
export type IntegrationConnectKeyOutput = void
|
||||||
|
|||||||
@@ -175,6 +175,8 @@ export interface Interface extends State.Transformable<Draft> {
|
|||||||
readonly integrationID: ID
|
readonly integrationID: ID
|
||||||
/** Secret entered by the user. */
|
/** Secret entered by the user. */
|
||||||
readonly key: string
|
readonly key: string
|
||||||
|
/** Provider-specific values collected before the secret. */
|
||||||
|
readonly inputs?: Inputs
|
||||||
/** User-facing label for the stored credential. */
|
/** User-facing label for the stored credential. */
|
||||||
readonly label?: string
|
readonly label?: string
|
||||||
}) => Effect.Effect<void, AuthorizationError>
|
}) => Effect.Effect<void, AuthorizationError>
|
||||||
@@ -704,7 +706,11 @@ const layer = Layer.effect(
|
|||||||
yield* credentials.create({
|
yield* credentials.create({
|
||||||
integrationID: input.integrationID,
|
integrationID: input.integrationID,
|
||||||
label: input.label,
|
label: input.label,
|
||||||
value: Credential.Key.make({ type: "key", key: input.key }),
|
value: Credential.Key.make({
|
||||||
|
type: "key",
|
||||||
|
key: input.key,
|
||||||
|
metadata: input.inputs && Object.keys(input.inputs).length > 0 ? input.inputs : undefined,
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
yield* bus.publish(Integration.Event.ConnectionUpdated, { integrationID: input.integrationID })
|
yield* bus.publish(Integration.Event.ConnectionUpdated, { integrationID: input.integrationID })
|
||||||
yield* bus.publish(Integration.Event.Updated, {})
|
yield* bus.publish(Integration.Event.Updated, {})
|
||||||
|
|||||||
@@ -192,6 +192,7 @@ export const make = Effect.fn("PluginHost.make")(function* (plugin: import("../p
|
|||||||
integration.connection.key({
|
integration.connection.key({
|
||||||
integrationID: Integration.ID.make(input.integrationID),
|
integrationID: Integration.ID.make(input.integrationID),
|
||||||
key: input.key,
|
key: input.key,
|
||||||
|
inputs: input.inputs,
|
||||||
label: input.label,
|
label: input.label,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
@@ -398,7 +399,7 @@ function methodImplementation(input: IntegrationMethodRegistration): Integration
|
|||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
integrationID: Integration.ID.make(input.integrationID),
|
integrationID: Integration.ID.make(input.integrationID),
|
||||||
method: { type: "key", label: input.method.label },
|
method: { type: "key", label: input.method.label, prompts: input.method.prompts },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,37 @@ import { define } from "@opencode-ai/plugin/effect/plugin"
|
|||||||
export const CloudflareAIGatewayPlugin = define({
|
export const CloudflareAIGatewayPlugin = define({
|
||||||
id: "opencode.provider.cloudflare-ai-gateway",
|
id: "opencode.provider.cloudflare-ai-gateway",
|
||||||
effect: Effect.fn(function* (ctx) {
|
effect: Effect.fn(function* (ctx) {
|
||||||
|
yield* ctx.integration.transform((draft) => {
|
||||||
|
draft.method.update({
|
||||||
|
integrationID: "cloudflare-ai-gateway",
|
||||||
|
method: {
|
||||||
|
type: "key",
|
||||||
|
label: "Gateway API token",
|
||||||
|
prompts: [
|
||||||
|
...(process.env.CLOUDFLARE_ACCOUNT_ID
|
||||||
|
? []
|
||||||
|
: [
|
||||||
|
{
|
||||||
|
type: "text" as const,
|
||||||
|
key: "accountId",
|
||||||
|
message: "Enter your Cloudflare Account ID",
|
||||||
|
placeholder: "e.g. 1234567890abcdef1234567890abcdef",
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
...(process.env.CLOUDFLARE_GATEWAY_ID
|
||||||
|
? []
|
||||||
|
: [
|
||||||
|
{
|
||||||
|
type: "text" as const,
|
||||||
|
key: "gatewayId",
|
||||||
|
message: "Enter your Cloudflare AI Gateway ID",
|
||||||
|
placeholder: "e.g. my-gateway",
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
yield* ctx.aisdk.hook(
|
yield* ctx.aisdk.hook(
|
||||||
"sdk",
|
"sdk",
|
||||||
Effect.fn(function* (evt) {
|
Effect.fn(function* (evt) {
|
||||||
|
|||||||
@@ -9,6 +9,25 @@ const providerID = Provider.ID.make("cloudflare-workers-ai")
|
|||||||
export const CloudflareWorkersAIPlugin = define({
|
export const CloudflareWorkersAIPlugin = define({
|
||||||
id: "opencode.provider.cloudflare-workers-ai",
|
id: "opencode.provider.cloudflare-workers-ai",
|
||||||
effect: Effect.fn(function* (ctx) {
|
effect: Effect.fn(function* (ctx) {
|
||||||
|
yield* ctx.integration.transform((draft) => {
|
||||||
|
draft.method.update({
|
||||||
|
integrationID: providerID,
|
||||||
|
method: {
|
||||||
|
type: "key",
|
||||||
|
label: "API key",
|
||||||
|
prompts: process.env.CLOUDFLARE_ACCOUNT_ID
|
||||||
|
? undefined
|
||||||
|
: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
key: "accountId",
|
||||||
|
message: "Enter your Cloudflare Account ID",
|
||||||
|
placeholder: "e.g. 1234567890abcdef1234567890abcdef",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
yield* ctx.catalog.transform((evt) => {
|
yield* ctx.catalog.transform((evt) => {
|
||||||
const item = evt.provider.get(providerID)
|
const item = evt.provider.get(providerID)
|
||||||
if (!item) return
|
if (!item) return
|
||||||
|
|||||||
@@ -151,6 +151,7 @@ describe("Integration", () => {
|
|||||||
yield* integrations.connection.key({
|
yield* integrations.connection.key({
|
||||||
integrationID,
|
integrationID,
|
||||||
key: "secret",
|
key: "secret",
|
||||||
|
inputs: { accountId: "account" },
|
||||||
label: "Work",
|
label: "Work",
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -158,7 +159,7 @@ describe("Integration", () => {
|
|||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
integrationID,
|
integrationID,
|
||||||
label: "Work",
|
label: "Work",
|
||||||
value: Credential.Key.make({ type: "key", key: "secret" }),
|
value: Credential.Key.make({ type: "key", key: "secret", metadata: { accountId: "account" } }),
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
expect((yield* Fiber.join(updated)).length).toBe(1)
|
expect((yield* Fiber.join(updated)).length).toBe(1)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { Plugin } from "@opencode-ai/core/plugin"
|
|||||||
import { PluginHost } from "@opencode-ai/core/plugin/host"
|
import { PluginHost } from "@opencode-ai/core/plugin/host"
|
||||||
import { CloudflareAIGatewayPlugin } from "@opencode-ai/core/plugin/provider/cloudflare-ai-gateway"
|
import { CloudflareAIGatewayPlugin } from "@opencode-ai/core/plugin/provider/cloudflare-ai-gateway"
|
||||||
import { Provider } from "@opencode-ai/core/provider"
|
import { Provider } from "@opencode-ai/core/provider"
|
||||||
|
import { Integration } from "@opencode-ai/core/integration"
|
||||||
import { testEffect } from "../lib/effect"
|
import { testEffect } from "../lib/effect"
|
||||||
import { PluginTestLayer } from "./fixture"
|
import { PluginTestLayer } from "./fixture"
|
||||||
|
|
||||||
@@ -102,6 +103,39 @@ mock.module("ai-gateway-provider/providers/unified", () => ({
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
describe("CloudflareAIGatewayPlugin", () => {
|
describe("CloudflareAIGatewayPlugin", () => {
|
||||||
|
it.effect("prompts for account and gateway IDs when the environment does not provide them", () =>
|
||||||
|
withEnv(
|
||||||
|
cloudflareEnv({
|
||||||
|
CLOUDFLARE_ACCOUNT_ID: undefined,
|
||||||
|
CLOUDFLARE_GATEWAY_ID: undefined,
|
||||||
|
}),
|
||||||
|
() =>
|
||||||
|
Effect.gen(function* () {
|
||||||
|
yield* addPlugin()
|
||||||
|
expect(
|
||||||
|
(yield* (yield* Integration.Service).get(Integration.ID.make("cloudflare-ai-gateway")))?.methods,
|
||||||
|
).toContainEqual({
|
||||||
|
type: "key",
|
||||||
|
label: "Gateway API token",
|
||||||
|
prompts: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
key: "accountId",
|
||||||
|
message: "Enter your Cloudflare Account ID",
|
||||||
|
placeholder: "e.g. 1234567890abcdef1234567890abcdef",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
key: "gatewayId",
|
||||||
|
message: "Enter your Cloudflare AI Gateway ID",
|
||||||
|
placeholder: "e.g. my-gateway",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
it.effect("requires account, gateway, and token before creating the unified SDK", () =>
|
it.effect("requires account, gateway, and token before creating the unified SDK", () =>
|
||||||
withEnv(
|
withEnv(
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { Plugin } from "@opencode-ai/core/plugin"
|
|||||||
import { PluginHost } from "@opencode-ai/core/plugin/host"
|
import { PluginHost } from "@opencode-ai/core/plugin/host"
|
||||||
import { CloudflareWorkersAIPlugin } from "@opencode-ai/core/plugin/provider/cloudflare-workers-ai"
|
import { CloudflareWorkersAIPlugin } from "@opencode-ai/core/plugin/provider/cloudflare-workers-ai"
|
||||||
import { Provider } from "@opencode-ai/core/provider"
|
import { Provider } from "@opencode-ai/core/provider"
|
||||||
|
import { Integration } from "@opencode-ai/core/integration"
|
||||||
import type { LanguageModelV3 } from "@ai-sdk/provider"
|
import type { LanguageModelV3 } from "@ai-sdk/provider"
|
||||||
import { testEffect } from "../lib/effect"
|
import { testEffect } from "../lib/effect"
|
||||||
import { PluginTestLayer } from "./fixture"
|
import { PluginTestLayer } from "./fixture"
|
||||||
@@ -79,6 +80,28 @@ function cloudflareHeaders(sdk: unknown, modelID = "@cf/model") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe("CloudflareWorkersAIPlugin", () => {
|
describe("CloudflareWorkersAIPlugin", () => {
|
||||||
|
it.effect("prompts for the account ID when the environment does not provide it", () =>
|
||||||
|
withEnv({ CLOUDFLARE_ACCOUNT_ID: undefined }, () =>
|
||||||
|
Effect.gen(function* () {
|
||||||
|
yield* addPlugin()
|
||||||
|
expect(
|
||||||
|
(yield* (yield* Integration.Service).get(Integration.ID.make("cloudflare-workers-ai")))?.methods,
|
||||||
|
).toContainEqual({
|
||||||
|
type: "key",
|
||||||
|
label: "API key",
|
||||||
|
prompts: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
key: "accountId",
|
||||||
|
message: "Enter your Cloudflare Account ID",
|
||||||
|
placeholder: "e.g. 1234567890abcdef1234567890abcdef",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
it.effect("maps account ID to endpoint URL and creates an OpenAI-compatible SDK", () =>
|
it.effect("maps account ID to endpoint URL and creates an OpenAI-compatible SDK", () =>
|
||||||
withEnv({ CLOUDFLARE_ACCOUNT_ID: "acct", CLOUDFLARE_API_KEY: "key" }, () =>
|
withEnv({ CLOUDFLARE_ACCOUNT_ID: "acct", CLOUDFLARE_API_KEY: "key" }, () =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ export const IntegrationGroup = HttpApiGroup.make("server.integration")
|
|||||||
query: LocationQuery,
|
query: LocationQuery,
|
||||||
payload: Schema.Struct({
|
payload: Schema.Struct({
|
||||||
key: Schema.String,
|
key: Schema.String,
|
||||||
|
inputs: Schema.optional(Inputs),
|
||||||
label: Schema.optional(Schema.String),
|
label: Schema.optional(Schema.String),
|
||||||
}),
|
}),
|
||||||
success: HttpApiSchema.NoContent,
|
success: HttpApiSchema.NoContent,
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ export interface KeyMethod extends Schema.Schema.Type<typeof KeyMethod> {}
|
|||||||
export const KeyMethod = Schema.Struct({
|
export const KeyMethod = Schema.Struct({
|
||||||
type: Schema.Literal("key"),
|
type: Schema.Literal("key"),
|
||||||
label: optional(Schema.String),
|
label: optional(Schema.String),
|
||||||
|
prompts: optional(Schema.Array(Prompt)),
|
||||||
}).annotate({ identifier: "Integration.KeyMethod" })
|
}).annotate({ identifier: "Integration.KeyMethod" })
|
||||||
|
|
||||||
export interface EnvMethod extends Schema.Schema.Type<typeof EnvMethod> {}
|
export interface EnvMethod extends Schema.Schema.Type<typeof EnvMethod> {}
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ export const IntegrationHandler = HttpApiBuilder.group(Api, "server.integration"
|
|||||||
service.connection.key({
|
service.connection.key({
|
||||||
integrationID: ctx.params.integrationID,
|
integrationID: ctx.params.integrationID,
|
||||||
key: ctx.payload.key,
|
key: ctx.payload.key,
|
||||||
|
inputs: ctx.payload.inputs,
|
||||||
label: ctx.payload.label,
|
label: ctx.payload.label,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ function openMethod(
|
|||||||
onConnected?: OnIntegrationConnected,
|
onConnected?: OnIntegrationConnected,
|
||||||
) {
|
) {
|
||||||
if (method.type === "key") {
|
if (method.type === "key") {
|
||||||
dialog.replace(() => <KeyMethod integration={integration} method={method} onConnected={onConnected} />)
|
void beginKey(integration, method, dialog, onConnected)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (method.type === "command") {
|
if (method.type === "command") {
|
||||||
@@ -190,6 +190,19 @@ function openMethod(
|
|||||||
void beginOAuth(integration, method, dialog, onConnected)
|
void beginOAuth(integration, method, dialog, onConnected)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function beginKey(
|
||||||
|
integration: IntegrationInfo,
|
||||||
|
method: Extract<ConnectMethod, { type: "key" }>,
|
||||||
|
dialog: ReturnType<typeof useDialog>,
|
||||||
|
onConnected?: OnIntegrationConnected,
|
||||||
|
) {
|
||||||
|
const inputs = method.prompts?.length ? await promptInputs(dialog, method.prompts) : {}
|
||||||
|
if (inputs === null) return
|
||||||
|
dialog.replace(() => (
|
||||||
|
<KeyMethod integration={integration} method={method} inputs={inputs} onConnected={onConnected} />
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
function CommandStarting(props: {
|
function CommandStarting(props: {
|
||||||
integration: IntegrationInfo
|
integration: IntegrationInfo
|
||||||
method: Extract<ConnectMethod, { type: "command" }>
|
method: Extract<ConnectMethod, { type: "command" }>
|
||||||
@@ -335,6 +348,7 @@ function CommandView(props: { title: string; output: string; message: string })
|
|||||||
function KeyMethod(props: {
|
function KeyMethod(props: {
|
||||||
integration: IntegrationInfo
|
integration: IntegrationInfo
|
||||||
method: Extract<ConnectMethod, { type: "key" }>
|
method: Extract<ConnectMethod, { type: "key" }>
|
||||||
|
inputs: Record<string, string>
|
||||||
onConnected?: OnIntegrationConnected
|
onConnected?: OnIntegrationConnected
|
||||||
}) {
|
}) {
|
||||||
const data = useData()
|
const data = useData()
|
||||||
@@ -355,6 +369,7 @@ function KeyMethod(props: {
|
|||||||
integrationID: props.integration.id,
|
integrationID: props.integration.id,
|
||||||
location: location(data),
|
location: location(data),
|
||||||
key,
|
key,
|
||||||
|
inputs: props.inputs,
|
||||||
})
|
})
|
||||||
.then(() => connected(props.integration, data, dialog, toast, props.onConnected))
|
.then(() => connected(props.integration, data, dialog, toast, props.onConnected))
|
||||||
.catch((cause) => setError(message(cause)))
|
.catch((cause) => setError(message(cause)))
|
||||||
|
|||||||
Reference in New Issue
Block a user