fix: port prepareClaudePromptBundle flow to claude_k8s adapter (FAR-11)
K8s Job pods were starting without the Paperclip skill loaded, so agents could not find their heartbeat procedure and reported "no issue content in my workspace" on every wake. Root cause: claude_local materialises skills into a PVC-backed prompt-bundle directory and passes --add-dir to Claude, but claude_k8s did neither. Changes: - Add src/server/prompt-cache.ts with prepareClaudePromptBundle (ported from adapter-claude-local). Writes skill symlinks and the agent's instructions file into a content-addressed bundle directory under the shared PVC (/paperclip/instances/.../claude-prompt-cache/<hash>/). - execute.ts: read desired skills and instructions file before building the Job manifest, then call prepareClaudePromptBundle and pass the resulting bundle to buildJobManifest. - job-manifest.ts: accept optional promptBundle in JobBuildInput; when present, pass --add-dir <bundle.addDir> and use bundle.instructionsFilePath for --append-system-prompt-file. Also fix: skip --append-system-prompt-file on session resumes to avoid wasting tokens on re-injection. - skills.ts: correct the detail string to reflect actual materialisation. - job-manifest.test.ts: add 5 new tests covering --add-dir injection, bundle path preference, session-resume skipping, and fallback behaviour. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
||||
renderTemplate,
|
||||
} from "@paperclipai/adapter-utils/server-utils";
|
||||
import { createHash } from "node:crypto";
|
||||
import type { ClaudePromptBundle } from "./prompt-cache.js";
|
||||
|
||||
/**
|
||||
* Build the shell command prefix that installs a native Node.js PostToolUse
|
||||
@@ -175,6 +176,8 @@ function parseKeyValueConfig(raw: unknown): Record<string, string> {
|
||||
export interface JobBuildInput {
|
||||
ctx: AdapterExecutionContext;
|
||||
selfPod: SelfPodInfo;
|
||||
/** Prepared prompt bundle (skills + instructions). When provided, --add-dir and --append-system-prompt-file use bundle paths. */
|
||||
promptBundle?: ClaudePromptBundle | null;
|
||||
}
|
||||
|
||||
/** When the prompt exceeds the env-var size limit, the manifest uses a
|
||||
@@ -327,7 +330,7 @@ function buildEnvVars(
|
||||
}
|
||||
|
||||
export function buildJobManifest(input: JobBuildInput): JobBuildResult {
|
||||
const { ctx, selfPod } = input;
|
||||
const { ctx, selfPod, promptBundle } = input;
|
||||
const { runId, agent, runtime, config: rawConfig, context } = ctx;
|
||||
const config = parseObject(rawConfig);
|
||||
|
||||
@@ -403,14 +406,22 @@ export function buildJobManifest(input: JobBuildInput): JobBuildResult {
|
||||
};
|
||||
|
||||
// Build Claude CLI args
|
||||
const instructionsFilePath = asString(config.instructionsFilePath, "").trim();
|
||||
// Prefer the bundle's materialized instructions file over the raw config path.
|
||||
// Never inject --append-system-prompt-file on session resumes — the instructions
|
||||
// are already in the session cache and re-injecting wastes tokens.
|
||||
const rawInstructionsFilePath = asString(config.instructionsFilePath, "").trim();
|
||||
const effectiveInstructionsFilePath =
|
||||
promptBundle?.instructionsFilePath ?? (rawInstructionsFilePath || null);
|
||||
const claudeArgs = ["--print", "-", "--output-format", "stream-json", "--verbose"];
|
||||
if (runtimeSessionId) claudeArgs.push("--resume", runtimeSessionId);
|
||||
if (dangerouslySkipPermissions) claudeArgs.push("--dangerously-skip-permissions");
|
||||
if (model) claudeArgs.push("--model", model);
|
||||
if (effort) claudeArgs.push("--effort", effort);
|
||||
if (maxTurns > 0) claudeArgs.push("--max-turns", String(maxTurns));
|
||||
if (instructionsFilePath) claudeArgs.push("--append-system-prompt-file", instructionsFilePath);
|
||||
if (effectiveInstructionsFilePath && !runtimeSessionId) {
|
||||
claudeArgs.push("--append-system-prompt-file", effectiveInstructionsFilePath);
|
||||
}
|
||||
if (promptBundle) claudeArgs.push("--add-dir", promptBundle.addDir);
|
||||
if (extraArgs.length > 0) claudeArgs.push(...extraArgs);
|
||||
|
||||
// Build env vars
|
||||
|
||||
Reference in New Issue
Block a user