@farhoodliquor/paperclip-adapter-opencode-k8s 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +56 -0
- package/dist/index.js.map +1 -0
- package/dist/server/execute.d.ts +3 -0
- package/dist/server/execute.d.ts.map +1 -0
- package/dist/server/execute.js +386 -0
- package/dist/server/execute.js.map +1 -0
- package/dist/server/index.d.ts +7 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +17 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/job-manifest.d.ts +17 -0
- package/dist/server/job-manifest.d.ts.map +1 -0
- package/dist/server/job-manifest.js +325 -0
- package/dist/server/job-manifest.js.map +1 -0
- package/dist/server/k8s-client.d.ts +37 -0
- package/dist/server/k8s-client.d.ts.map +1 -0
- package/dist/server/k8s-client.js +132 -0
- package/dist/server/k8s-client.js.map +1 -0
- package/dist/server/parse.d.ts +13 -0
- package/dist/server/parse.d.ts.map +1 -0
- package/dist/server/parse.js +97 -0
- package/dist/server/parse.js.map +1 -0
- package/dist/server/session.d.ts +3 -0
- package/dist/server/session.d.ts.map +1 -0
- package/dist/server/session.js +58 -0
- package/dist/server/session.js.map +1 -0
- package/dist/server/test.d.ts +3 -0
- package/dist/server/test.d.ts.map +1 -0
- package/dist/server/test.js +210 -0
- package/dist/server/test.js.map +1 -0
- package/dist/ui-parser.d.ts +20 -0
- package/dist/ui-parser.d.ts.map +1 -0
- package/dist/ui-parser.js +8 -0
- package/dist/ui-parser.js.map +1 -0
- package/package.json +34 -0
package/README.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# @farhoodliquor/paperclip-adapter-opencode-k8s
|
|
2
|
+
|
|
3
|
+
Paperclip adapter plugin that runs OpenCode agents as isolated Kubernetes Jobs instead of inside the main Paperclip process.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Spawns agent runs as K8s Jobs with full pod isolation
|
|
8
|
+
- Inherits container image, secrets, DNS, and PVC from the Paperclip Deployment automatically
|
|
9
|
+
- Real-time log streaming from Job pods back to the Paperclip UI
|
|
10
|
+
- Session resume via shared RWX PVC
|
|
11
|
+
- Per-agent concurrency guard
|
|
12
|
+
- Configurable resources, namespace, kubeconfig
|
|
13
|
+
- Runtime config injection for permission bypass
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
### Via Paperclip Adapter Manager
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
curl -X POST http://localhost:3100/api/adapters \
|
|
21
|
+
-H "Content-Type: application/json" \
|
|
22
|
+
-d '{"packageName": "@farhoodliquor/paperclip-adapter-opencode-k8s"}'
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Local Development
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
curl -X POST http://localhost:3100/api/adapters \
|
|
29
|
+
-H "Content-Type: application/json" \
|
|
30
|
+
-d '{"localPath": "/path/to/paperclip-adapter-opencode-k8s"}'
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Configuration
|
|
34
|
+
|
|
35
|
+
See the agent configuration documentation for all available fields:
|
|
36
|
+
|
|
37
|
+
- `model` (required) — OpenCode model in provider/model format
|
|
38
|
+
- `variant` — reasoning profile variant
|
|
39
|
+
- `namespace` — K8s namespace for Jobs
|
|
40
|
+
- `image` — Override container image
|
|
41
|
+
- `kubeconfig` — Path to kubeconfig file
|
|
42
|
+
- `resources` — CPU/memory requests and limits
|
|
43
|
+
- `timeoutSec` — Run timeout (0 = no timeout)
|
|
44
|
+
- `retainJobs` — Keep completed Jobs for debugging
|
|
45
|
+
|
|
46
|
+
## Requirements
|
|
47
|
+
|
|
48
|
+
- **Paperclip must be deployed on a Kubernetes cluster with a shared RWX PVC mounted at `/paperclip`** — this is required for session resume and workspace sharing between the Paperclip pod and agent Job pods
|
|
49
|
+
- Kubernetes cluster with RBAC permissions to create Jobs, list Pods, and read Pod logs
|
|
50
|
+
- `@paperclipai/adapter-utils` >= 0.3.0
|
|
51
|
+
|
|
52
|
+
## License
|
|
53
|
+
|
|
54
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const type = "opencode_k8s";
|
|
2
|
+
export declare const label = "OpenCode (Kubernetes)";
|
|
3
|
+
export declare const models: {
|
|
4
|
+
id: string;
|
|
5
|
+
label: string;
|
|
6
|
+
}[];
|
|
7
|
+
export declare const agentConfigurationDoc = "# opencode_k8s agent configuration\n\nAdapter: opencode_k8s\n\nRuns OpenCode inside an isolated Kubernetes Job pod instead of the main\nPaperclip process. The Job inherits the container image, imagePullSecrets,\nDNS config, and PVC from the running Paperclip Deployment automatically.\n\nCore fields:\n- model (string, required): OpenCode model id in provider/model format (e.g. anthropic/claude-sonnet-4-6)\n- variant (string, optional): provider-specific reasoning/profile variant passed as --variant\n- dangerouslySkipPermissions (boolean, optional): inject runtime config with permission.external_directory=allow; defaults to true\n- promptTemplate (string, optional): run prompt template\n- extraArgs (string[], optional): additional CLI args appended to the opencode command\n- env (object, optional): KEY=VALUE environment variables; overrides inherited vars from the Deployment\n\nKubernetes fields:\n- namespace (string, optional): namespace for Jobs; defaults to the Deployment namespace\n- image (string, optional): override container image; defaults to the running Deployment image\n- imagePullPolicy (string, optional): image pull policy; default \"IfNotPresent\"\n- kubeconfig (string, optional): absolute path to a kubeconfig file on disk; defaults to in-cluster service account auth\n- resources (object, optional): { requests: { cpu, memory }, limits: { cpu, memory } }\n- nodeSelector (object, optional): node selector for Job pods\n- tolerations (array, optional): tolerations for Job pods\n- labels (object, optional): extra labels added to Job metadata\n- ttlSecondsAfterFinished (number, optional): auto-cleanup delay; default 300\n- retainJobs (boolean, optional): skip cleanup on completion for debugging\n\nOperational fields:\n- timeoutSec (number, optional): run timeout in seconds; 0 means no timeout\n- graceSec (number, optional): additional grace before adapter gives up after Job deadline\n\nInherited from Deployment (no config needed):\n- ANTHROPIC_API_KEY, OPENAI_API_KEY, and other provider keys\n- CLAUDE_CODE_USE_BEDROCK, AWS_REGION, AWS_BEARER_TOKEN_BEDROCK\n- PAPERCLIP_API_URL\n- Container image, imagePullSecrets, DNS config, PVC mount, security context\n\nNotes:\n- Session resume works via the shared /paperclip PVC (HOME=/paperclip)\n- Skills are bundled in the container image\n- Prompts are delivered via a busybox init container writing to an emptyDir volume\n- Runtime config (permission.external_directory=allow) is written inside the Job container\n- OPENCODE_DISABLE_PROJECT_CONFIG=true is always set to prevent config file pollution\n";
|
|
8
|
+
export { createServerAdapter } from "./server/index.js";
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,IAAI,iBAAiB,CAAC;AACnC,eAAO,MAAM,KAAK,0BAA0B,CAAC;AAE7C,eAAO,MAAM,MAAM;;;GAMlB,CAAC;AAEF,eAAO,MAAM,qBAAqB,giFA4CjC,CAAC;AAEF,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export const type = "opencode_k8s";
|
|
2
|
+
export const label = "OpenCode (Kubernetes)";
|
|
3
|
+
export const models = [
|
|
4
|
+
{ id: "openai/gpt-5.2-codex", label: "openai/gpt-5.2-codex" },
|
|
5
|
+
{ id: "openai/gpt-5.4", label: "openai/gpt-5.4" },
|
|
6
|
+
{ id: "openai/gpt-5.2", label: "openai/gpt-5.2" },
|
|
7
|
+
{ id: "openai/gpt-5.1-codex-max", label: "openai/gpt-5.1-codex-max" },
|
|
8
|
+
{ id: "openai/gpt-5.1-codex-mini", label: "openai/gpt-5.1-codex-mini" },
|
|
9
|
+
];
|
|
10
|
+
export const agentConfigurationDoc = `# opencode_k8s agent configuration
|
|
11
|
+
|
|
12
|
+
Adapter: opencode_k8s
|
|
13
|
+
|
|
14
|
+
Runs OpenCode inside an isolated Kubernetes Job pod instead of the main
|
|
15
|
+
Paperclip process. The Job inherits the container image, imagePullSecrets,
|
|
16
|
+
DNS config, and PVC from the running Paperclip Deployment automatically.
|
|
17
|
+
|
|
18
|
+
Core fields:
|
|
19
|
+
- model (string, required): OpenCode model id in provider/model format (e.g. anthropic/claude-sonnet-4-6)
|
|
20
|
+
- variant (string, optional): provider-specific reasoning/profile variant passed as --variant
|
|
21
|
+
- dangerouslySkipPermissions (boolean, optional): inject runtime config with permission.external_directory=allow; defaults to true
|
|
22
|
+
- promptTemplate (string, optional): run prompt template
|
|
23
|
+
- extraArgs (string[], optional): additional CLI args appended to the opencode command
|
|
24
|
+
- env (object, optional): KEY=VALUE environment variables; overrides inherited vars from the Deployment
|
|
25
|
+
|
|
26
|
+
Kubernetes fields:
|
|
27
|
+
- namespace (string, optional): namespace for Jobs; defaults to the Deployment namespace
|
|
28
|
+
- image (string, optional): override container image; defaults to the running Deployment image
|
|
29
|
+
- imagePullPolicy (string, optional): image pull policy; default "IfNotPresent"
|
|
30
|
+
- kubeconfig (string, optional): absolute path to a kubeconfig file on disk; defaults to in-cluster service account auth
|
|
31
|
+
- resources (object, optional): { requests: { cpu, memory }, limits: { cpu, memory } }
|
|
32
|
+
- nodeSelector (object, optional): node selector for Job pods
|
|
33
|
+
- tolerations (array, optional): tolerations for Job pods
|
|
34
|
+
- labels (object, optional): extra labels added to Job metadata
|
|
35
|
+
- ttlSecondsAfterFinished (number, optional): auto-cleanup delay; default 300
|
|
36
|
+
- retainJobs (boolean, optional): skip cleanup on completion for debugging
|
|
37
|
+
|
|
38
|
+
Operational fields:
|
|
39
|
+
- timeoutSec (number, optional): run timeout in seconds; 0 means no timeout
|
|
40
|
+
- graceSec (number, optional): additional grace before adapter gives up after Job deadline
|
|
41
|
+
|
|
42
|
+
Inherited from Deployment (no config needed):
|
|
43
|
+
- ANTHROPIC_API_KEY, OPENAI_API_KEY, and other provider keys
|
|
44
|
+
- CLAUDE_CODE_USE_BEDROCK, AWS_REGION, AWS_BEARER_TOKEN_BEDROCK
|
|
45
|
+
- PAPERCLIP_API_URL
|
|
46
|
+
- Container image, imagePullSecrets, DNS config, PVC mount, security context
|
|
47
|
+
|
|
48
|
+
Notes:
|
|
49
|
+
- Session resume works via the shared /paperclip PVC (HOME=/paperclip)
|
|
50
|
+
- Skills are bundled in the container image
|
|
51
|
+
- Prompts are delivered via a busybox init container writing to an emptyDir volume
|
|
52
|
+
- Runtime config (permission.external_directory=allow) is written inside the Job container
|
|
53
|
+
- OPENCODE_DISABLE_PROJECT_CONFIG=true is always set to prevent config file pollution
|
|
54
|
+
`;
|
|
55
|
+
export { createServerAdapter } from "./server/index.js";
|
|
56
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,IAAI,GAAG,cAAc,CAAC;AACnC,MAAM,CAAC,MAAM,KAAK,GAAG,uBAAuB,CAAC;AAE7C,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,EAAE,EAAE,EAAE,sBAAsB,EAAE,KAAK,EAAE,sBAAsB,EAAE;IAC7D,EAAE,EAAE,EAAE,gBAAgB,EAAE,KAAK,EAAE,gBAAgB,EAAE;IACjD,EAAE,EAAE,EAAE,gBAAgB,EAAE,KAAK,EAAE,gBAAgB,EAAE;IACjD,EAAE,EAAE,EAAE,0BAA0B,EAAE,KAAK,EAAE,0BAA0B,EAAE;IACrE,EAAE,EAAE,EAAE,2BAA2B,EAAE,KAAK,EAAE,2BAA2B,EAAE;CACxE,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4CpC,CAAC;AAEF,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../src/server/execute.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AA2OlG,wBAAsB,OAAO,CAAC,GAAG,EAAE,uBAAuB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAuN3F"}
|
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
import { asString, asNumber, asBoolean, parseObject } from "@paperclipai/adapter-utils/server-utils";
|
|
2
|
+
function inferOpenAiCompatibleBiller(env, _fallback) {
|
|
3
|
+
if (env.OPENROUTER_API_KEY)
|
|
4
|
+
return "openrouter";
|
|
5
|
+
if (env.OPENAI_BASE_URL?.includes("openrouter"))
|
|
6
|
+
return "openrouter";
|
|
7
|
+
if (env.OPENAI_API_KEY)
|
|
8
|
+
return "openai";
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
import { parseOpenCodeJsonl, isOpenCodeUnknownSessionError, } from "./parse.js";
|
|
12
|
+
import { getSelfPodInfo, getBatchApi, getCoreApi, getLogApi } from "./k8s-client.js";
|
|
13
|
+
import { buildJobManifest } from "./job-manifest.js";
|
|
14
|
+
import { Writable } from "node:stream";
|
|
15
|
+
const POLL_INTERVAL_MS = 2000;
|
|
16
|
+
function parseModelProvider(model) {
|
|
17
|
+
if (!model)
|
|
18
|
+
return null;
|
|
19
|
+
const trimmed = model.trim();
|
|
20
|
+
if (!trimmed.includes("/"))
|
|
21
|
+
return null;
|
|
22
|
+
return trimmed.slice(0, trimmed.indexOf("/")).trim() || null;
|
|
23
|
+
}
|
|
24
|
+
async function waitForPod(namespace, jobName, timeoutMs, onLog, kubeconfigPath) {
|
|
25
|
+
const coreApi = getCoreApi(kubeconfigPath);
|
|
26
|
+
const deadline = Date.now() + timeoutMs;
|
|
27
|
+
const labelSelector = `job-name=${jobName}`;
|
|
28
|
+
await onLog("stdout", `[paperclip] Waiting for pod to be scheduled (job: ${jobName})...\n`);
|
|
29
|
+
let lastStatus = "";
|
|
30
|
+
while (Date.now() < deadline) {
|
|
31
|
+
const podList = await coreApi.listNamespacedPod({
|
|
32
|
+
namespace,
|
|
33
|
+
labelSelector,
|
|
34
|
+
});
|
|
35
|
+
const pod = podList.items[0];
|
|
36
|
+
if (!pod) {
|
|
37
|
+
if (lastStatus !== "no-pod") {
|
|
38
|
+
await onLog("stdout", `[paperclip] Waiting for Job controller to create pod...\n`);
|
|
39
|
+
lastStatus = "no-pod";
|
|
40
|
+
}
|
|
41
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const podName = pod.metadata?.name ?? "unknown";
|
|
45
|
+
const phase = pod.status?.phase ?? "Unknown";
|
|
46
|
+
const initStatuses = pod.status?.initContainerStatuses ?? [];
|
|
47
|
+
const containerStatuses = pod.status?.containerStatuses ?? [];
|
|
48
|
+
const statusKey = `${phase}:${initStatuses.map((s) => s.state?.waiting?.reason ?? s.state?.terminated?.reason ?? "ok").join(",")}:${containerStatuses.map((s) => s.state?.waiting?.reason ?? s.state?.running ? "running" : "waiting").join(",")}`;
|
|
49
|
+
if (statusKey !== lastStatus) {
|
|
50
|
+
const details = [`phase=${phase}`];
|
|
51
|
+
for (const init of initStatuses) {
|
|
52
|
+
if (init.state?.waiting)
|
|
53
|
+
details.push(`init/${init.name}: waiting (${init.state.waiting.reason ?? "unknown"})`);
|
|
54
|
+
else if (init.state?.running)
|
|
55
|
+
details.push(`init/${init.name}: running`);
|
|
56
|
+
else if (init.state?.terminated)
|
|
57
|
+
details.push(`init/${init.name}: done (exit ${init.state.terminated.exitCode})`);
|
|
58
|
+
}
|
|
59
|
+
for (const cs of containerStatuses) {
|
|
60
|
+
if (cs.state?.waiting)
|
|
61
|
+
details.push(`${cs.name}: waiting (${cs.state.waiting.reason ?? "unknown"})`);
|
|
62
|
+
else if (cs.state?.running)
|
|
63
|
+
details.push(`${cs.name}: running`);
|
|
64
|
+
}
|
|
65
|
+
await onLog("stdout", `[paperclip] Pod ${podName}: ${details.join(", ")}\n`);
|
|
66
|
+
lastStatus = statusKey;
|
|
67
|
+
}
|
|
68
|
+
if (phase === "Running" || phase === "Succeeded" || phase === "Failed") {
|
|
69
|
+
return podName;
|
|
70
|
+
}
|
|
71
|
+
const allInitsDone = initStatuses.length > 0 && initStatuses.every((s) => s.state?.terminated?.exitCode === 0);
|
|
72
|
+
const mainRunning = containerStatuses.some((s) => s.state?.running);
|
|
73
|
+
if (allInitsDone && mainRunning) {
|
|
74
|
+
return podName;
|
|
75
|
+
}
|
|
76
|
+
for (const init of initStatuses) {
|
|
77
|
+
const terminated = init.state?.terminated;
|
|
78
|
+
if (terminated && (terminated.exitCode ?? 0) !== 0) {
|
|
79
|
+
throw new Error(`Init container "${init.name}" failed with exit code ${terminated.exitCode}: ${terminated.reason ?? terminated.message ?? "unknown"}`);
|
|
80
|
+
}
|
|
81
|
+
const waiting = init.state?.waiting;
|
|
82
|
+
if (waiting?.reason === "ErrImagePull" || waiting?.reason === "ImagePullBackOff") {
|
|
83
|
+
throw new Error(`Init container "${init.name}" image pull failed: ${waiting.message ?? waiting.reason}`);
|
|
84
|
+
}
|
|
85
|
+
if (waiting?.reason === "CrashLoopBackOff") {
|
|
86
|
+
throw new Error(`Init container "${init.name}" crash loop: ${waiting.message ?? waiting.reason}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const conditions = pod.status?.conditions ?? [];
|
|
90
|
+
const unschedulable = conditions.find((c) => c.type === "PodScheduled" && c.status === "False" && c.reason === "Unschedulable");
|
|
91
|
+
if (unschedulable) {
|
|
92
|
+
throw new Error(`Pod unschedulable: ${unschedulable.message ?? "insufficient resources"}`);
|
|
93
|
+
}
|
|
94
|
+
for (const cs of containerStatuses) {
|
|
95
|
+
const waiting = cs.state?.waiting;
|
|
96
|
+
if (waiting?.reason === "ErrImagePull" || waiting?.reason === "ImagePullBackOff") {
|
|
97
|
+
throw new Error(`Image pull failed for "${cs.name}": ${waiting.message ?? waiting.reason}`);
|
|
98
|
+
}
|
|
99
|
+
if (waiting?.reason === "CrashLoopBackOff") {
|
|
100
|
+
throw new Error(`Container "${cs.name}" crash loop: ${waiting.message ?? waiting.reason}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
104
|
+
}
|
|
105
|
+
throw new Error(`Timed out waiting for pod to be scheduled (${Math.round(timeoutMs / 1000)}s)`);
|
|
106
|
+
}
|
|
107
|
+
async function streamPodLogs(namespace, podName, onLog, kubeconfigPath) {
|
|
108
|
+
const logApi = getLogApi(kubeconfigPath);
|
|
109
|
+
const chunks = [];
|
|
110
|
+
const writable = new Writable({
|
|
111
|
+
write(chunk, _encoding, callback) {
|
|
112
|
+
const text = chunk.toString("utf-8");
|
|
113
|
+
chunks.push(text);
|
|
114
|
+
void onLog("stdout", text).then(() => callback(), callback);
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
try {
|
|
118
|
+
await logApi.log(namespace, podName, "opencode", writable, {
|
|
119
|
+
follow: true,
|
|
120
|
+
pretty: false,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
// follow may fail if the container already exited
|
|
125
|
+
}
|
|
126
|
+
return chunks.join("");
|
|
127
|
+
}
|
|
128
|
+
async function readPodLogs(namespace, podName, kubeconfigPath) {
|
|
129
|
+
const coreApi = getCoreApi(kubeconfigPath);
|
|
130
|
+
try {
|
|
131
|
+
const log = await coreApi.readNamespacedPodLog({
|
|
132
|
+
name: podName,
|
|
133
|
+
namespace,
|
|
134
|
+
container: "opencode",
|
|
135
|
+
});
|
|
136
|
+
return typeof log === "string" ? log : "";
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
return "";
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
async function waitForJobCompletion(namespace, jobName, timeoutMs, kubeconfigPath) {
|
|
143
|
+
const batchApi = getBatchApi(kubeconfigPath);
|
|
144
|
+
const deadline = timeoutMs > 0 ? Date.now() + timeoutMs : 0;
|
|
145
|
+
while (deadline === 0 || Date.now() < deadline) {
|
|
146
|
+
const job = await batchApi.readNamespacedJob({ name: jobName, namespace });
|
|
147
|
+
const conditions = job.status?.conditions ?? [];
|
|
148
|
+
const complete = conditions.find((c) => c.type === "Complete" && c.status === "True");
|
|
149
|
+
if (complete)
|
|
150
|
+
return { succeeded: true, timedOut: false };
|
|
151
|
+
const failed = conditions.find((c) => c.type === "Failed" && c.status === "True");
|
|
152
|
+
if (failed) {
|
|
153
|
+
const isDeadlineExceeded = failed.reason === "DeadlineExceeded";
|
|
154
|
+
return { succeeded: false, timedOut: isDeadlineExceeded };
|
|
155
|
+
}
|
|
156
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
157
|
+
}
|
|
158
|
+
return { succeeded: false, timedOut: true };
|
|
159
|
+
}
|
|
160
|
+
async function getPodExitCode(namespace, jobName, kubeconfigPath) {
|
|
161
|
+
const coreApi = getCoreApi(kubeconfigPath);
|
|
162
|
+
const podList = await coreApi.listNamespacedPod({
|
|
163
|
+
namespace,
|
|
164
|
+
labelSelector: `job-name=${jobName}`,
|
|
165
|
+
});
|
|
166
|
+
const pod = podList.items[0];
|
|
167
|
+
if (!pod)
|
|
168
|
+
return null;
|
|
169
|
+
const containerStatus = pod.status?.containerStatuses?.find((s) => s.name === "opencode");
|
|
170
|
+
return containerStatus?.state?.terminated?.exitCode ?? null;
|
|
171
|
+
}
|
|
172
|
+
async function cleanupJob(namespace, jobName, onLog, kubeconfigPath) {
|
|
173
|
+
try {
|
|
174
|
+
const batchApi = getBatchApi(kubeconfigPath);
|
|
175
|
+
await batchApi.deleteNamespacedJob({
|
|
176
|
+
name: jobName,
|
|
177
|
+
namespace,
|
|
178
|
+
body: { propagationPolicy: "Background" },
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
catch (err) {
|
|
182
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
183
|
+
await onLog("stderr", `[paperclip] Warning: failed to cleanup job ${jobName}: ${msg}\n`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
export async function execute(ctx) {
|
|
187
|
+
const { runId, runtime, config: rawConfig, onLog, onMeta } = ctx;
|
|
188
|
+
const config = parseObject(rawConfig);
|
|
189
|
+
const timeoutSec = asNumber(config.timeoutSec, 0);
|
|
190
|
+
const graceSec = asNumber(config.graceSec, 60);
|
|
191
|
+
const retainJobs = asBoolean(config.retainJobs, false);
|
|
192
|
+
const kubeconfigPath = asString(config.kubeconfig, "") || undefined;
|
|
193
|
+
const model = asString(config.model, "").trim();
|
|
194
|
+
// Guard: single concurrency per agent (shared PVC/session)
|
|
195
|
+
const agentId = ctx.agent.id;
|
|
196
|
+
const selfPod = await getSelfPodInfo(kubeconfigPath);
|
|
197
|
+
const guardNamespace = asString(config.namespace, "") || selfPod.namespace;
|
|
198
|
+
try {
|
|
199
|
+
const batchApi = getBatchApi(kubeconfigPath);
|
|
200
|
+
const existing = await batchApi.listNamespacedJob({
|
|
201
|
+
namespace: guardNamespace,
|
|
202
|
+
labelSelector: `paperclip.io/agent-id=${agentId},paperclip.io/adapter-type=opencode_k8s`,
|
|
203
|
+
});
|
|
204
|
+
const running = existing.items.filter((j) => !j.status?.conditions?.some((c) => (c.type === "Complete" || c.type === "Failed") && c.status === "True"));
|
|
205
|
+
if (running.length > 0) {
|
|
206
|
+
const names = running.map((j) => j.metadata?.name).join(", ");
|
|
207
|
+
await onLog("stderr", `[paperclip] Concurrent run blocked: existing Job(s) still running for this agent: ${names}\n`);
|
|
208
|
+
return {
|
|
209
|
+
exitCode: null,
|
|
210
|
+
signal: null,
|
|
211
|
+
timedOut: false,
|
|
212
|
+
errorMessage: `Concurrent run blocked: Job ${names} is still running for this agent`,
|
|
213
|
+
errorCode: "k8s_concurrent_run_blocked",
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
// If we can't check, proceed — heartbeat service enforces concurrency too
|
|
219
|
+
}
|
|
220
|
+
const { job, jobName, namespace, prompt, opencodeArgs, promptMetrics } = buildJobManifest({
|
|
221
|
+
ctx,
|
|
222
|
+
selfPod,
|
|
223
|
+
});
|
|
224
|
+
if (onMeta) {
|
|
225
|
+
await onMeta({
|
|
226
|
+
adapterType: "opencode_k8s",
|
|
227
|
+
command: `kubectl job/${jobName}`,
|
|
228
|
+
cwd: namespace,
|
|
229
|
+
commandArgs: opencodeArgs,
|
|
230
|
+
commandNotes: [
|
|
231
|
+
`Image: ${job.spec?.template.spec?.containers[0]?.image ?? "unknown"}`,
|
|
232
|
+
`Namespace: ${namespace}`,
|
|
233
|
+
`Timeout: ${timeoutSec}s`,
|
|
234
|
+
],
|
|
235
|
+
prompt,
|
|
236
|
+
...(promptMetrics ? { promptMetrics } : {}),
|
|
237
|
+
context: ctx.context,
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
const batchApi = getBatchApi(kubeconfigPath);
|
|
241
|
+
try {
|
|
242
|
+
await batchApi.createNamespacedJob({ namespace, body: job });
|
|
243
|
+
}
|
|
244
|
+
catch (err) {
|
|
245
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
246
|
+
await onLog("stderr", `[paperclip] Failed to create K8s Job: ${msg}\n`);
|
|
247
|
+
return {
|
|
248
|
+
exitCode: null,
|
|
249
|
+
signal: null,
|
|
250
|
+
timedOut: false,
|
|
251
|
+
errorMessage: `Failed to create Kubernetes Job: ${msg}`,
|
|
252
|
+
errorCode: "k8s_job_create_failed",
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
await onLog("stdout", `[paperclip] Created K8s Job: ${jobName} in namespace ${namespace} (deadline: ${timeoutSec > 0 ? `${timeoutSec}s` : "none"})\n`);
|
|
256
|
+
let stdout = "";
|
|
257
|
+
let exitCode = null;
|
|
258
|
+
let jobTimedOut = false;
|
|
259
|
+
try {
|
|
260
|
+
const scheduleTimeoutMs = 120_000;
|
|
261
|
+
let podName;
|
|
262
|
+
try {
|
|
263
|
+
podName = await waitForPod(namespace, jobName, scheduleTimeoutMs, onLog, kubeconfigPath);
|
|
264
|
+
await onLog("stdout", `[paperclip] Pod running: ${podName}\n`);
|
|
265
|
+
}
|
|
266
|
+
catch (err) {
|
|
267
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
268
|
+
await onLog("stderr", `[paperclip] Pod scheduling failed: ${msg}\n`);
|
|
269
|
+
return {
|
|
270
|
+
exitCode: null,
|
|
271
|
+
signal: null,
|
|
272
|
+
timedOut: false,
|
|
273
|
+
errorMessage: `Pod scheduling failed: ${msg}`,
|
|
274
|
+
errorCode: "k8s_pod_schedule_failed",
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
const completionTimeoutMs = timeoutSec > 0 ? (timeoutSec + graceSec) * 1000 : 0;
|
|
278
|
+
const [logResult, completionResult] = await Promise.allSettled([
|
|
279
|
+
streamPodLogs(namespace, podName, onLog, kubeconfigPath),
|
|
280
|
+
waitForJobCompletion(namespace, jobName, completionTimeoutMs, kubeconfigPath),
|
|
281
|
+
]);
|
|
282
|
+
if (logResult.status === "fulfilled") {
|
|
283
|
+
stdout = logResult.value;
|
|
284
|
+
}
|
|
285
|
+
if (!stdout.trim()) {
|
|
286
|
+
await onLog("stdout", `[paperclip] Log stream returned empty — reading pod logs directly...\n`);
|
|
287
|
+
stdout = await readPodLogs(namespace, podName, kubeconfigPath);
|
|
288
|
+
if (stdout.trim()) {
|
|
289
|
+
await onLog("stdout", stdout);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
if (completionResult.status === "fulfilled") {
|
|
293
|
+
jobTimedOut = completionResult.value.timedOut;
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
jobTimedOut = true;
|
|
297
|
+
}
|
|
298
|
+
exitCode = await getPodExitCode(namespace, jobName, kubeconfigPath);
|
|
299
|
+
}
|
|
300
|
+
finally {
|
|
301
|
+
if (!retainJobs) {
|
|
302
|
+
await cleanupJob(namespace, jobName, onLog, kubeconfigPath);
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
await onLog("stdout", `[paperclip] Retaining job ${jobName} for debugging (retainJobs=true)\n`);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
if (jobTimedOut) {
|
|
309
|
+
return {
|
|
310
|
+
exitCode,
|
|
311
|
+
signal: null,
|
|
312
|
+
timedOut: true,
|
|
313
|
+
errorMessage: `Timed out after ${timeoutSec}s`,
|
|
314
|
+
errorCode: "timeout",
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
// Parse OpenCode JSONL output
|
|
318
|
+
const parsed = parseOpenCodeJsonl(stdout);
|
|
319
|
+
const runtimeSessionParams = parseObject(runtime.sessionParams);
|
|
320
|
+
const fallbackSessionId = asString(runtimeSessionParams.sessionId, runtime.sessionId ?? "");
|
|
321
|
+
const workspaceContext = parseObject(ctx.context.paperclipWorkspace);
|
|
322
|
+
const workspaceId = asString(workspaceContext.workspaceId, "") || null;
|
|
323
|
+
const workspaceRepoUrl = asString(workspaceContext.repoUrl, "") || null;
|
|
324
|
+
const workspaceRepoRef = asString(workspaceContext.repoRef, "") || null;
|
|
325
|
+
const cwd = asString(workspaceContext.cwd, "");
|
|
326
|
+
const resolvedSessionId = parsed.sessionId ?? (fallbackSessionId || null);
|
|
327
|
+
const resolvedSessionParams = resolvedSessionId
|
|
328
|
+
? {
|
|
329
|
+
sessionId: resolvedSessionId,
|
|
330
|
+
...(cwd ? { cwd } : {}),
|
|
331
|
+
...(workspaceId ? { workspaceId } : {}),
|
|
332
|
+
...(workspaceRepoUrl ? { repoUrl: workspaceRepoUrl } : {}),
|
|
333
|
+
...(workspaceRepoRef ? { repoRef: workspaceRepoRef } : {}),
|
|
334
|
+
}
|
|
335
|
+
: null;
|
|
336
|
+
const provider = parseModelProvider(model);
|
|
337
|
+
// Build a minimal env record for biller inference
|
|
338
|
+
const billerEnv = {};
|
|
339
|
+
for (const key of ["OPENAI_API_KEY", "OPENAI_BASE_URL", "OPENROUTER_API_KEY"]) {
|
|
340
|
+
const val = process.env[key];
|
|
341
|
+
if (val)
|
|
342
|
+
billerEnv[key] = val;
|
|
343
|
+
}
|
|
344
|
+
const biller = inferOpenAiCompatibleBiller(billerEnv, null) ?? provider ?? "unknown";
|
|
345
|
+
const parsedError = typeof parsed.errorMessage === "string" ? parsed.errorMessage.trim() : "";
|
|
346
|
+
const rawExitCode = exitCode;
|
|
347
|
+
const synthesizedExitCode = parsedError && (rawExitCode ?? 0) === 0 ? 1 : rawExitCode;
|
|
348
|
+
const failed = (synthesizedExitCode ?? 0) !== 0;
|
|
349
|
+
// If the session was stale, clear it so the next heartbeat starts fresh
|
|
350
|
+
if (failed && isOpenCodeUnknownSessionError(stdout, parsedError)) {
|
|
351
|
+
await onLog("stdout", `[paperclip] OpenCode session is unavailable; clearing for next run.\n`);
|
|
352
|
+
return {
|
|
353
|
+
exitCode: synthesizedExitCode,
|
|
354
|
+
signal: null,
|
|
355
|
+
timedOut: false,
|
|
356
|
+
errorMessage: parsedError || "Session unavailable",
|
|
357
|
+
errorCode: "session_unavailable",
|
|
358
|
+
clearSession: true,
|
|
359
|
+
resultJson: { stdout },
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
const firstStderrLine = stdout.split(/\r?\n/).map((l) => l.trim()).find(Boolean) ?? "";
|
|
363
|
+
const fallbackErrorMessage = parsedError || firstStderrLine || `OpenCode exited with code ${synthesizedExitCode ?? -1}`;
|
|
364
|
+
return {
|
|
365
|
+
exitCode: synthesizedExitCode,
|
|
366
|
+
signal: null,
|
|
367
|
+
timedOut: false,
|
|
368
|
+
errorMessage: (synthesizedExitCode ?? 0) === 0 ? null : fallbackErrorMessage,
|
|
369
|
+
usage: {
|
|
370
|
+
inputTokens: parsed.usage.inputTokens,
|
|
371
|
+
outputTokens: parsed.usage.outputTokens,
|
|
372
|
+
cachedInputTokens: parsed.usage.cachedInputTokens,
|
|
373
|
+
},
|
|
374
|
+
sessionId: resolvedSessionId,
|
|
375
|
+
sessionParams: resolvedSessionParams,
|
|
376
|
+
sessionDisplayId: resolvedSessionId,
|
|
377
|
+
provider,
|
|
378
|
+
model: model || null,
|
|
379
|
+
billingType: "unknown",
|
|
380
|
+
costUsd: parsed.costUsd,
|
|
381
|
+
resultJson: { stdout },
|
|
382
|
+
summary: parsed.summary,
|
|
383
|
+
clearSession: false,
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
//# sourceMappingURL=execute.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execute.js","sourceRoot":"","sources":["../../src/server/execute.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ServerAdapterModule } from "@paperclipai/adapter-utils";
|
|
2
|
+
import { execute } from "./execute.js";
|
|
3
|
+
import { testEnvironment } from "./test.js";
|
|
4
|
+
import { sessionCodec } from "./session.js";
|
|
5
|
+
export declare function createServerAdapter(): ServerAdapterModule;
|
|
6
|
+
export { execute, testEnvironment, sessionCodec };
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEtE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,wBAAgB,mBAAmB,IAAI,mBAAmB,CAUzD;AAED,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type, models, agentConfigurationDoc } from "../index.js";
|
|
2
|
+
import { execute } from "./execute.js";
|
|
3
|
+
import { testEnvironment } from "./test.js";
|
|
4
|
+
import { sessionCodec } from "./session.js";
|
|
5
|
+
export function createServerAdapter() {
|
|
6
|
+
return {
|
|
7
|
+
type,
|
|
8
|
+
execute,
|
|
9
|
+
testEnvironment,
|
|
10
|
+
sessionCodec,
|
|
11
|
+
models,
|
|
12
|
+
supportsLocalAgentJwt: true,
|
|
13
|
+
agentConfigurationDoc,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export { execute, testEnvironment, sessionCodec };
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,UAAU,mBAAmB;IACjC,OAAO;QACL,IAAI;QACJ,OAAO;QACP,eAAe;QACf,YAAY;QACZ,MAAM;QACN,qBAAqB,EAAE,IAAI;QAC3B,qBAAqB;KACtB,CAAC;AACJ,CAAC;AAED,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type * as k8s from "@kubernetes/client-node";
|
|
2
|
+
import type { AdapterExecutionContext } from "@paperclipai/adapter-utils";
|
|
3
|
+
import type { SelfPodInfo } from "./k8s-client.js";
|
|
4
|
+
export interface JobBuildInput {
|
|
5
|
+
ctx: AdapterExecutionContext;
|
|
6
|
+
selfPod: SelfPodInfo;
|
|
7
|
+
}
|
|
8
|
+
export interface JobBuildResult {
|
|
9
|
+
job: k8s.V1Job;
|
|
10
|
+
jobName: string;
|
|
11
|
+
namespace: string;
|
|
12
|
+
prompt: string;
|
|
13
|
+
opencodeArgs: string[];
|
|
14
|
+
promptMetrics: Record<string, number>;
|
|
15
|
+
}
|
|
16
|
+
export declare function buildJobManifest(input: JobBuildInput): JobBuildResult;
|
|
17
|
+
//# sourceMappingURL=job-manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"job-manifest.d.ts","sourceRoot":"","sources":["../../src/server/job-manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,GAAG,MAAM,yBAAyB,CAAC;AACpD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AA0C1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,uBAAuB,CAAC;IAC7B,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACvC;AA0GD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,GAAG,cAAc,CAyNrE"}
|