import { type ElicitationResponse, type OnElicitation, type ToolInvocationContext, type ToolMetadata, toTool, type ToolMap, type ToolPath,} from "@executor/codemode-core";import { type AccountId, ExecutionIdSchema, ExecutionInteractionIdSchema, SourceSchema, type Source, type WorkspaceId,} from "#schema";import * as Effect from "effect/Effect";import * as Cause from "effect/Cause";import * as Exit from "effect/Exit";import * as Schema from "effect/Schema";import type { RuntimeLocalWorkspaceState } from "./local-runtime-context";import { type LocalStorageServices, LocalInstallationStore, LocalSourceArtifactStore, LocalWorkspaceConfigStore, LocalWorkspaceStateStore, makeLocalStorageLayer,} from "./local-storage";import { provideOptionalRuntimeLocalWorkspace } from "./local-runtime-context"; /** Run an Effect as a Promise, preserving the original error (not FiberFailure). */const runEffect = async <A>( effect: Effect.Effect<A, unknown, LocalStorageServices>, runtimeLocalWorkspace: RuntimeLocalWorkspaceState | null = null,): Promise<A> => { const baseLayer = makeLocalStorageLayer({ installationStore: LocalInstallationStore, workspaceConfigStore: LocalWorkspaceConfigStore, workspaceStateStore: LocalWorkspaceStateStore, sourceArtifactStore: LocalSourceArtifactStore, }); const exit = await Effect.runPromiseExit( provideOptionalRuntimeLocalWorkspace( effect.pipe(Effect.provide(baseLayer)), runtimeLocalWorkspace, ), ); if (Exit.isSuccess(exit)) return exit.value; throw Cause.squash(exit.cause);}; import { type ExecutorAddSourceInput, type ExecutorHttpSourceAuthInput, type RuntimeSourceAuthService,} from "./source-auth-service";import { deriveSchemaJson, deriveSchemaTypeSignature,} from "./schema-type-signature";import { ExecutorAddSourceInputSchema, executorAddableSourceAdapters,} from "./source-adapters";import { decodeSourceCredentialSelectionContent } from "./source-credential-interactions"; const ExecutorSourcesAddInputSchema = Schema.standardSchemaV1( ExecutorAddSourceInputSchema,); const ExecutorSourcesAddOutputSchema = Schema.standardSchemaV1(SourceSchema); export const EXECUTOR_SOURCES_ADD_INPUT_HINT = deriveSchemaTypeSignature( ExecutorAddSourceInputSchema, 320,); export const EXECUTOR_SOURCES_ADD_OUTPUT_SIGNATURE = deriveSchemaTypeSignature( SourceSchema, 260,); export const EXECUTOR_SOURCES_ADD_INPUT_SCHEMA = deriveSchemaJson( ExecutorAddSourceInputSchema,) ?? {}; export const EXECUTOR_SOURCES_ADD_OUTPUT_SCHEMA = deriveSchemaJson( SourceSchema,) ?? {}; export const EXECUTOR_SOURCES_ADD_HELP_LINES = [ "Source add input shapes:", ...executorAddableSourceAdapters.flatMap((adapter) => adapter.executorAddInputSchema && adapter.executorAddInputSignatureWidth !== null && adapter.executorAddHelpText ? [ `- ${adapter.displayName}: ${deriveSchemaTypeSignature(adapter.executorAddInputSchema, adapter.executorAddInputSignatureWidth)}`, ...adapter.executorAddHelpText.map((line) => ` ${line}`), ] : [], ), " executor handles the credential setup for you.",] as const; export const buildExecutorSourcesAddDescription = (): string => [ "Add an MCP, OpenAPI, or GraphQL source to the current workspace.", ...EXECUTOR_SOURCES_ADD_HELP_LINES, ].join("\n"); const toExecutionId = (value: unknown) => { if (typeof value !== "string" || value.trim().length === 0) { throw new Error("Missing execution run id for executor.sources.add"); } return ExecutionIdSchema.make(value);}; const asToolPath = (value: string): ToolPath => value as ToolPath; const trimOrNull = (value: string | null | undefined): string | null => { if (value === null || value === undefined) { return null; } const trimmed = value.trim(); return trimmed.length > 0 ? trimmed : null;}; const toSerializableValue = <A>(value: A): A => JSON.parse(JSON.stringify(value)) as A; const resolveLocalCredentialUrl = (input: { baseUrl: string; workspaceId: WorkspaceId; sourceId: Source["id"]; executionId: string; interactionId: string;}): string => new URL( `/v1/workspaces/${encodeURIComponent(input.workspaceId)}/sources/${encodeURIComponent(input.sourceId)}/credentials?interactionId=${encodeURIComponent(`${input.executionId}:${input.interactionId}`)}`, input.baseUrl, ).toString(); const promptForSourceCredentialSelection = (input: { args: { workspaceId: WorkspaceId; sourceId: Source["id"]; kind: "openapi" | "graphql" | "google_discovery"; endpoint?: string; specUrl?: string; service?: string; version?: string; discoveryUrl?: string | null; name?: string | null; namespace?: string | null; }; credentialSlot: "runtime" | "import"; source: Source; executionId: string; interactionId: string; path: ToolPath; sourceKey: string; localServerBaseUrl: string | null; metadata?: ToolMetadata; invocation?: ToolInvocationContext; onElicitation?: OnElicitation;}) => Effect.gen(function* () { if (!input.onElicitation) { return yield* Effect.fail( new Error("executor.sources.add requires an elicitation-capable host"), ); } if (input.localServerBaseUrl === null) { return yield* Effect.fail( new Error("executor.sources.add requires a local server base URL for credential capture"), ); } const response: ElicitationResponse = yield* input.onElicitation({ interactionId: input.interactionId, path: input.path, sourceKey: input.sourceKey, args: input.args, metadata: input.metadata, context: input.invocation, elicitation: { mode: "url", message: input.credentialSlot === "import" ? `Open the secure credential page to configure import access for ${input.source.name}` : `Open the secure credential page to connect ${input.source.name}`, url: resolveLocalCredentialUrl({ baseUrl: input.localServerBaseUrl, workspaceId: input.args.workspaceId, sourceId: input.args.sourceId, executionId: input.executionId, interactionId: input.interactionId, }), elicitationId: input.interactionId, }, }).pipe(Effect.mapError((cause) => cause instanceof Error ? cause : new Error(String(cause)))); if (response.action !== "accept") { return yield* Effect.fail( new Error(`Source credential setup was not completed for ${input.source.name}`), ); } const content = yield* Effect.try({ try: () => decodeSourceCredentialSelectionContent(response.content), catch: () => new Error("Credential capture did not return a valid source auth choice for executor.sources.add"), }); if (content.authKind === "none") { return { kind: "none" } satisfies ExecutorHttpSourceAuthInput; } return { kind: "bearer", tokenRef: content.tokenRef, } satisfies ExecutorHttpSourceAuthInput; }); export const createExecutorToolMap = (input: { workspaceId: WorkspaceId; accountId: AccountId; sourceAuthService: RuntimeSourceAuthService; runtimeLocalWorkspace: RuntimeLocalWorkspaceState | null;}): ToolMap => ({ "executor.sources.add": toTool({ tool: { description: buildExecutorSourcesAddDescription(), inputSchema: ExecutorSourcesAddInputSchema, outputSchema: ExecutorSourcesAddOutputSchema, execute: async ( args: | { kind?: "mcp"; endpoint: string; name?: string | null; namespace?: string | null; } | { kind: "openapi"; endpoint: string; specUrl: string; name?: string | null; namespace?: string | null; } | { kind: "graphql"; endpoint: string; name?: string | null; namespace?: string | null; } | { kind: "google_discovery"; service: string; version: string; discoveryUrl?: string | null; name?: string | null; namespace?: string | null; }, context, ): Promise<Source> => { const executionId = toExecutionId(context?.invocation?.runId); const interactionId = ExecutionInteractionIdSchema.make( `executor.sources.add:${crypto.randomUUID()}`, ); const preparedArgs: ExecutorAddSourceInput = args.kind === undefined || args.kind === "mcp" ? { kind: args.kind, endpoint: args.endpoint, name: args.name ?? null, namespace: args.namespace ?? null, workspaceId: input.workspaceId, actorAccountId: input.accountId, executionId, interactionId, } : { ...args, workspaceId: input.workspaceId, actorAccountId: input.accountId, executionId, interactionId, }; let result = await runEffect( input.sourceAuthService.addExecutorSource( preparedArgs, context?.onElicitation ? { mcpDiscoveryElicitation: { onElicitation: context.onElicitation, path: context.path ?? asToolPath("executor.sources.add"), sourceKey: context.sourceKey, args, metadata: context.metadata, invocation: context.invocation, }, } : undefined, ), input.runtimeLocalWorkspace, ); if (result.kind === "connected") { return toSerializableValue(result.source); } if (result.kind === "credential_required") { let pendingResult = result; let pendingArgs = preparedArgs as Extract< ExecutorAddSourceInput, { kind: "openapi" | "graphql" | "google_discovery" } >; while (pendingResult.kind === "credential_required") { const selectedAuth = await runEffect( promptForSourceCredentialSelection({ args: { ...pendingArgs, workspaceId: input.workspaceId, sourceId: pendingResult.source.id, }, credentialSlot: pendingResult.credentialSlot, source: pendingResult.source, executionId, interactionId, path: context?.path ?? asToolPath("executor.sources.add"), sourceKey: context?.sourceKey ?? "executor", localServerBaseUrl: input.sourceAuthService.getLocalServerBaseUrl(), metadata: context?.metadata, invocation: context?.invocation, onElicitation: context?.onElicitation, }), input.runtimeLocalWorkspace, ); pendingArgs = pendingResult.credentialSlot === "import" && pendingArgs.importAuthPolicy === "separate" ? { ...pendingArgs, importAuth: selectedAuth, } : { ...pendingArgs, auth: selectedAuth, }; const completed = await runEffect( input.sourceAuthService.addExecutorSource( pendingArgs, context?.onElicitation ? { mcpDiscoveryElicitation: { onElicitation: context.onElicitation, path: context.path ?? asToolPath("executor.sources.add"), sourceKey: context.sourceKey, args, metadata: context.metadata, invocation: context.invocation, }, } : undefined, ), input.runtimeLocalWorkspace, ); if (completed.kind === "connected") { return toSerializableValue(completed.source); } if (completed.kind === "credential_required") { pendingResult = completed; continue; } result = completed; break; } if (pendingResult.kind === "credential_required") { result = pendingResult; } } if (!context?.onElicitation) { throw new Error("executor.sources.add requires an elicitation-capable host"); } if (result.kind !== "oauth_required") { throw new Error(`Source add did not reach OAuth continuation for ${result.source.id}`); } const response: ElicitationResponse = await runEffect( context.onElicitation({ interactionId, path: context.path ?? asToolPath("executor.sources.add"), sourceKey: context.sourceKey, args: preparedArgs, metadata: context.metadata, context: context.invocation, elicitation: { mode: "url", message: `Open the provider sign-in page to connect ${result.source.name}`, url: result.authorizationUrl, elicitationId: result.sessionId, }, }), input.runtimeLocalWorkspace, ); if (response.action !== "accept") { throw new Error(`Source add was not completed for ${result.source.id}`); } const connected = await runEffect( input.sourceAuthService.getSourceById({ workspaceId: input.workspaceId, sourceId: result.source.id, actorAccountId: input.accountId, }), input.runtimeLocalWorkspace, ); return toSerializableValue(connected); }, }, metadata: { inputTypePreview: EXECUTOR_SOURCES_ADD_INPUT_HINT, outputTypePreview: EXECUTOR_SOURCES_ADD_OUTPUT_SIGNATURE, inputSchema: EXECUTOR_SOURCES_ADD_INPUT_SCHEMA, outputSchema: EXECUTOR_SOURCES_ADD_OUTPUT_SCHEMA, sourceKey: "executor", interaction: "auto", }, }),});
import {
type ElicitationResponse,
type OnElicitation,
type ToolInvocationContext,
type ToolMetadata,
toTool,
type ToolMap,
type ToolPath,
} from "@executor/codemode-core";
import {
type AccountId,
ExecutionIdSchema,
ExecutionInteractionIdSchema,
SourceSchema,
type Source,
type WorkspaceId,
} from "#schema";
import * as Effect from "effect/Effect";
import * as Cause from "effect/Cause";
import * as Exit from "effect/Exit";
import * as Schema from "effect/Schema";
import type { RuntimeLocalWorkspaceState } from "./local-runtime-context";
import {
type LocalStorageServices,
LocalInstallationStore,
LocalSourceArtifactStore,
LocalWorkspaceConfigStore,
LocalWorkspaceStateStore,
makeLocalStorageLayer,
} from "./local-storage";
import { provideOptionalRuntimeLocalWorkspace } from "./local-runtime-context";
/** Run an Effect as a Promise, preserving the original error (not FiberFailure). */
const runEffect = async <A>(
effect: Effect.Effect<A, unknown, LocalStorageServices>,
runtimeLocalWorkspace: RuntimeLocalWorkspaceState | null = null,
): Promise<A> => {
const baseLayer = makeLocalStorageLayer({
installationStore: LocalInstallationStore,
workspaceConfigStore: LocalWorkspaceConfigStore,
workspaceStateStore: LocalWorkspaceStateStore,
sourceArtifactStore: LocalSourceArtifactStore,
});
const exit = await Effect.runPromiseExit(
provideOptionalRuntimeLocalWorkspace(
effect.pipe(Effect.provide(baseLayer)),
runtimeLocalWorkspace,
),
);
if (Exit.isSuccess(exit)) return exit.value;
throw Cause.squash(exit.cause);
};
import {
type ExecutorAddSourceInput,
type ExecutorHttpSourceAuthInput,
type RuntimeSourceAuthService,
} from "./source-auth-service";
import {
deriveSchemaJson,
deriveSchemaTypeSignature,
} from "./schema-type-signature";
import {
ExecutorAddSourceInputSchema,
executorAddableSourceAdapters,
} from "./source-adapters";
import { decodeSourceCredentialSelectionContent } from "./source-credential-interactions";
const ExecutorSourcesAddInputSchema = Schema.standardSchemaV1(
ExecutorAddSourceInputSchema,
);
const ExecutorSourcesAddOutputSchema = Schema.standardSchemaV1(SourceSchema);
export const EXECUTOR_SOURCES_ADD_INPUT_HINT = deriveSchemaTypeSignature(
ExecutorAddSourceInputSchema,
320,
);
export const EXECUTOR_SOURCES_ADD_OUTPUT_SIGNATURE = deriveSchemaTypeSignature(
SourceSchema,
260,
);
export const EXECUTOR_SOURCES_ADD_INPUT_SCHEMA = deriveSchemaJson(
ExecutorAddSourceInputSchema,
) ?? {};
export const EXECUTOR_SOURCES_ADD_OUTPUT_SCHEMA = deriveSchemaJson(
SourceSchema,
) ?? {};
export const EXECUTOR_SOURCES_ADD_HELP_LINES = [
"Source add input shapes:",
...executorAddableSourceAdapters.flatMap((adapter) =>
adapter.executorAddInputSchema
&& adapter.executorAddInputSignatureWidth !== null
&& adapter.executorAddHelpText
? [
`- ${adapter.displayName}: ${deriveSchemaTypeSignature(adapter.executorAddInputSchema, adapter.executorAddInputSignatureWidth)}`,
...adapter.executorAddHelpText.map((line) => ` ${line}`),
]
: [],
),
" executor handles the credential setup for you.",
] as const;
export const buildExecutorSourcesAddDescription = (): string =>
[
"Add an MCP, OpenAPI, or GraphQL source to the current workspace.",
...EXECUTOR_SOURCES_ADD_HELP_LINES,
].join("\n");
const toExecutionId = (value: unknown) => {
if (typeof value !== "string" || value.trim().length === 0) {
throw new Error("Missing execution run id for executor.sources.add");
}
return ExecutionIdSchema.make(value);
};
const asToolPath = (value: string): ToolPath => value as ToolPath;
const trimOrNull = (value: string | null | undefined): string | null => {
if (value === null || value === undefined) {
return null;
}
const trimmed = value.trim();
return trimmed.length > 0 ? trimmed : null;
};
const toSerializableValue = <A>(value: A): A =>
JSON.parse(JSON.stringify(value)) as A;
const resolveLocalCredentialUrl = (input: {
baseUrl: string;
workspaceId: WorkspaceId;
sourceId: Source["id"];
executionId: string;
interactionId: string;
}): string =>
new URL(
`/v1/workspaces/${encodeURIComponent(input.workspaceId)}/sources/${encodeURIComponent(input.sourceId)}/credentials?interactionId=${encodeURIComponent(`${input.executionId}:${input.interactionId}`)}`,
input.baseUrl,
).toString();
const promptForSourceCredentialSelection = (input: {
args: {
workspaceId: WorkspaceId;
sourceId: Source["id"];
kind: "openapi" | "graphql" | "google_discovery";
endpoint?: string;
specUrl?: string;
service?: string;
version?: string;
discoveryUrl?: string | null;
name?: string | null;
namespace?: string | null;
};
credentialSlot: "runtime" | "import";
source: Source;
executionId: string;
interactionId: string;
path: ToolPath;
sourceKey: string;
localServerBaseUrl: string | null;
metadata?: ToolMetadata;
invocation?: ToolInvocationContext;
onElicitation?: OnElicitation;
}) =>
Effect.gen(function* () {
if (!input.onElicitation) {
return yield* Effect.fail(
new Error("executor.sources.add requires an elicitation-capable host"),
);
}
if (input.localServerBaseUrl === null) {
return yield* Effect.fail(
new Error("executor.sources.add requires a local server base URL for credential capture"),
);
}
const response: ElicitationResponse = yield* input.onElicitation({
interactionId: input.interactionId,
path: input.path,
sourceKey: input.sourceKey,
args: input.args,
metadata: input.metadata,
context: input.invocation,
elicitation: {
mode: "url",
message:
input.credentialSlot === "import"
? `Open the secure credential page to configure import access for ${input.source.name}`
: `Open the secure credential page to connect ${input.source.name}`,
url: resolveLocalCredentialUrl({
baseUrl: input.localServerBaseUrl,
workspaceId: input.args.workspaceId,
sourceId: input.args.sourceId,
executionId: input.executionId,
interactionId: input.interactionId,
}),
elicitationId: input.interactionId,
},
}).pipe(Effect.mapError((cause) => cause instanceof Error ? cause : new Error(String(cause))));
if (response.action !== "accept") {
return yield* Effect.fail(
new Error(`Source credential setup was not completed for ${input.source.name}`),
);
}
const content = yield* Effect.try({
try: () => decodeSourceCredentialSelectionContent(response.content),
catch: () =>
new Error("Credential capture did not return a valid source auth choice for executor.sources.add"),
});
if (content.authKind === "none") {
return { kind: "none" } satisfies ExecutorHttpSourceAuthInput;
}
return {
kind: "bearer",
tokenRef: content.tokenRef,
} satisfies ExecutorHttpSourceAuthInput;
});
export const createExecutorToolMap = (input: {
workspaceId: WorkspaceId;
accountId: AccountId;
sourceAuthService: RuntimeSourceAuthService;
runtimeLocalWorkspace: RuntimeLocalWorkspaceState | null;
}): ToolMap => ({
"executor.sources.add": toTool({
tool: {
description: buildExecutorSourcesAddDescription(),
inputSchema: ExecutorSourcesAddInputSchema,
outputSchema: ExecutorSourcesAddOutputSchema,
execute: async (
args:
| {
kind?: "mcp";
endpoint: string;
name?: string | null;
namespace?: string | null;
}
| {
kind: "openapi";
endpoint: string;
specUrl: string;
name?: string | null;
namespace?: string | null;
}
| {
kind: "graphql";
endpoint: string;
name?: string | null;
namespace?: string | null;
}
| {
kind: "google_discovery";
service: string;
version: string;
discoveryUrl?: string | null;
name?: string | null;
namespace?: string | null;
},
context,
): Promise<Source> => {
const executionId = toExecutionId(context?.invocation?.runId);
const interactionId = ExecutionInteractionIdSchema.make(
`executor.sources.add:${crypto.randomUUID()}`,
);
const preparedArgs: ExecutorAddSourceInput =
args.kind === undefined || args.kind === "mcp"
? {
kind: args.kind,
endpoint: args.endpoint,
name: args.name ?? null,
namespace: args.namespace ?? null,
workspaceId: input.workspaceId,
actorAccountId: input.accountId,
executionId,
interactionId,
}
: {
...args,
workspaceId: input.workspaceId,
actorAccountId: input.accountId,
executionId,
interactionId,
};
let result = await runEffect(
input.sourceAuthService.addExecutorSource(
preparedArgs,
context?.onElicitation
? {
mcpDiscoveryElicitation: {
onElicitation: context.onElicitation,
path: context.path ?? asToolPath("executor.sources.add"),
sourceKey: context.sourceKey,
args,
metadata: context.metadata,
invocation: context.invocation,
},
}
: undefined,
),
input.runtimeLocalWorkspace,
);
if (result.kind === "connected") {
return toSerializableValue(result.source);
}
if (result.kind === "credential_required") {
let pendingResult = result;
let pendingArgs = preparedArgs as Extract<
ExecutorAddSourceInput,
{ kind: "openapi" | "graphql" | "google_discovery" }
>;
while (pendingResult.kind === "credential_required") {
const selectedAuth = await runEffect(
promptForSourceCredentialSelection({
args: {
...pendingArgs,
workspaceId: input.workspaceId,
sourceId: pendingResult.source.id,
},
credentialSlot: pendingResult.credentialSlot,
source: pendingResult.source,
executionId,
interactionId,
path: context?.path ?? asToolPath("executor.sources.add"),
sourceKey: context?.sourceKey ?? "executor",
localServerBaseUrl: input.sourceAuthService.getLocalServerBaseUrl(),
metadata: context?.metadata,
invocation: context?.invocation,
onElicitation: context?.onElicitation,
}),
input.runtimeLocalWorkspace,
);
pendingArgs = pendingResult.credentialSlot === "import"
&& pendingArgs.importAuthPolicy === "separate"
? {
...pendingArgs,
importAuth: selectedAuth,
}
: {
...pendingArgs,
auth: selectedAuth,
};
const completed = await runEffect(
input.sourceAuthService.addExecutorSource(
pendingArgs,
context?.onElicitation
? {
mcpDiscoveryElicitation: {
onElicitation: context.onElicitation,
path: context.path ?? asToolPath("executor.sources.add"),
sourceKey: context.sourceKey,
args,
metadata: context.metadata,
invocation: context.invocation,
},
}
: undefined,
),
input.runtimeLocalWorkspace,
);
if (completed.kind === "connected") {
return toSerializableValue(completed.source);
}
if (completed.kind === "credential_required") {
pendingResult = completed;
continue;
}
result = completed;
break;
}
if (pendingResult.kind === "credential_required") {
result = pendingResult;
}
}
if (!context?.onElicitation) {
throw new Error("executor.sources.add requires an elicitation-capable host");
}
if (result.kind !== "oauth_required") {
throw new Error(`Source add did not reach OAuth continuation for ${result.source.id}`);
}
const response: ElicitationResponse = await runEffect(
context.onElicitation({
interactionId,
path: context.path ?? asToolPath("executor.sources.add"),
sourceKey: context.sourceKey,
args: preparedArgs,
metadata: context.metadata,
context: context.invocation,
elicitation: {
mode: "url",
message: `Open the provider sign-in page to connect ${result.source.name}`,
url: result.authorizationUrl,
elicitationId: result.sessionId,
},
}),
input.runtimeLocalWorkspace,
);
if (response.action !== "accept") {
throw new Error(`Source add was not completed for ${result.source.id}`);
}
const connected = await runEffect(
input.sourceAuthService.getSourceById({
workspaceId: input.workspaceId,
sourceId: result.source.id,
actorAccountId: input.accountId,
}),
input.runtimeLocalWorkspace,
);
return toSerializableValue(connected);
},
},
metadata: {
inputTypePreview: EXECUTOR_SOURCES_ADD_INPUT_HINT,
outputTypePreview: EXECUTOR_SOURCES_ADD_OUTPUT_SIGNATURE,
inputSchema: EXECUTOR_SOURCES_ADD_INPUT_SCHEMA,
outputSchema: EXECUTOR_SOURCES_ADD_OUTPUT_SCHEMA,
sourceKey: "executor",
interaction: "auto",
},
}),
});