@miosa/sdk 1.2.5 → 1.2.6

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 (92) hide show
  1. package/README.md +107 -59
  2. package/dist/index.d.ts +331 -202
  3. package/dist/index.js +572 -603
  4. package/dist/index.js.map +1 -1
  5. package/package.json +1 -2
  6. package/src/client.ts +0 -293
  7. package/src/errors.ts +0 -136
  8. package/src/http.test.ts +0 -374
  9. package/src/http.ts +0 -390
  10. package/src/index.ts +0 -569
  11. package/src/resources/admin.ts +0 -348
  12. package/src/resources/analytics.ts +0 -60
  13. package/src/resources/api-keys.ts +0 -119
  14. package/src/resources/audit-log.ts +0 -64
  15. package/src/resources/benchmarks.ts +0 -104
  16. package/src/resources/builder-sessions.ts +0 -75
  17. package/src/resources/channels.ts +0 -143
  18. package/src/resources/checkpoints.ts +0 -225
  19. package/src/resources/command-center.ts +0 -73
  20. package/src/resources/community.ts +0 -103
  21. package/src/resources/completions.ts +0 -104
  22. package/src/resources/computer-auto-stop.ts +0 -43
  23. package/src/resources/computer-env.ts +0 -76
  24. package/src/resources/computer-logs.ts +0 -50
  25. package/src/resources/computer-osa.ts +0 -76
  26. package/src/resources/computer-ports.ts +0 -91
  27. package/src/resources/computer-terminal.ts +0 -61
  28. package/src/resources/computer-volumes.ts +0 -64
  29. package/src/resources/computer.ts +0 -551
  30. package/src/resources/computers.ts +0 -75
  31. package/src/resources/credits.ts +0 -43
  32. package/src/resources/cron-jobs.ts +0 -191
  33. package/src/resources/custom_domains.ts +0 -123
  34. package/src/resources/dashboard.ts +0 -49
  35. package/src/resources/databases.ts +0 -218
  36. package/src/resources/deployments.test.ts +0 -197
  37. package/src/resources/deployments.ts +0 -1208
  38. package/src/resources/desktop.ts +0 -134
  39. package/src/resources/devices.test.ts +0 -92
  40. package/src/resources/devices.ts +0 -291
  41. package/src/resources/egress.test.ts +0 -318
  42. package/src/resources/egressAudit.ts +0 -245
  43. package/src/resources/egressNetwork.ts +0 -450
  44. package/src/resources/egressSecrets.ts +0 -577
  45. package/src/resources/email.ts +0 -212
  46. package/src/resources/embeddings.ts +0 -36
  47. package/src/resources/events.ts +0 -296
  48. package/src/resources/exec.ts +0 -319
  49. package/src/resources/external-keys.ts +0 -79
  50. package/src/resources/files.test.ts +0 -339
  51. package/src/resources/files.ts +0 -220
  52. package/src/resources/flat-custom-domains.ts +0 -127
  53. package/src/resources/functions.ts +0 -178
  54. package/src/resources/health-checks.ts +0 -165
  55. package/src/resources/integrations.ts +0 -183
  56. package/src/resources/mcp.ts +0 -70
  57. package/src/resources/models.ts +0 -45
  58. package/src/resources/network_policy.ts +0 -73
  59. package/src/resources/open-computers/agents.ts +0 -91
  60. package/src/resources/open-computers/apps.ts +0 -102
  61. package/src/resources/open-computers/clusters.ts +0 -88
  62. package/src/resources/open-computers/desktop.ts +0 -34
  63. package/src/resources/open-computers/files.ts +0 -97
  64. package/src/resources/open-computers/hosts.ts +0 -85
  65. package/src/resources/open-computers/index.ts +0 -98
  66. package/src/resources/open-computers/jobs.ts +0 -75
  67. package/src/resources/open-computers/open_computers.test.ts +0 -288
  68. package/src/resources/open-computers/secrets.ts +0 -115
  69. package/src/resources/open-computers/terminal.ts +0 -33
  70. package/src/resources/open-computers/tunnels.ts +0 -87
  71. package/src/resources/open-computers/types.ts +0 -343
  72. package/src/resources/open-computers/workspaces.ts +0 -135
  73. package/src/resources/org-invites.ts +0 -189
  74. package/src/resources/project-auth.ts +0 -142
  75. package/src/resources/project-integrations.ts +0 -133
  76. package/src/resources/provider-defaults.ts +0 -89
  77. package/src/resources/regions.ts +0 -94
  78. package/src/resources/sandbox-templates.ts +0 -195
  79. package/src/resources/sandboxes.live.test.ts +0 -92
  80. package/src/resources/sandboxes.test.ts +0 -655
  81. package/src/resources/sandboxes.ts +0 -1437
  82. package/src/resources/settings.ts +0 -143
  83. package/src/resources/snapshots-standalone.ts +0 -51
  84. package/src/resources/storage.ts +0 -221
  85. package/src/resources/tenant.ts +0 -66
  86. package/src/resources/usage.ts +0 -85
  87. package/src/resources/volumes.ts +0 -117
  88. package/src/resources/webhooks.ts +0 -239
  89. package/src/resources/workspace-invites.ts +0 -188
  90. package/src/resources/workspace-members.test.ts +0 -121
  91. package/src/resources/workspace-members.ts +0 -143
  92. package/src/types.ts +0 -463
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createHmac, timingSafeEqual, randomUUID } from 'crypto';
1
+ import { randomUUID } from 'crypto';
2
2
  import EventEmitter from 'events';
3
3
 
4
4
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
@@ -592,6 +592,77 @@ var Admin = class {
592
592
  model_id: modelId
593
593
  });
594
594
  }
595
+ /** POST /api/v1/admin/impersonate — returns {token, expires_at}. */
596
+ impersonate(externalUserId, options = {}) {
597
+ return this.http.post("/admin/impersonate", {
598
+ external_user_id: externalUserId,
599
+ ttl_sec: options.ttlSec ?? 3600
600
+ });
601
+ }
602
+ };
603
+
604
+ // src/resources/agent-runs.ts
605
+ function stripUndefined(input) {
606
+ return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== void 0));
607
+ }
608
+ function createBody(params) {
609
+ return stripUndefined({
610
+ target_id: params.target_id ?? params.targetId ?? params.sandbox_id ?? params.sandboxId ?? params.computer_id ?? params.computerId,
611
+ target_kind: params.target_kind ?? params.targetKind,
612
+ provider: params.provider,
613
+ prompt: params.prompt,
614
+ instruction: params.instruction,
615
+ command: params.command,
616
+ model: params.model,
617
+ cwd: params.cwd,
618
+ timeout: params.timeout,
619
+ metadata: params.metadata
620
+ });
621
+ }
622
+ function listQuery(params) {
623
+ return {
624
+ target_id: params.target_id ?? params.targetId ?? params.sandbox_id ?? params.sandboxId ?? params.computer_id ?? params.computerId,
625
+ limit: params.limit
626
+ };
627
+ }
628
+ function unwrapRun(response) {
629
+ const run = response.data ?? response.run;
630
+ if (!run) {
631
+ throw new Error("Agent run response was empty.");
632
+ }
633
+ return run;
634
+ }
635
+ function unwrapRuns(response) {
636
+ if (Array.isArray(response)) return response;
637
+ return response.data ?? response.runs ?? [];
638
+ }
639
+ var AgentRuns = class {
640
+ constructor(http) {
641
+ this.http = http;
642
+ }
643
+ http;
644
+ /** Dispatch a prompt to a sandbox/computer and persist the run record. */
645
+ async create(params) {
646
+ const response = await this.http.post("/agent-runs", createBody(params));
647
+ return unwrapRun(response);
648
+ }
649
+ /** Alias for create(), matching the product language. */
650
+ async run(params) {
651
+ return this.create(params);
652
+ }
653
+ /** List recent agent runs for the authenticated tenant. */
654
+ async list(params = {}) {
655
+ const response = await this.http.get(
656
+ "/agent-runs",
657
+ listQuery(params)
658
+ );
659
+ return unwrapRuns(response);
660
+ }
661
+ /** Fetch one persisted agent run. */
662
+ async get(runId) {
663
+ const response = await this.http.get(`/agent-runs/${runId}`);
664
+ return unwrapRun(response);
665
+ }
595
666
  };
596
667
 
597
668
  // src/resources/analytics.ts
@@ -604,7 +675,7 @@ function unwrap(payload) {
604
675
  }
605
676
  return payload;
606
677
  }
607
- function stripUndefined(input) {
678
+ function stripUndefined2(input) {
608
679
  return Object.fromEntries(
609
680
  Object.entries(input).filter(([, v]) => v !== void 0)
610
681
  );
@@ -616,13 +687,13 @@ var Analytics = class {
616
687
  http;
617
688
  /** Get the platform analytics overview. */
618
689
  async overview(filters = {}) {
619
- const query = stripUndefined(filters);
690
+ const query = stripUndefined2(filters);
620
691
  const data = await this.http.get("/analytics/overview", query);
621
692
  return unwrap(data);
622
693
  }
623
694
  /** Get a timeseries for a metric over a period. */
624
695
  async timeseries(params = {}) {
625
- const query = stripUndefined(params);
696
+ const query = stripUndefined2(params);
626
697
  const data = await this.http.get("/analytics/timeseries", query);
627
698
  return unwrap(data);
628
699
  }
@@ -643,7 +714,7 @@ function listItems(payload, candidateKeys = ["data", "keys", "api_keys", "items"
643
714
  }
644
715
  return [];
645
716
  }
646
- function stripUndefined2(input) {
717
+ function stripUndefined3(input) {
647
718
  return Object.fromEntries(
648
719
  Object.entries(input).filter(([, v]) => v !== void 0)
649
720
  );
@@ -657,13 +728,13 @@ var ApiKeys = class {
657
728
  }
658
729
  http;
659
730
  async list(params = {}) {
660
- const query = stripUndefined2({ ...params });
731
+ const query = stripUndefined3({ ...params });
661
732
  const data = await this.http.get("/api-keys", query);
662
733
  return listItems(data);
663
734
  }
664
735
  async create(params) {
665
736
  const { idempotencyKey: ikey, expiresAt, ...rest } = params;
666
- const body = stripUndefined2({
737
+ const body = stripUndefined3({
667
738
  ...rest,
668
739
  expires_at: expiresAt ?? rest.expires_at
669
740
  });
@@ -674,6 +745,17 @@ var ApiKeys = class {
674
745
  });
675
746
  return unwrap2(data);
676
747
  }
748
+ /** POST /api/v1/api-keys/scoped — L2 delegation token bound to one external user. */
749
+ async createScoped(params) {
750
+ const body = stripUndefined3({
751
+ external_user_id: params.externalUserId,
752
+ scopes: params.scopes,
753
+ expires_at: params.expiresAt
754
+ });
755
+ return unwrap2(
756
+ await this.http.post("/api-keys/scoped", body)
757
+ );
758
+ }
677
759
  async delete(keyId) {
678
760
  await this.http.delete(`/api-keys/${keyId}`);
679
761
  }
@@ -689,7 +771,7 @@ function unwrap3(payload) {
689
771
  }
690
772
  return payload;
691
773
  }
692
- function stripUndefined3(input) {
774
+ function stripUndefined4(input) {
693
775
  return Object.fromEntries(
694
776
  Object.entries(input).filter(([, v]) => v !== void 0)
695
777
  );
@@ -701,7 +783,7 @@ var AuditLog = class {
701
783
  http;
702
784
  /** List audit-log events with optional filters. */
703
785
  async list(params = {}) {
704
- const query = stripUndefined3(params);
786
+ const query = stripUndefined4(params);
705
787
  const data = await this.http.get("/audit-log", query);
706
788
  const result = unwrap3(data);
707
789
  if (Array.isArray(result)) return result;
@@ -839,7 +921,7 @@ function unwrap6(payload) {
839
921
  }
840
922
  return payload;
841
923
  }
842
- function stripUndefined4(input) {
924
+ function stripUndefined5(input) {
843
925
  return Object.fromEntries(
844
926
  Object.entries(input).filter(([, v]) => v !== void 0)
845
927
  );
@@ -856,7 +938,7 @@ var Channels = class {
856
938
  http;
857
939
  /** List all channels for the tenant. */
858
940
  async list(params = {}) {
859
- const query = stripUndefined4(params);
941
+ const query = stripUndefined5(params);
860
942
  const data = await this.http.get("/channels", query);
861
943
  const result = unwrap6(data);
862
944
  if (Array.isArray(result)) return result;
@@ -1716,7 +1798,7 @@ function unwrapList8(payload) {
1716
1798
  }
1717
1799
  return [];
1718
1800
  }
1719
- function stripUndefined5(input) {
1801
+ function stripUndefined6(input) {
1720
1802
  return Object.fromEntries(
1721
1803
  Object.entries(input).filter(([, v]) => v !== void 0)
1722
1804
  );
@@ -1725,8 +1807,8 @@ function pickFirst(...values) {
1725
1807
  for (const v of values) if (v !== void 0) return v;
1726
1808
  return void 0;
1727
1809
  }
1728
- function listQuery(params) {
1729
- return stripUndefined5({
1810
+ function listQuery2(params) {
1811
+ return stripUndefined6({
1730
1812
  resource_id: pickFirst(params.resourceId, params.resource_id),
1731
1813
  resource_type: pickFirst(params.resourceType, params.resource_type),
1732
1814
  host: params.host,
@@ -1754,7 +1836,7 @@ var EgressAudit = class {
1754
1836
  async list(params = {}) {
1755
1837
  const data = await this.http.get(
1756
1838
  "/egress/audit",
1757
- listQuery(params)
1839
+ listQuery2(params)
1758
1840
  );
1759
1841
  return unwrapList8(data);
1760
1842
  }
@@ -1781,7 +1863,7 @@ var EgressAudit = class {
1781
1863
  if (since !== void 0) queryParams.since = since;
1782
1864
  const data = await this.http.get(
1783
1865
  "/egress/audit",
1784
- listQuery(queryParams)
1866
+ listQuery2(queryParams)
1785
1867
  );
1786
1868
  const events = unwrapList8(data);
1787
1869
  for (const event of events) {
@@ -1865,7 +1947,7 @@ function unwrapList9(payload) {
1865
1947
  }
1866
1948
  return [];
1867
1949
  }
1868
- function stripUndefined6(input) {
1950
+ function stripUndefined7(input) {
1869
1951
  return Object.fromEntries(
1870
1952
  Object.entries(input).filter(([, v]) => v !== void 0)
1871
1953
  );
@@ -1875,7 +1957,7 @@ function pickFirst2(...values) {
1875
1957
  return void 0;
1876
1958
  }
1877
1959
  function ruleBody(host, params, effect) {
1878
- return stripUndefined6({
1960
+ return stripUndefined7({
1879
1961
  host,
1880
1962
  effect,
1881
1963
  methods: params.methods,
@@ -1910,7 +1992,7 @@ var EgressNetwork = class {
1910
1992
  }
1911
1993
  /** List allowlist rules. */
1912
1994
  async rules(params = {}) {
1913
- const query = stripUndefined6({
1995
+ const query = stripUndefined7({
1914
1996
  policy_id: pickFirst2(params.policyId, params.policy_id),
1915
1997
  resource_id: pickFirst2(params.resourceId, params.resource_id),
1916
1998
  resource_type: pickFirst2(params.resourceType, params.resource_type)
@@ -1925,7 +2007,7 @@ var EgressNetwork = class {
1925
2007
  // ── policies ──────────────────────────────────────────────────────────────
1926
2008
  /** List egress policies. */
1927
2009
  async policies(params = {}) {
1928
- const query = stripUndefined6({
2010
+ const query = stripUndefined7({
1929
2011
  resource_id: pickFirst2(params.resourceId, params.resource_id),
1930
2012
  resource_type: pickFirst2(params.resourceType, params.resource_type)
1931
2013
  });
@@ -1934,7 +2016,7 @@ var EgressNetwork = class {
1934
2016
  }
1935
2017
  /** Create an egress policy. */
1936
2018
  async createPolicy(params) {
1937
- const body = stripUndefined6({
2019
+ const body = stripUndefined7({
1938
2020
  name: params.name,
1939
2021
  mode: params.mode ?? "enforce",
1940
2022
  default_effect: pickFirst2(
@@ -1954,7 +2036,7 @@ var EgressNetwork = class {
1954
2036
  }
1955
2037
  /** Update an egress policy by id. */
1956
2038
  async updatePolicy(policyId, params) {
1957
- const body = stripUndefined6({
2039
+ const body = stripUndefined7({
1958
2040
  mode: params.mode,
1959
2041
  default_effect: pickFirst2(params.defaultEffect, params.default_effect),
1960
2042
  name: params.name,
@@ -1982,7 +2064,7 @@ var EgressNetwork = class {
1982
2064
  if (policyId) {
1983
2065
  return this.updatePolicy(policyId, { mode });
1984
2066
  }
1985
- const body = resourceId !== void 0 && resourceType !== void 0 ? stripUndefined6({
2067
+ const body = resourceId !== void 0 && resourceType !== void 0 ? stripUndefined7({
1986
2068
  mode,
1987
2069
  resource_id: resourceId,
1988
2070
  resource_type: resourceType
@@ -1996,7 +2078,7 @@ var EgressNetwork = class {
1996
2078
  // ── suggestions ───────────────────────────────────────────────────────────
1997
2079
  /** AI-generated allowlist suggestions from recent denied egress. */
1998
2080
  async suggestions(params = {}) {
1999
- const query = stripUndefined6({
2081
+ const query = stripUndefined7({
2000
2082
  resource_id: pickFirst2(params.resourceId, params.resource_id),
2001
2083
  resource_type: pickFirst2(params.resourceType, params.resource_type),
2002
2084
  since: params.since ?? "7d"
@@ -2101,7 +2183,7 @@ function unwrapList10(payload) {
2101
2183
  }
2102
2184
  return [];
2103
2185
  }
2104
- function stripUndefined7(input) {
2186
+ function stripUndefined8(input) {
2105
2187
  return Object.fromEntries(
2106
2188
  Object.entries(input).filter(([, v]) => v !== void 0)
2107
2189
  );
@@ -2111,7 +2193,7 @@ function pickFirst3(...values) {
2111
2193
  return void 0;
2112
2194
  }
2113
2195
  function setBody(params) {
2114
- return stripUndefined7({
2196
+ return stripUndefined8({
2115
2197
  name: params.name,
2116
2198
  value: params.value,
2117
2199
  type: params.type ?? "api_key",
@@ -2131,8 +2213,8 @@ function setBody(params) {
2131
2213
  metadata: params.metadata
2132
2214
  });
2133
2215
  }
2134
- function listQuery2(params) {
2135
- return stripUndefined7({
2216
+ function listQuery3(params) {
2217
+ return stripUndefined8({
2136
2218
  scope: params.scope,
2137
2219
  type: params.type,
2138
2220
  workspace_id: pickFirst3(params.workspaceId, params.workspace_id),
@@ -2147,14 +2229,14 @@ function listQuery2(params) {
2147
2229
  });
2148
2230
  }
2149
2231
  function rotateBody(params) {
2150
- return stripUndefined7({
2232
+ return stripUndefined8({
2151
2233
  value: pickFirst3(params.newValue, params.new_value, params.value),
2152
2234
  refresh_token: pickFirst3(params.refreshToken, params.refresh_token),
2153
2235
  expires_at: pickFirst3(params.expiresAt, params.expires_at)
2154
2236
  });
2155
2237
  }
2156
2238
  function bindingBody(params) {
2157
- return stripUndefined7({
2239
+ return stripUndefined8({
2158
2240
  secret_id: pickFirst3(params.secretId, params.secret_id),
2159
2241
  resource_id: pickFirst3(params.resourceId, params.resource_id),
2160
2242
  resource_type: pickFirst3(params.resourceType, params.resource_type),
@@ -2162,14 +2244,14 @@ function bindingBody(params) {
2162
2244
  });
2163
2245
  }
2164
2246
  function bindingQuery(params) {
2165
- return stripUndefined7({
2247
+ return stripUndefined8({
2166
2248
  resource_id: pickFirst3(params.resourceId, params.resource_id),
2167
2249
  resource_type: pickFirst3(params.resourceType, params.resource_type),
2168
2250
  secret_id: pickFirst3(params.secretId, params.secret_id)
2169
2251
  });
2170
2252
  }
2171
2253
  function oauthBody(params) {
2172
- return stripUndefined7({
2254
+ return stripUndefined8({
2173
2255
  provider: params.provider,
2174
2256
  expose_as_env: pickFirst3(params.exposeAsEnv, params.expose_as_env),
2175
2257
  scope: params.scope,
@@ -2256,7 +2338,7 @@ var EgressSecrets = class {
2256
2338
  async list(params = {}) {
2257
2339
  const data = await this.http.get(
2258
2340
  "/egress/secrets",
2259
- listQuery2(params)
2341
+ listQuery3(params)
2260
2342
  );
2261
2343
  return unwrapList10(data);
2262
2344
  }
@@ -3381,7 +3463,7 @@ function listItems2(payload, candidateKeys = ["data", "cron_jobs", "executions",
3381
3463
  }
3382
3464
  return [];
3383
3465
  }
3384
- function stripUndefined8(input) {
3466
+ function stripUndefined9(input) {
3385
3467
  return Object.fromEntries(
3386
3468
  Object.entries(input).filter(([, v]) => v !== void 0)
3387
3469
  );
@@ -3395,7 +3477,7 @@ var CronJobs = class {
3395
3477
  }
3396
3478
  http;
3397
3479
  async list(params = {}) {
3398
- const query = stripUndefined8({ ...params });
3480
+ const query = stripUndefined9({ ...params });
3399
3481
  const data = await this.http.get("/cron-jobs", query);
3400
3482
  return listItems2(data);
3401
3483
  }
@@ -3405,7 +3487,7 @@ var CronJobs = class {
3405
3487
  }
3406
3488
  async create(params) {
3407
3489
  const { idempotencyKey: ikey, ...rest } = params;
3408
- const body = stripUndefined8(rest);
3490
+ const body = stripUndefined9(rest);
3409
3491
  const data = await this.http.request("/cron-jobs", {
3410
3492
  method: "POST",
3411
3493
  body,
@@ -3414,7 +3496,7 @@ var CronJobs = class {
3414
3496
  return unwrap20(data);
3415
3497
  }
3416
3498
  async update(jobId, params) {
3417
- const body = stripUndefined8(params);
3499
+ const body = stripUndefined9(params);
3418
3500
  const data = await this.http.patch(`/cron-jobs/${jobId}`, body);
3419
3501
  return unwrap20(data);
3420
3502
  }
@@ -3499,7 +3581,7 @@ function listItems3(payload, candidateKeys = ["data", "databases", "items"]) {
3499
3581
  }
3500
3582
  return [];
3501
3583
  }
3502
- function stripUndefined9(input) {
3584
+ function stripUndefined10(input) {
3503
3585
  return Object.fromEntries(
3504
3586
  Object.entries(input).filter(([, v]) => v !== void 0)
3505
3587
  );
@@ -3513,7 +3595,7 @@ var Databases = class {
3513
3595
  }
3514
3596
  http;
3515
3597
  async list(params = {}) {
3516
- const query = stripUndefined9({ ...params });
3598
+ const query = stripUndefined10({ ...params });
3517
3599
  const data = await this.http.get("/databases", query);
3518
3600
  return listItems3(data);
3519
3601
  }
@@ -3530,7 +3612,7 @@ var Databases = class {
3530
3612
  size: _deprecatedSize,
3531
3613
  ...rest
3532
3614
  } = params;
3533
- const body = stripUndefined9({
3615
+ const body = stripUndefined10({
3534
3616
  ...rest,
3535
3617
  engine_version: engine_version ?? version
3536
3618
  });
@@ -3573,7 +3655,7 @@ var Databases = class {
3573
3655
  return unwrap22(data);
3574
3656
  }
3575
3657
  async logs(databaseId, params = {}) {
3576
- const query = stripUndefined9({
3658
+ const query = stripUndefined10({
3577
3659
  lines: params.lines,
3578
3660
  since: params.since
3579
3661
  });
@@ -3616,46 +3698,16 @@ function listItems4(payload, candidateKeys = ["items", "deployments", "versions"
3616
3698
  }
3617
3699
  return [];
3618
3700
  }
3619
- function stripUndefined10(input) {
3701
+ function stripUndefined11(input) {
3620
3702
  return Object.fromEntries(
3621
3703
  Object.entries(input).filter(([, v]) => v !== void 0)
3622
3704
  );
3623
3705
  }
3624
- function dockerDeployMetadata(metadata, templateId) {
3625
- return stripUndefined10({
3706
+ function dockerDeployMetadata(metadata) {
3707
+ return {
3626
3708
  ...metadata ?? {},
3627
- deployment_product: "docker_deploy",
3628
- docker_deploy_template_id: templateId
3629
- });
3630
- }
3631
- function isRecord(value) {
3632
- return !!value && typeof value === "object" && !Array.isArray(value);
3633
- }
3634
- function stringValue(value) {
3635
- return typeof value === "string" && value.length > 0 ? value : void 0;
3636
- }
3637
- function runtimeMetadata(metadata) {
3638
- const runtime = metadata.runtime;
3639
- return isRecord(runtime) ? runtime : void 0;
3640
- }
3641
- function publicProbeUrl(publicUrl, probePath) {
3642
- const url = new URL(publicUrl);
3643
- const normalizedPath = probePath.startsWith("/") ? probePath : `/${probePath}`;
3644
- url.pathname = normalizedPath;
3645
- return url.toString();
3646
- }
3647
- function looksLikeMiosaGatewayJson(body) {
3648
- try {
3649
- const parsed = JSON.parse(body);
3650
- return isRecord(parsed) && parsed.ok === true && typeof parsed.run_id === "string" && Object.keys(parsed).every((key) => ["ok", "run_id"].includes(key));
3651
- } catch {
3652
- return false;
3653
- }
3654
- }
3655
- function addDoctorCheck(checks, name, ok, message, data) {
3656
- const check = { name, ok, message };
3657
- if (data !== void 0) check.data = data;
3658
- checks.push(check);
3709
+ deployment_product: "docker_deploy"
3710
+ };
3659
3711
  }
3660
3712
  var DeploymentVersions = class {
3661
3713
  constructor(http, deploymentId) {
@@ -3665,7 +3717,7 @@ var DeploymentVersions = class {
3665
3717
  http;
3666
3718
  deploymentId;
3667
3719
  async list(params = {}) {
3668
- const query = stripUndefined10({
3720
+ const query = stripUndefined11({
3669
3721
  state: params.state,
3670
3722
  limit: params.limit,
3671
3723
  cursor: params.cursor,
@@ -3684,7 +3736,7 @@ var DeploymentVersions = class {
3684
3736
  return unwrap23(data);
3685
3737
  }
3686
3738
  async promote(versionId, opts = {}) {
3687
- const body = stripUndefined10({ environment: opts.environment });
3739
+ const body = stripUndefined11({ environment: opts.environment });
3688
3740
  const data = await this.http.request(
3689
3741
  `/deployments/${this.deploymentId}/versions/${versionId}/promote`,
3690
3742
  {
@@ -3771,7 +3823,7 @@ var DeploymentDomains = class {
3771
3823
  `/deployments/${this.deploymentId}/domains`,
3772
3824
  {
3773
3825
  method: "POST",
3774
- body: stripUndefined10(body),
3826
+ body: stripUndefined11(body),
3775
3827
  headers: { "Idempotency-Key": idempotencyKey4(params.idempotencyKey) }
3776
3828
  }
3777
3829
  );
@@ -3803,7 +3855,7 @@ var Deployments = class {
3803
3855
  http;
3804
3856
  async list(params = {}) {
3805
3857
  const projectId = params.projectId ?? params.project_id;
3806
- const query = stripUndefined10({
3858
+ const query = stripUndefined11({
3807
3859
  project_id: projectId,
3808
3860
  state: params.state,
3809
3861
  limit: params.limit,
@@ -3821,7 +3873,7 @@ var Deployments = class {
3821
3873
  return unwrap23(data);
3822
3874
  }
3823
3875
  async create(params) {
3824
- const body = stripUndefined10({
3876
+ const body = stripUndefined11({
3825
3877
  name: params.name,
3826
3878
  repo_url: params.repoUrl ?? params.repo_url,
3827
3879
  branch: params.branch,
@@ -3829,7 +3881,6 @@ var Deployments = class {
3829
3881
  run_command: params.runCommand ?? params.run_command,
3830
3882
  auto_deploy: params.autoDeploy ?? params.auto_deploy,
3831
3883
  database: params.database,
3832
- docker_deploy_template_id: params.dockerDeployTemplateId ?? params.docker_deploy_template_id,
3833
3884
  metadata: params.metadata,
3834
3885
  ...attributionBody(params)
3835
3886
  });
@@ -3846,184 +3897,13 @@ var Deployments = class {
3846
3897
  * deployment so the control plane attaches it to the workspace Docker host.
3847
3898
  */
3848
3899
  async createDockerDeploy(params) {
3849
- const templateId = params.dockerDeployTemplateId ?? params.docker_deploy_template_id;
3850
3900
  return this.create({
3851
3901
  ...params,
3852
- metadata: dockerDeployMetadata(params.metadata, templateId)
3902
+ metadata: dockerDeployMetadata(params.metadata)
3853
3903
  });
3854
3904
  }
3855
- async listDockerDeployHosts(params = {}) {
3856
- const data = await this.http.get(
3857
- "/docker-deploy/hosts",
3858
- stripUndefined10({
3859
- workspace_id: params.workspaceId ?? params.workspace_id
3860
- })
3861
- );
3862
- return listItems4(data, ["hosts", "items"]);
3863
- }
3864
- async ensureDockerDeployHost(params) {
3865
- const data = await this.http.request("/docker-deploy/hosts/ensure", {
3866
- method: "POST",
3867
- body: stripUndefined10({
3868
- workspace_id: params.workspaceId ?? params.workspace_id,
3869
- region: params.region,
3870
- size: params.size,
3871
- appliance_image: params.applianceImage ?? params.appliance_image,
3872
- metadata: params.metadata
3873
- }),
3874
- headers: { "Idempotency-Key": idempotencyKey4(params.idempotencyKey) }
3875
- });
3876
- return unwrap23(data);
3877
- }
3878
- async getDockerDeployHost(hostId) {
3879
- const data = await this.http.get(`/docker-deploy/hosts/${hostId}`);
3880
- return unwrap23(data);
3881
- }
3882
- /**
3883
- * Verify a Docker Deploy deployment end-to-end.
3884
- *
3885
- * This checks the deployment product marker, Docker Deploy host linkage,
3886
- * appliance health, route runtime metadata, and optionally the public URL.
3887
- * It is intentionally agent-friendly: use this after sandbox.deployDocker()
3888
- * or createDockerDeploy() before telling a user the app is live.
3889
- */
3890
- async doctorDockerDeploy(deploymentId, params = {}) {
3891
- const checks = [];
3892
- const deployment = await this.get(deploymentId);
3893
- const metadata = isRecord(deployment.metadata) ? deployment.metadata : {};
3894
- const product = stringValue(deployment.deployment_product) ?? stringValue(metadata.deployment_product);
3895
- const hostId = stringValue(deployment.docker_deploy_host_id) ?? stringValue(metadata.docker_deploy_host_id);
3896
- addDoctorCheck(
3897
- checks,
3898
- "deployment_product",
3899
- product === "docker_deploy",
3900
- product === "docker_deploy" ? "Deployment is marked as Docker Deploy." : `Expected deployment_product=docker_deploy, got ${product ?? "missing"}.`,
3901
- { product: product ?? null }
3902
- );
3903
- addDoctorCheck(
3904
- checks,
3905
- "docker_deploy_host_id",
3906
- !!hostId,
3907
- hostId ? "Deployment is linked to a Docker Deploy appliance host." : "Deployment has no docker_deploy_host_id.",
3908
- { docker_deploy_host_id: hostId ?? null }
3909
- );
3910
- let host;
3911
- if (hostId) {
3912
- try {
3913
- host = await this.getDockerDeployHost(hostId);
3914
- const status = host.status ?? null;
3915
- const applianceStatus = host.appliance_status ?? null;
3916
- const badHostStates = /* @__PURE__ */ new Set(["failed", "error", "destroyed"]);
3917
- const badApplianceStates = /* @__PURE__ */ new Set(["failed", "error", "unhealthy"]);
3918
- const ok = !badHostStates.has(String(status)) && !badApplianceStates.has(String(applianceStatus));
3919
- addDoctorCheck(
3920
- checks,
3921
- "docker_deploy_host_health",
3922
- ok,
3923
- ok ? "Docker Deploy host is not reporting a failed state." : `Docker Deploy host is unhealthy: status=${status}, appliance_status=${applianceStatus}.`,
3924
- { status, appliance_status: applianceStatus }
3925
- );
3926
- } catch (err) {
3927
- addDoctorCheck(
3928
- checks,
3929
- "docker_deploy_host_health",
3930
- false,
3931
- `Could not fetch Docker Deploy host ${hostId}: ${err instanceof Error ? err.message : String(err)}`
3932
- );
3933
- }
3934
- }
3935
- const runtime = runtimeMetadata(metadata);
3936
- const runtimeIp = runtime ? stringValue(runtime.ip) ?? stringValue(runtime.ip_address) : void 0;
3937
- const runtimePort = runtime?.port;
3938
- addDoctorCheck(
3939
- checks,
3940
- "route_runtime",
3941
- !!runtimeIp && runtimePort !== void 0 && runtimePort !== null,
3942
- runtimeIp && runtimePort !== void 0 && runtimePort !== null ? "Deployment route metadata points at a runtime target." : "Deployment metadata has no runtime ip/port target.",
3943
- { ip: runtimeIp ?? null, port: runtimePort ?? null }
3944
- );
3945
- const publicUrl = stringValue(deployment.public_url) ?? stringValue(metadata.public_url);
3946
- addDoctorCheck(
3947
- checks,
3948
- "public_url",
3949
- !!publicUrl,
3950
- publicUrl ? "Deployment has a public URL." : "Deployment has no public URL to probe.",
3951
- { public_url: publicUrl ?? null }
3952
- );
3953
- let probe;
3954
- if (params.probe !== false && publicUrl) {
3955
- const fetchImpl = params.fetchImpl ?? fetch;
3956
- const url = publicProbeUrl(publicUrl, params.probePath ?? "/");
3957
- const controller = new AbortController();
3958
- const timer = setTimeout(() => controller.abort(), params.timeoutMs ?? 2e4);
3959
- try {
3960
- const response = await fetchImpl(url, {
3961
- headers: { Accept: "*/*" },
3962
- signal: controller.signal
3963
- });
3964
- const text = await response.text();
3965
- const gatewayJson = looksLikeMiosaGatewayJson(text);
3966
- const ok = response.ok && !gatewayJson;
3967
- probe = {
3968
- url,
3969
- status: response.status,
3970
- ok,
3971
- responseSnippet: text.slice(0, 500)
3972
- };
3973
- if (gatewayJson) probe.gatewayJson = true;
3974
- addDoctorCheck(
3975
- checks,
3976
- "public_url_probe",
3977
- ok,
3978
- ok ? `Public URL returned HTTP ${response.status}.` : gatewayJson ? "Public URL returned MIOSA gateway JSON instead of the app." : `Public URL returned HTTP ${response.status}.`,
3979
- { status: response.status, gateway_json: gatewayJson }
3980
- );
3981
- } catch (err) {
3982
- const message = err instanceof Error ? err.message : String(err);
3983
- probe = { url, status: null, ok: false, responseSnippet: message };
3984
- addDoctorCheck(
3985
- checks,
3986
- "public_url_probe",
3987
- false,
3988
- `Public URL probe failed: ${message}`
3989
- );
3990
- } finally {
3991
- clearTimeout(timer);
3992
- }
3993
- }
3994
- const result = {
3995
- ok: checks.every((check) => check.ok),
3996
- deployment,
3997
- checks
3998
- };
3999
- if (host) result.host = host;
4000
- if (publicUrl !== void 0) result.publicUrl = publicUrl;
4001
- if (probe) result.probe = probe;
4002
- return result;
4003
- }
4004
- async listDockerDeployTemplates(params = {}) {
4005
- const query = {
4006
- category: params.category,
4007
- runtime: params.runtime,
4008
- framework: params.framework,
4009
- include_preview: params.includePreview ?? params.include_preview
4010
- };
4011
- const data = await this.http.get(
4012
- "/docker-deploy/templates",
4013
- stripUndefined10(query)
4014
- );
4015
- const templates = unwrap23(data);
4016
- if (Array.isArray(templates)) return templates;
4017
- return (templates?.templates ?? templates?.items ?? templates?.data ?? []) || [];
4018
- }
4019
- async getDockerDeployTemplate(templateId) {
4020
- const data = await this.http.get(
4021
- `/docker-deploy/templates/${templateId}`
4022
- );
4023
- return unwrap23(data);
4024
- }
4025
3905
  async update(deploymentId, params) {
4026
- const body = stripUndefined10({
3906
+ const body = stripUndefined11({
4027
3907
  name: params.name,
4028
3908
  branch: params.branch,
4029
3909
  build_command: params.buildCommand ?? params.build_command,
@@ -4040,19 +3920,11 @@ var Deployments = class {
4040
3920
  await this.http.delete(`/deployments/${deploymentId}`);
4041
3921
  }
4042
3922
  async publish(deploymentId, params) {
4043
- const body = stripUndefined10({
3923
+ const body = stripUndefined11({
4044
3924
  source_sandbox_id: params.sourceSandboxId ?? params.source_sandbox_id,
4045
3925
  output_path: params.outputPath ?? params.output_path,
4046
3926
  entrypoint: params.entrypoint,
4047
- promote: params.promote,
4048
- build_command: params.buildCommand ?? params.build_command,
4049
- run_command: params.runCommand ?? params.run_command,
4050
- port: params.port,
4051
- health_check_path: params.healthCheckPath ?? params.health_check_path,
4052
- deployment_type: params.deploymentType ?? params.deployment_type,
4053
- docker_deploy_template_id: params.dockerDeployTemplateId ?? params.docker_deploy_template_id,
4054
- data_services: params.dataServices ?? params.data_services,
4055
- ...attributionBody(params)
3927
+ promote: params.promote
4056
3928
  });
4057
3929
  const data = await this.http.request(
4058
3930
  `/deployments/${deploymentId}/publish`,
@@ -4070,22 +3942,14 @@ var Deployments = class {
4070
3942
  * phase. Prefer `publish()` once Phase 2B/3 lands.
4071
3943
  */
4072
3944
  async publishFromSandbox(sandboxId, params = {}) {
4073
- const body = stripUndefined10({
3945
+ const body = stripUndefined11({
4074
3946
  name: params.name,
4075
3947
  deployment_id: params.deploymentId ?? params.deployment_id,
4076
3948
  output_path: params.outputPath ?? params.output_path,
4077
3949
  source_snapshot_path: params.sourceSnapshotPath ?? params.source_snapshot_path,
4078
3950
  entrypoint: params.entrypoint,
4079
3951
  domain: params.domain,
4080
- custom_domain: params.customDomain ?? params.custom_domain,
4081
- build_command: params.buildCommand ?? params.build_command,
4082
- run_command: params.runCommand ?? params.run_command,
4083
- port: params.port,
4084
- health_check_path: params.healthCheckPath ?? params.health_check_path,
4085
- deployment_type: params.deploymentType ?? params.deployment_type,
4086
- docker_deploy_template_id: params.dockerDeployTemplateId ?? params.docker_deploy_template_id,
4087
- data_services: params.dataServices ?? params.data_services,
4088
- ...attributionBody(params)
3952
+ custom_domain: params.customDomain ?? params.custom_domain
4089
3953
  });
4090
3954
  const data = await this.http.request(
4091
3955
  `/sandboxes/${sandboxId}/deploy`,
@@ -4098,7 +3962,7 @@ var Deployments = class {
4098
3962
  return unwrap23(data);
4099
3963
  }
4100
3964
  async rollback(deploymentId, params = {}) {
4101
- const body = stripUndefined10({
3965
+ const body = stripUndefined11({
4102
3966
  version_id: params.versionId ?? params.version_id
4103
3967
  });
4104
3968
  const data = await this.http.request(
@@ -4130,7 +3994,7 @@ var Deployments = class {
4130
3994
  return listItems4(data);
4131
3995
  }
4132
3996
  async setEnv(deploymentId, vars, opts = {}) {
4133
- const body = stripUndefined10({ env: vars, environment: opts.environment });
3997
+ const body = stripUndefined11({ env: vars, environment: opts.environment });
4134
3998
  const data = await this.http.post(
4135
3999
  `/deployments/${deploymentId}/env`,
4136
4000
  body
@@ -4154,205 +4018,89 @@ var Deployments = class {
4154
4018
  }
4155
4019
  };
4156
4020
 
4157
- // src/resources/devices.ts
4158
- var DEVICE_CATALOG = [
4159
- {
4160
- kind: "sandbox_worker",
4161
- label: "Sandbox Worker",
4162
- purpose: "Isolated Linux workspace for agents to create files, run code, preview apps, snapshot, fork, and publish.",
4163
- lifecycle: "Persistent by default; use stop/resume/snapshot/fork where the account backend supports saved state.",
4164
- persistence: "Use one-hour timeouts for interactive builds and checkpoint before long pauses.",
4165
- primaryCommands: [
4166
- "miosa.sandboxes.create({ templateId: 'nextjs', timeoutSec: 3600 })",
4167
- "sandbox.exec.run('codex ...', { cwd: '/workspace' })",
4168
- "sandbox.files.write('/workspace/app/page.jsx', source)",
4169
- "miosa.deployments.publishFromSandbox(...)"
4170
- ],
4171
- useWhen: [
4172
- "Coding agents should build inside the remote filesystem.",
4173
- "You need command execution, file writes, package installs, previews, artifacts, or app publish.",
4174
- "You want virtual-device behavior without a GUI desktop."
4175
- ],
4176
- avoidWhen: [
4177
- "The workflow requires full browser/desktop control.",
4178
- "The app is ready for production; publish it to a deployment runtime."
4179
- ]
4180
- },
4181
- {
4182
- kind: "computer",
4183
- label: "Computer",
4184
- purpose: "Durable VM/desktop device for browser automation, CUA sessions, SSH, tunnels, and persistent agent control.",
4185
- lifecycle: "Managed as a Computer with desktop/browser and operator-style control surfaces.",
4186
- persistence: "Use checkpoints, volumes, tunnels, and agent sessions for long-lived desktop workflows.",
4187
- primaryCommands: [
4188
- "miosa.computers.create({ name: 'browser-agent' })",
4189
- "computer.exec.run('npm test')",
4190
- "computer.desktop.open()"
4191
- ],
4192
- useWhen: [
4193
- "The agent needs Chromium or a full desktop.",
4194
- "The workflow logs into dashboards, fills forms, clicks buttons, or captures screenshots.",
4195
- "A human and agent share the same persistent machine state."
4196
- ],
4197
- avoidWhen: [
4198
- "Simple code generation/build/test work fits a cheaper sandbox worker.",
4199
- "You only need durable app hosting."
4200
- ]
4201
- },
4202
- {
4203
- kind: "local_device",
4204
- label: "Local Device",
4205
- purpose: "Developer-owned machine connected through CLI/MCP for local discovery and private tooling.",
4206
- lifecycle: "Not hosted by MIOSA; the user owns uptime and state.",
4207
- persistence: "State is local machine state. Do not assume cloud resume semantics.",
4208
- primaryCommands: ["miosa mcp install", "miosa doctor --json"],
4209
- useWhen: [
4210
- "The agent needs local repository discovery before cloud execution.",
4211
- "The user intentionally wants local private tools."
4212
- ],
4213
- avoidWhen: [
4214
- "Customer code must stay isolated in MIOSA-hosted infrastructure.",
4215
- "The workflow needs reproducible shared cloud state."
4216
- ]
4217
- },
4218
- {
4219
- kind: "docker_deploy_host",
4220
- label: "Docker Deploy Host",
4221
- purpose: "Workspace appliance VM that runs Docker containers for durable apps published from sandboxes.",
4222
- lifecycle: "Always-on deployment capacity; not an interactive coding workspace.",
4223
- persistence: "Versioned releases and routing are durable; edits happen in sandboxes before publish.",
4224
- primaryCommands: [
4225
- "miosa sandbox publish <id> --docker-deploy",
4226
- "miosa deploy --docker-deploy"
4227
- ],
4228
- useWhen: [
4229
- "You need many small apps, APIs, funnels, or client sites in one workspace appliance.",
4230
- "You want stable public URLs backed by Docker containers."
4231
- ],
4232
- avoidWhen: [
4233
- "Interactive agent work is still happening.",
4234
- "The app needs the standard MIOSA Deploy runtime."
4235
- ]
4236
- }
4237
- ];
4238
- var Devices = class {
4239
- http;
4021
+ // src/resources/docker-deploy.ts
4022
+ function workspaceId(params) {
4023
+ return params?.workspace_id ?? params?.workspaceId;
4024
+ }
4025
+ function ensureBody(params) {
4026
+ const body = {};
4027
+ const id = params.workspace_id ?? params.workspaceId;
4028
+ const externalId = params.external_workspace_id ?? params.externalWorkspaceId;
4029
+ if (id) body.workspace_id = id;
4030
+ if (externalId) body.external_workspace_id = externalId;
4031
+ return body;
4032
+ }
4033
+ function unwrapHost(response) {
4034
+ const host = response.data ?? response.host;
4035
+ if (!host) {
4036
+ throw new Error("Docker Deploy host response was empty.");
4037
+ }
4038
+ return host;
4039
+ }
4040
+ function unwrapTemplates(response) {
4041
+ return response.data ?? response.templates ?? [];
4042
+ }
4043
+ function unwrapTemplate(response) {
4044
+ const template = response.data ?? response.template;
4045
+ if (!template) {
4046
+ throw new Error("Docker Deploy template response was empty.");
4047
+ }
4048
+ return template;
4049
+ }
4050
+ var DockerDeploy = class {
4240
4051
  constructor(http) {
4241
4052
  this.http = http;
4242
4053
  }
4054
+ http;
4243
4055
  /**
4244
- * Return the static device catalog used by orchestration apps to choose the
4245
- * right MIOSA execution surface before creating resources.
4056
+ * List Docker Deploy appliance hosts scoped to the current tenant.
4057
+ *
4058
+ * Pass a workspace ID to inspect the dedicated always-on appliance machine
4059
+ * for one white-label workspace.
4246
4060
  */
4247
- catalog() {
4248
- return DEVICE_CATALOG.map((entry) => ({ ...entry }));
4061
+ async listHosts(params = {}) {
4062
+ const res = await this.http.get(
4063
+ "/docker-deploy/hosts",
4064
+ { workspace_id: workspaceId(params) }
4065
+ );
4066
+ return res.data ?? res.hosts ?? [];
4249
4067
  }
4250
4068
  /**
4251
- * List hosted devices by normalizing existing sandboxes and computers.
4252
- * Partial backend failures are returned in `errors` so orchestration UIs can
4253
- * still show usable inventory instead of failing the whole page.
4069
+ * Ensure a workspace has its dedicated Docker Deploy appliance host.
4070
+ *
4071
+ * The host may still be `pending`, `provisioning`, or `bootstrapping` after
4072
+ * this call. Treat `status === "active"` and `appliance_status === "healthy"`
4073
+ * as the ready condition before sending app/container traffic to it.
4254
4074
  */
4255
- async list(params = {}) {
4256
- const kind = normalizeKind(params.kind ?? "all");
4257
- const devices = [];
4258
- const errors = [];
4259
- if (kind === "all" || kind === "sandbox_worker") {
4260
- try {
4261
- const sandboxes = await this.http.get("/sandboxes");
4262
- devices.push(...unwrapList11(sandboxes, ["sandboxes"]).map(normalizeSandbox));
4263
- } catch (err) {
4264
- errors.push(toListError("sandboxes", err));
4265
- }
4266
- }
4267
- if (kind === "all" || kind === "computer") {
4268
- try {
4269
- const computers = await this.http.get("/computers");
4270
- devices.push(...unwrapList11(computers, ["computers"]).map(normalizeComputer));
4271
- } catch (err) {
4272
- errors.push(toListError("computers", err));
4273
- }
4274
- }
4275
- return { devices, errors };
4075
+ async ensureHost(params = {}) {
4076
+ const res = await this.http.post(
4077
+ "/docker-deploy/hosts/ensure",
4078
+ ensureBody(params)
4079
+ );
4080
+ return { host: unwrapHost(res), queued: res.queued ?? false };
4276
4081
  }
4277
- };
4278
- function normalizeKind(kind) {
4279
- if (kind === "all") return "all";
4280
- if (kind === "sandbox" || kind === "sandbox_worker") {
4281
- return "sandbox_worker";
4282
- }
4283
- if (kind === "computer") return "computer";
4284
- throw new Error(`Unsupported device kind: ${kind}`);
4285
- }
4286
- function normalizeSandbox(row) {
4287
- return compactRecord({
4288
- id: stringField(row, "id"),
4289
- kind: "sandbox_worker",
4290
- source: "sandboxes",
4291
- name: optionalString(row, "name"),
4292
- state: optionalString(row, "state") ?? optionalString(row, "status"),
4293
- ready: optionalBoolean(row, "ready"),
4294
- persistent: optionalBoolean(row, "persistent"),
4295
- alwaysOn: optionalBoolean(row, "always_on"),
4296
- template: optionalString(row, "template_id") ?? optionalString(row, "template"),
4297
- previewUrl: optionalString(row, "preview_url"),
4298
- timeoutRemainingMs: optionalNumber(row, "timeout_remaining_ms")
4299
- });
4300
- }
4301
- function normalizeComputer(row) {
4302
- return compactRecord({
4303
- id: stringField(row, "id"),
4304
- kind: "computer",
4305
- source: "computers",
4306
- name: optionalString(row, "name"),
4307
- state: optionalString(row, "status") ?? optionalString(row, "state"),
4308
- ready: optionalBoolean(row, "ready"),
4309
- region: optionalString(row, "region"),
4310
- template: optionalString(row, "template_type") ?? optionalString(row, "template")
4311
- });
4312
- }
4313
- function compactRecord(record) {
4314
- return Object.fromEntries(
4315
- Object.entries(record).filter(([, value]) => value !== void 0)
4316
- );
4317
- }
4318
- function unwrapList11(payload, keys) {
4319
- const value = isRecord2(payload) && "data" in payload ? payload.data : payload;
4320
- if (Array.isArray(value)) return value.filter(isRecord2);
4321
- if (isRecord2(value)) {
4322
- for (const key of keys) {
4323
- const nested = value[key];
4324
- if (Array.isArray(nested)) return nested.filter(isRecord2);
4325
- }
4082
+ /** Fetch one Docker Deploy host by ID. */
4083
+ async getHost(hostId) {
4084
+ const res = await this.http.get(
4085
+ `/docker-deploy/hosts/${hostId}`
4086
+ );
4087
+ return unwrapHost(res);
4326
4088
  }
4327
- return [];
4328
- }
4329
- function toListError(source, err) {
4330
- const message = err instanceof Error ? err.message : String(err);
4331
- return {
4332
- source,
4333
- message,
4334
- retryable: /fetch failed|ECONNRESET|HTTP 502|other side closed|socket hang up|bad gateway/i.test(
4335
- message
4336
- )
4337
- };
4338
- }
4339
- function stringField(row, key) {
4340
- const value = row[key];
4341
- return typeof value === "string" ? value : String(value ?? "");
4342
- }
4343
- function optionalString(row, key) {
4344
- const value = row[key];
4345
- return typeof value === "string" && value.length > 0 ? value : void 0;
4346
- }
4347
- function optionalBoolean(row, key) {
4348
- return typeof row[key] === "boolean" ? row[key] : void 0;
4349
- }
4350
- function optionalNumber(row, key) {
4351
- return typeof row[key] === "number" ? row[key] : void 0;
4352
- }
4353
- function isRecord2(value) {
4354
- return value !== null && typeof value === "object" && !Array.isArray(value);
4355
- }
4089
+ /** List Docker Deploy starter templates. */
4090
+ async listTemplates() {
4091
+ const res = await this.http.get(
4092
+ "/docker-deploy/templates"
4093
+ );
4094
+ return unwrapTemplates(res);
4095
+ }
4096
+ /** Fetch one Docker Deploy starter template by ID. */
4097
+ async getTemplate(templateId) {
4098
+ const res = await this.http.get(
4099
+ `/docker-deploy/templates/${encodeURIComponent(templateId)}`
4100
+ );
4101
+ return unwrapTemplate(res);
4102
+ }
4103
+ };
4356
4104
 
4357
4105
  // src/resources/email.ts
4358
4106
  function unwrap24(data) {
@@ -4371,7 +4119,7 @@ function unwrap24(data) {
4371
4119
  }
4372
4120
  return data;
4373
4121
  }
4374
- function unwrapList12(data) {
4122
+ function unwrapList11(data) {
4375
4123
  if (Array.isArray(data)) return data;
4376
4124
  if (data && typeof data === "object") {
4377
4125
  const d = data;
@@ -4399,7 +4147,7 @@ var EmailCampaigns = class {
4399
4147
  }
4400
4148
  http;
4401
4149
  async list(filters = {}) {
4402
- return unwrapList12(
4150
+ return unwrapList11(
4403
4151
  await this.http.get(
4404
4152
  "/admin/email-campaigns",
4405
4153
  filters
@@ -4435,7 +4183,7 @@ var EmailCampaigns = class {
4435
4183
  );
4436
4184
  }
4437
4185
  async deliveries(campaignId, filters = {}) {
4438
- return unwrapList12(
4186
+ return unwrapList11(
4439
4187
  await this.http.get(
4440
4188
  `/admin/email-campaigns/${campaignId}/deliveries`,
4441
4189
  filters
@@ -4449,7 +4197,7 @@ var EmailTemplates = class {
4449
4197
  }
4450
4198
  http;
4451
4199
  async list(filters = {}) {
4452
- return unwrapList12(
4200
+ return unwrapList11(
4453
4201
  await this.http.get("/admin/email-templates", filters)
4454
4202
  );
4455
4203
  }
@@ -4481,7 +4229,7 @@ var EmailInbox = class {
4481
4229
  }
4482
4230
  http;
4483
4231
  async list(filters = {}) {
4484
- return unwrapList12(
4232
+ return unwrapList11(
4485
4233
  await this.http.get("/admin/email-inbox", filters)
4486
4234
  );
4487
4235
  }
@@ -4545,7 +4293,7 @@ function unwrap25(payload) {
4545
4293
  }
4546
4294
  return payload;
4547
4295
  }
4548
- function stripUndefined11(input) {
4296
+ function stripUndefined12(input) {
4549
4297
  return Object.fromEntries(
4550
4298
  Object.entries(input).filter(([, v]) => v !== void 0)
4551
4299
  );
@@ -4564,7 +4312,7 @@ var ExternalKeys = class {
4564
4312
  }
4565
4313
  /** Create / register an external provider key. */
4566
4314
  async create(params) {
4567
- const body = stripUndefined11(params);
4315
+ const body = stripUndefined12(params);
4568
4316
  const data = await this.http.post("/external-keys", body);
4569
4317
  return unwrap25(data);
4570
4318
  }
@@ -4599,7 +4347,7 @@ function listItems5(payload, candidateKeys = ["data", "domains", "items"]) {
4599
4347
  }
4600
4348
  return [];
4601
4349
  }
4602
- function stripUndefined12(input) {
4350
+ function stripUndefined13(input) {
4603
4351
  return Object.fromEntries(
4604
4352
  Object.entries(input).filter(([, v]) => v !== void 0)
4605
4353
  );
@@ -4613,7 +4361,7 @@ var FlatCustomDomains = class {
4613
4361
  }
4614
4362
  http;
4615
4363
  async list(params = {}) {
4616
- const query = stripUndefined12({ ...params });
4364
+ const query = stripUndefined13({ ...params });
4617
4365
  const data = await this.http.get("/custom-domains", query);
4618
4366
  return listItems5(data);
4619
4367
  }
@@ -4625,7 +4373,7 @@ var FlatCustomDomains = class {
4625
4373
  redirectPolicy,
4626
4374
  ...rest
4627
4375
  } = params;
4628
- const body = stripUndefined12({
4376
+ const body = stripUndefined13({
4629
4377
  ...rest,
4630
4378
  resource_type: resourceType ?? rest.resource_type,
4631
4379
  resource_id: resourceId ?? rest.resource_id,
@@ -4658,7 +4406,7 @@ function listItems6(payload, candidateKeys = ["data", "functions", "items"]) {
4658
4406
  }
4659
4407
  return [];
4660
4408
  }
4661
- function stripUndefined13(input) {
4409
+ function stripUndefined14(input) {
4662
4410
  return Object.fromEntries(
4663
4411
  Object.entries(input).filter(([, v]) => v !== void 0)
4664
4412
  );
@@ -4672,7 +4420,7 @@ var Functions = class {
4672
4420
  }
4673
4421
  http;
4674
4422
  async list(params = {}) {
4675
- const query = stripUndefined13({ ...params });
4423
+ const query = stripUndefined14({ ...params });
4676
4424
  const data = await this.http.get("/functions", query);
4677
4425
  return listItems6(data);
4678
4426
  }
@@ -4682,7 +4430,7 @@ var Functions = class {
4682
4430
  }
4683
4431
  async create(params) {
4684
4432
  const { idempotencyKey: ikey, memoryMb, timeoutSec, ...rest } = params;
4685
- const body = stripUndefined13({
4433
+ const body = stripUndefined14({
4686
4434
  ...rest,
4687
4435
  memory_mb: memoryMb ?? rest.memory_mb,
4688
4436
  timeout_sec: timeoutSec ?? rest.timeout_sec
@@ -4696,7 +4444,7 @@ var Functions = class {
4696
4444
  }
4697
4445
  async update(functionId, params) {
4698
4446
  const { memoryMb, timeoutSec, ...rest } = params;
4699
- const body = stripUndefined13({
4447
+ const body = stripUndefined14({
4700
4448
  ...rest,
4701
4449
  memory_mb: memoryMb ?? rest.memory_mb,
4702
4450
  timeout_sec: timeoutSec ?? rest.timeout_sec
@@ -4742,7 +4490,7 @@ function listItems7(payload, candidateKeys = ["data", "health_checks", "items"])
4742
4490
  }
4743
4491
  return [];
4744
4492
  }
4745
- function stripUndefined14(input) {
4493
+ function stripUndefined15(input) {
4746
4494
  return Object.fromEntries(
4747
4495
  Object.entries(input).filter(([, v]) => v !== void 0)
4748
4496
  );
@@ -4756,7 +4504,7 @@ var HealthChecks = class {
4756
4504
  }
4757
4505
  http;
4758
4506
  async list(params = {}) {
4759
- const query = stripUndefined14({ ...params });
4507
+ const query = stripUndefined15({ ...params });
4760
4508
  const data = await this.http.get("/health-checks", query);
4761
4509
  return listItems7(data);
4762
4510
  }
@@ -4772,7 +4520,7 @@ var HealthChecks = class {
4772
4520
  expectedStatus,
4773
4521
  ...rest
4774
4522
  } = params;
4775
- const body = stripUndefined14({
4523
+ const body = stripUndefined15({
4776
4524
  ...rest,
4777
4525
  interval_sec: intervalSec ?? rest.interval_sec,
4778
4526
  timeout_sec: timeoutSec ?? rest.timeout_sec,
@@ -4787,7 +4535,7 @@ var HealthChecks = class {
4787
4535
  }
4788
4536
  async update(checkId, params) {
4789
4537
  const { intervalSec, timeoutSec, expectedStatus, ...rest } = params;
4790
- const body = stripUndefined14({
4538
+ const body = stripUndefined15({
4791
4539
  ...rest,
4792
4540
  interval_sec: intervalSec ?? rest.interval_sec,
4793
4541
  timeout_sec: timeoutSec ?? rest.timeout_sec,
@@ -4819,7 +4567,7 @@ function listItems8(payload) {
4819
4567
  if (Array.isArray(result)) return result;
4820
4568
  return [];
4821
4569
  }
4822
- function stripUndefined15(input) {
4570
+ function stripUndefined16(input) {
4823
4571
  return Object.fromEntries(
4824
4572
  Object.entries(input).filter(([, v]) => v !== void 0)
4825
4573
  );
@@ -4871,7 +4619,7 @@ var Integrations = class {
4871
4619
  // ── Test hooks ─────────────────────────────────────────────────────────────
4872
4620
  /** Send a test message to the connected Slack channel. */
4873
4621
  async slackSendTest(params = {}) {
4874
- const body = stripUndefined15(params);
4622
+ const body = stripUndefined16(params);
4875
4623
  const data = await this.http.post(
4876
4624
  "/integrations/slack/send-test",
4877
4625
  body
@@ -4880,7 +4628,7 @@ var Integrations = class {
4880
4628
  }
4881
4629
  /** Send a test message to the connected Discord channel. */
4882
4630
  async discordSendTest(params = {}) {
4883
- const body = stripUndefined15(params);
4631
+ const body = stripUndefined16(params);
4884
4632
  const data = await this.http.post(
4885
4633
  "/integrations/discord/send-test",
4886
4634
  body
@@ -4895,7 +4643,7 @@ var Integrations = class {
4895
4643
  }
4896
4644
  /** Create a Linear issue via the connected workspace. */
4897
4645
  async linearCreateIssue(params = {}) {
4898
- const body = stripUndefined15(params);
4646
+ const body = stripUndefined16(params);
4899
4647
  const data = await this.http.post(
4900
4648
  "/integrations/linear/create-issue",
4901
4649
  body
@@ -4914,7 +4662,7 @@ function unwrap30(payload) {
4914
4662
  }
4915
4663
  return payload;
4916
4664
  }
4917
- function stripUndefined16(input) {
4665
+ function stripUndefined17(input) {
4918
4666
  return Object.fromEntries(
4919
4667
  Object.entries(input).filter(([, v]) => v !== void 0)
4920
4668
  );
@@ -4926,7 +4674,7 @@ var Mcp = class {
4926
4674
  http;
4927
4675
  /** Send a JSON-RPC request to the MCP endpoint. */
4928
4676
  async dispatch(params = {}) {
4929
- const body = stripUndefined16(params);
4677
+ const body = stripUndefined17(params);
4930
4678
  const data = await this.http.post(
4931
4679
  "/mcp",
4932
4680
  Object.keys(body).length > 0 ? body : void 0
@@ -5505,49 +5253,49 @@ var OcWorkspaces = class {
5505
5253
  /**
5506
5254
  * Fetch a single workspace.
5507
5255
  */
5508
- async get(hostId, workspaceId) {
5256
+ async get(hostId, workspaceId2) {
5509
5257
  return this.http.get(
5510
- `${this.base(hostId)}/${workspaceId}`
5258
+ `${this.base(hostId)}/${workspaceId2}`
5511
5259
  );
5512
5260
  }
5513
5261
  /**
5514
5262
  * Update workspace metadata (name, branch).
5515
5263
  */
5516
- async update(hostId, workspaceId, params) {
5264
+ async update(hostId, workspaceId2, params) {
5517
5265
  return this.http.patch(
5518
- `${this.base(hostId)}/${workspaceId}`,
5266
+ `${this.base(hostId)}/${workspaceId2}`,
5519
5267
  params
5520
5268
  );
5521
5269
  }
5522
5270
  /**
5523
5271
  * Delete a workspace.
5524
5272
  */
5525
- async delete(hostId, workspaceId) {
5526
- return this.http.delete(`${this.base(hostId)}/${workspaceId}`);
5273
+ async delete(hostId, workspaceId2) {
5274
+ return this.http.delete(`${this.base(hostId)}/${workspaceId2}`);
5527
5275
  }
5528
5276
  /**
5529
5277
  * Pull the latest changes from the remote repository.
5530
5278
  */
5531
- async pull(hostId, workspaceId) {
5279
+ async pull(hostId, workspaceId2) {
5532
5280
  return this.http.post(
5533
- `${this.base(hostId)}/${workspaceId}/pull`
5281
+ `${this.base(hostId)}/${workspaceId2}/pull`
5534
5282
  );
5535
5283
  }
5536
5284
  /**
5537
5285
  * Open a terminal session scoped to the workspace root directory.
5538
5286
  * Returns a short-lived WebSocket ticket.
5539
5287
  */
5540
- async openTerminal(hostId, workspaceId) {
5288
+ async openTerminal(hostId, workspaceId2) {
5541
5289
  return this.http.post(
5542
- `${this.base(hostId)}/${workspaceId}/open-terminal`
5290
+ `${this.base(hostId)}/${workspaceId2}/open-terminal`
5543
5291
  );
5544
5292
  }
5545
5293
  /**
5546
5294
  * Stream workspace setup / clone / install events.
5547
5295
  */
5548
- events(hostId, workspaceId) {
5296
+ events(hostId, workspaceId2) {
5549
5297
  return this.http.stream(
5550
- `${this.base(hostId)}/${workspaceId}/events`
5298
+ `${this.base(hostId)}/${workspaceId2}/events`
5551
5299
  );
5552
5300
  }
5553
5301
  };
@@ -5601,7 +5349,7 @@ function resourcePayload(params) {
5601
5349
  return { resource_type, resource_id };
5602
5350
  }
5603
5351
  function authConfig(params) {
5604
- return stripUndefined17({
5352
+ return stripUndefined18({
5605
5353
  ...params.config ?? {},
5606
5354
  signup_enabled: params.signup_enabled ?? params.signupEnabled,
5607
5355
  email_confirm_required: params.email_confirm_required ?? params.emailConfirmRequired,
@@ -5609,7 +5357,7 @@ function authConfig(params) {
5609
5357
  });
5610
5358
  }
5611
5359
  function requestBody(params) {
5612
- return stripUndefined17({
5360
+ return stripUndefined18({
5613
5361
  ...resourcePayload(params),
5614
5362
  config: authConfig(params)
5615
5363
  });
@@ -5623,7 +5371,7 @@ function unwrap32(payload) {
5623
5371
  }
5624
5372
  return payload;
5625
5373
  }
5626
- function stripUndefined17(input) {
5374
+ function stripUndefined18(input) {
5627
5375
  return Object.fromEntries(
5628
5376
  Object.entries(input).filter(([, v]) => v !== void 0)
5629
5377
  );
@@ -5678,7 +5426,7 @@ function listItems9(payload) {
5678
5426
  if (Array.isArray(result)) return result;
5679
5427
  return [];
5680
5428
  }
5681
- function stripUndefined18(input) {
5429
+ function stripUndefined19(input) {
5682
5430
  return Object.fromEntries(
5683
5431
  Object.entries(input).filter(([, v]) => v !== void 0)
5684
5432
  );
@@ -5695,7 +5443,7 @@ var ProjectIntegrations = class {
5695
5443
  http;
5696
5444
  /** List project integrations. */
5697
5445
  async list(params = {}) {
5698
- const query = stripUndefined18(params);
5446
+ const query = stripUndefined19(params);
5699
5447
  const data = await this.http.get("/project-integrations", query);
5700
5448
  return listItems9(data);
5701
5449
  }
@@ -5859,6 +5607,10 @@ function encodeContent(content) {
5859
5607
  return btoa(bin);
5860
5608
  }
5861
5609
  var SANDBOX_TEMPLATE = "miosa-sandbox";
5610
+ var AGENT_WORKSPACE_TIMEOUT_SEC = 86400;
5611
+ var AGENT_WORKSPACE_IDLE_TIMEOUT_SEC = 1800;
5612
+ var AGENT_WORKSPACE_SNAPSHOT_EXPIRATION_DAYS = 30;
5613
+ var AGENT_WORKSPACE_KEEP_LAST_SNAPSHOTS = 1;
5862
5614
  function unwrap36(payload) {
5863
5615
  if (payload !== null && typeof payload === "object" && "data" in payload && payload.data !== void 0) {
5864
5616
  return payload.data;
@@ -5873,19 +5625,30 @@ function listItems11(payload) {
5873
5625
  if ("items" in payload && Array.isArray(payload.items)) return payload.items;
5874
5626
  return [];
5875
5627
  }
5876
- function createBody(params = {}) {
5628
+ function createBody2(params = {}) {
5877
5629
  const templateId = params.templateId ?? params.template_id ?? params.image ?? SANDBOX_TEMPLATE;
5878
- return stripUndefined19({
5630
+ const persistent = params.persistent;
5631
+ const snapshotExpirationSec = snapshotExpirationSeconds(params);
5632
+ const keepLastSnapshots = params.keepLastSnapshots ?? params.keep_last_snapshots;
5633
+ const metadata = { ...params.metadata ?? {} };
5634
+ if (persistent !== void 0) metadata.miosa_persistent = persistent;
5635
+ if (snapshotExpirationSec !== void 0) {
5636
+ metadata.snapshot_expiration_sec = snapshotExpirationSec;
5637
+ }
5638
+ if (keepLastSnapshots !== void 0) {
5639
+ metadata.keep_last_snapshots = keepLastSnapshots;
5640
+ }
5641
+ return stripUndefined20({
5879
5642
  template_id: templateId,
5880
5643
  cpu_count: params.cpuCount ?? params.cpu_count,
5881
5644
  memory_mb: params.memoryMb ?? params.memory_mb,
5882
5645
  disk_mb: params.diskMb ?? params.disk_mb,
5883
5646
  disk_size_mb: params.diskSizeMb ?? params.disk_size_mb,
5884
- timeout_sec: params.timeoutSec ?? params.timeout_sec,
5885
- idle_timeout_sec: params.idleTimeoutSec ?? params.idle_timeout_sec,
5647
+ timeout_sec: params.timeoutSec ?? params.timeout_sec ?? (persistent === true ? 86400 : void 0),
5648
+ idle_timeout_sec: params.idleTimeoutSec ?? params.idle_timeout_sec ?? (persistent === true ? 1800 : void 0),
5886
5649
  always_on: params.alwaysOn ?? params.always_on,
5887
5650
  env: params.env,
5888
- metadata: params.metadata,
5651
+ metadata: Object.keys(metadata).length > 0 ? metadata : void 0,
5889
5652
  services: params.services,
5890
5653
  readiness_probe: params.readinessProbe ?? params.readiness_probe,
5891
5654
  database: params.database,
@@ -5903,18 +5666,24 @@ function createBody(params = {}) {
5903
5666
  });
5904
5667
  }
5905
5668
  function execBody(command, options = {}) {
5906
- return stripUndefined19({
5669
+ return stripUndefined20({
5907
5670
  command,
5908
5671
  cwd: options.cwd ?? options.workingDir ?? options.working_dir,
5909
5672
  env: options.env,
5910
5673
  timeout: options.timeout ?? options.timeoutSec ?? options.timeout_sec
5911
5674
  });
5912
5675
  }
5913
- function stripUndefined19(input) {
5676
+ function stripUndefined20(input) {
5914
5677
  return Object.fromEntries(
5915
5678
  Object.entries(input).filter(([, value]) => value !== void 0)
5916
5679
  );
5917
5680
  }
5681
+ function snapshotExpirationSeconds(params) {
5682
+ const seconds = params.snapshotExpirationSec ?? params.snapshot_expiration_sec;
5683
+ if (seconds !== void 0) return seconds;
5684
+ const days = params.snapshotExpirationDays ?? params.snapshot_expiration_days;
5685
+ return days === void 0 ? void 0 : days * 86400;
5686
+ }
5918
5687
  var SandboxCommands = class {
5919
5688
  constructor(sandbox) {
5920
5689
  this.sandbox = sandbox;
@@ -6412,10 +6181,25 @@ var Sandbox = class _Sandbox {
6412
6181
  * PATCH /api/v1/sandboxes/{id} — update mutable sandbox fields.
6413
6182
  */
6414
6183
  async update(params) {
6415
- const body = {};
6416
- for (const [k, v] of Object.entries(params)) {
6417
- if (v !== void 0) body[k] = v;
6184
+ const snapshotExpirationSec = snapshotExpirationSeconds(params);
6185
+ const metadata = { ...params.metadata ?? {} };
6186
+ if (params.persistent !== void 0) metadata.miosa_persistent = params.persistent;
6187
+ if (snapshotExpirationSec !== void 0) {
6188
+ metadata.snapshot_expiration_sec = snapshotExpirationSec;
6189
+ }
6190
+ const keepLastSnapshots = params.keepLastSnapshots ?? params.keep_last_snapshots;
6191
+ if (keepLastSnapshots !== void 0) {
6192
+ metadata.keep_last_snapshots = keepLastSnapshots;
6418
6193
  }
6194
+ const body = stripUndefined20({
6195
+ name: params.name,
6196
+ slug: params.slug,
6197
+ tags: params.tags,
6198
+ metadata: Object.keys(metadata).length > 0 ? metadata : void 0,
6199
+ always_on: params.always_on ?? params.alwaysOn,
6200
+ timeout_sec: params.timeout_sec ?? params.timeoutSec,
6201
+ idle_timeout_sec: params.idle_timeout_sec ?? params.idleTimeoutSec
6202
+ });
6419
6203
  const data = unwrap36(
6420
6204
  await this.http.patch(
6421
6205
  `/sandboxes/${this.id}`,
@@ -6425,6 +6209,16 @@ var Sandbox = class _Sandbox {
6425
6209
  this.data = data;
6426
6210
  return this;
6427
6211
  }
6212
+ async extend(timeoutSec) {
6213
+ const data = unwrap36(
6214
+ await this.http.post(
6215
+ `/sandboxes/${this.id}/extend`,
6216
+ { timeout_sec: timeoutSec }
6217
+ )
6218
+ );
6219
+ this.data = data;
6220
+ return this;
6221
+ }
6428
6222
  /**
6429
6223
  * POST /api/v1/sandboxes/{id}/preview-token → {token, url, expires_at, scope}
6430
6224
  */
@@ -6462,7 +6256,7 @@ var Sandbox = class _Sandbox {
6462
6256
  const idempotencyKey11 = params.idempotencyKey ?? params.idempotency_key;
6463
6257
  const requestOptions = {
6464
6258
  method: "POST",
6465
- body: stripUndefined19({
6259
+ body: stripUndefined20({
6466
6260
  name: params.name,
6467
6261
  deployment_id: params.deploymentId ?? params.deployment_id,
6468
6262
  output_path: params.outputPath ?? params.output_path ?? params.path ?? params.sourcePath ?? params.source_path,
@@ -6474,7 +6268,6 @@ var Sandbox = class _Sandbox {
6474
6268
  port: params.port,
6475
6269
  health_check_path: params.healthCheckPath ?? params.health_check_path,
6476
6270
  deployment_type: params.deploymentType ?? params.deployment_type,
6477
- docker_deploy_template_id: params.dockerDeployTemplateId ?? params.docker_deploy_template_id,
6478
6271
  type: params.type,
6479
6272
  mode: params.mode,
6480
6273
  database: params.database,
@@ -6628,11 +6421,37 @@ var Sandboxes = class {
6628
6421
  this.http = http;
6629
6422
  }
6630
6423
  http;
6424
+ /**
6425
+ * Create a persistent agent workspace.
6426
+ *
6427
+ * This is the preferred entry point for AI builders, coding agents, and
6428
+ * product workspaces. It gives the sandbox a stable name, a longer interactive
6429
+ * timeout, and metadata that makes the workspace easy to identify later. The
6430
+ * agent should create/edit files in `/workspace`, run installs/tests/builds
6431
+ * inside the sandbox, expose previews from the sandbox, and publish from the
6432
+ * sandbox when ready.
6433
+ */
6434
+ async createAgentWorkspace(params) {
6435
+ const metadata = {
6436
+ ...params.metadata ?? {},
6437
+ miosa_workspace_kind: "agent_workspace"
6438
+ };
6439
+ return this.getOrCreate({
6440
+ persistent: true,
6441
+ timeoutSec: AGENT_WORKSPACE_TIMEOUT_SEC,
6442
+ idleTimeoutSec: AGENT_WORKSPACE_IDLE_TIMEOUT_SEC,
6443
+ snapshotExpirationDays: AGENT_WORKSPACE_SNAPSHOT_EXPIRATION_DAYS,
6444
+ keepLastSnapshots: AGENT_WORKSPACE_KEEP_LAST_SNAPSHOTS,
6445
+ waitUntilReady: true,
6446
+ ...params,
6447
+ metadata
6448
+ });
6449
+ }
6631
6450
  async create(params = {}) {
6632
6451
  const idempotencyKey11 = params.idempotencyKey ?? params.idempotency_key;
6633
6452
  const requestOptions = {
6634
6453
  method: "POST",
6635
- body: createBody(params)
6454
+ body: createBody2(params)
6636
6455
  };
6637
6456
  if (idempotencyKey11) {
6638
6457
  requestOptions.headers = { "Idempotency-Key": idempotencyKey11 };
@@ -6664,6 +6483,37 @@ var Sandboxes = class {
6664
6483
  connect(id) {
6665
6484
  return this.get(id);
6666
6485
  }
6486
+ async getByName(name) {
6487
+ const data = unwrap36(
6488
+ await this.http.get(
6489
+ `/sandboxes/by-name/${encodeURIComponent(name)}`
6490
+ )
6491
+ );
6492
+ return new Sandbox(this.http, data);
6493
+ }
6494
+ /**
6495
+ * Idempotently obtain a persistent sandbox by stable name.
6496
+ *
6497
+ * If the sandbox exists, it is returned. If it is paused and `resume !== false`,
6498
+ * it is resumed first. If it does not exist, it is created with the supplied
6499
+ * params. Destroyed sandboxes are permanent and are not resumed by this helper.
6500
+ */
6501
+ async getOrCreate(params) {
6502
+ let sandbox;
6503
+ try {
6504
+ sandbox = await this.getByName(params.name);
6505
+ } catch (error) {
6506
+ if (!(error instanceof NotFoundError)) throw error;
6507
+ sandbox = await this.create(params);
6508
+ }
6509
+ if (sandbox.state === "paused" && params.resume !== false) {
6510
+ await sandbox.resume();
6511
+ }
6512
+ if (params.waitUntilReady === true) {
6513
+ await sandbox.waitUntilReady({ timeout: params.waitTimeoutSec ?? 60 });
6514
+ }
6515
+ return sandbox;
6516
+ }
6667
6517
  async delete(id) {
6668
6518
  await this.http.delete(`/sandboxes/${id}`);
6669
6519
  }
@@ -6691,7 +6541,7 @@ var Sandboxes = class {
6691
6541
  async createTemplate(params) {
6692
6542
  const response = await this.http.post(
6693
6543
  "/sandbox-templates",
6694
- stripUndefined19({
6544
+ stripUndefined20({
6695
6545
  name: params.name,
6696
6546
  slug: params.slug,
6697
6547
  description: params.description,
@@ -6704,7 +6554,7 @@ var Sandboxes = class {
6704
6554
  async createTemplateBuild(templateId, params = {}) {
6705
6555
  const response = await this.http.post(
6706
6556
  `/sandbox-templates/${templateId}/builds`,
6707
- stripUndefined19({
6557
+ stripUndefined20({
6708
6558
  build_spec: params.buildSpec ?? params.build_spec,
6709
6559
  metadata: params.metadata
6710
6560
  })
@@ -6749,7 +6599,7 @@ function listItems12(payload, candidateKeys = ["data", "templates", "builds", "i
6749
6599
  }
6750
6600
  return [];
6751
6601
  }
6752
- function stripUndefined20(input) {
6602
+ function stripUndefined21(input) {
6753
6603
  return Object.fromEntries(
6754
6604
  Object.entries(input).filter(([, v]) => v !== void 0)
6755
6605
  );
@@ -6786,7 +6636,7 @@ var SandboxTemplates = class {
6786
6636
  name,
6787
6637
  ...rest
6788
6638
  } = params;
6789
- const body = stripUndefined20({
6639
+ const body = stripUndefined21({
6790
6640
  name,
6791
6641
  build_spec: buildSpec ?? build_spec,
6792
6642
  ...rest
@@ -6820,7 +6670,7 @@ var SandboxTemplates = class {
6820
6670
  }
6821
6671
  async createBuild(templateId, params = {}) {
6822
6672
  const { idempotencyKey: ikey, ...rest } = params;
6823
- const body = stripUndefined20(rest);
6673
+ const body = stripUndefined21(rest);
6824
6674
  const data = await this.http.request(
6825
6675
  `/sandbox-templates/${templateId}/builds`,
6826
6676
  {
@@ -6854,7 +6704,7 @@ function listItems13(payload) {
6854
6704
  if (Array.isArray(result)) return result;
6855
6705
  return [];
6856
6706
  }
6857
- function stripUndefined21(input) {
6707
+ function stripUndefined22(input) {
6858
6708
  return Object.fromEntries(
6859
6709
  Object.entries(input).filter(([, v]) => v !== void 0)
6860
6710
  );
@@ -6871,7 +6721,7 @@ var Settings = class {
6871
6721
  }
6872
6722
  /** Update tenant settings. */
6873
6723
  async update(params) {
6874
- const body = stripUndefined21(params);
6724
+ const body = stripUndefined22(params);
6875
6725
  const data = await this.http.put("/settings", body);
6876
6726
  return unwrap38(data);
6877
6727
  }
@@ -6883,7 +6733,7 @@ var Settings = class {
6883
6733
  }
6884
6734
  /** Update tenant branding. */
6885
6735
  async updateBranding(params) {
6886
- const body = stripUndefined21(params);
6736
+ const body = stripUndefined22(params);
6887
6737
  const data = await this.http.put("/settings/branding", body);
6888
6738
  return unwrap38(data);
6889
6739
  }
@@ -6916,7 +6766,7 @@ var Settings = class {
6916
6766
  }
6917
6767
  /** Create or update a BYOK provider key. */
6918
6768
  async upsertProviderKey(provider, params) {
6919
- const body = stripUndefined21(params);
6769
+ const body = stripUndefined22(params);
6920
6770
  const data = await this.http.put(
6921
6771
  `/settings/provider-keys/${provider}`,
6922
6772
  body
@@ -6939,7 +6789,7 @@ function unwrap39(data) {
6939
6789
  }
6940
6790
  return data;
6941
6791
  }
6942
- function unwrapList13(data) {
6792
+ function unwrapList12(data) {
6943
6793
  if (Array.isArray(data)) return data;
6944
6794
  if (data && typeof data === "object") {
6945
6795
  const d = data;
@@ -6958,7 +6808,7 @@ var SnapshotsStandalone = class {
6958
6808
  const query = Object.fromEntries(
6959
6809
  Object.entries(filters).filter(([, v]) => v !== void 0)
6960
6810
  );
6961
- return unwrapList13(await this.http.get("/admin/snapshots", query));
6811
+ return unwrapList12(await this.http.get("/admin/snapshots", query));
6962
6812
  }
6963
6813
  async get(snapshotId) {
6964
6814
  return unwrap39(
@@ -6984,7 +6834,7 @@ function listItems14(payload, candidateKeys = ["data", "buckets", "objects", "it
6984
6834
  }
6985
6835
  return [];
6986
6836
  }
6987
- function stripUndefined22(input) {
6837
+ function stripUndefined23(input) {
6988
6838
  return Object.fromEntries(
6989
6839
  Object.entries(input).filter(([, v]) => v !== void 0)
6990
6840
  );
@@ -7001,7 +6851,7 @@ var Storage = class {
7001
6851
  }
7002
6852
  async createBucket(params) {
7003
6853
  const { name, public: isPublic, visibility, ...rest } = params;
7004
- const body = stripUndefined22({
6854
+ const body = stripUndefined23({
7005
6855
  name,
7006
6856
  visibility: visibility ?? (isPublic === void 0 ? void 0 : isPublic ? "public" : "private"),
7007
6857
  ...rest
@@ -7018,7 +6868,7 @@ var Storage = class {
7018
6868
  }
7019
6869
  // ── Objects ────────────────────────────────────────────────────────────────
7020
6870
  async listObjects(bucketId, params = {}) {
7021
- const query = stripUndefined22({
6871
+ const query = stripUndefined23({
7022
6872
  prefix: params.prefix,
7023
6873
  max_keys: params.max_keys ?? params.maxKeys ?? params.limit,
7024
6874
  marker: params.marker ?? params.cursor
@@ -7052,7 +6902,7 @@ var Storage = class {
7052
6902
  // ── Presigned URLs ─────────────────────────────────────────────────────────
7053
6903
  async presign(bucketId, params) {
7054
6904
  const operationMethod = params.operation === "put" ? "PUT" : params.operation === "get" ? "GET" : void 0;
7055
- const body = stripUndefined22({
6905
+ const body = stripUndefined23({
7056
6906
  key: params.key,
7057
6907
  method: params.method ?? operationMethod ?? "GET",
7058
6908
  expires_in: params.expiresIn ?? params.expires_in ?? params.expiresInSec ?? params.expires_in_sec ?? 3600
@@ -7182,7 +7032,7 @@ function unwrap42(payload) {
7182
7032
  }
7183
7033
  return payload;
7184
7034
  }
7185
- function stripUndefined23(input) {
7035
+ function stripUndefined24(input) {
7186
7036
  return Object.fromEntries(
7187
7037
  Object.entries(input).filter(([, v]) => v !== void 0)
7188
7038
  );
@@ -7199,7 +7049,7 @@ var Usage = class {
7199
7049
  }
7200
7050
  /** List per-session metering events. */
7201
7051
  async sessions(params = {}) {
7202
- const query = stripUndefined23(params);
7052
+ const query = stripUndefined24(params);
7203
7053
  const data = await this.http.get("/usage/sessions", query);
7204
7054
  const result = unwrap42(data);
7205
7055
  if (Array.isArray(result)) return result;
@@ -7207,7 +7057,7 @@ var Usage = class {
7207
7057
  }
7208
7058
  /** Get a usage report for a period. */
7209
7059
  async report(params = {}) {
7210
- const query = stripUndefined23(params);
7060
+ const query = stripUndefined24(params);
7211
7061
  const data = await this.http.get("/usage/summary", query);
7212
7062
  return unwrap42(data);
7213
7063
  }
@@ -7228,7 +7078,7 @@ function listItems15(payload, candidateKeys = ["data", "volumes", "items"]) {
7228
7078
  }
7229
7079
  return [];
7230
7080
  }
7231
- function stripUndefined24(input) {
7081
+ function stripUndefined25(input) {
7232
7082
  return Object.fromEntries(
7233
7083
  Object.entries(input).filter(([, v]) => v !== void 0)
7234
7084
  );
@@ -7242,7 +7092,7 @@ var Volumes = class {
7242
7092
  }
7243
7093
  http;
7244
7094
  async list(params = {}) {
7245
- const query = stripUndefined24({ ...params });
7095
+ const query = stripUndefined25({ ...params });
7246
7096
  const data = await this.http.get("/volumes", query);
7247
7097
  return listItems15(data);
7248
7098
  }
@@ -7252,7 +7102,7 @@ var Volumes = class {
7252
7102
  }
7253
7103
  async create(params) {
7254
7104
  const { idempotencyKey: ikey, sizeGb, ...rest } = params;
7255
- const body = stripUndefined24({
7105
+ const body = stripUndefined25({
7256
7106
  ...rest,
7257
7107
  size_gb: sizeGb ?? rest.size_gb
7258
7108
  });
@@ -7283,7 +7133,7 @@ function listItems16(payload, candidateKeys = ["data", "webhooks", "deliveries",
7283
7133
  }
7284
7134
  return [];
7285
7135
  }
7286
- function stripUndefined25(input) {
7136
+ function stripUndefined26(input) {
7287
7137
  return Object.fromEntries(
7288
7138
  Object.entries(input).filter(([, v]) => v !== void 0)
7289
7139
  );
@@ -7291,53 +7141,13 @@ function stripUndefined25(input) {
7291
7141
  function idempotencyKey10(key) {
7292
7142
  return key ?? randomUUID();
7293
7143
  }
7294
- function parseSignatureHeader(header) {
7295
- const parts = header.split(",").map((part) => part.trim());
7296
- let timestamp = null;
7297
- const signatures = [];
7298
- for (const part of parts) {
7299
- const [key, value] = part.split("=", 2);
7300
- if (!key || !value) continue;
7301
- if (key === "t") {
7302
- const parsed = Number(value);
7303
- if (Number.isFinite(parsed)) timestamp = parsed;
7304
- } else if (key === "v1") {
7305
- signatures.push(value);
7306
- }
7307
- }
7308
- if (timestamp == null || signatures.length === 0) return null;
7309
- return { timestamp, signatures };
7310
- }
7311
- function verifySignature(body, header, secret, options = {}) {
7312
- const parsed = parseSignatureHeader(header);
7313
- if (!parsed) return false;
7314
- const toleranceSeconds = options.toleranceSeconds ?? 300;
7315
- const ageSeconds = Math.abs(Math.floor(Date.now() / 1e3) - parsed.timestamp);
7316
- if (ageSeconds > toleranceSeconds) {
7317
- throw new Error("Webhook signature timestamp is too old");
7318
- }
7319
- const bodyBuffer = Buffer.isBuffer(body) ? body : Buffer.from(body);
7320
- const signedPayload = Buffer.concat([
7321
- Buffer.from(`${parsed.timestamp}.`),
7322
- bodyBuffer
7323
- ]);
7324
- const expected = createHmac("sha256", secret).update(signedPayload).digest("hex");
7325
- const expectedBuffer = Buffer.from(expected, "hex");
7326
- return parsed.signatures.some((signature) => {
7327
- const actualBuffer = Buffer.from(signature, "hex");
7328
- if (actualBuffer.length !== expectedBuffer.length) return false;
7329
- return timingSafeEqual(actualBuffer, expectedBuffer);
7330
- });
7331
- }
7332
7144
  var Webhooks = class {
7333
7145
  constructor(http) {
7334
7146
  this.http = http;
7335
7147
  }
7336
7148
  http;
7337
- static verifySignature = verifySignature;
7338
- static verify_signature = verifySignature;
7339
7149
  async list(params = {}) {
7340
- const query = stripUndefined25({ ...params });
7150
+ const query = stripUndefined26({ ...params });
7341
7151
  const data = await this.http.get("/webhooks", query);
7342
7152
  return listItems16(data);
7343
7153
  }
@@ -7347,7 +7157,7 @@ var Webhooks = class {
7347
7157
  }
7348
7158
  async create(params) {
7349
7159
  const { idempotencyKey: ikey, ...rest } = params;
7350
- const body = stripUndefined25(rest);
7160
+ const body = stripUndefined26(rest);
7351
7161
  const data = await this.http.request("/webhooks", {
7352
7162
  method: "POST",
7353
7163
  body,
@@ -7356,7 +7166,7 @@ var Webhooks = class {
7356
7166
  return unwrap44(data);
7357
7167
  }
7358
7168
  async update(webhookId, params) {
7359
- const body = stripUndefined25(params);
7169
+ const body = stripUndefined26(params);
7360
7170
  const data = await this.http.patch(`/webhooks/${webhookId}`, body);
7361
7171
  return unwrap44(data);
7362
7172
  }
@@ -7400,9 +7210,9 @@ var WorkspaceInvites = class {
7400
7210
  *
7401
7211
  * `POST /workspaces/:id/invites`
7402
7212
  */
7403
- async create(workspaceId, params) {
7213
+ async create(workspaceId2, params) {
7404
7214
  return this.http.post(
7405
- `/workspaces/${workspaceId}/invites`,
7215
+ `/workspaces/${workspaceId2}/invites`,
7406
7216
  params
7407
7217
  );
7408
7218
  }
@@ -7411,9 +7221,9 @@ var WorkspaceInvites = class {
7411
7221
  *
7412
7222
  * `GET /workspaces/:id/invites`
7413
7223
  */
7414
- async list(workspaceId) {
7224
+ async list(workspaceId2) {
7415
7225
  const res = await this.http.get(
7416
- `/workspaces/${workspaceId}/invites`
7226
+ `/workspaces/${workspaceId2}/invites`
7417
7227
  );
7418
7228
  return res.data ?? [];
7419
7229
  }
@@ -7425,9 +7235,9 @@ var WorkspaceInvites = class {
7425
7235
  *
7426
7236
  * `DELETE /workspaces/:id/invites/:invite_id`
7427
7237
  */
7428
- async revoke(workspaceId, inviteId) {
7238
+ async revoke(workspaceId2, inviteId) {
7429
7239
  return this.http.delete(
7430
- `/workspaces/${workspaceId}/invites/${inviteId}`
7240
+ `/workspaces/${workspaceId2}/invites/${inviteId}`
7431
7241
  );
7432
7242
  }
7433
7243
  /**
@@ -7481,9 +7291,9 @@ var WorkspaceMembers = class {
7481
7291
  *
7482
7292
  * `GET /workspaces/:id/members`
7483
7293
  */
7484
- async list(workspaceId) {
7294
+ async list(workspaceId2) {
7485
7295
  const res = await this.http.get(
7486
- `/workspaces/${workspaceId}/members`
7296
+ `/workspaces/${workspaceId2}/members`
7487
7297
  );
7488
7298
  return res.data ?? res;
7489
7299
  }
@@ -7499,9 +7309,9 @@ var WorkspaceMembers = class {
7499
7309
  * @throws `MiosaError` with code `NOT_TENANT_MEMBER` if the user is not an
7500
7310
  * org member.
7501
7311
  */
7502
- async add(workspaceId, params) {
7312
+ async add(workspaceId2, params) {
7503
7313
  const res = await this.http.post(
7504
- `/workspaces/${workspaceId}/members`,
7314
+ `/workspaces/${workspaceId2}/members`,
7505
7315
  params
7506
7316
  );
7507
7317
  return res.data ?? res;
@@ -7511,9 +7321,9 @@ var WorkspaceMembers = class {
7511
7321
  *
7512
7322
  * `PATCH /workspaces/:id/members/:user_id`
7513
7323
  */
7514
- async updateRole(workspaceId, userId, params) {
7324
+ async updateRole(workspaceId2, userId, params) {
7515
7325
  const res = await this.http.patch(
7516
- `/workspaces/${workspaceId}/members/${userId}`,
7326
+ `/workspaces/${workspaceId2}/members/${userId}`,
7517
7327
  params
7518
7328
  );
7519
7329
  return res.data ?? res;
@@ -7528,9 +7338,9 @@ var WorkspaceMembers = class {
7528
7338
  *
7529
7339
  * @throws `MiosaError` with code `LAST_OWNER` if the target is the sole owner.
7530
7340
  */
7531
- async remove(workspaceId, userId) {
7341
+ async remove(workspaceId2, userId) {
7532
7342
  return this.http.delete(
7533
- `/workspaces/${workspaceId}/members/${userId}`
7343
+ `/workspaces/${workspaceId2}/members/${userId}`
7534
7344
  );
7535
7345
  }
7536
7346
  };
@@ -7542,6 +7352,8 @@ var DEFAULT_MAX_RETRIES2 = 3;
7542
7352
  var Miosa = class {
7543
7353
  /** Per-workspace user roster — list, add, update role, remove. */
7544
7354
  workspaceMembers;
7355
+ /** Target-agnostic prompt dispatch to sandboxes/computers with durable records. */
7356
+ agentRuns;
7545
7357
  /**
7546
7358
  * Workspace invite flow — create invite, list, revoke, preview, accept.
7547
7359
  * Sending to an email already in the org adds the user directly.
@@ -7582,13 +7394,13 @@ var Miosa = class {
7582
7394
  computers;
7583
7395
  /** Sandboxes — native code-execution environments under `/sandboxes`. */
7584
7396
  sandboxes;
7585
- /** Agent device facade — route work across Sandboxes, Computers, and deploy hosts. */
7586
- devices;
7587
7397
  /**
7588
7398
  * Deployments — publish from a sandbox to a stable production URL.
7589
7399
  * Versions, releases, rollback, custom domains.
7590
7400
  */
7591
7401
  deployments;
7402
+ /** Docker Deploy appliance hosts — one always-on workspace host, many apps. */
7403
+ dockerDeploy;
7592
7404
  /** Credit balance and usage. */
7593
7405
  credits;
7594
7406
  /** Admin surface (`/api/v1/admin/*`) — requires an admin credential. */
@@ -7664,6 +7476,7 @@ var Miosa = class {
7664
7476
  timeout: config.timeout ?? DEFAULT_TIMEOUT2,
7665
7477
  maxRetries: config.maxRetries ?? DEFAULT_MAX_RETRIES2
7666
7478
  });
7479
+ this.agentRuns = new AgentRuns(this.http);
7667
7480
  this.workspaceMembers = new WorkspaceMembers(this.http);
7668
7481
  this.workspaceInvites = new WorkspaceInvites(this.http);
7669
7482
  this.orgInvites = new OrgInvites(this.http);
@@ -7682,8 +7495,8 @@ var Miosa = class {
7682
7495
  this.mcp = new Mcp(this.http);
7683
7496
  this.computers = new Computers(this.http);
7684
7497
  this.sandboxes = new Sandboxes(this.http);
7685
- this.devices = new Devices(this.http);
7686
7498
  this.deployments = new Deployments(this.http);
7499
+ this.dockerDeploy = new DockerDeploy(this.http);
7687
7500
  this.credits = new Credits(this.http);
7688
7501
  this.admin = new Admin(this.http);
7689
7502
  this.openComputers = new OpenComputers(this.http);
@@ -7713,6 +7526,162 @@ var Miosa = class {
7713
7526
  }
7714
7527
  };
7715
7528
 
7716
- export { Admin, Analytics, ApiKeys, AuditLog, AuthError, Benchmarks, BuilderSessions, Channels, Checkpoints, CommandCenter, Community, Completions, Computer, ComputerAudit, ComputerAutoStop, ComputerEnv, ComputerInbox, ComputerLogs, ComputerNetwork, ComputerOsa, ComputerPorts, ComputerSecrets, ComputerTerminal, ComputerVolumes, Computers, Credits, CronJobs, Dashboard, Databases, DeploymentDomains, DeploymentReleases, DeploymentRuntimeInstances, DeploymentVersions, Deployments, Desktop, Devices, EgressAudit, EgressNetwork, EgressSecrets, Email, EmailCampaigns, EmailInbox, EmailTemplates, Embeddings, Exec, ExternalKeys, Files, FlatCustomDomains, Functions, HealthChecks, InsufficientCreditsError, Integrations, Mcp, Miosa, MiosaError, Models, NetworkError, NetworkPolicy, NotFoundError, OAuthFlow, OpenComputers, OrgInvites, ProjectAuth, ProjectIntegrations, ProviderDefaults, RateLimitError, Regions, SANDBOX_TEMPLATE, Sandbox, SandboxArtifacts, SandboxAudit, SandboxCommands, SandboxEnv, SandboxEvents, SandboxFiles, SandboxNetwork, SandboxPreview, SandboxPreviews, SandboxSecrets, SandboxTags, SandboxTemplates, SandboxTerminal, Sandboxes, ScopedFs, Settings, SnapshotsStandalone, Storage, Tenant, TimeoutError, Usage, ValidationError, Volumes, Webhooks, WorkspaceInvites, WorkspaceMembers, verifySignature };
7529
+ // src/resources/app-auth.ts
7530
+ function unwrapSession(data) {
7531
+ const d = data && typeof data === "object" && "data" in data ? data.data : data;
7532
+ const userId = d.user_id ?? d.userId;
7533
+ const token = d.token ?? d.access_token;
7534
+ const expiresAt = d.expires_at ?? d.expiresAt ?? "";
7535
+ if (!userId || !token) {
7536
+ throw new Error(
7537
+ `AppAuth: unexpected response shape \u2014 got: ${JSON.stringify(d)}`
7538
+ );
7539
+ }
7540
+ return {
7541
+ userId,
7542
+ token,
7543
+ expiresAt
7544
+ };
7545
+ }
7546
+ function base64UrlDecode(s) {
7547
+ const padded = s.replace(/-/g, "+").replace(/_/g, "/");
7548
+ const bin = atob(padded);
7549
+ const bytes = new Uint8Array(bin.length);
7550
+ for (let i = 0; i < bin.length; i++) {
7551
+ bytes[i] = bin.charCodeAt(i);
7552
+ }
7553
+ return bytes;
7554
+ }
7555
+ var AppAuth = class {
7556
+ baseUrl;
7557
+ resourceType;
7558
+ resourceId;
7559
+ jwtSecret;
7560
+ constructor(config) {
7561
+ const authUrl = config.authUrl ?? (typeof process !== "undefined" ? process.env["AUTH_URL"] : void 0);
7562
+ if (!authUrl) {
7563
+ throw new Error(
7564
+ "AppAuth: authUrl is required. Pass authUrl in config or set AUTH_URL env var."
7565
+ );
7566
+ }
7567
+ if (!config.resourceType || !config.resourceId) {
7568
+ throw new Error("AppAuth: resourceType and resourceId are required.");
7569
+ }
7570
+ this.baseUrl = authUrl.replace(/\/$/, "");
7571
+ this.resourceType = config.resourceType;
7572
+ this.resourceId = config.resourceId;
7573
+ this.jwtSecret = config.jwtSecret ?? (typeof process !== "undefined" ? process.env["AUTH_JWT_SECRET"] : void 0);
7574
+ }
7575
+ /** POST /app-auth/:resourceType/:resourceId/signup */
7576
+ async signup(email, password) {
7577
+ return unwrapSession(await this._post("signup", { email, password }));
7578
+ }
7579
+ /** POST /app-auth/:resourceType/:resourceId/login */
7580
+ async login(email, password) {
7581
+ return unwrapSession(await this._post("login", { email, password }));
7582
+ }
7583
+ /**
7584
+ * POST /app-auth/:resourceType/:resourceId/verify
7585
+ * Verifies an email confirmation or magic-link token issued by the backend.
7586
+ */
7587
+ async verify(token) {
7588
+ return unwrapSession(await this._post("verify", { token }));
7589
+ }
7590
+ /** POST /app-auth/:resourceType/:resourceId/password-reset */
7591
+ async passwordReset(email) {
7592
+ const data = await this._post("password-reset", { email });
7593
+ return { ok: true, ...data };
7594
+ }
7595
+ /**
7596
+ * POST /app-auth/:resourceType/:resourceId/logout
7597
+ * Invalidates the given bearer token server-side.
7598
+ */
7599
+ async logout(token) {
7600
+ const data = await this._post("logout", { token });
7601
+ return { ok: true, ...data };
7602
+ }
7603
+ /**
7604
+ * GET /app-auth/:resourceType/:resourceId/me
7605
+ * Returns the session for the bearer token.
7606
+ */
7607
+ async me(token) {
7608
+ const url = `${this.baseUrl}/app-auth/${this.resourceType}/${this.resourceId}/me`;
7609
+ const resp = await fetch(url, {
7610
+ method: "GET",
7611
+ headers: {
7612
+ "Content-Type": "application/json",
7613
+ Authorization: `Bearer ${token}`
7614
+ }
7615
+ });
7616
+ if (!resp.ok) {
7617
+ const body = await resp.text();
7618
+ throw new Error(`AppAuth me failed (${resp.status}): ${body}`);
7619
+ }
7620
+ return unwrapSession(await resp.json());
7621
+ }
7622
+ /**
7623
+ * Verifies a JWT token locally using HS256 + AUTH_JWT_SECRET.
7624
+ *
7625
+ * Does NOT make a network call. Throws if the signature is invalid or the
7626
+ * token is expired. Returns the decoded payload on success.
7627
+ */
7628
+ async verifyToken(token) {
7629
+ if (!this.jwtSecret) {
7630
+ throw new Error(
7631
+ "AppAuth.verifyToken: jwtSecret is required. Pass jwtSecret in config or set AUTH_JWT_SECRET env var."
7632
+ );
7633
+ }
7634
+ const parts = token.split(".");
7635
+ if (parts.length !== 3) {
7636
+ throw new Error("AppAuth.verifyToken: malformed JWT \u2014 expected 3 parts");
7637
+ }
7638
+ const [headerB64, payloadB64, signatureB64] = parts;
7639
+ const payloadJson = new TextDecoder().decode(base64UrlDecode(payloadB64));
7640
+ const payload = JSON.parse(payloadJson);
7641
+ const now = Math.floor(Date.now() / 1e3);
7642
+ if (typeof payload.exp === "number" && payload.exp < now) {
7643
+ throw new Error(
7644
+ `AppAuth.verifyToken: token expired at ${new Date(payload.exp * 1e3).toISOString()}`
7645
+ );
7646
+ }
7647
+ const encoder = new TextEncoder();
7648
+ const signingInput = `${headerB64}.${payloadB64}`;
7649
+ const secretBytes = encoder.encode(this.jwtSecret);
7650
+ const key = await crypto.subtle.importKey(
7651
+ "raw",
7652
+ secretBytes,
7653
+ { name: "HMAC", hash: "SHA-256" },
7654
+ false,
7655
+ ["verify"]
7656
+ );
7657
+ const signatureBytes = base64UrlDecode(signatureB64).buffer;
7658
+ const valid = await crypto.subtle.verify(
7659
+ "HMAC",
7660
+ key,
7661
+ signatureBytes,
7662
+ encoder.encode(signingInput)
7663
+ );
7664
+ if (!valid) {
7665
+ throw new Error("AppAuth.verifyToken: invalid JWT signature");
7666
+ }
7667
+ return payload;
7668
+ }
7669
+ // ── Private ──────────────────────────────────────────────────────────────────
7670
+ async _post(action, body) {
7671
+ const url = `${this.baseUrl}/app-auth/${this.resourceType}/${this.resourceId}/${action}`;
7672
+ const resp = await fetch(url, {
7673
+ method: "POST",
7674
+ headers: { "Content-Type": "application/json" },
7675
+ body: JSON.stringify(body)
7676
+ });
7677
+ if (!resp.ok) {
7678
+ const text = await resp.text();
7679
+ throw new Error(`AppAuth ${action} failed (${resp.status}): ${text}`);
7680
+ }
7681
+ return resp.json();
7682
+ }
7683
+ };
7684
+
7685
+ export { Admin, AgentRuns, Analytics, ApiKeys, AppAuth, AuditLog, AuthError, Benchmarks, BuilderSessions, Channels, Checkpoints, CommandCenter, Community, Completions, Computer, ComputerAudit, ComputerAutoStop, ComputerEnv, ComputerInbox, ComputerLogs, ComputerNetwork, ComputerOsa, ComputerPorts, ComputerSecrets, ComputerTerminal, ComputerVolumes, Computers, Credits, CronJobs, Dashboard, Databases, DeploymentDomains, DeploymentReleases, DeploymentRuntimeInstances, DeploymentVersions, Deployments, Desktop, DockerDeploy, EgressAudit, EgressNetwork, EgressSecrets, Email, EmailCampaigns, EmailInbox, EmailTemplates, Embeddings, Exec, ExternalKeys, Files, FlatCustomDomains, Functions, HealthChecks, InsufficientCreditsError, Integrations, Mcp, Miosa, MiosaError, Models, NetworkError, NetworkPolicy, NotFoundError, OAuthFlow, OpenComputers, OrgInvites, ProjectAuth, ProjectIntegrations, ProviderDefaults, RateLimitError, Regions, SANDBOX_TEMPLATE, Sandbox, SandboxArtifacts, SandboxAudit, SandboxCommands, SandboxEnv, SandboxEvents, SandboxFiles, SandboxNetwork, SandboxPreview, SandboxPreviews, SandboxSecrets, SandboxTags, SandboxTemplates, SandboxTerminal, Sandboxes, ScopedFs, Settings, SnapshotsStandalone, Storage, Tenant, TimeoutError, Usage, ValidationError, Volumes, Webhooks, WorkspaceInvites, WorkspaceMembers };
7717
7686
  //# sourceMappingURL=index.js.map
7718
7687
  //# sourceMappingURL=index.js.map