@tickernelz/paperclip-pro-plugin-kubernetes 2026.925.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/LICENSE +22 -0
- package/README.md +180 -0
- package/dist/adapter-defaults.d.ts +29 -0
- package/dist/adapter-defaults.d.ts.map +1 -0
- package/dist/adapter-defaults.js +98 -0
- package/dist/adapter-defaults.js.map +1 -0
- package/dist/adapter-registry.d.ts +64 -0
- package/dist/adapter-registry.d.ts.map +1 -0
- package/dist/adapter-registry.js +25 -0
- package/dist/adapter-registry.js.map +1 -0
- package/dist/cilium-network-policy.d.ts +12 -0
- package/dist/cilium-network-policy.d.ts.map +1 -0
- package/dist/cilium-network-policy.js +60 -0
- package/dist/cilium-network-policy.js.map +1 -0
- package/dist/file-sync.d.ts +73 -0
- package/dist/file-sync.d.ts.map +1 -0
- package/dist/file-sync.js +752 -0
- package/dist/file-sync.js.map +1 -0
- package/dist/image-allowlist.d.ts +18 -0
- package/dist/image-allowlist.d.ts.map +1 -0
- package/dist/image-allowlist.js +39 -0
- package/dist/image-allowlist.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/job-orchestrator.d.ts +24 -0
- package/dist/job-orchestrator.d.ts.map +1 -0
- package/dist/job-orchestrator.js +90 -0
- package/dist/job-orchestrator.js.map +1 -0
- package/dist/kube-client.d.ts +15 -0
- package/dist/kube-client.d.ts.map +1 -0
- package/dist/kube-client.js +23 -0
- package/dist/kube-client.js.map +1 -0
- package/dist/lease-lifecycle.d.ts +62 -0
- package/dist/lease-lifecycle.d.ts.map +1 -0
- package/dist/lease-lifecycle.js +155 -0
- package/dist/lease-lifecycle.js.map +1 -0
- package/dist/manifest.d.ts +4 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +108 -0
- package/dist/manifest.js.map +1 -0
- package/dist/network-policy.d.ts +22 -0
- package/dist/network-policy.d.ts.map +1 -0
- package/dist/network-policy.js +116 -0
- package/dist/network-policy.js.map +1 -0
- package/dist/plugin.d.ts +3 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +820 -0
- package/dist/plugin.js.map +1 -0
- package/dist/pod-exec.d.ts +67 -0
- package/dist/pod-exec.d.ts.map +1 -0
- package/dist/pod-exec.js +401 -0
- package/dist/pod-exec.js.map +1 -0
- package/dist/pod-spec-builder.d.ts +25 -0
- package/dist/pod-spec-builder.d.ts.map +1 -0
- package/dist/pod-spec-builder.js +82 -0
- package/dist/pod-spec-builder.js.map +1 -0
- package/dist/sandbox-cr-builder.d.ts +40 -0
- package/dist/sandbox-cr-builder.d.ts.map +1 -0
- package/dist/sandbox-cr-builder.js +123 -0
- package/dist/sandbox-cr-builder.js.map +1 -0
- package/dist/sandbox-cr-orchestrator.d.ts +62 -0
- package/dist/sandbox-cr-orchestrator.d.ts.map +1 -0
- package/dist/sandbox-cr-orchestrator.js +248 -0
- package/dist/sandbox-cr-orchestrator.js.map +1 -0
- package/dist/sandbox-orchestrator.d.ts +39 -0
- package/dist/sandbox-orchestrator.d.ts.map +1 -0
- package/dist/sandbox-orchestrator.js +2 -0
- package/dist/sandbox-orchestrator.js.map +1 -0
- package/dist/scoped-network-egress.d.ts +19 -0
- package/dist/scoped-network-egress.d.ts.map +1 -0
- package/dist/scoped-network-egress.js +86 -0
- package/dist/scoped-network-egress.js.map +1 -0
- package/dist/secret-manager.d.ts +14 -0
- package/dist/secret-manager.d.ts.map +1 -0
- package/dist/secret-manager.js +39 -0
- package/dist/secret-manager.js.map +1 -0
- package/dist/tenant-orchestrator.d.ts +35 -0
- package/dist/tenant-orchestrator.d.ts.map +1 -0
- package/dist/tenant-orchestrator.js +263 -0
- package/dist/tenant-orchestrator.js.map +1 -0
- package/dist/types.d.ts +279 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +65 -0
- package/dist/types.js.map +1 -0
- package/dist/upload-interceptor.d.ts +44 -0
- package/dist/upload-interceptor.d.ts.map +1 -0
- package/dist/upload-interceptor.js +114 -0
- package/dist/upload-interceptor.js.map +1 -0
- package/dist/utils.d.ts +11 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +51 -0
- package/dist/utils.js.map +1 -0
- package/dist/worker.d.ts +3 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +5 -0
- package/dist/worker.js.map +1 -0
- package/manifests/operator-prerequisites.yaml +22 -0
- package/package.json +47 -0
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const kubernetesProviderConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
3
|
+
inCluster: z.ZodDefault<z.ZodBoolean>;
|
|
4
|
+
kubeconfig: z.ZodOptional<z.ZodString>;
|
|
5
|
+
namespacePrefix: z.ZodDefault<z.ZodString>;
|
|
6
|
+
companySlug: z.ZodOptional<z.ZodString>;
|
|
7
|
+
imageRegistry: z.ZodOptional<z.ZodString>;
|
|
8
|
+
imageAllowList: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
9
|
+
imagePullSecrets: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
10
|
+
egressAllowFqdns: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
11
|
+
egressAllowCidrs: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
12
|
+
egressMode: z.ZodDefault<z.ZodEnum<["cilium", "standard"]>>;
|
|
13
|
+
defaultResources: z.ZodOptional<z.ZodObject<{
|
|
14
|
+
requests: z.ZodOptional<z.ZodObject<{
|
|
15
|
+
cpu: z.ZodOptional<z.ZodString>;
|
|
16
|
+
memory: z.ZodOptional<z.ZodString>;
|
|
17
|
+
}, "strip", z.ZodTypeAny, {
|
|
18
|
+
cpu?: string | undefined;
|
|
19
|
+
memory?: string | undefined;
|
|
20
|
+
}, {
|
|
21
|
+
cpu?: string | undefined;
|
|
22
|
+
memory?: string | undefined;
|
|
23
|
+
}>>;
|
|
24
|
+
limits: z.ZodOptional<z.ZodObject<{
|
|
25
|
+
cpu: z.ZodOptional<z.ZodString>;
|
|
26
|
+
memory: z.ZodOptional<z.ZodString>;
|
|
27
|
+
}, "strip", z.ZodTypeAny, {
|
|
28
|
+
cpu?: string | undefined;
|
|
29
|
+
memory?: string | undefined;
|
|
30
|
+
}, {
|
|
31
|
+
cpu?: string | undefined;
|
|
32
|
+
memory?: string | undefined;
|
|
33
|
+
}>>;
|
|
34
|
+
}, "strip", z.ZodTypeAny, {
|
|
35
|
+
limits?: {
|
|
36
|
+
cpu?: string | undefined;
|
|
37
|
+
memory?: string | undefined;
|
|
38
|
+
} | undefined;
|
|
39
|
+
requests?: {
|
|
40
|
+
cpu?: string | undefined;
|
|
41
|
+
memory?: string | undefined;
|
|
42
|
+
} | undefined;
|
|
43
|
+
}, {
|
|
44
|
+
limits?: {
|
|
45
|
+
cpu?: string | undefined;
|
|
46
|
+
memory?: string | undefined;
|
|
47
|
+
} | undefined;
|
|
48
|
+
requests?: {
|
|
49
|
+
cpu?: string | undefined;
|
|
50
|
+
memory?: string | undefined;
|
|
51
|
+
} | undefined;
|
|
52
|
+
}>>;
|
|
53
|
+
runtimeClassName: z.ZodOptional<z.ZodString>;
|
|
54
|
+
serviceAccountAnnotations: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
55
|
+
jobTtlSecondsAfterFinished: z.ZodDefault<z.ZodNumber>;
|
|
56
|
+
podActivityDeadlineSec: z.ZodDefault<z.ZodNumber>;
|
|
57
|
+
/**
|
|
58
|
+
* The adapter type that Jobs in this environment will run.
|
|
59
|
+
* Each Kubernetes environment is bound to one adapter; create multiple
|
|
60
|
+
* environments for different adapters.
|
|
61
|
+
* Defaults to `"claude_local"`.
|
|
62
|
+
*/
|
|
63
|
+
adapterType: z.ZodEffects<z.ZodDefault<z.ZodString>, string, string | undefined>;
|
|
64
|
+
/**
|
|
65
|
+
* Optional declarative adapter registry. When present it is authoritative
|
|
66
|
+
* for runtime image / envKeys / allowFqdns / probe / defaultEnv resolution
|
|
67
|
+
* (replace semantics). Absent = built-in defaults.
|
|
68
|
+
*/
|
|
69
|
+
adapters: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
70
|
+
adapterType: z.ZodString;
|
|
71
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
72
|
+
runtimeImage: z.ZodOptional<z.ZodString>;
|
|
73
|
+
envKeys: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
74
|
+
allowFqdns: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
75
|
+
probeCommand: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
76
|
+
defaultEnv: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
77
|
+
}, "strict", z.ZodTypeAny, {
|
|
78
|
+
adapterType: string;
|
|
79
|
+
enabled: boolean;
|
|
80
|
+
runtimeImage?: string | undefined;
|
|
81
|
+
envKeys?: string[] | undefined;
|
|
82
|
+
allowFqdns?: string[] | undefined;
|
|
83
|
+
probeCommand?: string[] | undefined;
|
|
84
|
+
defaultEnv?: Record<string, string> | undefined;
|
|
85
|
+
}, {
|
|
86
|
+
adapterType: string;
|
|
87
|
+
enabled?: boolean | undefined;
|
|
88
|
+
runtimeImage?: string | undefined;
|
|
89
|
+
envKeys?: string[] | undefined;
|
|
90
|
+
allowFqdns?: string[] | undefined;
|
|
91
|
+
probeCommand?: string[] | undefined;
|
|
92
|
+
defaultEnv?: Record<string, string> | undefined;
|
|
93
|
+
}>, "many">>;
|
|
94
|
+
/**
|
|
95
|
+
* The sandbox backend to use.
|
|
96
|
+
*
|
|
97
|
+
* - `"sandbox-cr"` (default, alpha) — uses the kubernetes-sigs/agent-sandbox
|
|
98
|
+
* Sandbox CRD (agents.x-k8s.io/v1alpha1). Creates a long-lived pod that
|
|
99
|
+
* paperclip-server can exec into for multi-command adapter-install workflows.
|
|
100
|
+
* Requires the agent-sandbox controller to be installed in the cluster.
|
|
101
|
+
*
|
|
102
|
+
* - `"job"` — uses batch/v1 Job (stable fallback). One-shot entrypoint; does
|
|
103
|
+
* NOT support multi-command exec. Use this for clusters without agent-sandbox
|
|
104
|
+
* installed, or when you need stable (non-alpha) k8s APIs.
|
|
105
|
+
*/
|
|
106
|
+
backend: z.ZodDefault<z.ZodEnum<["sandbox-cr", "job"]>>;
|
|
107
|
+
}, "strip", z.ZodTypeAny, {
|
|
108
|
+
adapterType: string;
|
|
109
|
+
inCluster: boolean;
|
|
110
|
+
namespacePrefix: string;
|
|
111
|
+
imageAllowList: string[];
|
|
112
|
+
imagePullSecrets: string[];
|
|
113
|
+
egressAllowFqdns: string[];
|
|
114
|
+
egressAllowCidrs: string[];
|
|
115
|
+
egressMode: "standard" | "cilium";
|
|
116
|
+
serviceAccountAnnotations: Record<string, string>;
|
|
117
|
+
jobTtlSecondsAfterFinished: number;
|
|
118
|
+
podActivityDeadlineSec: number;
|
|
119
|
+
backend: "job" | "sandbox-cr";
|
|
120
|
+
kubeconfig?: string | undefined;
|
|
121
|
+
companySlug?: string | undefined;
|
|
122
|
+
imageRegistry?: string | undefined;
|
|
123
|
+
defaultResources?: {
|
|
124
|
+
limits?: {
|
|
125
|
+
cpu?: string | undefined;
|
|
126
|
+
memory?: string | undefined;
|
|
127
|
+
} | undefined;
|
|
128
|
+
requests?: {
|
|
129
|
+
cpu?: string | undefined;
|
|
130
|
+
memory?: string | undefined;
|
|
131
|
+
} | undefined;
|
|
132
|
+
} | undefined;
|
|
133
|
+
runtimeClassName?: string | undefined;
|
|
134
|
+
adapters?: {
|
|
135
|
+
adapterType: string;
|
|
136
|
+
enabled: boolean;
|
|
137
|
+
runtimeImage?: string | undefined;
|
|
138
|
+
envKeys?: string[] | undefined;
|
|
139
|
+
allowFqdns?: string[] | undefined;
|
|
140
|
+
probeCommand?: string[] | undefined;
|
|
141
|
+
defaultEnv?: Record<string, string> | undefined;
|
|
142
|
+
}[] | undefined;
|
|
143
|
+
}, {
|
|
144
|
+
adapterType?: string | undefined;
|
|
145
|
+
inCluster?: boolean | undefined;
|
|
146
|
+
kubeconfig?: string | undefined;
|
|
147
|
+
namespacePrefix?: string | undefined;
|
|
148
|
+
companySlug?: string | undefined;
|
|
149
|
+
imageRegistry?: string | undefined;
|
|
150
|
+
imageAllowList?: string[] | undefined;
|
|
151
|
+
imagePullSecrets?: string[] | undefined;
|
|
152
|
+
egressAllowFqdns?: string[] | undefined;
|
|
153
|
+
egressAllowCidrs?: string[] | undefined;
|
|
154
|
+
egressMode?: "standard" | "cilium" | undefined;
|
|
155
|
+
defaultResources?: {
|
|
156
|
+
limits?: {
|
|
157
|
+
cpu?: string | undefined;
|
|
158
|
+
memory?: string | undefined;
|
|
159
|
+
} | undefined;
|
|
160
|
+
requests?: {
|
|
161
|
+
cpu?: string | undefined;
|
|
162
|
+
memory?: string | undefined;
|
|
163
|
+
} | undefined;
|
|
164
|
+
} | undefined;
|
|
165
|
+
runtimeClassName?: string | undefined;
|
|
166
|
+
serviceAccountAnnotations?: Record<string, string> | undefined;
|
|
167
|
+
jobTtlSecondsAfterFinished?: number | undefined;
|
|
168
|
+
podActivityDeadlineSec?: number | undefined;
|
|
169
|
+
adapters?: {
|
|
170
|
+
adapterType: string;
|
|
171
|
+
enabled?: boolean | undefined;
|
|
172
|
+
runtimeImage?: string | undefined;
|
|
173
|
+
envKeys?: string[] | undefined;
|
|
174
|
+
allowFqdns?: string[] | undefined;
|
|
175
|
+
probeCommand?: string[] | undefined;
|
|
176
|
+
defaultEnv?: Record<string, string> | undefined;
|
|
177
|
+
}[] | undefined;
|
|
178
|
+
backend?: "job" | "sandbox-cr" | undefined;
|
|
179
|
+
}>, {
|
|
180
|
+
adapterType: string;
|
|
181
|
+
inCluster: boolean;
|
|
182
|
+
namespacePrefix: string;
|
|
183
|
+
imageAllowList: string[];
|
|
184
|
+
imagePullSecrets: string[];
|
|
185
|
+
egressAllowFqdns: string[];
|
|
186
|
+
egressAllowCidrs: string[];
|
|
187
|
+
egressMode: "standard" | "cilium";
|
|
188
|
+
serviceAccountAnnotations: Record<string, string>;
|
|
189
|
+
jobTtlSecondsAfterFinished: number;
|
|
190
|
+
podActivityDeadlineSec: number;
|
|
191
|
+
backend: "job" | "sandbox-cr";
|
|
192
|
+
kubeconfig?: string | undefined;
|
|
193
|
+
companySlug?: string | undefined;
|
|
194
|
+
imageRegistry?: string | undefined;
|
|
195
|
+
defaultResources?: {
|
|
196
|
+
limits?: {
|
|
197
|
+
cpu?: string | undefined;
|
|
198
|
+
memory?: string | undefined;
|
|
199
|
+
} | undefined;
|
|
200
|
+
requests?: {
|
|
201
|
+
cpu?: string | undefined;
|
|
202
|
+
memory?: string | undefined;
|
|
203
|
+
} | undefined;
|
|
204
|
+
} | undefined;
|
|
205
|
+
runtimeClassName?: string | undefined;
|
|
206
|
+
adapters?: {
|
|
207
|
+
adapterType: string;
|
|
208
|
+
enabled: boolean;
|
|
209
|
+
runtimeImage?: string | undefined;
|
|
210
|
+
envKeys?: string[] | undefined;
|
|
211
|
+
allowFqdns?: string[] | undefined;
|
|
212
|
+
probeCommand?: string[] | undefined;
|
|
213
|
+
defaultEnv?: Record<string, string> | undefined;
|
|
214
|
+
}[] | undefined;
|
|
215
|
+
}, {
|
|
216
|
+
adapterType?: string | undefined;
|
|
217
|
+
inCluster?: boolean | undefined;
|
|
218
|
+
kubeconfig?: string | undefined;
|
|
219
|
+
namespacePrefix?: string | undefined;
|
|
220
|
+
companySlug?: string | undefined;
|
|
221
|
+
imageRegistry?: string | undefined;
|
|
222
|
+
imageAllowList?: string[] | undefined;
|
|
223
|
+
imagePullSecrets?: string[] | undefined;
|
|
224
|
+
egressAllowFqdns?: string[] | undefined;
|
|
225
|
+
egressAllowCidrs?: string[] | undefined;
|
|
226
|
+
egressMode?: "standard" | "cilium" | undefined;
|
|
227
|
+
defaultResources?: {
|
|
228
|
+
limits?: {
|
|
229
|
+
cpu?: string | undefined;
|
|
230
|
+
memory?: string | undefined;
|
|
231
|
+
} | undefined;
|
|
232
|
+
requests?: {
|
|
233
|
+
cpu?: string | undefined;
|
|
234
|
+
memory?: string | undefined;
|
|
235
|
+
} | undefined;
|
|
236
|
+
} | undefined;
|
|
237
|
+
runtimeClassName?: string | undefined;
|
|
238
|
+
serviceAccountAnnotations?: Record<string, string> | undefined;
|
|
239
|
+
jobTtlSecondsAfterFinished?: number | undefined;
|
|
240
|
+
podActivityDeadlineSec?: number | undefined;
|
|
241
|
+
adapters?: {
|
|
242
|
+
adapterType: string;
|
|
243
|
+
enabled?: boolean | undefined;
|
|
244
|
+
runtimeImage?: string | undefined;
|
|
245
|
+
envKeys?: string[] | undefined;
|
|
246
|
+
allowFqdns?: string[] | undefined;
|
|
247
|
+
probeCommand?: string[] | undefined;
|
|
248
|
+
defaultEnv?: Record<string, string> | undefined;
|
|
249
|
+
}[] | undefined;
|
|
250
|
+
backend?: "job" | "sandbox-cr" | undefined;
|
|
251
|
+
}>;
|
|
252
|
+
export type KubernetesProviderConfig = z.infer<typeof kubernetesProviderConfigSchema>;
|
|
253
|
+
export declare function parseKubernetesProviderConfig(input: unknown): KubernetesProviderConfig;
|
|
254
|
+
export interface KubernetesLeaseMetadata {
|
|
255
|
+
namespace: string;
|
|
256
|
+
/** Name of the workload resource (Job name for job backend, Sandbox CR name for sandbox-cr backend). */
|
|
257
|
+
jobName: string;
|
|
258
|
+
podName: string | null;
|
|
259
|
+
secretName: string;
|
|
260
|
+
phase: "Pending" | "Running" | "Succeeded" | "Failed";
|
|
261
|
+
/** Which backend provisioned this lease. */
|
|
262
|
+
backend: "sandbox-cr" | "job";
|
|
263
|
+
scopedNetworkPolicyName: string | null;
|
|
264
|
+
scopedNetworkEgress: {
|
|
265
|
+
allowFqdns: string[];
|
|
266
|
+
allowCidrs: string[];
|
|
267
|
+
};
|
|
268
|
+
/**
|
|
269
|
+
* True when this lease's backend has NO data channel for the native file-sync
|
|
270
|
+
* transport. Native sync streams over a pod exec, which only the `sandbox-cr`
|
|
271
|
+
* backend exposes; the `job` backend carries no exec path, so its sync hook
|
|
272
|
+
* rejects immediately. The server's per-lease sync-capability gate honors this
|
|
273
|
+
* opt-out so a job lease keeps the byte-identical base64 fallback instead of
|
|
274
|
+
* being routed to a native hook that would only error. Absent/false ⇒ native
|
|
275
|
+
* sync may be used when the worker advertises the verbs.
|
|
276
|
+
*/
|
|
277
|
+
nativeFileSyncUnsupported?: boolean;
|
|
278
|
+
}
|
|
279
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA6BvC;;;;;OAKG;;IAQH;;;;OAIG;;;;;;;;;;;;;;;;;;;;;;;;;;IAGH;;;;;;;;;;;OAWG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EASJ,CAAC;AAEJ,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC;AAEtF,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,OAAO,GAAG,wBAAwB,CAEtF;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,wGAAwG;IACxG,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;IACtD,4CAA4C;IAC5C,OAAO,EAAE,YAAY,GAAG,KAAK,CAAC;IAC9B,uBAAuB,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,mBAAmB,EAAE;QACnB,UAAU,EAAE,MAAM,EAAE,CAAC;QACrB,UAAU,EAAE,MAAM,EAAE,CAAC;KACtB,CAAC;IACF;;;;;;;;OAQG;IACH,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { adapterRegistrySchema } from "./adapter-registry.js";
|
|
3
|
+
import { KNOWN_ADAPTER_TYPES } from "./adapter-defaults.js";
|
|
4
|
+
const cidrRegex = /^(\d{1,3}\.){3}\d{1,3}\/\d{1,2}$/;
|
|
5
|
+
export const kubernetesProviderConfigSchema = z
|
|
6
|
+
.object({
|
|
7
|
+
inCluster: z.boolean().default(false),
|
|
8
|
+
kubeconfig: z.string().optional(),
|
|
9
|
+
namespacePrefix: z.string().regex(/^[a-z0-9-]{1,32}$/).default("paperclip-"),
|
|
10
|
+
companySlug: z.string().regex(/^[a-z0-9-]{1,32}$/).optional(),
|
|
11
|
+
imageRegistry: z.string().url().optional(),
|
|
12
|
+
imageAllowList: z.array(z.string()).default([]),
|
|
13
|
+
imagePullSecrets: z.array(z.string()).default([]),
|
|
14
|
+
egressAllowFqdns: z.array(z.string()).default([]),
|
|
15
|
+
egressAllowCidrs: z.array(z.string().regex(cidrRegex, "Invalid CIDR")).default([]),
|
|
16
|
+
egressMode: z.enum(["cilium", "standard"]).default("standard"),
|
|
17
|
+
defaultResources: z
|
|
18
|
+
.object({
|
|
19
|
+
requests: z.object({ cpu: z.string(), memory: z.string() }).partial().optional(),
|
|
20
|
+
limits: z.object({ cpu: z.string(), memory: z.string() }).partial().optional(),
|
|
21
|
+
})
|
|
22
|
+
.optional(),
|
|
23
|
+
runtimeClassName: z.string().optional(),
|
|
24
|
+
serviceAccountAnnotations: z.record(z.string()).default({}),
|
|
25
|
+
jobTtlSecondsAfterFinished: z.number().int().nonnegative().default(900),
|
|
26
|
+
podActivityDeadlineSec: z.number().int().positive().default(3600),
|
|
27
|
+
/**
|
|
28
|
+
* The adapter type that Jobs in this environment will run.
|
|
29
|
+
* Each Kubernetes environment is bound to one adapter; create multiple
|
|
30
|
+
* environments for different adapters.
|
|
31
|
+
* Defaults to `"claude_local"`.
|
|
32
|
+
*/
|
|
33
|
+
adapterType: z
|
|
34
|
+
.string()
|
|
35
|
+
.default("claude_local")
|
|
36
|
+
.refine((v) => KNOWN_ADAPTER_TYPES.has(v), {
|
|
37
|
+
message: "adapterType must be one of the known adapter types",
|
|
38
|
+
}),
|
|
39
|
+
/**
|
|
40
|
+
* Optional declarative adapter registry. When present it is authoritative
|
|
41
|
+
* for runtime image / envKeys / allowFqdns / probe / defaultEnv resolution
|
|
42
|
+
* (replace semantics). Absent = built-in defaults.
|
|
43
|
+
*/
|
|
44
|
+
adapters: adapterRegistrySchema.optional(),
|
|
45
|
+
/**
|
|
46
|
+
* The sandbox backend to use.
|
|
47
|
+
*
|
|
48
|
+
* - `"sandbox-cr"` (default, alpha) — uses the kubernetes-sigs/agent-sandbox
|
|
49
|
+
* Sandbox CRD (agents.x-k8s.io/v1alpha1). Creates a long-lived pod that
|
|
50
|
+
* paperclip-server can exec into for multi-command adapter-install workflows.
|
|
51
|
+
* Requires the agent-sandbox controller to be installed in the cluster.
|
|
52
|
+
*
|
|
53
|
+
* - `"job"` — uses batch/v1 Job (stable fallback). One-shot entrypoint; does
|
|
54
|
+
* NOT support multi-command exec. Use this for clusters without agent-sandbox
|
|
55
|
+
* installed, or when you need stable (non-alpha) k8s APIs.
|
|
56
|
+
*/
|
|
57
|
+
backend: z.enum(["sandbox-cr", "job"]).default("sandbox-cr"),
|
|
58
|
+
})
|
|
59
|
+
.refine((cfg) => cfg.inCluster || cfg.kubeconfig, {
|
|
60
|
+
message: "kubernetes provider requires one of `inCluster` or `kubeconfig`",
|
|
61
|
+
});
|
|
62
|
+
export function parseKubernetesProviderConfig(input) {
|
|
63
|
+
return kubernetesProviderConfigSchema.parse(input);
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export interface InterceptStateFlush {
|
|
2
|
+
/** Final target path on the remote (decoded payload goes here). */
|
|
3
|
+
targetPath: string;
|
|
4
|
+
/** Decoded payload bytes. */
|
|
5
|
+
payload: Buffer;
|
|
6
|
+
}
|
|
7
|
+
export type InterceptDecision =
|
|
8
|
+
/** Pattern recognized; respond with success without running the command. */
|
|
9
|
+
{
|
|
10
|
+
action: "ack";
|
|
11
|
+
reason: string;
|
|
12
|
+
}
|
|
13
|
+
/** Pattern recognized; flush via single exec. Caller does the exec. */
|
|
14
|
+
| {
|
|
15
|
+
action: "flush";
|
|
16
|
+
flush: InterceptStateFlush;
|
|
17
|
+
}
|
|
18
|
+
/** Pattern not recognized; pass through to the normal exec path. */
|
|
19
|
+
| {
|
|
20
|
+
action: "passthrough";
|
|
21
|
+
reason: string;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Stateful interceptor. Keyed by the base64 temp path (`<TARGET>.paperclip-upload.b64`).
|
|
25
|
+
* One instance per plugin worker is fine — concurrent uploads to different paths
|
|
26
|
+
* don't interfere.
|
|
27
|
+
*/
|
|
28
|
+
export declare class FastUploadInterceptor {
|
|
29
|
+
private buffers;
|
|
30
|
+
/**
|
|
31
|
+
* Inspect a single shell command (the literal argument to `sh -c <cmd>`).
|
|
32
|
+
* Returns the action the plugin should take.
|
|
33
|
+
*/
|
|
34
|
+
decide(command: string): InterceptDecision;
|
|
35
|
+
/**
|
|
36
|
+
* Drop all buffered state. Called on releaseLease so a new lease doesn't
|
|
37
|
+
* inherit stale buffers (lease IDs are unique so target paths shouldn't
|
|
38
|
+
* collide, but cleanup is hygiene).
|
|
39
|
+
*/
|
|
40
|
+
reset(): void;
|
|
41
|
+
/** Number of in-flight uploads being tracked. Mostly for tests / diagnostics. */
|
|
42
|
+
get pendingCount(): number;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=upload-interceptor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload-interceptor.d.ts","sourceRoot":"","sources":["../src/upload-interceptor.ts"],"names":[],"mappings":"AAoCA,MAAM,WAAW,mBAAmB;IAClC,mEAAmE;IACnE,UAAU,EAAE,MAAM,CAAC;IACnB,6BAA6B;IAC7B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,iBAAiB;AAC3B,4EAA4E;AAC1E;IAAE,MAAM,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AACnC,uEAAuE;GACrE;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,mBAAmB,CAAA;CAAE;AACjD,oEAAoE;GAClE;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAQ9C;;;;GAIG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,OAAO,CAAkC;IAEjD;;;OAGG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB;IA+D1C;;;;OAIG;IACH,KAAK,IAAI,IAAI;IAIb,iFAAiF;IACjF,IAAI,YAAY,IAAI,MAAM,CAEzB;CACF"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fast-upload interceptor for the chunked-shell file transfer protocol used by
|
|
3
|
+
* `@tickernelz/paperclip-pro-adapter-utils`'s `command-managed-runtime.writeFile()`.
|
|
4
|
+
*
|
|
5
|
+
* The default protocol uploads a binary file by:
|
|
6
|
+
* 1. INIT: mkdir -p '<DIR>' && rm -f '<B64>' && : > '<B64>'
|
|
7
|
+
* 2. CHUNKS: printf '%s' '<base64-chunk>' >> '<B64>' (repeated N times)
|
|
8
|
+
* 3. FINALIZE: base64 -d < '<B64>' > '<TARGET>' && rm -f '<B64>'
|
|
9
|
+
*
|
|
10
|
+
* Where `<B64>` is `<TARGET>.paperclip-upload.b64`. Over k8s exec each call costs
|
|
11
|
+
* ~50-100ms (new WebSocket + container exec), so N chunks = N round trips. For
|
|
12
|
+
* a 1MB payload split into 64KB base64 chunks that's ~250 round trips.
|
|
13
|
+
*
|
|
14
|
+
* This interceptor short-circuits the protocol entirely:
|
|
15
|
+
* - INIT: capture `<B64>`, start a buffer, RESPOND success without exec.
|
|
16
|
+
* - CHUNK: append the literal base64 chunk to the buffer, RESPOND success.
|
|
17
|
+
* - FINALIZE: decode the buffered base64 → bytes → one exec `cat > '<TARGET>'`
|
|
18
|
+
* with stdin = bytes. Drop intermediate `.b64` entirely.
|
|
19
|
+
*
|
|
20
|
+
* If any step doesn't match the protocol exactly, we abandon the buffer and let
|
|
21
|
+
* the caller go through the slow path (passthrough). This keeps the optimization
|
|
22
|
+
* **transparent and safe**: pattern drift → graceful fallback.
|
|
23
|
+
*
|
|
24
|
+
* Reference: see packages/adapter-utils/src/command-managed-runtime.ts.
|
|
25
|
+
*/
|
|
26
|
+
import { posix as pathPosix } from "node:path";
|
|
27
|
+
const INIT_RE = /^mkdir -p '([^']+)' && rm -f '([^']+)\.paperclip-upload\.b64' && : > '\2\.paperclip-upload\.b64'$/;
|
|
28
|
+
const CHUNK_RE = /^printf '%s' '([A-Za-z0-9+/=]+)' >> '([^']+)\.paperclip-upload\.b64'$/;
|
|
29
|
+
const FINALIZE_RE = /^base64 -d < '([^']+)\.paperclip-upload\.b64' > '\1' && rm -f '\1\.paperclip-upload\.b64'$/;
|
|
30
|
+
const MAX_BUFFER_BYTES = 100 * 1024 * 1024; // 100MB safety cap
|
|
31
|
+
/**
|
|
32
|
+
* Stateful interceptor. Keyed by the base64 temp path (`<TARGET>.paperclip-upload.b64`).
|
|
33
|
+
* One instance per plugin worker is fine — concurrent uploads to different paths
|
|
34
|
+
* don't interfere.
|
|
35
|
+
*/
|
|
36
|
+
export class FastUploadInterceptor {
|
|
37
|
+
buffers = new Map();
|
|
38
|
+
/**
|
|
39
|
+
* Inspect a single shell command (the literal argument to `sh -c <cmd>`).
|
|
40
|
+
* Returns the action the plugin should take.
|
|
41
|
+
*/
|
|
42
|
+
decide(command) {
|
|
43
|
+
// 1. INIT
|
|
44
|
+
const initMatch = INIT_RE.exec(command);
|
|
45
|
+
if (initMatch) {
|
|
46
|
+
const dir = initMatch[1];
|
|
47
|
+
const targetPath = initMatch[2];
|
|
48
|
+
const b64Path = `${targetPath}.paperclip-upload.b64`;
|
|
49
|
+
// Sanity: dir should be the parent of target. If not, fall through.
|
|
50
|
+
if (pathPosix.dirname(targetPath) !== dir) {
|
|
51
|
+
return { action: "passthrough", reason: "init dir/target mismatch" };
|
|
52
|
+
}
|
|
53
|
+
this.buffers.set(b64Path, { targetPath, chunks: [], totalChars: 0 });
|
|
54
|
+
return { action: "ack", reason: `init upload to ${targetPath}` };
|
|
55
|
+
}
|
|
56
|
+
// 2. CHUNK
|
|
57
|
+
const chunkMatch = CHUNK_RE.exec(command);
|
|
58
|
+
if (chunkMatch) {
|
|
59
|
+
const base64 = chunkMatch[1];
|
|
60
|
+
const targetPath = chunkMatch[2];
|
|
61
|
+
const b64Path = `${targetPath}.paperclip-upload.b64`;
|
|
62
|
+
const state = this.buffers.get(b64Path);
|
|
63
|
+
if (!state) {
|
|
64
|
+
// Chunk arrived without init — must passthrough (the upload was started
|
|
65
|
+
// some other way, perhaps before we started tracking).
|
|
66
|
+
return { action: "passthrough", reason: "chunk without prior init" };
|
|
67
|
+
}
|
|
68
|
+
if (state.totalChars + base64.length > MAX_BUFFER_BYTES * 4 / 3) {
|
|
69
|
+
// base64 is ~4/3 of binary size; cap memory.
|
|
70
|
+
this.buffers.delete(b64Path);
|
|
71
|
+
return { action: "passthrough", reason: "buffer cap exceeded" };
|
|
72
|
+
}
|
|
73
|
+
state.chunks.push(base64);
|
|
74
|
+
state.totalChars += base64.length;
|
|
75
|
+
return { action: "ack", reason: `buffered ${base64.length} b64 chars` };
|
|
76
|
+
}
|
|
77
|
+
// 3. FINALIZE
|
|
78
|
+
const finalizeMatch = FINALIZE_RE.exec(command);
|
|
79
|
+
if (finalizeMatch) {
|
|
80
|
+
const targetPath = finalizeMatch[1];
|
|
81
|
+
const b64Path = `${targetPath}.paperclip-upload.b64`;
|
|
82
|
+
const state = this.buffers.get(b64Path);
|
|
83
|
+
if (!state) {
|
|
84
|
+
return { action: "passthrough", reason: "finalize without buffered state" };
|
|
85
|
+
}
|
|
86
|
+
this.buffers.delete(b64Path);
|
|
87
|
+
// Decode in one go. base64.decode handles concatenated base64 strings
|
|
88
|
+
// because each chunk was emitted from the encoder in fixed-size pieces.
|
|
89
|
+
const joined = state.chunks.join("");
|
|
90
|
+
const payload = Buffer.from(joined, "base64");
|
|
91
|
+
return {
|
|
92
|
+
action: "flush",
|
|
93
|
+
flush: {
|
|
94
|
+
targetPath: state.targetPath,
|
|
95
|
+
payload,
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
return { action: "passthrough", reason: "no upload pattern" };
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Drop all buffered state. Called on releaseLease so a new lease doesn't
|
|
103
|
+
* inherit stale buffers (lease IDs are unique so target paths shouldn't
|
|
104
|
+
* collide, but cleanup is hygiene).
|
|
105
|
+
*/
|
|
106
|
+
reset() {
|
|
107
|
+
this.buffers.clear();
|
|
108
|
+
}
|
|
109
|
+
/** Number of in-flight uploads being tracked. Mostly for tests / diagnostics. */
|
|
110
|
+
get pendingCount() {
|
|
111
|
+
return this.buffers.size;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=upload-interceptor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload-interceptor.js","sourceRoot":"","sources":["../src/upload-interceptor.ts"],"names":[],"mappings":"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"}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare function deriveCompanySlug(input: string): string;
|
|
2
|
+
export declare function deriveNamespaceName(prefix: string, slug: string): string;
|
|
3
|
+
export declare function newRunUlidDns(now?: () => number): string;
|
|
4
|
+
export interface LabelsInput {
|
|
5
|
+
runId: string;
|
|
6
|
+
agentId: string;
|
|
7
|
+
companyId: string;
|
|
8
|
+
adapterType: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function paperclipLabels(input: LabelsInput): Record<string, string>;
|
|
11
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAQA,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAevD;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAExE;AAED,wBAAgB,aAAa,CAAC,GAAG,GAAE,MAAM,MAAiB,GAAG,MAAM,CAclE;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQ1E"}
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { createHash, randomInt } from "node:crypto";
|
|
2
|
+
const ULID_ALPHABET = "0123456789abcdefghjkmnpqrstvwxyz";
|
|
3
|
+
// Namespace names are capped at 63 chars (RFC 1123). The default "paperclip-"
|
|
4
|
+
// prefix leaves 53 for the slug, which fits a full 36-char UUID untruncated.
|
|
5
|
+
const MAX_SLUG_LENGTH = 53;
|
|
6
|
+
export function deriveCompanySlug(input) {
|
|
7
|
+
const slug = input
|
|
8
|
+
.toLowerCase()
|
|
9
|
+
.replace(/[^a-z0-9-]+/g, "-")
|
|
10
|
+
.replace(/^-+|-+$/g, "")
|
|
11
|
+
.replace(/-+$/, "");
|
|
12
|
+
if (slug.length === 0)
|
|
13
|
+
return "company";
|
|
14
|
+
if (slug.length <= MAX_SLUG_LENGTH)
|
|
15
|
+
return slug;
|
|
16
|
+
// Never drop entropy by plain truncation: two long inputs sharing a prefix
|
|
17
|
+
// (e.g. UUIDs differing only in their tail) must not map to the same slug,
|
|
18
|
+
// or the tenants would share a namespace and each other's per-run Secrets.
|
|
19
|
+
// Keep a readable head and append a hash of the FULL input so every byte
|
|
20
|
+
// contributes to the final name.
|
|
21
|
+
const digest = createHash("sha256").update(input).digest("hex").slice(0, 8);
|
|
22
|
+
return `${slug.slice(0, MAX_SLUG_LENGTH - 9).replace(/-+$/, "")}-${digest}`;
|
|
23
|
+
}
|
|
24
|
+
export function deriveNamespaceName(prefix, slug) {
|
|
25
|
+
return `${prefix}${slug}`;
|
|
26
|
+
}
|
|
27
|
+
export function newRunUlidDns(now = Date.now) {
|
|
28
|
+
const timestamp = now();
|
|
29
|
+
let out = "";
|
|
30
|
+
let t = timestamp;
|
|
31
|
+
for (let i = 0; i < 10; i++) {
|
|
32
|
+
out = ULID_ALPHABET[t & 0x1f] + out;
|
|
33
|
+
t = Math.floor(t / 32);
|
|
34
|
+
}
|
|
35
|
+
for (let i = 0; i < 16; i++) {
|
|
36
|
+
// crypto-strength randomness: these become Job/Sandbox CR names and the
|
|
37
|
+
// providerLeaseId, so they must not be enumerable.
|
|
38
|
+
out += ULID_ALPHABET[randomInt(32)];
|
|
39
|
+
}
|
|
40
|
+
return out;
|
|
41
|
+
}
|
|
42
|
+
export function paperclipLabels(input) {
|
|
43
|
+
return {
|
|
44
|
+
"paperclip.io/run-id": input.runId,
|
|
45
|
+
"paperclip.io/agent-id": input.agentId,
|
|
46
|
+
"paperclip.io/company-id": input.companyId,
|
|
47
|
+
"paperclip.io/adapter": input.adapterType,
|
|
48
|
+
"paperclip.io/managed-by": "paperclip-k8s-plugin",
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAEpD,MAAM,aAAa,GAAG,kCAAkC,CAAC;AAEzD,8EAA8E;AAC9E,6EAA6E;AAC7E,MAAM,eAAe,GAAG,EAAE,CAAC;AAE3B,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,MAAM,IAAI,GAAG,KAAK;SACf,WAAW,EAAE;SACb,OAAO,CAAC,cAAc,EAAE,GAAG,CAAC;SAC5B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACtB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACxC,IAAI,IAAI,CAAC,MAAM,IAAI,eAAe;QAAE,OAAO,IAAI,CAAC;IAChD,2EAA2E;IAC3E,2EAA2E;IAC3E,2EAA2E;IAC3E,yEAAyE;IACzE,iCAAiC;IACjC,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5E,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,eAAe,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,MAAM,EAAE,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAc,EAAE,IAAY;IAC9D,OAAO,GAAG,MAAM,GAAG,IAAI,EAAE,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAoB,IAAI,CAAC,GAAG;IACxD,MAAM,SAAS,GAAG,GAAG,EAAE,CAAC;IACxB,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,IAAI,CAAC,GAAG,SAAS,CAAC;IAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,GAAG,GAAG,aAAa,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,GAAG,CAAC;QACpC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;IACzB,CAAC;IACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,wEAAwE;QACxE,mDAAmD;QACnD,GAAG,IAAI,aAAa,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AASD,MAAM,UAAU,eAAe,CAAC,KAAkB;IAChD,OAAO;QACL,qBAAqB,EAAE,KAAK,CAAC,KAAK;QAClC,uBAAuB,EAAE,KAAK,CAAC,OAAO;QACtC,yBAAyB,EAAE,KAAK,CAAC,SAAS;QAC1C,sBAAsB,EAAE,KAAK,CAAC,WAAW;QACzC,yBAAyB,EAAE,sBAAsB;KAClD,CAAC;AACJ,CAAC"}
|
package/dist/worker.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AACA,OAAO,MAAM,MAAM,aAAa,CAAC;AAEjC,eAAe,MAAM,CAAC"}
|
package/dist/worker.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,sCAAsC,CAAC;AACjE,OAAO,MAAM,MAAM,aAAa,CAAC;AAEjC,eAAe,MAAM,CAAC;AACtB,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# This plugin uses only stable Kubernetes APIs. No CRD installation is required.
|
|
2
|
+
#
|
|
3
|
+
# Minimum cluster version: Kubernetes 1.27+
|
|
4
|
+
# - batch/v1 Job (GA since k8s 1.21)
|
|
5
|
+
# - core/v1 Pod, Secret, Namespace, ServiceAccount, ResourceQuota, LimitRange (GA since k8s 1.0)
|
|
6
|
+
# - rbac.authorization.k8s.io/v1 Role, RoleBinding (GA since k8s 1.8)
|
|
7
|
+
# - networking.k8s.io/v1 NetworkPolicy (GA since k8s 1.7)
|
|
8
|
+
# - Pod Security Standards namespace labels (GA in k8s 1.25)
|
|
9
|
+
# - fsGroupChangePolicy: OnRootMismatch (GA in k8s 1.23)
|
|
10
|
+
# - seccompProfile.type: RuntimeDefault (GA in k8s 1.19)
|
|
11
|
+
#
|
|
12
|
+
# Optional CNI prerequisites for FQDN-based egress (egressMode: cilium):
|
|
13
|
+
# - Cilium >= 1.11 with hubble + DNS proxy enabled
|
|
14
|
+
# - cilium.io/v2 CiliumNetworkPolicy (provided by Cilium installation)
|
|
15
|
+
#
|
|
16
|
+
# Optional runtime class for microVM isolation (runtimeClassName: kata-fc):
|
|
17
|
+
# - kata-containers with Firecracker hypervisor
|
|
18
|
+
# - nested-virt-capable nodes
|
|
19
|
+
#
|
|
20
|
+
# Future backends (not currently required):
|
|
21
|
+
# - kubernetes-sigs/agent-sandbox (when it reaches v1beta1) as an alternative
|
|
22
|
+
# backend for warm pools / templates / pause-resume.
|