refactor(search): simplify provider flow
This commit is contained in:
parent
ccad83549d
commit
61676a1d3c
6 changed files with 33 additions and 43 deletions
|
|
@ -192,10 +192,7 @@ export const make = Effect.fn("PluginHost.make")(function* (plugin: PluginV2.Int
|
|||
connection.type === "credential" ? { ...connection, id: Credential.ID.make(connection.id) } : connection,
|
||||
),
|
||||
},
|
||||
register: (definition) =>
|
||||
integration.transform((draft) => {
|
||||
registerIntegration(draft, definition)
|
||||
}),
|
||||
register: (definition) => integration.transform((draft) => registerIntegration(draft, definition)),
|
||||
transform: (callback) =>
|
||||
integration.transform((draft) => {
|
||||
callback({
|
||||
|
|
|
|||
|
|
@ -120,14 +120,14 @@ export function fromPromise(plugin: Plugin) {
|
|||
}
|
||||
|
||||
function adaptIntegration(definition: IntegrationDefinition) {
|
||||
const { methods, search, ...info } = definition
|
||||
const { methods, search, ...definitionInfo } = definition
|
||||
return {
|
||||
...info,
|
||||
...definitionInfo,
|
||||
methods: methods?.map((method) => {
|
||||
if (method.type !== "oauth") return method
|
||||
const { authorize, refresh, ...info } = method
|
||||
const { authorize, refresh, ...methodInfo } = method
|
||||
return {
|
||||
...info,
|
||||
...methodInfo,
|
||||
authorize: (inputs: Parameters<typeof authorize>[0]) =>
|
||||
Effect.tryPromise({ try: () => authorize(inputs), catch: (cause) => cause }).pipe(
|
||||
Effect.map((authorization) => {
|
||||
|
|
|
|||
|
|
@ -74,7 +74,8 @@ const layer = Layer.effect(
|
|||
const integrations = yield* Integration.Service
|
||||
const onboarding = Semaphore.makeUnsafe(1)
|
||||
const decodeOutput = Schema.decodeUnknownEffect(ProviderOutput)
|
||||
let pending: Integration.ID | undefined
|
||||
const globalConfigPath = path.resolve(global.config)
|
||||
let pendingProviderID: Integration.ID | undefined
|
||||
|
||||
const requireProvider = (
|
||||
providers: Map<Integration.ID, Integration.SearchImplementation>,
|
||||
|
|
@ -84,45 +85,31 @@ const layer = Layer.effect(
|
|||
return provider ? Effect.succeed(provider) : Effect.fail(new ProviderNotFoundError({ providerID }))
|
||||
}
|
||||
|
||||
const configuredProvider = Effect.fn("Search.configuredProvider")(function* () {
|
||||
const providerID = Config.latest(yield* config.entries(), "search")?.provider
|
||||
if (providerID) return providerID
|
||||
if (process.env.OPENCODE_WEBSEARCH_PROVIDER) {
|
||||
return Integration.ID.make(process.env.OPENCODE_WEBSEARCH_PROVIDER)
|
||||
}
|
||||
if (truthy("OPENCODE_ENABLE_PARALLEL") || truthy("OPENCODE_EXPERIMENTAL_PARALLEL")) {
|
||||
return Integration.ID.make("parallel")
|
||||
}
|
||||
if (truthy("OPENCODE_EXPERIMENTAL") || truthy("OPENCODE_ENABLE_EXA") || truthy("OPENCODE_EXPERIMENTAL_EXA")) {
|
||||
return Integration.ID.make("exa")
|
||||
}
|
||||
})
|
||||
|
||||
const globalProvider = Effect.fn("Search.globalProvider")(function* () {
|
||||
const globalProviderID = Effect.fn("Search.globalProviderID")(function* () {
|
||||
const entries = (yield* config.entries()).filter(
|
||||
(entry) => entry.type === "document" && entry.path && path.dirname(entry.path) === path.resolve(global.config),
|
||||
(entry) => entry.type === "document" && entry.path && path.dirname(entry.path) === globalConfigPath,
|
||||
)
|
||||
return Config.latest(entries, "search")?.provider
|
||||
})
|
||||
|
||||
const selected = Effect.fn("Search.selected")(function* () {
|
||||
return pending ?? (yield* globalProvider())
|
||||
return pendingProviderID ?? (yield* globalProviderID())
|
||||
})
|
||||
|
||||
const save = Effect.fn("Search.save")(function* (providerID: Integration.ID) {
|
||||
pending = providerID
|
||||
const saveProvider = Effect.fn("Search.saveProvider")(function* (providerID: Integration.ID) {
|
||||
pendingProviderID = providerID
|
||||
yield* configGlobal.update(["search"], new ConfigSearch.Info({ provider: providerID })).pipe(
|
||||
Effect.tapError(() => Effect.sync(() => (pending = undefined))),
|
||||
Effect.tapError(() => Effect.sync(() => (pendingProviderID = undefined))),
|
||||
Effect.orDie,
|
||||
)
|
||||
})
|
||||
|
||||
yield* events.subscribe(ConfigSchema.Event.Updated).pipe(
|
||||
Stream.runForEach(() =>
|
||||
globalProvider().pipe(
|
||||
globalProviderID().pipe(
|
||||
Effect.tap((providerID) =>
|
||||
Effect.sync(() => {
|
||||
if (providerID === pending) pending = undefined
|
||||
if (providerID === pendingProviderID) pendingProviderID = undefined
|
||||
}),
|
||||
),
|
||||
Effect.ignore,
|
||||
|
|
@ -201,8 +188,17 @@ const layer = Layer.effect(
|
|||
(yield* integrations.search.list()).map((provider) => [provider.integrationID, provider]),
|
||||
)
|
||||
if (input.providerID) return yield* requireProvider(providers, input.providerID)
|
||||
const override = yield* configuredProvider()
|
||||
if (override) return yield* requireProvider(providers, override)
|
||||
const configuredProviderID = Config.latest(yield* config.entries(), "search")?.provider
|
||||
if (configuredProviderID) return yield* requireProvider(providers, configuredProviderID)
|
||||
if (process.env.OPENCODE_WEBSEARCH_PROVIDER) {
|
||||
return yield* requireProvider(providers, Integration.ID.make(process.env.OPENCODE_WEBSEARCH_PROVIDER))
|
||||
}
|
||||
if (truthy("OPENCODE_ENABLE_PARALLEL") || truthy("OPENCODE_EXPERIMENTAL_PARALLEL")) {
|
||||
return yield* requireProvider(providers, Integration.ID.make("parallel"))
|
||||
}
|
||||
if (truthy("OPENCODE_EXPERIMENTAL") || truthy("OPENCODE_ENABLE_EXA") || truthy("OPENCODE_EXPERIMENTAL_EXA")) {
|
||||
return yield* requireProvider(providers, Integration.ID.make("exa"))
|
||||
}
|
||||
const providerID = yield* selected()
|
||||
const provider = providerID ? providers.get(providerID) : undefined
|
||||
if (provider) return provider
|
||||
|
|
@ -215,7 +211,7 @@ const layer = Layer.effect(
|
|||
if (selectedProvider) return selectedProvider
|
||||
const provider = yield* ask(providers, sessionID)
|
||||
yield* connect(provider, sessionID)
|
||||
yield* save(provider.integrationID)
|
||||
yield* saveProvider(provider.integrationID)
|
||||
return provider
|
||||
}),
|
||||
)
|
||||
|
|
@ -226,7 +222,7 @@ const layer = Layer.effect(
|
|||
select: Effect.fn("Search.select")(function* (providerID) {
|
||||
const provider = yield* integrations.search.get(providerID)
|
||||
if (!provider) return yield* new ProviderNotFoundError({ providerID })
|
||||
yield* save(providerID)
|
||||
yield* saveProvider(providerID)
|
||||
}),
|
||||
query: Effect.fn("Search.query")(function* (input) {
|
||||
const provider = yield* resolve(input)
|
||||
|
|
|
|||
|
|
@ -207,10 +207,7 @@ export function integrationHost(integration: Integration.Interface): PluginConte
|
|||
connection.type === "credential" ? { ...connection, id: Credential.ID.make(connection.id) } : connection,
|
||||
),
|
||||
},
|
||||
register: (definition) =>
|
||||
integration.transform((draft) => {
|
||||
registerIntegration(draft, definition)
|
||||
}),
|
||||
register: (definition) => integration.transform((draft) => registerIntegration(draft, definition)),
|
||||
transform: (callback) =>
|
||||
integration.transform((draft) =>
|
||||
callback({
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import { response } from "../location"
|
|||
|
||||
export const SearchHandler = HttpApiBuilder.group(Api, "server.search", (handlers) =>
|
||||
Effect.gen(function* () {
|
||||
const ready = Effect.fn("server.search.ready")(function* () {
|
||||
const awaitPlugins = Effect.fn("server.search.awaitPlugins")(function* () {
|
||||
const plugins = yield* PluginSupervisor.Service
|
||||
yield* plugins.ready.pipe(
|
||||
Effect.timeoutOrElse({
|
||||
|
|
@ -34,7 +34,7 @@ export const SearchHandler = HttpApiBuilder.group(Api, "server.search", (handler
|
|||
.handle(
|
||||
"search.provider.select",
|
||||
Effect.fn("server.search.provider.select")(function* (request) {
|
||||
yield* ready()
|
||||
yield* awaitPlugins()
|
||||
const search = yield* Search.Service
|
||||
yield* search.select(request.payload.providerID).pipe(
|
||||
Effect.mapError(
|
||||
|
|
@ -52,7 +52,7 @@ export const SearchHandler = HttpApiBuilder.group(Api, "server.search", (handler
|
|||
.handle(
|
||||
"search.query",
|
||||
Effect.fn("server.search.query")(function* (request) {
|
||||
yield* ready()
|
||||
yield* awaitPlugins()
|
||||
const search = yield* Search.Service
|
||||
return yield* response(
|
||||
search.query(request.payload).pipe(
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ function manageIntegration(
|
|||
const sdk = useSDK()
|
||||
const toast = useToast()
|
||||
const credentials = credentialConnections(integration)
|
||||
const selected = () => data.location.search.provider() === integration.id
|
||||
const selected = createMemo(() => data.location.search.provider() === integration.id)
|
||||
const selectSearch = () => {
|
||||
void sdk.api.search
|
||||
.selectProvider({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue