@rarebit-one/harness-kernel 0.5.1

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.
Files changed (163) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +286 -0
  3. package/dist/agent.d.ts +71 -0
  4. package/dist/agent.d.ts.map +1 -0
  5. package/dist/agent.js +258 -0
  6. package/dist/agent.js.map +1 -0
  7. package/dist/connectors/mcpClient.d.ts +22 -0
  8. package/dist/connectors/mcpClient.d.ts.map +1 -0
  9. package/dist/connectors/mcpClient.js +63 -0
  10. package/dist/connectors/mcpClient.js.map +1 -0
  11. package/dist/context/types.d.ts +68 -0
  12. package/dist/context/types.d.ts.map +1 -0
  13. package/dist/context/types.js +43 -0
  14. package/dist/context/types.js.map +1 -0
  15. package/dist/engines/capability.d.ts +67 -0
  16. package/dist/engines/capability.d.ts.map +1 -0
  17. package/dist/engines/capability.js +73 -0
  18. package/dist/engines/capability.js.map +1 -0
  19. package/dist/engines/capabilityEmissions.d.ts +27 -0
  20. package/dist/engines/capabilityEmissions.d.ts.map +1 -0
  21. package/dist/engines/capabilityEmissions.js +37 -0
  22. package/dist/engines/capabilityEmissions.js.map +1 -0
  23. package/dist/engines/capabilityMcp.d.ts +23 -0
  24. package/dist/engines/capabilityMcp.d.ts.map +1 -0
  25. package/dist/engines/capabilityMcp.js +36 -0
  26. package/dist/engines/capabilityMcp.js.map +1 -0
  27. package/dist/engines/capabilityStdio.d.ts +46 -0
  28. package/dist/engines/capabilityStdio.d.ts.map +1 -0
  29. package/dist/engines/capabilityStdio.js +39 -0
  30. package/dist/engines/capabilityStdio.js.map +1 -0
  31. package/dist/engines/claudeCode.d.ts +73 -0
  32. package/dist/engines/claudeCode.d.ts.map +1 -0
  33. package/dist/engines/claudeCode.js +100 -0
  34. package/dist/engines/claudeCode.js.map +1 -0
  35. package/dist/engines/claudeCodeDriver.d.ts +14 -0
  36. package/dist/engines/claudeCodeDriver.d.ts.map +1 -0
  37. package/dist/engines/claudeCodeDriver.js +90 -0
  38. package/dist/engines/claudeCodeDriver.js.map +1 -0
  39. package/dist/engines/codex.d.ts +72 -0
  40. package/dist/engines/codex.d.ts.map +1 -0
  41. package/dist/engines/codex.js +157 -0
  42. package/dist/engines/codex.js.map +1 -0
  43. package/dist/engines/codexDriver.d.ts +43 -0
  44. package/dist/engines/codexDriver.d.ts.map +1 -0
  45. package/dist/engines/codexDriver.js +110 -0
  46. package/dist/engines/codexDriver.js.map +1 -0
  47. package/dist/engines/connectorMcp.d.ts +60 -0
  48. package/dist/engines/connectorMcp.d.ts.map +1 -0
  49. package/dist/engines/connectorMcp.js +137 -0
  50. package/dist/engines/connectorMcp.js.map +1 -0
  51. package/dist/engines/index.d.ts +33 -0
  52. package/dist/engines/index.d.ts.map +1 -0
  53. package/dist/engines/index.js +29 -0
  54. package/dist/engines/index.js.map +1 -0
  55. package/dist/engines/native.d.ts +55 -0
  56. package/dist/engines/native.d.ts.map +1 -0
  57. package/dist/engines/native.js +117 -0
  58. package/dist/engines/native.js.map +1 -0
  59. package/dist/engines/types.d.ts +107 -0
  60. package/dist/engines/types.d.ts.map +1 -0
  61. package/dist/engines/types.js +2 -0
  62. package/dist/engines/types.js.map +1 -0
  63. package/dist/events.d.ts +211 -0
  64. package/dist/events.d.ts.map +1 -0
  65. package/dist/events.js +69 -0
  66. package/dist/events.js.map +1 -0
  67. package/dist/index.d.ts +63 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +82 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/loop.d.ts +132 -0
  72. package/dist/loop.d.ts.map +1 -0
  73. package/dist/loop.js +77 -0
  74. package/dist/loop.js.map +1 -0
  75. package/dist/models/chat.d.ts +65 -0
  76. package/dist/models/chat.d.ts.map +1 -0
  77. package/dist/models/chat.js +66 -0
  78. package/dist/models/chat.js.map +1 -0
  79. package/dist/models/middleware.d.ts +63 -0
  80. package/dist/models/middleware.d.ts.map +1 -0
  81. package/dist/models/middleware.js +139 -0
  82. package/dist/models/middleware.js.map +1 -0
  83. package/dist/models/registry.d.ts +78 -0
  84. package/dist/models/registry.d.ts.map +1 -0
  85. package/dist/models/registry.js +0 -0
  86. package/dist/models/registry.js.map +1 -0
  87. package/dist/models/types.d.ts +149 -0
  88. package/dist/models/types.d.ts.map +1 -0
  89. package/dist/models/types.js +64 -0
  90. package/dist/models/types.js.map +1 -0
  91. package/dist/primitives/codeExec.d.ts +25 -0
  92. package/dist/primitives/codeExec.d.ts.map +1 -0
  93. package/dist/primitives/codeExec.js +69 -0
  94. package/dist/primitives/codeExec.js.map +1 -0
  95. package/dist/primitives/download.d.ts +19 -0
  96. package/dist/primitives/download.d.ts.map +1 -0
  97. package/dist/primitives/download.js +113 -0
  98. package/dist/primitives/download.js.map +1 -0
  99. package/dist/primitives/fs.d.ts +5 -0
  100. package/dist/primitives/fs.d.ts.map +1 -0
  101. package/dist/primitives/fs.js +59 -0
  102. package/dist/primitives/fs.js.map +1 -0
  103. package/dist/primitives/http.d.ts +100 -0
  104. package/dist/primitives/http.d.ts.map +1 -0
  105. package/dist/primitives/http.js +257 -0
  106. package/dist/primitives/http.js.map +1 -0
  107. package/dist/providers/anthropic.d.ts +15 -0
  108. package/dist/providers/anthropic.d.ts.map +1 -0
  109. package/dist/providers/anthropic.js +90 -0
  110. package/dist/providers/anthropic.js.map +1 -0
  111. package/dist/providers/clientOptions.d.ts +14 -0
  112. package/dist/providers/clientOptions.d.ts.map +1 -0
  113. package/dist/providers/clientOptions.js +26 -0
  114. package/dist/providers/clientOptions.js.map +1 -0
  115. package/dist/providers/index.d.ts +24 -0
  116. package/dist/providers/index.d.ts.map +1 -0
  117. package/dist/providers/index.js +51 -0
  118. package/dist/providers/index.js.map +1 -0
  119. package/dist/providers/mock.d.ts +25 -0
  120. package/dist/providers/mock.d.ts.map +1 -0
  121. package/dist/providers/mock.js +85 -0
  122. package/dist/providers/mock.js.map +1 -0
  123. package/dist/providers/openai.d.ts +32 -0
  124. package/dist/providers/openai.d.ts.map +1 -0
  125. package/dist/providers/openai.js +118 -0
  126. package/dist/providers/openai.js.map +1 -0
  127. package/dist/providers/openrouter.d.ts +29 -0
  128. package/dist/providers/openrouter.d.ts.map +1 -0
  129. package/dist/providers/openrouter.js +35 -0
  130. package/dist/providers/openrouter.js.map +1 -0
  131. package/dist/providers/types.d.ts +60 -0
  132. package/dist/providers/types.d.ts.map +1 -0
  133. package/dist/providers/types.js +2 -0
  134. package/dist/providers/types.js.map +1 -0
  135. package/dist/routing/staticResolver.d.ts +41 -0
  136. package/dist/routing/staticResolver.d.ts.map +1 -0
  137. package/dist/routing/staticResolver.js +67 -0
  138. package/dist/routing/staticResolver.js.map +1 -0
  139. package/dist/routing/types.d.ts +72 -0
  140. package/dist/routing/types.d.ts.map +1 -0
  141. package/dist/routing/types.js +11 -0
  142. package/dist/routing/types.js.map +1 -0
  143. package/dist/secrets.d.ts +8 -0
  144. package/dist/secrets.d.ts.map +1 -0
  145. package/dist/secrets.js +14 -0
  146. package/dist/secrets.js.map +1 -0
  147. package/dist/tools/metadata.d.ts +93 -0
  148. package/dist/tools/metadata.d.ts.map +1 -0
  149. package/dist/tools/metadata.js +49 -0
  150. package/dist/tools/metadata.js.map +1 -0
  151. package/dist/tools/modelTool.d.ts +35 -0
  152. package/dist/tools/modelTool.d.ts.map +1 -0
  153. package/dist/tools/modelTool.js +37 -0
  154. package/dist/tools/modelTool.js.map +1 -0
  155. package/dist/tools/registry.d.ts +65 -0
  156. package/dist/tools/registry.d.ts.map +1 -0
  157. package/dist/tools/registry.js +166 -0
  158. package/dist/tools/registry.js.map +1 -0
  159. package/dist/types.d.ts +71 -0
  160. package/dist/types.d.ts.map +1 -0
  161. package/dist/types.js +10 -0
  162. package/dist/types.js.map +1 -0
  163. package/package.json +72 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/models/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAEjD,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAE5D;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,SAAS,CAAA;IACf,EAAE,EAAE,MAAM,CAAA;CACX;AAED,4EAA4E;AAC5E,MAAM,MAAM,YAAY,CAAC,GAAG,EAAE,GAAG,IAAI,MAAM,eAAe,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;AASpE,6EAA6E;AAC7E,MAAM,MAAM,YAAY,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAEvE,kEAAkE;AAClE,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAA;gBAEV,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE;CAM3C;AAID;;;;;;;;;;;;GAYG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4C;IACtE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAmB;IAE9C;;;OAGG;IACH,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,IAAI;IASxE,4EAA4E;IAC5E,gBAAgB,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,eAAe,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,IAAI;IAIlE;;;;OAIG;IACH,GAAG,CAAC,GAAG,UAAU,EAAE,UAAU,EAAE,GAAG,IAAI;IAKtC,GAAG,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO;IAI3B,2EAA2E;IAC3E,QAAQ,CAAC,GAAG,EAAE,QAAQ,GAAG,YAAY;IAKrC;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,GAAG,eAAe,CAAC,GAAG,EAAE,GAAG,CAAC;IAO3D,oDAAoD;IACpD,KAAK,IAAI,SAAS,EAAE;IASpB,yCAAyC;IACzC,GAAG,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,EAAE;IAO9B,mEAAmE;IACnE,UAAU,IAAI,MAAM,EAAE;CAGvB"}
Binary file
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/models/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,149 @@
1
+ /**
2
+ * The neutral model-invocation seam.
3
+ *
4
+ * A chat LLM is not the only kind of model a harness calls. Object detection,
5
+ * speech recognition and forecasting are all "hand a model a request, get a
6
+ * typed result" — they differ in payload, not in shape. So this seam unifies the
7
+ * **arrow and the envelope** (`invoke`, {@link ModelResult}, {@link InvokeContext},
8
+ * {@link ModelCaps}, `probe`) and deliberately leaves `Req`/`Res` **generic per
9
+ * kind**.
10
+ *
11
+ * That generic-per-kind rule is load-bearing. Collapsing a chat request and an
12
+ * image buffer into one `unknown` payload would erase exactly the typing that
13
+ * makes a `DetectionResult` or a `ForecastResult` worth having. A kind declares
14
+ * its own request and result types; the seam only guarantees how they travel.
15
+ */
16
+ /**
17
+ * What a model does. The listed kinds are conventions, not a closed set — an
18
+ * application registers whatever kinds it needs, and the `(string & {})` arm
19
+ * keeps editor completion for the common ones without restricting the type.
20
+ */
21
+ export type ModelKind = "chat" | "vision.detect" | "audio.asr" | "timeseries.forecast" | (string & {});
22
+ /**
23
+ * What an invocation can actually do. Declared by the implementation and
24
+ * **checked** at the call site: asking for an unsupported capability fails loud
25
+ * rather than silently degrading to a lesser path.
26
+ */
27
+ export interface ModelCaps {
28
+ /** `invokeStream` is implemented and may be called. */
29
+ streaming: boolean;
30
+ /** The request may carry tool definitions and the result may carry tool calls. */
31
+ tools: boolean;
32
+ /** The request may carry image/audio/binary parts. */
33
+ multimodalInput: boolean;
34
+ /** Results carry a populated `usage`. */
35
+ usage: boolean;
36
+ }
37
+ /** Token accounting, for kinds billed per token. */
38
+ export interface TokenUsage {
39
+ inputTokens?: number;
40
+ outputTokens?: number;
41
+ totalTokens?: number;
42
+ }
43
+ /**
44
+ * Accounting for kinds that aren't billed per token — frames processed, seconds
45
+ * of audio, rows forecast. A perception call's "usage" is the same idea in a
46
+ * different unit, which is why the envelope carries both shapes.
47
+ */
48
+ export interface UnitUsage {
49
+ units: number;
50
+ /** What the units are (e.g. "frames", "seconds"). Free-form. */
51
+ unit?: string;
52
+ }
53
+ export type Usage = TokenUsage | UnitUsage;
54
+ /** The uniform envelope every invocation returns, whatever its kind. */
55
+ export interface ModelResult<Res> {
56
+ /** The typed result. Its shape is the kind's contract. */
57
+ value: Res;
58
+ /** Cost/consumption, when the implementation reports it (`caps.usage`). */
59
+ usage?: Usage;
60
+ /** Implementation-specific detail — latency, model revision, cache hits. */
61
+ meta?: Record<string, unknown>;
62
+ }
63
+ /**
64
+ * Ambient per-call context. Carries the concerns that are cross-cutting rather
65
+ * than payload-specific, so middleware can act on them uniformly across kinds.
66
+ */
67
+ export interface InvokeContext {
68
+ /** Append a line to the caller's run log. */
69
+ log: (line: string) => void;
70
+ /** Cooperative cancellation. Implementations should honour it where they can. */
71
+ signal?: AbortSignal;
72
+ /** Ties this call to a wider trace. Middleware propagates it. */
73
+ correlationId?: string;
74
+ /** Wall-clock budget for this single call. */
75
+ budget?: {
76
+ maxDurationMs?: number;
77
+ };
78
+ }
79
+ export type HealthStatus = "up" | "down" | "degraded" | "unknown";
80
+ /** The outcome of a {@link ModelInvocation.probe}. */
81
+ export interface Health {
82
+ status: HealthStatus;
83
+ /** Human-readable explanation, especially for `down`/`degraded`/`unknown`. */
84
+ detail?: string;
85
+ meta?: Record<string, unknown>;
86
+ }
87
+ /**
88
+ * The normalized streaming event stream. Every implementation emits the same
89
+ * three-event sequence per tool call — `onToolCallStart`, one or more
90
+ * `onToolCallDelta`, then `onToolCallComplete` — even when the underlying API
91
+ * delivers arguments in one piece. Consumers therefore write one handler, not
92
+ * one per provider. Every handler is optional; a sink may care only about text.
93
+ */
94
+ export interface StreamSink {
95
+ onTextDelta?: (delta: string) => void;
96
+ onToolCallStart?: (toolCallId: string, toolName: string) => void;
97
+ onToolCallDelta?: (toolCallId: string, argumentsDelta: string) => void;
98
+ onToolCallComplete?: (toolCallId: string, toolName: string, args: string) => void;
99
+ }
100
+ /**
101
+ * Emit the canonical three-event sequence for a tool call whose arguments
102
+ * arrived whole. Implementations backed by an API that doesn't stream argument
103
+ * fragments call this so their output is indistinguishable from one that does.
104
+ */
105
+ export declare function emitCompleteToolCall(sink: StreamSink, toolCallId: string, toolName: string, args: string): void;
106
+ /**
107
+ * One callable model capability. `Req` and `Res` belong to the kind: the chat
108
+ * kind's `Req` carries messages and tools and its `Res` carries tool calls;
109
+ * a `vision.detect` kind's `Req` is an image reference and its `Res` is a
110
+ * detection struct with `caps.tools === false`.
111
+ */
112
+ export interface ModelInvocation<Req, Res> {
113
+ /** Identifies the concrete model within its kind (cf. a provider's name). */
114
+ readonly id: string;
115
+ readonly kind: ModelKind;
116
+ readonly caps: ModelCaps;
117
+ invoke(req: Req, ctx: InvokeContext): Promise<ModelResult<Res>>;
118
+ /** Present only when `caps.streaming`. Use {@link invokeStreaming} to call it safely. */
119
+ invokeStream?(req: Req, sink: StreamSink, ctx: InvokeContext): Promise<ModelResult<Res>>;
120
+ probe(): Promise<Health>;
121
+ }
122
+ /** The identity of an invocation, without its payload types — what middleware sees. */
123
+ export interface ModelIdentity {
124
+ id: string;
125
+ kind: ModelKind;
126
+ caps: ModelCaps;
127
+ }
128
+ /** Narrow a {@link ModelInvocation} to its identity. */
129
+ export declare function modelIdentity(model: ModelInvocation<never, unknown>): ModelIdentity;
130
+ /**
131
+ * Thrown when a call asks for something the invocation declared it cannot do.
132
+ * The kernel never silently degrades — a caller that asked to stream and got a
133
+ * buffered response back would have no way to notice.
134
+ */
135
+ export declare class CapabilityError extends Error {
136
+ readonly model: ModelIdentity;
137
+ readonly capability: keyof ModelCaps;
138
+ constructor(model: ModelIdentity, capability: keyof ModelCaps, detail?: string);
139
+ }
140
+ /** Assert a capability before relying on it, failing loud when it's absent. */
141
+ export declare function requireCapability(model: ModelIdentity, capability: keyof ModelCaps, detail?: string): void;
142
+ /**
143
+ * Stream an invocation, enforcing the capability gate. Fails loud when the
144
+ * model declared `streaming: false` or left `invokeStream` unimplemented —
145
+ * never falls back to the buffered path, because a caller that wanted deltas
146
+ * would otherwise get none and be unable to tell.
147
+ */
148
+ export declare function invokeStreaming<Req, Res>(model: ModelInvocation<Req, Res>, req: Req, sink: StreamSink, ctx: InvokeContext): Promise<ModelResult<Res>>;
149
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/models/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * The neutral model-invocation seam.
3
+ *
4
+ * A chat LLM is not the only kind of model a harness calls. Object detection,
5
+ * speech recognition and forecasting are all "hand a model a request, get a
6
+ * typed result" — they differ in payload, not in shape. So this seam unifies the
7
+ * **arrow and the envelope** (`invoke`, {@link ModelResult}, {@link InvokeContext},
8
+ * {@link ModelCaps}, `probe`) and deliberately leaves `Req`/`Res` **generic per
9
+ * kind**.
10
+ *
11
+ * That generic-per-kind rule is load-bearing. Collapsing a chat request and an
12
+ * image buffer into one `unknown` payload would erase exactly the typing that
13
+ * makes a `DetectionResult` or a `ForecastResult` worth having. A kind declares
14
+ * its own request and result types; the seam only guarantees how they travel.
15
+ */
16
+ /**
17
+ * Emit the canonical three-event sequence for a tool call whose arguments
18
+ * arrived whole. Implementations backed by an API that doesn't stream argument
19
+ * fragments call this so their output is indistinguishable from one that does.
20
+ */
21
+ export function emitCompleteToolCall(sink, toolCallId, toolName, args) {
22
+ sink.onToolCallStart?.(toolCallId, toolName);
23
+ sink.onToolCallDelta?.(toolCallId, args);
24
+ sink.onToolCallComplete?.(toolCallId, toolName, args);
25
+ }
26
+ /** Narrow a {@link ModelInvocation} to its identity. */
27
+ export function modelIdentity(model) {
28
+ return { id: model.id, kind: model.kind, caps: model.caps };
29
+ }
30
+ /**
31
+ * Thrown when a call asks for something the invocation declared it cannot do.
32
+ * The kernel never silently degrades — a caller that asked to stream and got a
33
+ * buffered response back would have no way to notice.
34
+ */
35
+ export class CapabilityError extends Error {
36
+ model;
37
+ capability;
38
+ constructor(model, capability, detail) {
39
+ super(`model ${model.kind}:${model.id} does not support ${capability}${detail ? ` (${detail})` : ""}`);
40
+ this.name = "CapabilityError";
41
+ this.model = model;
42
+ this.capability = capability;
43
+ }
44
+ }
45
+ /** Assert a capability before relying on it, failing loud when it's absent. */
46
+ export function requireCapability(model, capability, detail) {
47
+ if (!model.caps[capability])
48
+ throw new CapabilityError(model, capability, detail);
49
+ }
50
+ /**
51
+ * Stream an invocation, enforcing the capability gate. Fails loud when the
52
+ * model declared `streaming: false` or left `invokeStream` unimplemented —
53
+ * never falls back to the buffered path, because a caller that wanted deltas
54
+ * would otherwise get none and be unable to tell.
55
+ */
56
+ export async function invokeStreaming(model, req, sink, ctx) {
57
+ const identity = modelIdentity(model);
58
+ requireCapability(identity, "streaming");
59
+ if (!model.invokeStream) {
60
+ throw new CapabilityError(identity, "streaming", "declared streaming but has no invokeStream");
61
+ }
62
+ return model.invokeStream(req, sink, ctx);
63
+ }
64
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/models/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AA+FH;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAClC,IAAgB,EAChB,UAAkB,EAClB,QAAgB,EAChB,IAAY;IAEZ,IAAI,CAAC,eAAe,EAAE,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAA;IAC5C,IAAI,CAAC,eAAe,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;IACxC,IAAI,CAAC,kBAAkB,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAA;AACvD,CAAC;AA0BD,wDAAwD;AACxD,MAAM,UAAU,aAAa,CAAC,KAAsC;IAClE,OAAO,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAA;AAC7D,CAAC;AAED;;;;GAIG;AACH,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAC/B,KAAK,CAAe;IACpB,UAAU,CAAiB;IAEpC,YAAY,KAAoB,EAAE,UAA2B,EAAE,MAAe;QAC5E,KAAK,CACH,SAAS,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,EAAE,qBAAqB,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAChG,CAAA;QACD,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAA;QAC7B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;QAClB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;IAC9B,CAAC;CACF;AAED,+EAA+E;AAC/E,MAAM,UAAU,iBAAiB,CAC/B,KAAoB,EACpB,UAA2B,EAC3B,MAAe;IAEf,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC;QAAE,MAAM,IAAI,eAAe,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,CAAC,CAAA;AACnF,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAAgC,EAChC,GAAQ,EACR,IAAgB,EAChB,GAAkB;IAElB,MAAM,QAAQ,GAAG,aAAa,CAAC,KAAK,CAAC,CAAA;IACrC,iBAAiB,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAA;IACxC,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;QACxB,MAAM,IAAI,eAAe,CAAC,QAAQ,EAAE,WAAW,EAAE,4CAA4C,CAAC,CAAA;IAChG,CAAC;IACD,OAAO,KAAK,CAAC,YAAY,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC,CAAA;AAC3C,CAAC"}
@@ -0,0 +1,25 @@
1
+ export interface RunCodeOptions {
2
+ /** Working directory — normally the run sandbox. */
3
+ cwd: string;
4
+ command: string;
5
+ args?: string[];
6
+ /** Extra environment (e.g. secretsToEnv output). Merged over a minimal base. */
7
+ env?: NodeJS.ProcessEnv;
8
+ timeoutMs?: number;
9
+ stdin?: string;
10
+ maxBuffer?: number;
11
+ }
12
+ export interface RunCodeResult {
13
+ stdout: string;
14
+ stderr: string;
15
+ exitCode: number | null;
16
+ timedOut: boolean;
17
+ }
18
+ /**
19
+ * Run a command inside the sandbox. This is the general-purpose escape hatch the
20
+ * agent uses to run the workspace's OWN repo scripts — or code it writes on the
21
+ * fly — so domain logic lives in user code, never baked into the platform.
22
+ * Secrets are passed via `env` (see secretsToEnv) and are never logged here.
23
+ */
24
+ export declare function runCode(options: RunCodeOptions): Promise<RunCodeResult>;
25
+ //# sourceMappingURL=codeExec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codeExec.d.ts","sourceRoot":"","sources":["../../src/primitives/codeExec.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc;IAC7B,oDAAoD;IACpD,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,gFAAgF;IAChF,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;IACvB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,QAAQ,EAAE,OAAO,CAAA;CAClB;AAKD;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAuEvE"}
@@ -0,0 +1,69 @@
1
+ import { spawn } from "node:child_process";
2
+ const DEFAULT_TIMEOUT_MS = 60_000;
3
+ const DEFAULT_MAX_BUFFER = 8 * 1024 * 1024;
4
+ /**
5
+ * Run a command inside the sandbox. This is the general-purpose escape hatch the
6
+ * agent uses to run the workspace's OWN repo scripts — or code it writes on the
7
+ * fly — so domain logic lives in user code, never baked into the platform.
8
+ * Secrets are passed via `env` (see secretsToEnv) and are never logged here.
9
+ */
10
+ export function runCode(options) {
11
+ const { cwd, command, args = [], env, stdin, timeoutMs = DEFAULT_TIMEOUT_MS, maxBuffer = DEFAULT_MAX_BUFFER, } = options;
12
+ return new Promise((resolve, reject) => {
13
+ // A minimal base env with the caller's env — including resolved secrets —
14
+ // layered on top. We forward only non-secret runtime vars: PATH (so binaries
15
+ // resolve) and HOME (so npm/tooling use a stable cache dir — `$HOME/.npm`
16
+ // persists across runs on the warm pool, so a beat's `setup: [npm ci]` relinks
17
+ // instead of re-downloading). The runner's other env (tokens, provider keys)
18
+ // is deliberately NOT forwarded. `detached` puts the child in its own process
19
+ // group so the timeout can kill the WHOLE tree (a repo script that spawns
20
+ // subprocesses would otherwise orphan them).
21
+ const child = spawn(command, args, {
22
+ cwd,
23
+ env: { PATH: process.env.PATH, HOME: process.env.HOME, ...env },
24
+ detached: true,
25
+ });
26
+ let stdout = "";
27
+ let stderr = "";
28
+ let timedOut = false;
29
+ let settled = false;
30
+ const cap = (current, chunk) => current.length >= maxBuffer ? current : (current + chunk.toString()).slice(0, maxBuffer);
31
+ const killTree = () => {
32
+ try {
33
+ if (child.pid !== undefined)
34
+ process.kill(-child.pid, "SIGKILL"); // negative pid = process group
35
+ }
36
+ catch {
37
+ child.kill("SIGKILL");
38
+ }
39
+ };
40
+ const timer = setTimeout(() => {
41
+ timedOut = true;
42
+ killTree();
43
+ }, timeoutMs);
44
+ child.stdout?.on("data", (c) => {
45
+ stdout = cap(stdout, c);
46
+ });
47
+ child.stderr?.on("data", (c) => {
48
+ stderr = cap(stderr, c);
49
+ });
50
+ child.on("error", (err) => {
51
+ if (settled)
52
+ return;
53
+ settled = true;
54
+ clearTimeout(timer);
55
+ reject(err);
56
+ });
57
+ child.on("close", (code) => {
58
+ if (settled)
59
+ return;
60
+ settled = true;
61
+ clearTimeout(timer);
62
+ resolve({ stdout, stderr, exitCode: code, timedOut });
63
+ });
64
+ if (stdin !== undefined)
65
+ child.stdin?.write(stdin);
66
+ child.stdin?.end();
67
+ });
68
+ }
69
+ //# sourceMappingURL=codeExec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codeExec.js","sourceRoot":"","sources":["../../src/primitives/codeExec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { type Lookup } from "./http.js";
2
+ export interface DownloadOptions {
3
+ maxBytes?: number;
4
+ timeoutMs?: number;
5
+ /** DNS resolver, injectable to test the SSRF guard without real DNS. */
6
+ lookup?: Lookup;
7
+ }
8
+ /**
9
+ * Download a (binary) URL to a file on disk, bounded by a byte cap and a timeout,
10
+ * with the same SSRF guard as httpFetch (internal hosts refused, every redirect
11
+ * hop re-validated). Unlike httpFetch this streams to disk — snapshot tarballs are
12
+ * binary and can be far larger than httpFetch's in-memory string cap. Used to fetch
13
+ * a run's snapshot `.tar.gz` from a presigned object-store URL (or, in local dev, a
14
+ * co-located `file://` URL).
15
+ *
16
+ * On any failure the partial file is removed and the error re-thrown.
17
+ */
18
+ export declare function downloadToFile(url: string, destPath: string, opts?: DownloadOptions): Promise<void>;
19
+ //# sourceMappingURL=download.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"download.d.ts","sourceRoot":"","sources":["../../src/primitives/download.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiB,KAAK,MAAM,EAAE,MAAM,WAAW,CAAA;AAMtD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAYD;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,eAAoB,GACzB,OAAO,CAAC,IAAI,CAAC,CAqFf"}
@@ -0,0 +1,113 @@
1
+ import { createWriteStream } from "node:fs";
2
+ import { copyFile, rm } from "node:fs/promises";
3
+ import { fileURLToPath } from "node:url";
4
+ import { assertSafeUrl } from "./http.js";
5
+ const FALLBACK_MAX_BYTES = 1024 * 1024 * 1024; // 1 GiB
6
+ const FALLBACK_TIMEOUT_MS = 120_000;
7
+ const MAX_REDIRECTS = 5;
8
+ function defaultMaxBytes() {
9
+ const raw = Number(process.env.RUNNER_BUNDLE_MAX_BYTES);
10
+ return Number.isFinite(raw) && raw > 0 ? raw : FALLBACK_MAX_BYTES;
11
+ }
12
+ function defaultTimeoutMs() {
13
+ const raw = Number(process.env.RUNNER_BUNDLE_TIMEOUT_MS);
14
+ return Number.isFinite(raw) && raw > 0 ? raw : FALLBACK_TIMEOUT_MS;
15
+ }
16
+ /**
17
+ * Download a (binary) URL to a file on disk, bounded by a byte cap and a timeout,
18
+ * with the same SSRF guard as httpFetch (internal hosts refused, every redirect
19
+ * hop re-validated). Unlike httpFetch this streams to disk — snapshot tarballs are
20
+ * binary and can be far larger than httpFetch's in-memory string cap. Used to fetch
21
+ * a run's snapshot `.tar.gz` from a presigned object-store URL (or, in local dev, a
22
+ * co-located `file://` URL).
23
+ *
24
+ * On any failure the partial file is removed and the error re-thrown.
25
+ */
26
+ export async function downloadToFile(url, destPath, opts = {}) {
27
+ // Local/dev handoff: the LocalAdapter object store hands a `file://` URL (the
28
+ // caller and the kernel are co-located on one machine). Copy it straight from
29
+ // disk — never through fetch/the SSRF guard. This reads an arbitrary local path, so
30
+ // it is OPT-IN via RUNNER_ALLOW_FILE_URLS (dev/test only); production uses https
31
+ // presigned URLs and leaves it off, so a misconfigured `file://` URL is refused.
32
+ if (url.startsWith("file://")) {
33
+ if (process.env.RUNNER_ALLOW_FILE_URLS !== "1") {
34
+ throw new Error("file:// URLs are disabled; set RUNNER_ALLOW_FILE_URLS=1 for local dev");
35
+ }
36
+ await copyFile(fileURLToPath(url), destPath);
37
+ return;
38
+ }
39
+ const maxBytes = opts.maxBytes ?? defaultMaxBytes();
40
+ const timeoutMs = opts.timeoutMs ?? defaultTimeoutMs();
41
+ const controller = new AbortController();
42
+ let timedOut = false;
43
+ const timer = setTimeout(() => {
44
+ timedOut = true;
45
+ controller.abort();
46
+ }, timeoutMs);
47
+ try {
48
+ // Follow redirects manually so each hop is re-validated against the SSRF guard.
49
+ // Private/VPC object stores (and the MinIO-backed load-test rig) hand out
50
+ // presigned URLs on hosts that resolve to private addresses, which the guard
51
+ // refuses. OPT-IN escape hatch in the spirit of RUNNER_ALLOW_FILE_URLS: skip
52
+ // the guard for the snapshot download only (byte cap, timeout, and redirect
53
+ // bounds still apply). Leave unset in production with a public object store.
54
+ // NOTE: when set, the skip DELIBERATELY applies to every hop, redirect
55
+ // targets included — once private hosts are trusted there is no meaningful
56
+ // boundary left for per-hop re-validation to defend. Don't "fix" that by
57
+ // reinstating per-hop checks under the flag; it would break private stores
58
+ // that redirect internally.
59
+ const allowPrivate = process.env.RUNNER_ALLOW_PRIVATE_BUNDLE_HOSTS === "1";
60
+ let current = url;
61
+ let res;
62
+ for (let hops = 0;; hops++) {
63
+ if (!allowPrivate)
64
+ await assertSafeUrl(current, { lookup: opts.lookup });
65
+ res = await fetch(current, { redirect: "manual", signal: controller.signal });
66
+ if (res.status >= 300 && res.status < 400 && res.headers.has("location")) {
67
+ if (hops >= MAX_REDIRECTS)
68
+ throw new Error("too many redirects");
69
+ current = new URL(res.headers.get("location"), current).toString();
70
+ continue;
71
+ }
72
+ break;
73
+ }
74
+ if (res.status < 200 || res.status >= 300) {
75
+ throw new Error(`download failed: HTTP ${res.status} for ${url}`);
76
+ }
77
+ if (!res.body)
78
+ throw new Error(`download failed: empty body for ${url}`);
79
+ const out = createWriteStream(destPath);
80
+ // undici's ReadableStream types are non-generic, so the reader yields `any`;
81
+ // fetch response bodies are always byte streams.
82
+ const reader = res.body.getReader();
83
+ let total = 0;
84
+ try {
85
+ for (;;) {
86
+ const { done, value } = await reader.read();
87
+ if (done)
88
+ break;
89
+ total += value.byteLength;
90
+ if (total > maxBytes) {
91
+ await reader.cancel();
92
+ throw new Error(`download exceeds ${maxBytes} bytes`);
93
+ }
94
+ await new Promise((resolve, reject) => {
95
+ out.write(value, (err) => (err ? reject(err) : resolve()));
96
+ });
97
+ }
98
+ }
99
+ finally {
100
+ await new Promise((resolve, reject) => out.end((err) => (err ? reject(err) : resolve())));
101
+ }
102
+ }
103
+ catch (err) {
104
+ await rm(destPath, { force: true });
105
+ if (timedOut)
106
+ throw new Error(`download timeout after ${timeoutMs}ms: ${url}`, { cause: err });
107
+ throw err;
108
+ }
109
+ finally {
110
+ clearTimeout(timer);
111
+ }
112
+ }
113
+ //# sourceMappingURL=download.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"download.js","sourceRoot":"","sources":["../../src/primitives/download.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /** Read a UTF-8 file within the sandbox, or null if missing / not a file / too big / a symlink escape. */
2
+ export declare function readFileSafe(dir: string, relPath: string, maxBytes?: number): Promise<string | null>;
3
+ /** List files (recursively, `.git` excluded) under `relDir`, as sandbox-relative paths. */
4
+ export declare function listFiles(dir: string, relDir?: string): Promise<string[]>;
5
+ //# sourceMappingURL=fs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/primitives/fs.ts"],"names":[],"mappings":"AAsBA,0GAA0G;AAC1G,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,QAAQ,GAAE,MAA0B,GACnC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAWxB;AAED,2FAA2F;AAC3F,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,SAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAqB5E"}
@@ -0,0 +1,59 @@
1
+ import { readFile, readdir, stat, realpath } from "node:fs/promises";
2
+ import path from "node:path";
3
+ const DEFAULT_MAX_BYTES = 64 * 1024;
4
+ /** Lexical guard: refuse a relative path that escapes the sandbox via `..`. */
5
+ function resolveWithin(dir, relPath) {
6
+ const base = path.resolve(dir);
7
+ const target = path.resolve(base, relPath);
8
+ if (target !== base && !target.startsWith(base + path.sep)) {
9
+ throw new Error(`path escapes sandbox: ${relPath}`);
10
+ }
11
+ return target;
12
+ }
13
+ /** True if `target`'s real (symlink-resolved) path stays within the real base. */
14
+ async function realWithin(base, target) {
15
+ const realBase = await realpath(base);
16
+ const real = await realpath(target);
17
+ return real === realBase || real.startsWith(realBase + path.sep);
18
+ }
19
+ /** Read a UTF-8 file within the sandbox, or null if missing / not a file / too big / a symlink escape. */
20
+ export async function readFileSafe(dir, relPath, maxBytes = DEFAULT_MAX_BYTES) {
21
+ const target = resolveWithin(dir, relPath);
22
+ try {
23
+ // Resolve symlinks and re-check: a link inside the sandbox must not point out.
24
+ if (!(await realWithin(dir, target)))
25
+ return null;
26
+ const info = await stat(target);
27
+ if (!info.isFile() || info.size > maxBytes)
28
+ return null;
29
+ return await readFile(target, "utf8");
30
+ }
31
+ catch {
32
+ return null;
33
+ }
34
+ }
35
+ /** List files (recursively, `.git` excluded) under `relDir`, as sandbox-relative paths. */
36
+ export async function listFiles(dir, relDir = ".") {
37
+ const base = path.resolve(dir);
38
+ const root = resolveWithin(dir, relDir);
39
+ const out = [];
40
+ async function walk(current) {
41
+ const entries = await readdir(current, { withFileTypes: true });
42
+ for (const entry of entries) {
43
+ const abs = path.join(current, entry.name);
44
+ if (entry.isSymbolicLink())
45
+ continue; // don't follow symlinks out of the sandbox
46
+ if (entry.isDirectory()) {
47
+ if (entry.name === ".git")
48
+ continue;
49
+ await walk(abs);
50
+ }
51
+ else if (entry.isFile()) {
52
+ out.push(path.relative(base, abs));
53
+ }
54
+ }
55
+ }
56
+ await walk(root);
57
+ return out.sort();
58
+ }
59
+ //# sourceMappingURL=fs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs.js","sourceRoot":"","sources":["../../src/primitives/fs.ts"],"names":[],"mappings":"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"}