diff --git a/.changeset/extract-base-adapter.md b/.changeset/extract-base-adapter.md new file mode 100644 index 00000000..23024bd2 --- /dev/null +++ b/.changeset/extract-base-adapter.md @@ -0,0 +1,12 @@ +--- +"@perstack/core": patch +"@perstack/docker": patch +"@perstack/claude-code": patch +"@perstack/cursor": patch +"@perstack/gemini": patch +"@perstack/runtime": patch +--- + +refactor: extract BaseAdapter from @perstack/core to @perstack/adapter-base + +This makes @perstack/core client-safe by removing child_process dependency. diff --git a/apps/runtime/package.json b/apps/runtime/package.json index 0c275583..b70bf4f0 100644 --- a/apps/runtime/package.json +++ b/apps/runtime/package.json @@ -41,6 +41,7 @@ "@ai-sdk/openai": "^2.0.0", "@modelcontextprotocol/sdk": "^1.25.1", "@paralleldrive/cuid2": "^3.0.4", + "@perstack/adapter-base": "workspace:*", "@perstack/api-client": "workspace:*", "@perstack/base": "workspace:*", "@perstack/core": "workspace:*", diff --git a/apps/runtime/src/perstack-adapter.ts b/apps/runtime/src/perstack-adapter.ts index 40a33a20..b6cc8087 100644 --- a/apps/runtime/src/perstack-adapter.ts +++ b/apps/runtime/src/perstack-adapter.ts @@ -1,5 +1,6 @@ import type { ChildProcess } from "node:child_process" import { spawn } from "node:child_process" +import { BaseAdapter } from "@perstack/adapter-base" import type { AdapterRunParams, AdapterRunResult, @@ -11,7 +12,7 @@ import type { RuntimeEvent, RuntimeExpertConfig, } from "@perstack/core" -import { BaseAdapter, checkpointSchema, getFilteredEnv } from "@perstack/core" +import { checkpointSchema, getFilteredEnv } from "@perstack/core" import { findLockfile, loadLockfile } from "./helpers/index.js" import { run as perstackRun } from "./run.js" diff --git a/packages/core/src/adapters/index.ts b/packages/core/src/adapters/index.ts index 3498ef73..e2af1bd4 100644 --- a/packages/core/src/adapters/index.ts +++ b/packages/core/src/adapters/index.ts @@ -1,4 +1,3 @@ -export { BaseAdapter, type ExecResult } from "./base-adapter.js" export { type CreateCheckpointParams, createCallToolsEvent, diff --git a/packages/runtimes/adapter-base/package.json b/packages/runtimes/adapter-base/package.json new file mode 100644 index 00000000..d791c2ed --- /dev/null +++ b/packages/runtimes/adapter-base/package.json @@ -0,0 +1,42 @@ +{ + "private": true, + "version": "0.0.1", + "name": "@perstack/adapter-base", + "description": "Base adapter class for Perstack runtime adapters", + "author": "Wintermute Technologies, Inc.", + "license": "Apache-2.0", + "type": "module", + "exports": { + ".": "./src/index.ts" + }, + "publishConfig": { + "access": "public", + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + } + }, + "files": [ + "dist" + ], + "scripts": { + "clean": "rm -rf dist", + "build": "pnpm run clean && tsup --config ../../../tsup.config.ts", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "@perstack/core": "workspace:*" + }, + "devDependencies": { + "@tsconfig/node22": "^22.0.5", + "@types/node": "^25.0.3", + "tsup": "^8.5.1", + "typescript": "^5.9.3", + "vitest": "^4.0.16" + }, + "engines": { + "node": ">=22.0.0" + } +} diff --git a/packages/core/src/adapters/base-adapter.ts b/packages/runtimes/adapter-base/src/base-adapter.ts similarity index 96% rename from packages/core/src/adapters/base-adapter.ts rename to packages/runtimes/adapter-base/src/base-adapter.ts index cf64c92f..53c7f016 100644 --- a/packages/core/src/adapters/base-adapter.ts +++ b/packages/runtimes/adapter-base/src/base-adapter.ts @@ -1,13 +1,13 @@ import type { ChildProcess } from "node:child_process" import { spawn } from "node:child_process" -import type { Expert } from "../schemas/expert.js" import type { AdapterRunParams, AdapterRunResult, + Expert, PrerequisiteResult, RuntimeAdapter, RuntimeExpertConfig, -} from "./types.js" +} from "@perstack/core" export type ExecResult = { stdout: string diff --git a/packages/runtimes/adapter-base/src/index.ts b/packages/runtimes/adapter-base/src/index.ts new file mode 100644 index 00000000..4e6cedf3 --- /dev/null +++ b/packages/runtimes/adapter-base/src/index.ts @@ -0,0 +1 @@ +export { BaseAdapter, type ExecResult } from "./base-adapter.js" diff --git a/packages/runtimes/adapter-base/tsconfig.json b/packages/runtimes/adapter-base/tsconfig.json new file mode 100644 index 00000000..d42c9662 --- /dev/null +++ b/packages/runtimes/adapter-base/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "@tsconfig/node22/tsconfig.json", + "compilerOptions": { + "outDir": "./dist", + "rootDir": ".", + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "moduleResolution": "bundler", + "module": "ESNext", + "target": "ESNext", + "resolveJsonModule": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/runtimes/claude-code/package.json b/packages/runtimes/claude-code/package.json index 0fe31154..b021f3fc 100644 --- a/packages/runtimes/claude-code/package.json +++ b/packages/runtimes/claude-code/package.json @@ -28,6 +28,7 @@ }, "dependencies": { "@paralleldrive/cuid2": "^3.0.4", + "@perstack/adapter-base": "workspace:*", "@perstack/core": "workspace:*" }, "devDependencies": { diff --git a/packages/runtimes/claude-code/src/claude-code-adapter.ts b/packages/runtimes/claude-code/src/claude-code-adapter.ts index 027dd765..6bc11341 100644 --- a/packages/runtimes/claude-code/src/claude-code-adapter.ts +++ b/packages/runtimes/claude-code/src/claude-code-adapter.ts @@ -1,6 +1,7 @@ import type { ChildProcess } from "node:child_process" import { spawn } from "node:child_process" import { createId } from "@paralleldrive/cuid2" +import { BaseAdapter } from "@perstack/adapter-base" import type { AdapterRunParams, AdapterRunResult, @@ -13,7 +14,6 @@ import type { ToolMessage, } from "@perstack/core" import { - BaseAdapter, createCallToolsEvent, createCompleteRunEvent, createEmptyUsage, diff --git a/packages/runtimes/cursor/package.json b/packages/runtimes/cursor/package.json index 53859f4a..e37cd83f 100644 --- a/packages/runtimes/cursor/package.json +++ b/packages/runtimes/cursor/package.json @@ -28,6 +28,7 @@ }, "dependencies": { "@paralleldrive/cuid2": "^3.0.4", + "@perstack/adapter-base": "workspace:*", "@perstack/core": "workspace:*" }, "devDependencies": { diff --git a/packages/runtimes/cursor/src/cursor-adapter.ts b/packages/runtimes/cursor/src/cursor-adapter.ts index 82ae2643..8a7799d2 100644 --- a/packages/runtimes/cursor/src/cursor-adapter.ts +++ b/packages/runtimes/cursor/src/cursor-adapter.ts @@ -1,6 +1,7 @@ import type { ChildProcess } from "node:child_process" import { spawn } from "node:child_process" import { createId } from "@paralleldrive/cuid2" +import { BaseAdapter } from "@perstack/adapter-base" import type { AdapterRunParams, AdapterRunResult, @@ -13,7 +14,6 @@ import type { ToolMessage, } from "@perstack/core" import { - BaseAdapter, createCallToolsEvent, createCompleteRunEvent, createEmptyUsage, diff --git a/packages/runtimes/docker/package.json b/packages/runtimes/docker/package.json index 412f01c1..b71b29bf 100644 --- a/packages/runtimes/docker/package.json +++ b/packages/runtimes/docker/package.json @@ -28,6 +28,7 @@ "test": "vitest run" }, "dependencies": { + "@perstack/adapter-base": "workspace:*", "@perstack/core": "workspace:*", "smol-toml": "^1.5.2" }, diff --git a/packages/runtimes/docker/src/docker-adapter.ts b/packages/runtimes/docker/src/docker-adapter.ts index a489d849..dfb9a051 100644 --- a/packages/runtimes/docker/src/docker-adapter.ts +++ b/packages/runtimes/docker/src/docker-adapter.ts @@ -2,6 +2,7 @@ import type { ChildProcess, SpawnOptions } from "node:child_process" import * as fs from "node:fs" import * as os from "node:os" import * as path from "node:path" +import { BaseAdapter } from "@perstack/adapter-base" import type { AdapterRunParams, AdapterRunResult, @@ -13,7 +14,7 @@ import type { RuntimeEvent, RuntimeExpertConfig, } from "@perstack/core" -import { BaseAdapter, createRuntimeEvent } from "@perstack/core" +import { createRuntimeEvent } from "@perstack/core" import { generateBuildContext } from "./compose-generator.js" import { extractRequiredEnvVars, resolveEnvValues } from "./env-resolver.js" import { selectBuildStrategy } from "./lib/build-strategy.js" diff --git a/packages/runtimes/docker/src/lib/build-strategy.ts b/packages/runtimes/docker/src/lib/build-strategy.ts index 0c53daf9..e1c11ae6 100644 --- a/packages/runtimes/docker/src/lib/build-strategy.ts +++ b/packages/runtimes/docker/src/lib/build-strategy.ts @@ -1,5 +1,6 @@ import * as path from "node:path" -import type { ExecResult, RunEvent, RuntimeEvent } from "@perstack/core" +import type { ExecResult } from "@perstack/adapter-base" +import type { RunEvent, RuntimeEvent } from "@perstack/core" import { createRuntimeEvent } from "@perstack/core" import { parseBuildOutputLine } from "./output-parser.js" import type { ProcessFactory } from "./process-factory.js" diff --git a/packages/runtimes/docker/src/lib/test-utils.ts b/packages/runtimes/docker/src/lib/test-utils.ts index eafe790a..cc6c288a 100644 --- a/packages/runtimes/docker/src/lib/test-utils.ts +++ b/packages/runtimes/docker/src/lib/test-utils.ts @@ -1,6 +1,7 @@ import type { ChildProcess, SpawnOptions } from "node:child_process" import { EventEmitter } from "node:events" -import type { ExecResult, RunEvent, RuntimeEvent } from "@perstack/core" +import type { ExecResult } from "@perstack/adapter-base" +import type { RunEvent, RuntimeEvent } from "@perstack/core" import { vi } from "vitest" import { DockerAdapter } from "../docker-adapter.js" import type { ProcessFactory } from "./process-factory.js" diff --git a/packages/runtimes/gemini/package.json b/packages/runtimes/gemini/package.json index 3cd4286f..85e16bd8 100644 --- a/packages/runtimes/gemini/package.json +++ b/packages/runtimes/gemini/package.json @@ -28,6 +28,7 @@ }, "dependencies": { "@paralleldrive/cuid2": "^3.0.4", + "@perstack/adapter-base": "workspace:*", "@perstack/core": "workspace:*" }, "devDependencies": { diff --git a/packages/runtimes/gemini/src/gemini-adapter.ts b/packages/runtimes/gemini/src/gemini-adapter.ts index 0666078a..0ce2606f 100644 --- a/packages/runtimes/gemini/src/gemini-adapter.ts +++ b/packages/runtimes/gemini/src/gemini-adapter.ts @@ -1,6 +1,7 @@ import type { ChildProcess } from "node:child_process" import { spawn } from "node:child_process" import { createId } from "@paralleldrive/cuid2" +import { BaseAdapter } from "@perstack/adapter-base" import type { AdapterRunParams, AdapterRunResult, @@ -13,7 +14,6 @@ import type { ToolMessage, } from "@perstack/core" import { - BaseAdapter, createCallToolsEvent, createCompleteRunEvent, createEmptyUsage, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9167f6d7..0d8074d1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -240,6 +240,9 @@ importers: '@paralleldrive/cuid2': specifier: ^3.0.4 version: 3.0.4 + '@perstack/adapter-base': + specifier: workspace:* + version: link:../../packages/runtimes/adapter-base '@perstack/api-client': specifier: workspace:* version: link:../../packages/api-client @@ -751,11 +754,36 @@ importers: specifier: ^4.0.16 version: 4.0.16(@opentelemetry/api@1.9.0)(@types/node@25.0.3)(jiti@2.6.1)(jsdom@27.4.0)(lightningcss@1.30.2)(msw@2.12.4(@types/node@25.0.3)(typescript@5.9.3))(tsx@4.21.0)(yaml@2.8.2) + packages/runtimes/adapter-base: + dependencies: + '@perstack/core': + specifier: workspace:* + version: link:../../core + devDependencies: + '@tsconfig/node22': + specifier: ^22.0.5 + version: 22.0.5 + '@types/node': + specifier: ^25.0.3 + version: 25.0.3 + tsup: + specifier: ^8.5.1 + version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2) + typescript: + specifier: ^5.9.3 + version: 5.9.3 + vitest: + specifier: ^4.0.16 + version: 4.0.16(@opentelemetry/api@1.9.0)(@types/node@25.0.3)(jiti@2.6.1)(jsdom@27.4.0)(lightningcss@1.30.2)(msw@2.12.4(@types/node@25.0.3)(typescript@5.9.3))(tsx@4.21.0)(yaml@2.8.2) + packages/runtimes/claude-code: dependencies: '@paralleldrive/cuid2': specifier: ^3.0.4 version: 3.0.4 + '@perstack/adapter-base': + specifier: workspace:* + version: link:../adapter-base '@perstack/core': specifier: workspace:* version: link:../../core @@ -781,6 +809,9 @@ importers: '@paralleldrive/cuid2': specifier: ^3.0.4 version: 3.0.4 + '@perstack/adapter-base': + specifier: workspace:* + version: link:../adapter-base '@perstack/core': specifier: workspace:* version: link:../../core @@ -803,6 +834,9 @@ importers: packages/runtimes/docker: dependencies: + '@perstack/adapter-base': + specifier: workspace:* + version: link:../adapter-base '@perstack/core': specifier: workspace:* version: link:../../core @@ -831,6 +865,9 @@ importers: '@paralleldrive/cuid2': specifier: ^3.0.4 version: 3.0.4 + '@perstack/adapter-base': + specifier: workspace:* + version: link:../adapter-base '@perstack/core': specifier: workspace:* version: link:../../core