Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 14 additions & 19 deletions apps/desktop/scripts/smoke-sidecar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@
*
* Flow:
* 1. Spin up a tiny local OpenAPI server (one operation, returns 42).
* 2. Write a temp executor.jsonc that points at it as a source.
* 3. Spawn the compiled `executor-sidecar` binary with EXECUTOR_PORT=0
* 2. Spawn the compiled `executor-sidecar` binary with EXECUTOR_PORT=0
* and parse the `EXECUTOR_READY:<port>` sentinel.
* 4. Connect via MCP streamable HTTP, call the `execute` tool with code
* that invokes the OpenAPI tool, assert the answer round-trips as 42.
* 3. Connect via MCP streamable HTTP, call the `execute` tool with code
* that registers and invokes the OpenAPI tool, assert the answer
* round-trips as 42.
*
* Run after `bun ./scripts/build-sidecar.ts`. Exits non-zero on any
* deviation so it can gate CI.
*/
import { mkdtemp, rm, writeFile } from "node:fs/promises";
import { mkdtemp, rm } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join, resolve } from "node:path";
import { spawn, type Subprocess } from "bun";
Expand Down Expand Up @@ -182,18 +182,6 @@ const main = async () => {
console.log(`[smoke-sidecar] scope: ${scopeDir}`);
console.log(`[smoke-sidecar] openapi: ${openapi.origin}`);

const config = {
sources: [
{
kind: "openapi",
spec: `${openapi.origin}/openapi.json`,
baseUrl: openapi.origin,
namespace: "petstore",
},
],
};
await writeFile(join(scopeDir, "executor.jsonc"), JSON.stringify(config, null, 2));

const proc = spawn({
cmd: [BINARY],
env: {
Expand Down Expand Up @@ -241,9 +229,16 @@ const main = async () => {
if (!hasExecute) fail(`MCP tools/list missing "execute": ${JSON.stringify(tools.tools)}`);

// Drive the running OpenAPI server through a multi-step orchestration
// in one execute. Covers: array list response, path param dispatch, and
// object responses — all going out over real HTTP from inside QuickJS.
// in one execute. Covers: source registration, array list response, path
// param dispatch, and object responses — all going out over real HTTP from
// inside QuickJS.
const code = `
await tools.executor.openapi.addSource({
scope: ${JSON.stringify(scopeDir)},
spec: ${JSON.stringify(`${openapi.origin}/openapi.json`)},
baseUrl: ${JSON.stringify(openapi.origin)},
namespace: "petstore",
});
const list = await tools.petstore.pets.listPets({});
const fetched = await tools.petstore.pets.getPet({ petId: list[1].id });
return {
Expand Down
6 changes: 3 additions & 3 deletions apps/desktop/src/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ import { SERVER_SETTINGS_USERNAME, type DesktopServerSettings } from "../shared/

// Pin userData to a friendly app-name-scoped dir BEFORE app.ready so every
// Electron-side consumer (electron-store, electron-log, window-state) lands
// at a predictable spot. User-mutable executor state (executor.jsonc,
// data.db) is pinned separately to ~/.executor in main/sidecar.ts — that
// path matches the CLI's default.
// at a predictable spot. User-mutable executor state (data.db and the optional
// executor.jsonc plugin manifest) is pinned separately to ~/.executor in
// main/sidecar.ts — that path matches the CLI's default.
app.setName("Executor");
app.setPath("userData", join(app.getPath("appData"), "Executor"));

Expand Down
15 changes: 8 additions & 7 deletions apps/desktop/src/main/sidecar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,14 @@ export async function startSidecar(options: StartOptions = {}): Promise<SidecarC
);
}

// executor.jsonc and data.db go to ~/.executor — the same path the CLI's
// `executor web` uses. Desktop and CLI share state on the same machine so
// sources/secrets/policies set up in one show up in the other, and
// user-facing commands like `executor mcp --scope ~/.executor` stay
// copy-paste-friendly. Electron's userData (set in main/index.ts) is
// still used for electron-store, electron-log, and window-state — those
// stay app-scoped to avoid colliding with anything else under HOME.
// data.db and the optional executor.jsonc plugin manifest live under
// ~/.executor — the same path the CLI's `executor web` uses. Desktop and CLI
// share state on the same machine so sources/secrets/policies set up in one
// show up in the other, and user-facing commands like
// `executor mcp --scope ~/.executor` stay copy-paste-friendly. Electron's
// userData (set in main/index.ts) is still used for electron-store,
// electron-log, and window-state — those stay app-scoped to avoid colliding
// with anything else under HOME.
const scopeDir = join(homedir(), ".executor");
mkdirSync(scopeDir, { recursive: true });

Expand Down
16 changes: 5 additions & 11 deletions apps/local/executor.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { defineExecutorConfig } from "@executor-js/sdk";
import type { ConfigFileSink } from "@executor-js/config";
import { openApiHttpPlugin } from "@executor-js/plugin-openapi/api";
import { mcpHttpPlugin } from "@executor-js/plugin-mcp/api";
import { googleDiscoveryHttpPlugin } from "@executor-js/plugin-google-discovery/api";
Expand All @@ -14,24 +13,19 @@ import { desktopSettingsPlugin } from "@executor-js/plugin-desktop-settings/serv
//
// Consumed by:
// - the schema-gen CLI (reads `plugin.schema` only; calls `plugins({})`)
// - the host runtime (calls `plugins({ configFile })` with a real sink)
// - the host runtime
//
// `TDeps` is inferred from the factory parameter annotation directly.
// First-party and third-party plugins use the same import-and-call flow.
// ---------------------------------------------------------------------------

interface LocalPluginDeps {
readonly configFile?: ConfigFileSink;
}

export default defineExecutorConfig({
dialect: "sqlite",
plugins: ({ configFile }: LocalPluginDeps = {}) =>
plugins: () =>
[
openApiHttpPlugin({ configFile }),
mcpHttpPlugin({ dangerouslyAllowStdioMCP: true, configFile }),
openApiHttpPlugin(),
mcpHttpPlugin({ dangerouslyAllowStdioMCP: true }),
googleDiscoveryHttpPlugin(),
graphqlHttpPlugin({ configFile }),
graphqlHttpPlugin(),
keychainPlugin(),
fileSecretsPlugin(),
onepasswordHttpPlugin(),
Expand Down
225 changes: 0 additions & 225 deletions apps/local/src/server/config-sync.boot.test.ts

This file was deleted.

Loading
Loading