Add RTK integration for token-optimized command output
When enableRtk is set in adapter config, the adapter: - Adds an init container (curlimages/curl) to download the RTK binary - Mounts RTK binary in the main container via shared emptyDir volume - Runs `rtk install claude-code` before invoking Claude to set up hooks - Disables RTK telemetry (RTK_NO_TELEMETRY=1) for automated environments - Supports optional rtkVersion config for pinning specific versions RTK filters CLI command output before it reaches the LLM context, reducing token consumption by ~80%. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -148,6 +148,10 @@ function buildEnvVars(
|
||||
// HOME must be /paperclip to match PVC mount and enable session resume
|
||||
merged.HOME = "/paperclip";
|
||||
|
||||
if (asBoolean(config.enableRtk, false)) {
|
||||
merged.RTK_NO_TELEMETRY = "1";
|
||||
}
|
||||
|
||||
// Convert to V1EnvVar array
|
||||
const envVars: k8s.V1EnvVar[] = Object.entries(merged).map(([name, value]) => ({
|
||||
name,
|
||||
@@ -171,6 +175,8 @@ export function buildJobManifest(input: JobBuildInput): JobBuildResult {
|
||||
// K8s Job pods are always unattended — no one to approve permission prompts
|
||||
const dangerouslySkipPermissions = asBoolean(config.dangerouslySkipPermissions, true);
|
||||
const extraArgs = asStringArray(config.extraArgs);
|
||||
const enableRtk = asBoolean(config.enableRtk, false);
|
||||
const rtkVersion = asString(config.rtkVersion, "latest");
|
||||
const timeoutSec = asNumber(config.timeoutSec, 0);
|
||||
const ttlSeconds = asNumber(config.ttlSecondsAfterFinished, 300);
|
||||
const resources = parseObject(config.resources);
|
||||
@@ -282,6 +288,11 @@ export function buildJobManifest(input: JobBuildInput): JobBuildResult {
|
||||
},
|
||||
];
|
||||
|
||||
if (enableRtk) {
|
||||
volumes.push({ name: "rtk-bin", emptyDir: {} });
|
||||
volumeMounts.push({ name: "rtk-bin", mountPath: "/tmp/rtk-bin" });
|
||||
}
|
||||
|
||||
// Mount shared PVC for /paperclip (session state, workspaces, data)
|
||||
if (selfPod.pvcClaimName) {
|
||||
volumes.push({
|
||||
@@ -326,7 +337,10 @@ export function buildJobManifest(input: JobBuildInput): JobBuildResult {
|
||||
|
||||
// Build the claude command string for the main container
|
||||
const claudeArgsEscaped = claudeArgs.map((a) => `'${a.replace(/'/g, "'\\''")}'`).join(" ");
|
||||
const mainCommand = `cat /tmp/prompt/prompt.txt | claude ${claudeArgsEscaped}`;
|
||||
const claudeCommand = `cat /tmp/prompt/prompt.txt | claude ${claudeArgsEscaped}`;
|
||||
const mainCommand = enableRtk
|
||||
? `export PATH="/tmp/rtk-bin:$PATH" && rtk install claude-code && ${claudeCommand}`
|
||||
: claudeCommand;
|
||||
|
||||
const job: k8s.V1Job = {
|
||||
apiVersion: "batch/v1",
|
||||
@@ -368,6 +382,28 @@ export function buildJobManifest(input: JobBuildInput): JobBuildResult {
|
||||
limits: { cpu: "100m", memory: "64Mi" },
|
||||
},
|
||||
},
|
||||
...(enableRtk
|
||||
? [
|
||||
{
|
||||
name: "install-rtk",
|
||||
image: "curlimages/curl:8.12.1",
|
||||
imagePullPolicy: "IfNotPresent" as const,
|
||||
command: [
|
||||
"sh",
|
||||
"-c",
|
||||
rtkVersion === "latest"
|
||||
? "curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh | RTK_INSTALL_DIR=/tmp/rtk-bin sh"
|
||||
: `curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh | RTK_INSTALL_DIR=/tmp/rtk-bin RTK_VERSION=${rtkVersion} sh`,
|
||||
],
|
||||
volumeMounts: [{ name: "rtk-bin", mountPath: "/tmp/rtk-bin" }],
|
||||
securityContext,
|
||||
resources: {
|
||||
requests: { cpu: "10m", memory: "32Mi" },
|
||||
limits: { cpu: "200m", memory: "128Mi" },
|
||||
},
|
||||
},
|
||||
]
|
||||
: []),
|
||||
],
|
||||
containers: [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user