@helmr/sdk 0.1.1-rc.3 → 0.1.1-rc.4

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/dist/compile.d.ts CHANGED
@@ -5,5 +5,5 @@ export interface CompileOptions {
5
5
  readonly modulePath: string;
6
6
  readonly exportName?: string;
7
7
  }
8
- export declare const IMAGE_FORMAT_VERSION = 1;
8
+ export declare const IMAGE_FORMAT_VERSION = 0;
9
9
  export declare function compile(opts: CompileOptions): Bundle;
package/dist/compile.js CHANGED
@@ -97,8 +97,8 @@ function hasBrand(value, brand) {
97
97
  }
98
98
 
99
99
  // sdk/typescript/src/compile.ts
100
- var IMAGE_FORMAT_VERSION = 1;
101
- var IMAGE_KEY_DOMAIN = `helmr.image.v1
100
+ var IMAGE_FORMAT_VERSION = 0;
101
+ var IMAGE_KEY_DOMAIN = `helmr.image.v0
102
102
  `;
103
103
  function compile(opts) {
104
104
  const task = opts.task;
package/dist/config.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { type HelmrConfig } from "./internal.js";
2
2
  export interface HelmrConfigInput {
3
- readonly project?: string;
3
+ readonly project: string;
4
4
  readonly dirs: readonly string[];
5
5
  readonly ignorePatterns?: readonly string[];
6
6
  }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ApprovalTimeoutError, ConcurrentWaitError, MessageTimeoutError, validateSecretName, type CacheBuilder, type CacheMount, type CacheMountBinding, type EmitContent, type EmitEvent, type ImageBuilder, type ImageRunOptions, type Placement, type SandboxBuilder, type SecretDecls, type SecretMountBinding, type SourceCapabilities, type SourceDirRef, type SourceDirectoryOptions, type SourceFileRef, type TaskContext, type TaskOutput, type TaskPayload, type WorkspaceCapabilities, type WorkspaceSpec } from "./internal.js";
1
+ import { ApprovalTimeoutError, ConcurrentWaitError, MessageTimeoutError, validateSecretName, type CacheBuilder, type CacheMount, type CacheMountBinding, type EmitContent, type EmitEvent, type ImageBuilder, type ImageRunOptions, type Placement, type SandboxBuilder, type SecretDecls, type SecretMountBinding, type SourceCapabilities, type SourceDirRef, type SourceDirectoryOptions, type SourceFileRef, type TaskContext, type TaskSource, type TaskWorkspace, type GitHubRefKind, type GitHubPullRequestMetadata, type GitHubTaskSource, type TaskOutput, type TaskPayload, type WorkspaceCapabilities, type WorkspaceSpec } from "./internal.js";
2
2
  import { HelmrClient } from "./runtime/client.js";
3
3
  export type { WaitpointResponseToken, WaitpointTokenAction, WaitpointTokenCompleteOptions, WaitpointTokenCreateOptions, } from "./runtime/client.js";
4
4
  import { sandbox } from "./sandbox.js";
@@ -31,4 +31,4 @@ export declare const runs: {
31
31
  };
32
32
  };
33
33
  export declare const waitpoints: import("./runtime/client.js").WaitpointsApi;
34
- export type { CacheBuilder, CacheMount, CacheMountBinding, EmitContent, EmitEvent, ImageBuilder, ImageRunOptions, SandboxBuilder, SecretMountBinding, SourceCapabilities, SourceDirRef, SourceDirectoryOptions, SourceFileRef, WorkspaceCapabilities, WorkspaceSpec, TaskContext, };
34
+ export type { CacheBuilder, CacheMount, CacheMountBinding, EmitContent, EmitEvent, ImageBuilder, ImageRunOptions, SandboxBuilder, SecretMountBinding, SourceCapabilities, SourceDirRef, SourceDirectoryOptions, SourceFileRef, WorkspaceCapabilities, WorkspaceSpec, TaskContext, TaskSource, TaskWorkspace, GitHubRefKind, GitHubPullRequestMetadata, GitHubTaskSource, };
package/dist/index.js CHANGED
@@ -192,7 +192,7 @@ function stackFrameFile(line) {
192
192
  return match[1].startsWith("file://") ? decodeURIComponent(new URL(match[1]).pathname) : match[1];
193
193
  }
194
194
  function isSdkInternalFrame(file) {
195
- return file.includes("/sdk/typescript/src/internal.ts") || file.includes("/sdk/typescript/src/task.ts") || file.includes("/sdk/typescript/src/index.ts") || file.includes("/runtime/typescript/src/");
195
+ return file.includes("/sdk/typescript/src/internal") || file.includes("/sdk/typescript/src/task") || file.includes("/sdk/typescript/src/index") || file.includes("/runtime/typescript/src/");
196
196
  }
197
197
 
198
198
  class ImageBuilderImpl {
@@ -412,6 +412,8 @@ function runWorkspaceFromSpec(spec) {
412
412
  }
413
413
 
414
414
  // sdk/typescript/src/runtime/client.ts
415
+ var MAX_SSE_BUFFER_CHARS = 1024 * 1024;
416
+
415
417
  class HelmrClient {
416
418
  #baseUrl;
417
419
  #apiKey;
@@ -471,16 +473,21 @@ class HelmrClient {
471
473
  const timeoutMs = opts.timeoutMs;
472
474
  const intervalMs = opts.intervalMs ?? 1000;
473
475
  const started = Date.now();
474
- for (;; ) {
475
- throwIfAborted(opts.signal);
476
- const run = await this.runs.retrieve(id, retrieveOptions(opts.signal));
477
- if (isTerminalRunStatus(run.status)) {
478
- return run;
479
- }
480
- if (timeoutMs !== undefined && Date.now() - started > timeoutMs) {
481
- throw new TimeoutError(`run ${id} did not finish within ${timeoutMs}ms`);
476
+ const wait = waitSignal(opts.signal, timeoutMs, () => new TimeoutError(`run ${id} did not finish within ${timeoutMs}ms`));
477
+ try {
478
+ for (;; ) {
479
+ throwIfAborted(wait.signal);
480
+ const run = await this.runs.retrieve(id, retrieveOptions(wait.signal));
481
+ if (isTerminalRunStatus(run.status)) {
482
+ return run;
483
+ }
484
+ if (timeoutMs !== undefined && Date.now() - started > timeoutMs) {
485
+ throw new TimeoutError(`run ${id} did not finish within ${timeoutMs}ms`);
486
+ }
487
+ await delay(intervalMs, wait.signal);
482
488
  }
483
- await delay(intervalMs, opts.signal);
489
+ } finally {
490
+ wait.cleanup();
484
491
  }
485
492
  },
486
493
  list: async (opts = {}) => {
@@ -730,6 +737,28 @@ function retrieveOptions(signal) {
730
737
  function requestSignal(signal) {
731
738
  return signal === undefined ? {} : { signal };
732
739
  }
740
+ function waitSignal(signal, timeoutMs, timeoutError) {
741
+ if (timeoutMs === undefined) {
742
+ return { signal, cleanup: () => {} };
743
+ }
744
+ const controller = new AbortController;
745
+ const abortFromParent = () => {
746
+ controller.abort(signal?.reason);
747
+ };
748
+ if (signal?.aborted === true) {
749
+ abortFromParent();
750
+ } else {
751
+ signal?.addEventListener("abort", abortFromParent, { once: true });
752
+ }
753
+ const timeout = setTimeout(() => controller.abort(timeoutError()), timeoutMs);
754
+ return {
755
+ signal: controller.signal,
756
+ cleanup: () => {
757
+ clearTimeout(timeout);
758
+ signal?.removeEventListener("abort", abortFromParent);
759
+ }
760
+ };
761
+ }
733
762
  function throwIfAborted(signal) {
734
763
  if (signal?.aborted !== true)
735
764
  return;
@@ -763,30 +792,46 @@ async function* parseSse(response) {
763
792
  }
764
793
  const decoder = new TextDecoder;
765
794
  let buffer = "";
766
- for (;; ) {
767
- const { value, done } = await reader.read();
768
- if (done) {
769
- return;
770
- }
771
- buffer += decoder.decode(value, { stream: true });
772
- let boundary = findSseBoundary(buffer);
773
- while (boundary !== -1) {
774
- const delimiter = buffer.startsWith(`\r
795
+ try {
796
+ for (;; ) {
797
+ const { value, done } = await reader.read();
798
+ if (done) {
799
+ buffer += decoder.decode();
800
+ const finalEvent = parseSseFrame(buffer);
801
+ if (finalEvent !== undefined) {
802
+ yield finalEvent;
803
+ }
804
+ return;
805
+ }
806
+ buffer += decoder.decode(value, { stream: true });
807
+ let boundary = findSseBoundary(buffer);
808
+ while (boundary !== -1) {
809
+ const delimiter = buffer.startsWith(`\r
775
810
  \r
776
811
  `, boundary) ? 4 : 2;
777
- const raw = buffer.slice(0, boundary);
778
- buffer = buffer.slice(boundary + delimiter);
779
- const data = raw.split(/\r?\n/).filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trimStart()).join(`
780
- `);
781
- if (data !== "") {
782
- const event = runEventRecordToRunEvent(JSON.parse(data));
812
+ const raw = buffer.slice(0, boundary);
813
+ buffer = buffer.slice(boundary + delimiter);
814
+ const event = parseSseFrame(raw);
783
815
  if (event !== undefined) {
784
816
  yield event;
785
817
  }
818
+ boundary = findSseBoundary(buffer);
819
+ }
820
+ if (buffer.length > MAX_SSE_BUFFER_CHARS) {
821
+ throw new Error("SSE event exceeded the maximum buffer size");
786
822
  }
787
- boundary = findSseBoundary(buffer);
788
823
  }
824
+ } finally {
825
+ reader.releaseLock();
826
+ }
827
+ }
828
+ function parseSseFrame(raw) {
829
+ const data = raw.split(/\r?\n/).filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trimStart()).join(`
830
+ `);
831
+ if (data === "") {
832
+ return;
789
833
  }
834
+ return runEventRecordToRunEvent(JSON.parse(data));
790
835
  }
791
836
  function findSseBoundary(buffer) {
792
837
  const lf = buffer.indexOf(`
@@ -951,20 +996,21 @@ function defineConfig(config) {
951
996
  if (config === null || typeof config !== "object") {
952
997
  throw new Error("defineConfig() requires an object");
953
998
  }
999
+ if (!("project" in config)) {
1000
+ throw new Error("defineConfig({ project }) requires a non-empty string");
1001
+ }
1002
+ if (typeof config.project !== "string" || config.project.trim() === "") {
1003
+ throw new Error("defineConfig({ project }) must be a non-empty string");
1004
+ }
1005
+ if (config.project.includes("\x00")) {
1006
+ throw new Error("defineConfig({ project }) must not contain NUL");
1007
+ }
954
1008
  if (!("dirs" in config)) {
955
1009
  throw new Error("defineConfig({ dirs }) requires a non-empty dirs array");
956
1010
  }
957
1011
  if (!Array.isArray(config.dirs) || config.dirs.length === 0) {
958
1012
  throw new Error("defineConfig({ dirs }) requires a non-empty dirs array");
959
1013
  }
960
- if (config.project !== undefined) {
961
- if (typeof config.project !== "string" || config.project.trim() === "") {
962
- throw new Error("defineConfig({ project }) must be a non-empty string");
963
- }
964
- if (config.project.includes("\x00")) {
965
- throw new Error("defineConfig({ project }) must not contain NUL");
966
- }
967
- }
968
1014
  for (const dir of config.dirs) {
969
1015
  if (typeof dir !== "string" || dir.trim() === "") {
970
1016
  throw new Error("defineConfig({ dirs }) entries must be non-empty strings");
@@ -987,7 +1033,7 @@ function defineConfig(config) {
987
1033
  }
988
1034
  }
989
1035
  return markConfig({
990
- ...config.project === undefined ? {} : { project: config.project },
1036
+ project: config.project,
991
1037
  dirs: [...config.dirs],
992
1038
  ...config.ignorePatterns === undefined ? {} : { ignorePatterns: [...config.ignorePatterns] }
993
1039
  });
@@ -19,6 +19,31 @@ export interface WorkspaceSpec {
19
19
  readonly ref: string;
20
20
  readonly subpath?: string;
21
21
  }
22
+ export type GitHubRefKind = "branch" | "tag" | "sha" | "pull_request" | "unknown";
23
+ export interface GitHubPullRequestMetadata {
24
+ readonly number: number;
25
+ readonly baseRef: string;
26
+ readonly baseSha: string;
27
+ readonly headRef: string;
28
+ readonly headSha: string;
29
+ }
30
+ export interface GitHubTaskSource {
31
+ readonly kind: "github";
32
+ readonly repository: string;
33
+ readonly requestedRef: string;
34
+ readonly resolvedSha: string;
35
+ readonly refKind?: GitHubRefKind;
36
+ readonly refName?: string;
37
+ readonly fullRef?: string;
38
+ readonly subpath?: string;
39
+ readonly defaultBranch?: string;
40
+ readonly pullRequest?: GitHubPullRequestMetadata;
41
+ }
42
+ export type TaskSource = GitHubTaskSource;
43
+ export interface TaskWorkspace {
44
+ readonly path: string;
45
+ readonly projectPath: string;
46
+ }
22
47
  export interface SourceFileRef {
23
48
  readonly path: string;
24
49
  }
@@ -91,6 +116,11 @@ export interface TaskContext {
91
116
  readonly run: {
92
117
  readonly id: string;
93
118
  };
119
+ readonly task: {
120
+ readonly id: string;
121
+ };
122
+ readonly source: TaskSource;
123
+ readonly workspace: TaskWorkspace;
94
124
  }
95
125
  export type EmitContent = {
96
126
  readonly type: "text";
@@ -193,7 +223,7 @@ export declare function isTaskDefinition(value: unknown): value is AnyTask & {
193
223
  };
194
224
  export declare function taskOriginFile(value: unknown): string | null;
195
225
  export interface HelmrConfig {
196
- readonly project?: string;
226
+ readonly project: string;
197
227
  readonly dirs: readonly string[];
198
228
  readonly ignorePatterns?: readonly string[];
199
229
  }
package/dist/internal.js CHANGED
@@ -205,7 +205,7 @@ function stackFrameFile(line) {
205
205
  return match[1].startsWith("file://") ? decodeURIComponent(new URL(match[1]).pathname) : match[1];
206
206
  }
207
207
  function isSdkInternalFrame(file) {
208
- return file.includes("/sdk/typescript/src/internal.ts") || file.includes("/sdk/typescript/src/task.ts") || file.includes("/sdk/typescript/src/index.ts") || file.includes("/runtime/typescript/src/");
208
+ return file.includes("/sdk/typescript/src/internal") || file.includes("/sdk/typescript/src/task") || file.includes("/sdk/typescript/src/index") || file.includes("/runtime/typescript/src/");
209
209
  }
210
210
 
211
211
  class ImageBuilderImpl {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@helmr/sdk",
3
- "version": "0.1.1-rc.3",
3
+ "version": "0.1.1-rc.4",
4
4
  "description": "TypeScript SDK for authoring and triggering Helmr tasks.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -43,6 +43,6 @@
43
43
  ],
44
44
  "dependencies": {
45
45
  "@bufbuild/protobuf": "^2.11.0",
46
- "@helmr/proto": "0.1.1-rc.3"
46
+ "@helmr/proto": "0.1.1-rc.4"
47
47
  }
48
48
  }