@blaxel/core 0.2.96-preview.203 → 0.2.96-preview.205

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 (90) hide show
  1. package/README.md +37 -2
  2. package/dist/cjs/.tsbuildinfo +1 -1
  3. package/dist/cjs/client/sdk.gen.js +113 -2
  4. package/dist/cjs/common/pagination.js +92 -0
  5. package/dist/cjs/common/pagination.test.js +81 -0
  6. package/dist/cjs/common/settings.js +3 -3
  7. package/dist/cjs/common/settings.test.js +3 -3
  8. package/dist/cjs/drive/index.js +39 -4
  9. package/dist/cjs/index.js +1 -0
  10. package/dist/cjs/jobs/jobs.js +42 -10
  11. package/dist/cjs/sandbox/client/sdk.gen.js +2 -2
  12. package/dist/cjs/sandbox/index.js +1 -0
  13. package/dist/cjs/sandbox/preview.js +8 -3
  14. package/dist/cjs/sandbox/sandbox.js +43 -33
  15. package/dist/cjs/sandbox/schedule.js +91 -0
  16. package/dist/cjs/types/client/sdk.gen.d.ts +31 -1
  17. package/dist/cjs/types/client/types.gen.d.ts +347 -0
  18. package/dist/cjs/types/common/pagination.d.ts +35 -0
  19. package/dist/cjs/types/common/pagination.test.d.ts +1 -0
  20. package/dist/cjs/types/drive/index.d.ts +35 -5
  21. package/dist/cjs/types/index.d.ts +1 -0
  22. package/dist/cjs/types/jobs/jobs.d.ts +33 -3
  23. package/dist/cjs/types/sandbox/client/sdk.gen.d.ts +2 -2
  24. package/dist/cjs/types/sandbox/client/types.gen.d.ts +28 -1
  25. package/dist/cjs/types/sandbox/index.d.ts +1 -0
  26. package/dist/cjs/types/sandbox/preview.d.ts +2 -2
  27. package/dist/cjs/types/sandbox/sandbox.d.ts +38 -3
  28. package/dist/cjs/types/sandbox/schedule.d.ts +16 -0
  29. package/dist/cjs/types/volume/index.d.ts +37 -4
  30. package/dist/cjs/volume/index.js +41 -4
  31. package/dist/cjs-browser/.tsbuildinfo +1 -1
  32. package/dist/cjs-browser/client/sdk.gen.js +113 -2
  33. package/dist/cjs-browser/common/pagination.js +92 -0
  34. package/dist/cjs-browser/common/pagination.test.js +81 -0
  35. package/dist/cjs-browser/common/settings.js +3 -3
  36. package/dist/cjs-browser/common/settings.test.js +3 -3
  37. package/dist/cjs-browser/drive/index.js +39 -4
  38. package/dist/cjs-browser/index.js +1 -0
  39. package/dist/cjs-browser/jobs/jobs.js +42 -10
  40. package/dist/cjs-browser/sandbox/client/sdk.gen.js +2 -2
  41. package/dist/cjs-browser/sandbox/index.js +1 -0
  42. package/dist/cjs-browser/sandbox/preview.js +8 -3
  43. package/dist/cjs-browser/sandbox/sandbox.js +43 -33
  44. package/dist/cjs-browser/sandbox/schedule.js +91 -0
  45. package/dist/cjs-browser/types/client/sdk.gen.d.ts +31 -1
  46. package/dist/cjs-browser/types/client/types.gen.d.ts +347 -0
  47. package/dist/cjs-browser/types/common/pagination.d.ts +35 -0
  48. package/dist/cjs-browser/types/common/pagination.test.d.ts +1 -0
  49. package/dist/cjs-browser/types/drive/index.d.ts +35 -5
  50. package/dist/cjs-browser/types/index.d.ts +1 -0
  51. package/dist/cjs-browser/types/jobs/jobs.d.ts +33 -3
  52. package/dist/cjs-browser/types/sandbox/client/sdk.gen.d.ts +2 -2
  53. package/dist/cjs-browser/types/sandbox/client/types.gen.d.ts +28 -1
  54. package/dist/cjs-browser/types/sandbox/index.d.ts +1 -0
  55. package/dist/cjs-browser/types/sandbox/preview.d.ts +2 -2
  56. package/dist/cjs-browser/types/sandbox/sandbox.d.ts +38 -3
  57. package/dist/cjs-browser/types/sandbox/schedule.d.ts +16 -0
  58. package/dist/cjs-browser/types/volume/index.d.ts +37 -4
  59. package/dist/cjs-browser/volume/index.js +41 -4
  60. package/dist/esm/.tsbuildinfo +1 -1
  61. package/dist/esm/client/sdk.gen.js +104 -0
  62. package/dist/esm/common/pagination.js +88 -0
  63. package/dist/esm/common/pagination.test.js +79 -0
  64. package/dist/esm/common/settings.js +3 -3
  65. package/dist/esm/common/settings.test.js +3 -3
  66. package/dist/esm/drive/index.js +39 -4
  67. package/dist/esm/index.js +1 -0
  68. package/dist/esm/jobs/jobs.js +42 -10
  69. package/dist/esm/sandbox/client/sdk.gen.js +2 -2
  70. package/dist/esm/sandbox/index.js +1 -0
  71. package/dist/esm/sandbox/preview.js +8 -3
  72. package/dist/esm/sandbox/sandbox.js +43 -33
  73. package/dist/esm/sandbox/schedule.js +87 -0
  74. package/dist/esm/volume/index.js +41 -4
  75. package/dist/esm-browser/.tsbuildinfo +1 -1
  76. package/dist/esm-browser/client/sdk.gen.js +104 -0
  77. package/dist/esm-browser/common/pagination.js +88 -0
  78. package/dist/esm-browser/common/pagination.test.js +79 -0
  79. package/dist/esm-browser/common/settings.js +3 -3
  80. package/dist/esm-browser/common/settings.test.js +3 -3
  81. package/dist/esm-browser/drive/index.js +39 -4
  82. package/dist/esm-browser/index.js +1 -0
  83. package/dist/esm-browser/jobs/jobs.js +42 -10
  84. package/dist/esm-browser/sandbox/client/sdk.gen.js +2 -2
  85. package/dist/esm-browser/sandbox/index.js +1 -0
  86. package/dist/esm-browser/sandbox/preview.js +8 -3
  87. package/dist/esm-browser/sandbox/sandbox.js +43 -33
  88. package/dist/esm-browser/sandbox/schedule.js +87 -0
  89. package/dist/esm-browser/volume/index.js +41 -4
  90. package/package.json +1 -1
@@ -2,8 +2,9 @@
2
2
  // This file is auto-generated by @hey-api/openapi-ts
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.createIntegrationConnection = exports.listIntegrationConnections = exports.getIntegration = exports.deleteImageTag = exports.unshareImage = exports.shareImage = exports.listImageShares = exports.getImage = exports.deleteImage = exports.createImage = exports.listImages = exports.cleanupImages = exports.listFunctionRevisions = exports.updateFunction = exports.getFunction = exports.deleteFunction = exports.createFunction = exports.listFunctions = exports.testFeatureFlag = exports.getWorkspaceFeatures = exports.listAllEgressIps = exports.getEgressGatewayUsage = exports.listAllEgressGateways = exports.getDriveJwks = exports.createDriveAccessToken = exports.updateDrive = exports.getDrive = exports.deleteDrive = exports.createDrive = exports.listDrives = exports.verifyCustomDomain = exports.updateCustomDomain = exports.getCustomDomain = exports.deleteCustomDomain = exports.createCustomDomain = exports.listCustomDomains = exports.getConfiguration = exports.listApplicationRevisions = exports.createApplicationCustomDomain = exports.updateApplication = exports.getApplication = exports.deleteApplication = exports.createApplication = exports.listApplications = exports.listAgentRevisions = exports.updateAgent = exports.getAgent = exports.deleteAgent = exports.createAgent = exports.listAgents = void 0;
5
- exports.getSandboxByExternalId = exports.deleteSandboxPreviewToken = exports.createSandboxPreviewToken = exports.listSandboxPreviewTokens = exports.updateSandboxPreview = exports.getSandboxPreview = exports.deleteSandboxPreview = exports.createSandboxPreview = exports.listSandboxPreviews = exports.updateSandbox = exports.getSandbox = exports.deleteSandbox = exports.createSandbox = exports.listSandboxes = exports.listSandboxHubDefinitions = exports.listPublicIps = exports.getPolicyUsages = exports.updatePolicy = exports.getPolicy = exports.deletePolicy = exports.createPolicy = exports.listPolicies = exports.declineImageShare = exports.acceptImageShare = exports.listPendingImageShares = exports.listModelRevisions = exports.updateModel = exports.getModel = exports.deleteModel = exports.createModel = exports.listModels = exports.listMcpHubDefinitions = exports.listLocations = exports.listJobRevisions = exports.listJobExecutionTasks = exports.getJobExecution = exports.deleteJobExecution = exports.createJobExecution = exports.listJobExecutions = exports.updateJob = exports.getJob = exports.deleteJob = exports.createJob = exports.listJobs = exports.getIntegrationConnectionModel = exports.listIntegrationConnectionModels = exports.getIntegrationConnectionModelEndpointConfigurations = exports.updateIntegrationConnection = exports.getIntegrationConnection = exports.deleteIntegrationConnection = void 0;
6
- exports.checkWorkspaceAvailability = exports.leaveWorkspace = exports.acceptWorkspaceInvitation = exports.declineWorkspaceInvitation = exports.updateWorkspace = exports.getWorkspace = exports.deleteWorkspace = exports.createWorkspace = exports.listWorkspaces = exports.getEgressIp = exports.deleteEgressIp = exports.createEgressIp = exports.listEgressIps = exports.getEgressGateway = exports.deleteEgressGateway = exports.createEgressGateway = exports.listEgressGateways = exports.getVpc = exports.deleteVpc = exports.createVpc = exports.listVpcs = exports.updateVolume = exports.getVolume = exports.deleteVolume = exports.createVolume = exports.listVolumes = exports.deleteVolumeTemplateVersion = exports.updateVolumeTemplate = exports.getVolumeTemplate = exports.deleteVolumeTemplate = exports.createVolumeTemplate = exports.listVolumeTemplates = exports.updateWorkspaceUserRole = exports.removeWorkspaceUser = exports.inviteWorkspaceUser = exports.listWorkspaceUsers = exports.getTemplate = exports.listTemplates = exports.deleteApiKeyForServiceAccount = exports.createApiKeyForServiceAccount = exports.listApiKeysForServiceAccount = exports.updateWorkspaceServiceAccount = exports.deleteWorkspaceServiceAccount = exports.createWorkspaceServiceAccount = exports.getWorkspaceServiceAccounts = void 0;
5
+ exports.listSandboxScheduleExecutions = exports.deleteSandboxPreviewToken = exports.createSandboxPreviewToken = exports.listSandboxPreviewTokens = exports.updateSandboxPreview = exports.getSandboxPreview = exports.deleteSandboxPreview = exports.createSandboxPreview = exports.listSandboxPreviews = exports.updateSandbox = exports.getSandbox = exports.deleteSandbox = exports.createSandbox = exports.listSandboxes = exports.listSandboxHubDefinitions = exports.listPublicIps = exports.getPolicyUsages = exports.updatePolicy = exports.getPolicy = exports.deletePolicy = exports.createPolicy = exports.listPolicies = exports.declineImageShare = exports.acceptImageShare = exports.listPendingImageShares = exports.listModelRevisions = exports.updateModel = exports.getModel = exports.deleteModel = exports.createModel = exports.listModels = exports.listMcpHubDefinitions = exports.listLocations = exports.listJobRevisions = exports.listJobExecutionTasks = exports.getJobExecution = exports.deleteJobExecution = exports.createJobExecution = exports.listJobExecutions = exports.updateJob = exports.getJob = exports.deleteJob = exports.createJob = exports.listJobs = exports.getIntegrationConnectionModel = exports.listIntegrationConnectionModels = exports.getIntegrationConnectionModelEndpointConfigurations = exports.updateIntegrationConnection = exports.getIntegrationConnection = exports.deleteIntegrationConnection = void 0;
6
+ exports.leaveWorkspace = exports.acceptWorkspaceInvitation = exports.declineWorkspaceInvitation = exports.updateWorkspace = exports.getWorkspace = exports.deleteWorkspace = exports.createWorkspace = exports.listWorkspaces = exports.getEgressIp = exports.deleteEgressIp = exports.createEgressIp = exports.listEgressIps = exports.getEgressGateway = exports.deleteEgressGateway = exports.createEgressGateway = exports.listEgressGateways = exports.getVpc = exports.deleteVpc = exports.createVpc = exports.listVpcs = exports.updateVolume = exports.getVolume = exports.deleteVolume = exports.createVolume = exports.listVolumes = exports.deleteVolumeTemplateVersion = exports.updateVolumeTemplate = exports.getVolumeTemplate = exports.deleteVolumeTemplate = exports.createVolumeTemplate = exports.listVolumeTemplates = exports.updateWorkspaceUserRole = exports.removeWorkspaceUser = exports.inviteWorkspaceUser = exports.listWorkspaceUsers = exports.getTemplate = exports.listTemplates = exports.deleteApiKeyForServiceAccount = exports.createApiKeyForServiceAccount = exports.listApiKeysForServiceAccount = exports.updateWorkspaceServiceAccount = exports.deleteWorkspaceServiceAccount = exports.createWorkspaceServiceAccount = exports.getWorkspaceServiceAccounts = exports.getSandboxByExternalId = exports.updateSandboxSchedule = exports.getSandboxSchedule = exports.deleteSandboxSchedule = exports.createSandboxSchedule = exports.listSandboxSchedules = void 0;
7
+ exports.checkWorkspaceAvailability = void 0;
7
8
  const client_gen_1 = require("./client.gen");
8
9
  /**
9
10
  * List all agents
@@ -1782,6 +1783,116 @@ const deleteSandboxPreviewToken = (options) => {
1782
1783
  });
1783
1784
  };
1784
1785
  exports.deleteSandboxPreviewToken = deleteSandboxPreviewToken;
1786
+ /**
1787
+ * List Sandbox Schedule Executions
1788
+ * Returns the execution history of a Sandbox's schedules (across all schedules of the sandbox), newest first. Cursor-paginated via the `cursor` and `limit` query parameters. Each item records the HTTP status of submitting the scheduled command and the process name for log lookup.
1789
+ */
1790
+ const listSandboxScheduleExecutions = (options) => {
1791
+ return (options.client ?? client_gen_1.client).get({
1792
+ security: [
1793
+ {
1794
+ scheme: 'bearer',
1795
+ type: 'http'
1796
+ }
1797
+ ],
1798
+ url: '/sandboxes/{sandboxName}/schedule-executions',
1799
+ ...options
1800
+ });
1801
+ };
1802
+ exports.listSandboxScheduleExecutions = listSandboxScheduleExecutions;
1803
+ /**
1804
+ * List Sandbox Schedules
1805
+ * Returns the schedules configured on a Sandbox. Starting with API version 2026-04-28 the response is wrapped in `{data, meta}` and supports cursor pagination via the `cursor` and `limit` query parameters; older versions return a bare array.
1806
+ */
1807
+ const listSandboxSchedules = (options) => {
1808
+ return (options.client ?? client_gen_1.client).get({
1809
+ security: [
1810
+ {
1811
+ scheme: 'bearer',
1812
+ type: 'http'
1813
+ }
1814
+ ],
1815
+ url: '/sandboxes/{sandboxName}/schedules',
1816
+ ...options
1817
+ });
1818
+ };
1819
+ exports.listSandboxSchedules = listSandboxSchedules;
1820
+ /**
1821
+ * Create Sandbox Schedule
1822
+ * Adds a schedule to a Sandbox.
1823
+ */
1824
+ const createSandboxSchedule = (options) => {
1825
+ return (options.client ?? client_gen_1.client).post({
1826
+ security: [
1827
+ {
1828
+ scheme: 'bearer',
1829
+ type: 'http'
1830
+ }
1831
+ ],
1832
+ url: '/sandboxes/{sandboxName}/schedules',
1833
+ ...options,
1834
+ headers: {
1835
+ 'Content-Type': 'application/json',
1836
+ ...options?.headers
1837
+ }
1838
+ });
1839
+ };
1840
+ exports.createSandboxSchedule = createSandboxSchedule;
1841
+ /**
1842
+ * Delete Sandbox Schedule
1843
+ * Deletes a Sandbox Schedule by id.
1844
+ */
1845
+ const deleteSandboxSchedule = (options) => {
1846
+ return (options.client ?? client_gen_1.client).delete({
1847
+ security: [
1848
+ {
1849
+ scheme: 'bearer',
1850
+ type: 'http'
1851
+ }
1852
+ ],
1853
+ url: '/sandboxes/{sandboxName}/schedules/{scheduleId}',
1854
+ ...options
1855
+ });
1856
+ };
1857
+ exports.deleteSandboxSchedule = deleteSandboxSchedule;
1858
+ /**
1859
+ * Get Sandbox Schedule
1860
+ * Returns a Sandbox Schedule by id.
1861
+ */
1862
+ const getSandboxSchedule = (options) => {
1863
+ return (options.client ?? client_gen_1.client).get({
1864
+ security: [
1865
+ {
1866
+ scheme: 'bearer',
1867
+ type: 'http'
1868
+ }
1869
+ ],
1870
+ url: '/sandboxes/{sandboxName}/schedules/{scheduleId}',
1871
+ ...options
1872
+ });
1873
+ };
1874
+ exports.getSandboxSchedule = getSandboxSchedule;
1875
+ /**
1876
+ * Update Sandbox Schedule
1877
+ * Updates a Sandbox Schedule by id.
1878
+ */
1879
+ const updateSandboxSchedule = (options) => {
1880
+ return (options.client ?? client_gen_1.client).put({
1881
+ security: [
1882
+ {
1883
+ scheme: 'bearer',
1884
+ type: 'http'
1885
+ }
1886
+ ],
1887
+ url: '/sandboxes/{sandboxName}/schedules/{scheduleId}',
1888
+ ...options,
1889
+ headers: {
1890
+ 'Content-Type': 'application/json',
1891
+ ...options?.headers
1892
+ }
1893
+ });
1894
+ };
1895
+ exports.updateSandboxSchedule = updateSandboxSchedule;
1785
1896
  /**
1786
1897
  * Get sandbox by external ID
1787
1898
  * Returns the most recent non-terminated sandbox matching the given external ID. If no active sandbox is found, returns 404.
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.unwrapListData = unwrapListData;
4
+ exports.createPaginatedList = createPaginatedList;
5
+ function unwrapListData(response) {
6
+ if (!response) {
7
+ return [];
8
+ }
9
+ if (Array.isArray(response)) {
10
+ return response;
11
+ }
12
+ return response.data ?? [];
13
+ }
14
+ function unwrapListMeta(response) {
15
+ if (!response || Array.isArray(response)) {
16
+ return { hasMore: false };
17
+ }
18
+ return response.meta ?? { hasMore: false };
19
+ }
20
+ async function createPaginatedList({ response, fetchPage, mapItem, query, seenCursors, }) {
21
+ const meta = unwrapListMeta(response);
22
+ const data = await Promise.all(unwrapListData(response).map(mapItem));
23
+ const cursors = new Set(seenCursors);
24
+ if (query?.cursor) {
25
+ cursors.add(query.cursor);
26
+ }
27
+ const list = {
28
+ data,
29
+ meta,
30
+ // Derive `hasMore` from cursor presence, not `meta.hasMore`: `nextPage()`
31
+ // can only advance when there is a `nextCursor`, so a consumer doing
32
+ // `if (page.hasMore) await page.nextPage()` must never see `hasMore: true`
33
+ // while `nextPage()` returns null. Keeping the two in sync prevents silent
34
+ // truncation if the API ever sends `hasMore: true` without a cursor.
35
+ get hasMore() {
36
+ return Boolean(list.nextCursor);
37
+ },
38
+ get nextCursor() {
39
+ return meta.nextCursor || undefined;
40
+ },
41
+ async nextPage() {
42
+ const cursor = list.nextCursor;
43
+ if (!cursor) {
44
+ return null;
45
+ }
46
+ if (cursors.has(cursor)) {
47
+ throw new Error("Pagination returned a repeated cursor");
48
+ }
49
+ const nextQuery = { ...(query ?? {}), cursor };
50
+ const nextSeenCursors = new Set(cursors);
51
+ nextSeenCursors.add(cursor);
52
+ return createPaginatedList({
53
+ response: await fetchPage(nextQuery),
54
+ fetchPage,
55
+ mapItem,
56
+ query: nextQuery,
57
+ seenCursors: nextSeenCursors,
58
+ });
59
+ },
60
+ async autoPagingEach(onItem) {
61
+ for await (const item of list) {
62
+ const shouldContinue = await onItem(item);
63
+ if (shouldContinue === false) {
64
+ return;
65
+ }
66
+ }
67
+ },
68
+ async autoPagingToArray(options) {
69
+ if (!options || !Number.isFinite(options.limit) || options.limit <= 0) {
70
+ throw new Error("autoPagingToArray requires a positive limit");
71
+ }
72
+ const items = [];
73
+ for await (const item of list) {
74
+ items.push(item);
75
+ if (items.length >= options.limit) {
76
+ return items;
77
+ }
78
+ }
79
+ return items;
80
+ },
81
+ async *[Symbol.asyncIterator]() {
82
+ let page = list;
83
+ while (page) {
84
+ for (const item of page.data) {
85
+ yield item;
86
+ }
87
+ page = await page.nextPage();
88
+ }
89
+ },
90
+ };
91
+ return list;
92
+ }
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const pagination_js_1 = require("./pagination.js");
5
+ (0, vitest_1.describe)("pagination helpers", () => {
6
+ (0, vitest_1.it)("unwraps legacy array and paginated list responses", () => {
7
+ (0, vitest_1.expect)((0, pagination_js_1.unwrapListData)([{ name: "legacy" }])).toEqual([{ name: "legacy" }]);
8
+ (0, vitest_1.expect)((0, pagination_js_1.unwrapListData)({
9
+ data: [{ name: "paginated" }],
10
+ meta: { hasMore: false },
11
+ })).toEqual([{ name: "paginated" }]);
12
+ });
13
+ (0, vitest_1.it)("returns page data and lets callers request the next page", async () => {
14
+ const cursors = [];
15
+ const fetchPage = async (query) => {
16
+ await Promise.resolve();
17
+ cursors.push(query?.cursor);
18
+ if (!query?.cursor) {
19
+ return {
20
+ data: ["first"],
21
+ meta: { hasMore: true, nextCursor: "next-page" },
22
+ };
23
+ }
24
+ return {
25
+ data: ["second"],
26
+ meta: { hasMore: false },
27
+ };
28
+ };
29
+ const page = await (0, pagination_js_1.createPaginatedList)({
30
+ response: await fetchPage(),
31
+ fetchPage,
32
+ mapItem: (item) => item.toUpperCase(),
33
+ });
34
+ (0, vitest_1.expect)(page.data).toEqual(["FIRST"]);
35
+ (0, vitest_1.expect)(page.hasMore).toBe(true);
36
+ (0, vitest_1.expect)(page.nextCursor).toBe("next-page");
37
+ const nextPage = await page.nextPage();
38
+ (0, vitest_1.expect)(nextPage?.data).toEqual(["SECOND"]);
39
+ (0, vitest_1.expect)(cursors).toEqual([undefined, "next-page"]);
40
+ });
41
+ (0, vitest_1.it)("keeps hasMore consistent with nextPage when the API omits a cursor", async () => {
42
+ const fetchPage = async () => {
43
+ await Promise.resolve();
44
+ // API reports more data but gives no cursor to fetch it.
45
+ return {
46
+ data: ["only"],
47
+ meta: { hasMore: true },
48
+ };
49
+ };
50
+ const page = await (0, pagination_js_1.createPaginatedList)({
51
+ response: await fetchPage(),
52
+ fetchPage,
53
+ mapItem: (item) => item,
54
+ });
55
+ // hasMore must reflect what nextPage() can actually deliver.
56
+ (0, vitest_1.expect)(page.hasMore).toBe(false);
57
+ await (0, vitest_1.expect)(page.nextPage()).resolves.toBeNull();
58
+ await (0, vitest_1.expect)(page.autoPagingToArray({ limit: 10 })).resolves.toEqual(["only"]);
59
+ });
60
+ (0, vitest_1.it)("supports auto paging with an explicit limit", async () => {
61
+ const fetchPage = async (query) => {
62
+ await Promise.resolve();
63
+ if (!query?.cursor) {
64
+ return {
65
+ data: ["first"],
66
+ meta: { hasMore: true, nextCursor: "next-page" },
67
+ };
68
+ }
69
+ return {
70
+ data: ["second"],
71
+ meta: { hasMore: false },
72
+ };
73
+ };
74
+ const page = await (0, pagination_js_1.createPaginatedList)({
75
+ response: await fetchPage(),
76
+ fetchPage,
77
+ mapItem: (item) => item,
78
+ });
79
+ await (0, vitest_1.expect)(page.autoPagingToArray({ limit: 2 })).resolves.toEqual(["first", "second"]);
80
+ });
81
+ });
@@ -28,10 +28,10 @@ function missingCredentialsMessage() {
28
28
  return "No Blaxel credentials found. Set the BL_API_KEY and BL_WORKSPACE environment variables, or run `bl login`.";
29
29
  }
30
30
  // Build info - these placeholders are replaced at build time by build:replace-imports
31
- const BUILD_VERSION = "0.2.96-preview.203";
32
- const BUILD_COMMIT = "a709e2f3c52a8973b18719ac1325f315896dabc0";
31
+ const BUILD_VERSION = "0.2.96-preview.205";
32
+ const BUILD_COMMIT = "b2439e6cde8dee15ff0ff166366670a4f48d8ade";
33
33
  const BUILD_SENTRY_DSN = "https://fd5e60e1c9820e1eef5ccebb84a07127@o4508714045276160.ingest.us.sentry.io/4510465864564736";
34
- const BLAXEL_API_VERSION = "2026-04-16";
34
+ const BLAXEL_API_VERSION = "2026-04-28";
35
35
  // Cache for config.yaml tracking value
36
36
  let configTrackingValue = null;
37
37
  let configTrackingLoaded = false;
@@ -43,10 +43,10 @@ const env_js_1 = require("./env.js");
43
43
  (0, vitest_1.afterEach)(() => {
44
44
  delete env_js_1.env.BL_API_VERSION;
45
45
  });
46
- (0, vitest_1.it)('defaults to 2026-04-16 when BL_API_VERSION is not set', async () => {
46
+ (0, vitest_1.it)('defaults to 2026-04-28 when BL_API_VERSION is not set', async () => {
47
47
  delete env_js_1.env.BL_API_VERSION;
48
48
  const { settings } = await Promise.resolve().then(() => __importStar(require('./settings.js')));
49
- (0, vitest_1.expect)(settings.apiVersion).toBe('2026-04-16');
49
+ (0, vitest_1.expect)(settings.apiVersion).toBe('2026-04-28');
50
50
  });
51
51
  (0, vitest_1.it)('headers include Blaxel-Version set to the default', async () => {
52
52
  delete env_js_1.env.BL_API_VERSION;
@@ -55,7 +55,7 @@ const env_js_1 = require("./env.js");
55
55
  const previous = settings.credentials;
56
56
  settings.credentials = new apikey_js_1.ApiKey({ apiKey: 'test-key', workspace: 'test-ws' });
57
57
  try {
58
- (0, vitest_1.expect)(settings.headers['Blaxel-Version']).toBe('2026-04-16');
58
+ (0, vitest_1.expect)(settings.headers['Blaxel-Version']).toBe('2026-04-28');
59
59
  }
60
60
  finally {
61
61
  settings.credentials = previous;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DriveInstance = void 0;
4
4
  const uuid_1 = require("uuid");
5
5
  const index_js_1 = require("../client/index.js");
6
+ const pagination_js_1 = require("../common/pagination.js");
6
7
  const settings_js_1 = require("../common/settings.js");
7
8
  class DriveInstance {
8
9
  drive;
@@ -90,10 +91,44 @@ class DriveInstance {
90
91
  });
91
92
  return new DriveInstance(data);
92
93
  }
93
- static async list() {
94
- const { data } = await (0, index_js_1.listDrives)({ throwOnError: true });
95
- const items = Array.isArray(data) ? data : (data?.data ?? []);
96
- return items.map((drive) => new DriveInstance(drive));
94
+ /**
95
+ * List one page of drives.
96
+ *
97
+ * The returned page exposes `data` for the current page, `meta` for cursor
98
+ * metadata, and helpers to fetch more pages only when you need them.
99
+ *
100
+ * @example
101
+ * ```ts
102
+ * const page = await DriveInstance.list({ limit: 50 });
103
+ *
104
+ * for (const drive of page.data) {
105
+ * console.log(drive.name);
106
+ * }
107
+ *
108
+ * const nextPage = await page.nextPage();
109
+ * ```
110
+ *
111
+ * @example
112
+ * ```ts
113
+ * const allDrives = await (await DriveInstance.list()).autoPagingToArray({
114
+ * limit: 1000,
115
+ * });
116
+ * ```
117
+ */
118
+ static async list(query) {
119
+ const fetchPage = async (pageQuery) => {
120
+ const { data } = await (0, index_js_1.listDrives)({
121
+ query: pageQuery,
122
+ throwOnError: true,
123
+ });
124
+ return data;
125
+ };
126
+ return (0, pagination_js_1.createPaginatedList)({
127
+ response: await fetchPage(query),
128
+ fetchPage,
129
+ mapItem: (drive) => new DriveInstance(drive),
130
+ query,
131
+ });
97
132
  }
98
133
  static async delete(driveName) {
99
134
  const { data } = await (0, index_js_1.deleteDrive)({
package/dist/cjs/index.js CHANGED
@@ -23,6 +23,7 @@ __exportStar(require("./common/node.js"), exports);
23
23
  __exportStar(require("./common/errors.js"), exports);
24
24
  __exportStar(require("./common/internal.js"), exports);
25
25
  __exportStar(require("./common/logger.js"), exports);
26
+ __exportStar(require("./common/pagination.js"), exports);
26
27
  __exportStar(require("./common/settings.js"), exports);
27
28
  __exportStar(require("./common/webhook.js"), exports);
28
29
  __exportStar(require("./drive/index.js"), exports);
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.blJob = void 0;
4
4
  const index_js_1 = require("../client/index.js");
5
5
  const logger_js_1 = require("../common/logger.js");
6
+ const pagination_js_1 = require("../common/pagination.js");
6
7
  const settings_js_1 = require("../common/settings.js");
7
8
  const telemetry_js_1 = require("../telemetry/telemetry.js");
8
9
  class BlJob {
@@ -78,19 +79,50 @@ class BlJob {
78
79
  return data;
79
80
  }
80
81
  /**
81
- * List all executions for this job
82
+ * List one page of executions for this job.
83
+ *
84
+ * The returned page exposes `data` for the current page, `meta` for cursor
85
+ * metadata, and helpers to fetch more pages only when you need them.
86
+ *
87
+ * @example
88
+ * ```ts
89
+ * const job = blJob("daily-import");
90
+ * const page = await job.listExecutions({ limit: 50 });
91
+ *
92
+ * for (const execution of page.data) {
93
+ * console.log(execution.status);
94
+ * }
95
+ *
96
+ * const nextPage = await page.nextPage();
97
+ * ```
98
+ *
99
+ * @example
100
+ * ```ts
101
+ * const job = blJob("daily-import");
102
+ * const executions = await (await job.listExecutions()).autoPagingToArray({
103
+ * limit: 1000,
104
+ * });
105
+ * ```
82
106
  */
83
- async listExecutions() {
107
+ async listExecutions(query) {
84
108
  logger_js_1.logger.debug(`Listing executions for job: ${this.jobName}`);
85
- const { data } = await (0, index_js_1.listJobExecutions)({
86
- path: {
87
- jobId: this.jobName,
88
- },
89
- headers: settings_js_1.settings.headers,
90
- throwOnError: true,
109
+ const fetchPage = async (pageQuery) => {
110
+ const { data } = await (0, index_js_1.listJobExecutions)({
111
+ path: {
112
+ jobId: this.jobName,
113
+ },
114
+ query: pageQuery,
115
+ headers: settings_js_1.settings.headers,
116
+ throwOnError: true,
117
+ });
118
+ return data;
119
+ };
120
+ return (0, pagination_js_1.createPaginatedList)({
121
+ response: await fetchPage(query),
122
+ fetchPage,
123
+ mapItem: (execution) => execution,
124
+ query,
91
125
  });
92
- const items = Array.isArray(data) ? data : (data?.data ?? []);
93
- return items;
94
126
  }
95
127
  /**
96
128
  * Get the status of a specific execution
@@ -92,7 +92,7 @@ const getDrivesMount = (options) => {
92
92
  exports.getDrivesMount = getDrivesMount;
93
93
  /**
94
94
  * Attach a drive to a local path
95
- * Mounts an agent drive using the blfs binary to a local path, optionally mounting a subpath within the drive
95
+ * Mounts an agent drive using the blfs binary to a local path, optionally mounting a subpath within the drive. Supports optional UID/GID mapping to remap file ownership between the local sandbox and the filer (always mapped to filer UID/GID 0). Mapping values can be set per-request via uidMap/gidMap fields, or globally via BLFS_UID_MAP/BLFS_GID_MAP environment variables (request values take precedence).
96
96
  */
97
97
  const postDrivesMount = (options) => {
98
98
  return (options.client ?? client_gen_1.client).post({
@@ -643,7 +643,7 @@ exports.getProcessByIdentifierLogsStream = getProcessByIdentifierLogsStream;
643
643
  * Triggers an upgrade of the sandbox-api process. Returns 200 immediately before upgrading.
644
644
  * The upgrade will: download the specified binary from GitHub releases, validate it, and restart.
645
645
  * All running processes will be preserved across the upgrade.
646
- * Available versions: "develop" (default), "main", "latest", or specific tag like "v1.0.0"
646
+ * Available versions: "latest" (default, most recent release), "develop", "main", or specific tag like "v1.0.0"
647
647
  * You can also specify a custom baseUrl for forks (defaults to https://github.com/blaxel-ai/sandbox/releases)
648
648
  */
649
649
  const postUpgrade = (options) => {
@@ -37,6 +37,7 @@ __exportStar(require("./codegen/index.js"), exports);
37
37
  var index_js_2 = require("./drive/index.js");
38
38
  Object.defineProperty(exports, "SandboxDrive", { enumerable: true, get: function () { return index_js_2.SandboxDrive; } });
39
39
  __exportStar(require("./preview.js"), exports);
40
+ __exportStar(require("./schedule.js"), exports);
40
41
  __exportStar(require("./session.js"), exports);
41
42
  __exportStar(require("./sandbox.js"), exports);
42
43
  __exportStar(require("./system.js"), exports);
@@ -105,24 +105,29 @@ class SandboxPreviews {
105
105
  });
106
106
  return data.map((preview) => new SandboxPreview(preview));
107
107
  }
108
- async create(preview) {
108
+ async create(preview, force) {
109
+ const query = {};
110
+ if (force) {
111
+ query['force'] = 'true';
112
+ }
109
113
  const { data } = await (0, index_js_1.createSandboxPreview)({
110
114
  path: {
111
115
  sandboxName: this.sandboxName,
112
116
  },
117
+ query,
113
118
  body: preview,
114
119
  throwOnError: true,
115
120
  });
116
121
  return new SandboxPreview(data);
117
122
  }
118
- async createIfNotExists(preview) {
123
+ async createIfNotExists(preview, force) {
119
124
  try {
120
125
  const previewInstance = await this.get(preview.metadata.name);
121
126
  return previewInstance;
122
127
  }
123
128
  catch (e) {
124
129
  if (typeof e === "object" && e !== null && "code" in e && e.code === 404) {
125
- return this.create(preview);
130
+ return this.create(preview, force);
126
131
  }
127
132
  throw e;
128
133
  }
@@ -37,6 +37,7 @@ exports.SandboxInstance = void 0;
37
37
  const uuid_1 = require("uuid");
38
38
  const index_js_1 = require("../client/index.js");
39
39
  const logger_js_1 = require("../common/logger.js");
40
+ const pagination_js_1 = require("../common/pagination.js");
40
41
  const settings_js_1 = require("../common/settings.js");
41
42
  const index_js_2 = require("./codegen/index.js");
42
43
  const index_js_3 = require("./drive/index.js");
@@ -44,6 +45,7 @@ const index_js_4 = require("./filesystem/index.js");
44
45
  const index_js_5 = require("./network/index.js");
45
46
  const preview_js_1 = require("./preview.js");
46
47
  const index_js_6 = require("./process/index.js");
48
+ const schedule_js_1 = require("./schedule.js");
47
49
  const session_js_1 = require("./session.js");
48
50
  const system_js_1 = require("./system.js");
49
51
  const types_js_1 = require("./types.js");
@@ -77,6 +79,7 @@ class SandboxInstance {
77
79
  network;
78
80
  process;
79
81
  previews;
82
+ schedules;
80
83
  sessions;
81
84
  codegen;
82
85
  system;
@@ -88,6 +91,7 @@ class SandboxInstance {
88
91
  this.fs = new index_js_4.SandboxFileSystem(sandbox, this.process);
89
92
  this.network = new index_js_5.SandboxNetwork(sandbox);
90
93
  this.previews = new preview_js_1.SandboxPreviews(sandbox);
94
+ this.schedules = new schedule_js_1.SandboxSchedules(sandbox);
91
95
  this.sessions = new session_js_1.SandboxSessions(sandbox);
92
96
  this.codegen = new index_js_2.SandboxCodegen(sandbox);
93
97
  this.system = new system_js_1.SandboxSystem(sandbox);
@@ -280,40 +284,46 @@ class SandboxInstance {
280
284
  const instance = new SandboxInstance(data);
281
285
  return SandboxInstance.attachH2Session(instance);
282
286
  }
283
- static async list({ externalId } = {}) {
284
- const { data: raw } = await (0, index_js_1.listSandboxes)({
285
- query: externalId ? { externalId } : undefined,
286
- throwOnError: true,
287
+ /**
288
+ * List one page of sandboxes.
289
+ *
290
+ * The returned page exposes `data` for the current page, `meta` for cursor
291
+ * metadata, and helpers to fetch more pages only when you need them.
292
+ *
293
+ * @example
294
+ * ```ts
295
+ * const page = await SandboxInstance.list({ limit: 50 });
296
+ *
297
+ * for (const sandbox of page.data) {
298
+ * console.log(sandbox.metadata.name);
299
+ * }
300
+ *
301
+ * const nextPage = await page.nextPage();
302
+ * ```
303
+ *
304
+ * @example
305
+ * ```ts
306
+ * const page = await SandboxInstance.list({ limit: 100 });
307
+ *
308
+ * for await (const sandbox of page) {
309
+ * console.log(sandbox.metadata.name);
310
+ * }
311
+ * ```
312
+ */
313
+ static async list(query) {
314
+ const fetchPage = async (pageQuery) => {
315
+ const { data } = await (0, index_js_1.listSandboxes)({
316
+ query: pageQuery,
317
+ throwOnError: true,
318
+ });
319
+ return data;
320
+ };
321
+ return (0, pagination_js_1.createPaginatedList)({
322
+ response: await fetchPage(query),
323
+ fetchPage,
324
+ mapItem: (sandbox) => SandboxInstance.attachH2Session(new SandboxInstance(sandbox)),
325
+ query,
287
326
  });
288
- const items = (Array.isArray(raw) ? raw : (raw?.data ?? []));
289
- const instances = items.map((sb) => new SandboxInstance(sb));
290
- if (!settings_js_1.settings.disableH2) {
291
- const { h2Pool } = await Promise.resolve().then(() => __importStar(require("../common/h2pool.js")));
292
- const uniqueDomains = [
293
- ...new Set(instances
294
- .map((i) => SandboxInstance.edgeDomainForRegion(i.spec?.region))
295
- .filter((d) => d !== null)),
296
- ];
297
- const sessionByDomain = new Map();
298
- await Promise.all(uniqueDomains.map(async (domain) => {
299
- try {
300
- sessionByDomain.set(domain, await h2Pool.get(domain));
301
- }
302
- catch {
303
- sessionByDomain.set(domain, null);
304
- }
305
- }));
306
- for (const instance of instances) {
307
- const domain = SandboxInstance.edgeDomainForRegion(instance.spec?.region);
308
- if (domain) {
309
- const session = sessionByDomain.get(domain) ?? null;
310
- instance.h2Session = session;
311
- instance.sandbox.h2Session = session;
312
- instance.sandbox.h2Domain = domain;
313
- }
314
- }
315
- }
316
- return instances;
317
327
  }
318
328
  static async delete(sandboxName) {
319
329
  const { data } = await (0, index_js_1.deleteSandbox)({