diff --git a/package.json b/package.json index 417b365..64f86ad 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "paperclip-adapter-opencode-k8s", - "version": "0.1.21", + "version": "0.1.22", "description": "Paperclip adapter plugin that runs OpenCode agents as Kubernetes Jobs", "license": "MIT", "type": "module", diff --git a/src/server/execute.test.ts b/src/server/execute.test.ts index 485c514..80a7ebc 100644 --- a/src/server/execute.test.ts +++ b/src/server/execute.test.ts @@ -16,6 +16,13 @@ vi.mock("./job-manifest.js", () => ({ LARGE_PROMPT_THRESHOLD_BYTES: 256 * 1024, })); +// Prevent skill loading from reading real SKILL.md files during tests — the +// real filesystem read delays timer registration and breaks fake-timer tests. +vi.mock("@paperclipai/adapter-utils/server-utils", async (importOriginal) => { + const actual = await importOriginal(); + return { ...actual, readPaperclipRuntimeSkillEntries: vi.fn().mockResolvedValue([]) }; +}); + const MOCK_SELF_POD = { namespace: "test-ns", image: "test-image:latest", diff --git a/src/server/execute.ts b/src/server/execute.ts index a2c7165..09b68e7 100644 --- a/src/server/execute.ts +++ b/src/server/execute.ts @@ -2,6 +2,7 @@ import type { AdapterExecutionContext, AdapterExecutionResult } from "@paperclip import { inferOpenAiCompatibleBiller, redactHomePathUserSegments } from "@paperclipai/adapter-utils"; import { asString, asNumber, asBoolean, parseObject, readPaperclipRuntimeSkillEntries, resolvePaperclipDesiredSkillNames } from "@paperclipai/adapter-utils/server-utils"; import { readFile } from "node:fs/promises"; +import path from "node:path"; import { parseOpenCodeJsonl, isOpenCodeUnknownSessionError, @@ -928,14 +929,24 @@ export async function execute(ctx: AdapterExecutionContext): Promise e.key === key); if (entry?.source) { try { - const text = (await readFile(entry.source, "utf-8")).trim(); + // entry.source from listPaperclipSkillEntries is a directory; read SKILL.md from it. + // Fall back to reading entry.source directly for file-based paperclipRuntimeSkills entries. + let text: string; + try { + text = (await readFile(path.join(entry.source, "SKILL.md"), "utf-8")).trim(); + } catch { + text = (await readFile(entry.source, "utf-8")).trim(); + } if (text) skillTexts.push(text); } catch { // skip unreadable skill files — non-fatal diff --git a/src/server/job-manifest.ts b/src/server/job-manifest.ts index bfea102..8407596 100644 --- a/src/server/job-manifest.ts +++ b/src/server/job-manifest.ts @@ -286,7 +286,9 @@ export function buildJobManifest(input: JobBuildInput): JobBuildResult { // Build opencode CLI args const opencodeArgs = ["run", "--format", "json"]; - if (runtimeSessionId) opencodeArgs.push("--session", runtimeSessionId); + // resumeLastSession defaults to true (preserve existing behaviour); set to false to start fresh. + const resumeLastSession = asBoolean(config.resumeLastSession, true); + if (runtimeSessionId && resumeLastSession) opencodeArgs.push("--session", runtimeSessionId); if (model) opencodeArgs.push("--model", model); if (variant) opencodeArgs.push("--variant", variant); if (extraArgs.length > 0) opencodeArgs.push(...extraArgs);