@miosa/sdk 1.2.3 → 1.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -39
- package/dist/index.d.ts +201 -182
- package/dist/index.js +433 -309
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +5 -5
- package/src/index.ts +16 -11
- package/src/resources/admin.ts +0 -11
- package/src/resources/api-keys.ts +0 -16
- package/src/resources/custom_domains.ts +1 -1
- package/src/resources/deployments.test.ts +127 -51
- package/src/resources/deployments.ts +326 -125
- package/src/resources/devices.test.ts +92 -0
- package/src/resources/devices.ts +291 -0
- package/src/resources/sandboxes.test.ts +2 -0
- package/src/resources/sandboxes.ts +4 -0
- package/src/resources/tenant.ts +19 -101
- package/src/resources/webhooks.ts +54 -39
- package/src/types.ts +5 -5
- package/src/resources/docker-deploy.test.ts +0 -102
- package/src/resources/docker-deploy.ts +0 -183
- package/src/resources/governance.test.ts +0 -355
- package/src/resources/governance.ts +0 -528
- package/src/resources/phase1.test.ts +0 -187
- package/src/resources/quotas.ts +0 -77
- package/src/resources/sandbox-processes.ts +0 -112
- package/src/resources/sandbox-shares.ts +0 -83
- package/src/resources/tenant-events.ts +0 -32
- package/src/resources/workspaces.ts +0 -285
package/dist/index.js
CHANGED
|
@@ -592,13 +592,6 @@ 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
595
|
};
|
|
603
596
|
|
|
604
597
|
// src/resources/analytics.ts
|
|
@@ -681,17 +674,6 @@ var ApiKeys = class {
|
|
|
681
674
|
});
|
|
682
675
|
return unwrap2(data);
|
|
683
676
|
}
|
|
684
|
-
/** POST /api/v1/api-keys/scoped — L2 delegation token bound to one external user. */
|
|
685
|
-
async createScoped(params) {
|
|
686
|
-
const body = stripUndefined2({
|
|
687
|
-
external_user_id: params.externalUserId,
|
|
688
|
-
scopes: params.scopes,
|
|
689
|
-
expires_at: params.expiresAt
|
|
690
|
-
});
|
|
691
|
-
return unwrap2(
|
|
692
|
-
await this.http.post("/api-keys/scoped", body)
|
|
693
|
-
);
|
|
694
|
-
}
|
|
695
677
|
async delete(keyId) {
|
|
696
678
|
await this.http.delete(`/api-keys/${keyId}`);
|
|
697
679
|
}
|
|
@@ -3639,32 +3621,42 @@ function stripUndefined10(input) {
|
|
|
3639
3621
|
Object.entries(input).filter(([, v]) => v !== void 0)
|
|
3640
3622
|
);
|
|
3641
3623
|
}
|
|
3642
|
-
function dockerDeployMetadata(metadata) {
|
|
3643
|
-
return {
|
|
3624
|
+
function dockerDeployMetadata(metadata, templateId) {
|
|
3625
|
+
return stripUndefined10({
|
|
3644
3626
|
...metadata ?? {},
|
|
3645
|
-
deployment_product: "docker_deploy"
|
|
3646
|
-
|
|
3647
|
-
}
|
|
3648
|
-
function dockerDeployProduct(deployment) {
|
|
3649
|
-
return deployment.deployment_product ?? deployment.metadata?.["deployment_product"];
|
|
3627
|
+
deployment_product: "docker_deploy",
|
|
3628
|
+
docker_deploy_template_id: templateId
|
|
3629
|
+
});
|
|
3650
3630
|
}
|
|
3651
|
-
function
|
|
3652
|
-
|
|
3653
|
-
return deployment.docker_deploy_host_id ?? (typeof metadataHost === "string" ? metadataHost : null);
|
|
3631
|
+
function isRecord(value) {
|
|
3632
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
3654
3633
|
}
|
|
3655
|
-
function
|
|
3656
|
-
|
|
3634
|
+
function stringValue(value) {
|
|
3635
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
3657
3636
|
}
|
|
3658
|
-
function
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
);
|
|
3637
|
+
function runtimeMetadata(metadata) {
|
|
3638
|
+
const runtime = metadata.runtime;
|
|
3639
|
+
return isRecord(runtime) ? runtime : void 0;
|
|
3662
3640
|
}
|
|
3663
|
-
function
|
|
3641
|
+
function publicProbeUrl(publicUrl, probePath) {
|
|
3664
3642
|
const url = new URL(publicUrl);
|
|
3665
|
-
|
|
3643
|
+
const normalizedPath = probePath.startsWith("/") ? probePath : `/${probePath}`;
|
|
3644
|
+
url.pathname = normalizedPath;
|
|
3666
3645
|
return url.toString();
|
|
3667
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);
|
|
3659
|
+
}
|
|
3668
3660
|
var DeploymentVersions = class {
|
|
3669
3661
|
constructor(http, deploymentId) {
|
|
3670
3662
|
this.http = http;
|
|
@@ -3837,6 +3829,7 @@ var Deployments = class {
|
|
|
3837
3829
|
run_command: params.runCommand ?? params.run_command,
|
|
3838
3830
|
auto_deploy: params.autoDeploy ?? params.auto_deploy,
|
|
3839
3831
|
database: params.database,
|
|
3832
|
+
docker_deploy_template_id: params.dockerDeployTemplateId ?? params.docker_deploy_template_id,
|
|
3840
3833
|
metadata: params.metadata,
|
|
3841
3834
|
...attributionBody(params)
|
|
3842
3835
|
});
|
|
@@ -3853,118 +3846,181 @@ var Deployments = class {
|
|
|
3853
3846
|
* deployment so the control plane attaches it to the workspace Docker host.
|
|
3854
3847
|
*/
|
|
3855
3848
|
async createDockerDeploy(params) {
|
|
3849
|
+
const templateId = params.dockerDeployTemplateId ?? params.docker_deploy_template_id;
|
|
3856
3850
|
return this.create({
|
|
3857
3851
|
...params,
|
|
3858
|
-
metadata: dockerDeployMetadata(params.metadata)
|
|
3852
|
+
metadata: dockerDeployMetadata(params.metadata, templateId)
|
|
3859
3853
|
});
|
|
3860
3854
|
}
|
|
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
|
+
}
|
|
3861
3882
|
/**
|
|
3862
|
-
* Verify a Docker Deploy deployment
|
|
3863
|
-
*
|
|
3864
|
-
*
|
|
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.
|
|
3865
3889
|
*/
|
|
3866
3890
|
async doctorDockerDeploy(deploymentId, params = {}) {
|
|
3867
3891
|
const checks = [];
|
|
3868
3892
|
const deployment = await this.get(deploymentId);
|
|
3869
|
-
const metadata = deployment.metadata
|
|
3870
|
-
const product =
|
|
3871
|
-
const hostId =
|
|
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);
|
|
3872
3896
|
addDoctorCheck(
|
|
3873
3897
|
checks,
|
|
3874
3898
|
"deployment_product",
|
|
3875
3899
|
product === "docker_deploy",
|
|
3876
|
-
product === "docker_deploy" ? "Deployment is marked
|
|
3877
|
-
{
|
|
3900
|
+
product === "docker_deploy" ? "Deployment is marked as Docker Deploy." : `Expected deployment_product=docker_deploy, got ${product ?? "missing"}.`,
|
|
3901
|
+
{ product: product ?? null }
|
|
3878
3902
|
);
|
|
3879
3903
|
addDoctorCheck(
|
|
3880
3904
|
checks,
|
|
3881
3905
|
"docker_deploy_host_id",
|
|
3882
|
-
|
|
3883
|
-
hostId ? "Deployment
|
|
3884
|
-
{ docker_deploy_host_id: hostId }
|
|
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 }
|
|
3885
3909
|
);
|
|
3886
3910
|
let host;
|
|
3887
3911
|
if (hostId) {
|
|
3888
3912
|
try {
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
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));
|
|
3893
3919
|
addDoctorCheck(
|
|
3894
3920
|
checks,
|
|
3895
3921
|
"docker_deploy_host_health",
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
{
|
|
3899
|
-
status: host.status,
|
|
3900
|
-
appliance_status: host.appliance_status
|
|
3901
|
-
}
|
|
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 }
|
|
3902
3925
|
);
|
|
3903
|
-
} catch (
|
|
3926
|
+
} catch (err) {
|
|
3904
3927
|
addDoctorCheck(
|
|
3905
3928
|
checks,
|
|
3906
3929
|
"docker_deploy_host_health",
|
|
3907
3930
|
false,
|
|
3908
|
-
|
|
3931
|
+
`Could not fetch Docker Deploy host ${hostId}: ${err instanceof Error ? err.message : String(err)}`
|
|
3909
3932
|
);
|
|
3910
3933
|
}
|
|
3911
3934
|
}
|
|
3912
|
-
const runtime = metadata
|
|
3913
|
-
const
|
|
3935
|
+
const runtime = runtimeMetadata(metadata);
|
|
3936
|
+
const runtimeIp = runtime ? stringValue(runtime.ip) ?? stringValue(runtime.ip_address) : void 0;
|
|
3937
|
+
const runtimePort = runtime?.port;
|
|
3914
3938
|
addDoctorCheck(
|
|
3915
3939
|
checks,
|
|
3916
|
-
"
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
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 }
|
|
3920
3952
|
);
|
|
3921
3953
|
let probe;
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
const url = probeUrl(publicUrl, path);
|
|
3954
|
+
if (params.probe !== false && publicUrl) {
|
|
3955
|
+
const fetchImpl = params.fetchImpl ?? fetch;
|
|
3956
|
+
const url = publicProbeUrl(publicUrl, params.probePath ?? "/");
|
|
3926
3957
|
const controller = new AbortController();
|
|
3927
|
-
const
|
|
3928
|
-
() => controller.abort(),
|
|
3929
|
-
params.timeoutMs ?? params.timeout_ms ?? 1e4
|
|
3930
|
-
);
|
|
3958
|
+
const timer = setTimeout(() => controller.abort(), params.timeoutMs ?? 2e4);
|
|
3931
3959
|
try {
|
|
3932
|
-
const response = await
|
|
3933
|
-
|
|
3960
|
+
const response = await fetchImpl(url, {
|
|
3961
|
+
headers: { Accept: "*/*" },
|
|
3934
3962
|
signal: controller.signal
|
|
3935
3963
|
});
|
|
3936
|
-
|
|
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;
|
|
3937
3974
|
addDoctorCheck(
|
|
3938
3975
|
checks,
|
|
3939
3976
|
"public_url_probe",
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
{
|
|
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 }
|
|
3943
3980
|
);
|
|
3944
|
-
} catch (
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
ok: false,
|
|
3948
|
-
error: error instanceof Error ? error.message : String(error)
|
|
3949
|
-
};
|
|
3981
|
+
} catch (err) {
|
|
3982
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
3983
|
+
probe = { url, status: null, ok: false, responseSnippet: message };
|
|
3950
3984
|
addDoctorCheck(
|
|
3951
3985
|
checks,
|
|
3952
3986
|
"public_url_probe",
|
|
3953
3987
|
false,
|
|
3954
|
-
|
|
3955
|
-
{ url }
|
|
3988
|
+
`Public URL probe failed: ${message}`
|
|
3956
3989
|
);
|
|
3957
3990
|
} finally {
|
|
3958
|
-
clearTimeout(
|
|
3991
|
+
clearTimeout(timer);
|
|
3959
3992
|
}
|
|
3960
3993
|
}
|
|
3961
|
-
|
|
3994
|
+
const result = {
|
|
3962
3995
|
ok: checks.every((check) => check.ok),
|
|
3963
3996
|
deployment,
|
|
3964
|
-
|
|
3965
|
-
checks,
|
|
3966
|
-
...probe ? { probe } : {}
|
|
3997
|
+
checks
|
|
3967
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);
|
|
3968
4024
|
}
|
|
3969
4025
|
async update(deploymentId, params) {
|
|
3970
4026
|
const body = stripUndefined10({
|
|
@@ -3988,7 +4044,15 @@ var Deployments = class {
|
|
|
3988
4044
|
source_sandbox_id: params.sourceSandboxId ?? params.source_sandbox_id,
|
|
3989
4045
|
output_path: params.outputPath ?? params.output_path,
|
|
3990
4046
|
entrypoint: params.entrypoint,
|
|
3991
|
-
promote: params.promote
|
|
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)
|
|
3992
4056
|
});
|
|
3993
4057
|
const data = await this.http.request(
|
|
3994
4058
|
`/deployments/${deploymentId}/publish`,
|
|
@@ -4013,7 +4077,15 @@ var Deployments = class {
|
|
|
4013
4077
|
source_snapshot_path: params.sourceSnapshotPath ?? params.source_snapshot_path,
|
|
4014
4078
|
entrypoint: params.entrypoint,
|
|
4015
4079
|
domain: params.domain,
|
|
4016
|
-
custom_domain: params.customDomain ?? params.custom_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)
|
|
4017
4089
|
});
|
|
4018
4090
|
const data = await this.http.request(
|
|
4019
4091
|
`/sandboxes/${sandboxId}/deploy`,
|
|
@@ -4082,89 +4154,205 @@ var Deployments = class {
|
|
|
4082
4154
|
}
|
|
4083
4155
|
};
|
|
4084
4156
|
|
|
4085
|
-
// src/resources/
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
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;
|
|
4115
4240
|
constructor(http) {
|
|
4116
4241
|
this.http = http;
|
|
4117
4242
|
}
|
|
4118
|
-
http;
|
|
4119
4243
|
/**
|
|
4120
|
-
*
|
|
4121
|
-
*
|
|
4122
|
-
* Pass a workspace ID to inspect the dedicated always-on appliance machine
|
|
4123
|
-
* for one white-label workspace.
|
|
4244
|
+
* Return the static device catalog used by orchestration apps to choose the
|
|
4245
|
+
* right MIOSA execution surface before creating resources.
|
|
4124
4246
|
*/
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
"/docker-deploy/hosts",
|
|
4128
|
-
{ workspace_id: workspaceId(params) }
|
|
4129
|
-
);
|
|
4130
|
-
return res.data ?? res.hosts ?? [];
|
|
4247
|
+
catalog() {
|
|
4248
|
+
return DEVICE_CATALOG.map((entry) => ({ ...entry }));
|
|
4131
4249
|
}
|
|
4132
4250
|
/**
|
|
4133
|
-
*
|
|
4134
|
-
*
|
|
4135
|
-
*
|
|
4136
|
-
* this call. Treat `status === "active"` and `appliance_status === "healthy"`
|
|
4137
|
-
* as the ready condition before sending app/container traffic to it.
|
|
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.
|
|
4138
4254
|
*/
|
|
4139
|
-
async
|
|
4140
|
-
const
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
)
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
/** Fetch one Docker Deploy starter template by ID. */
|
|
4161
|
-
async getTemplate(templateId) {
|
|
4162
|
-
const res = await this.http.get(
|
|
4163
|
-
`/docker-deploy/templates/${encodeURIComponent(templateId)}`
|
|
4164
|
-
);
|
|
4165
|
-
return unwrapTemplate(res);
|
|
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 };
|
|
4166
4276
|
}
|
|
4167
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
|
+
}
|
|
4326
|
+
}
|
|
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
|
+
}
|
|
4168
4356
|
|
|
4169
4357
|
// src/resources/email.ts
|
|
4170
4358
|
function unwrap24(data) {
|
|
@@ -4183,7 +4371,7 @@ function unwrap24(data) {
|
|
|
4183
4371
|
}
|
|
4184
4372
|
return data;
|
|
4185
4373
|
}
|
|
4186
|
-
function
|
|
4374
|
+
function unwrapList12(data) {
|
|
4187
4375
|
if (Array.isArray(data)) return data;
|
|
4188
4376
|
if (data && typeof data === "object") {
|
|
4189
4377
|
const d = data;
|
|
@@ -4211,7 +4399,7 @@ var EmailCampaigns = class {
|
|
|
4211
4399
|
}
|
|
4212
4400
|
http;
|
|
4213
4401
|
async list(filters = {}) {
|
|
4214
|
-
return
|
|
4402
|
+
return unwrapList12(
|
|
4215
4403
|
await this.http.get(
|
|
4216
4404
|
"/admin/email-campaigns",
|
|
4217
4405
|
filters
|
|
@@ -4247,7 +4435,7 @@ var EmailCampaigns = class {
|
|
|
4247
4435
|
);
|
|
4248
4436
|
}
|
|
4249
4437
|
async deliveries(campaignId, filters = {}) {
|
|
4250
|
-
return
|
|
4438
|
+
return unwrapList12(
|
|
4251
4439
|
await this.http.get(
|
|
4252
4440
|
`/admin/email-campaigns/${campaignId}/deliveries`,
|
|
4253
4441
|
filters
|
|
@@ -4261,7 +4449,7 @@ var EmailTemplates = class {
|
|
|
4261
4449
|
}
|
|
4262
4450
|
http;
|
|
4263
4451
|
async list(filters = {}) {
|
|
4264
|
-
return
|
|
4452
|
+
return unwrapList12(
|
|
4265
4453
|
await this.http.get("/admin/email-templates", filters)
|
|
4266
4454
|
);
|
|
4267
4455
|
}
|
|
@@ -4293,7 +4481,7 @@ var EmailInbox = class {
|
|
|
4293
4481
|
}
|
|
4294
4482
|
http;
|
|
4295
4483
|
async list(filters = {}) {
|
|
4296
|
-
return
|
|
4484
|
+
return unwrapList12(
|
|
4297
4485
|
await this.http.get("/admin/email-inbox", filters)
|
|
4298
4486
|
);
|
|
4299
4487
|
}
|
|
@@ -5317,49 +5505,49 @@ var OcWorkspaces = class {
|
|
|
5317
5505
|
/**
|
|
5318
5506
|
* Fetch a single workspace.
|
|
5319
5507
|
*/
|
|
5320
|
-
async get(hostId,
|
|
5508
|
+
async get(hostId, workspaceId) {
|
|
5321
5509
|
return this.http.get(
|
|
5322
|
-
`${this.base(hostId)}/${
|
|
5510
|
+
`${this.base(hostId)}/${workspaceId}`
|
|
5323
5511
|
);
|
|
5324
5512
|
}
|
|
5325
5513
|
/**
|
|
5326
5514
|
* Update workspace metadata (name, branch).
|
|
5327
5515
|
*/
|
|
5328
|
-
async update(hostId,
|
|
5516
|
+
async update(hostId, workspaceId, params) {
|
|
5329
5517
|
return this.http.patch(
|
|
5330
|
-
`${this.base(hostId)}/${
|
|
5518
|
+
`${this.base(hostId)}/${workspaceId}`,
|
|
5331
5519
|
params
|
|
5332
5520
|
);
|
|
5333
5521
|
}
|
|
5334
5522
|
/**
|
|
5335
5523
|
* Delete a workspace.
|
|
5336
5524
|
*/
|
|
5337
|
-
async delete(hostId,
|
|
5338
|
-
return this.http.delete(`${this.base(hostId)}/${
|
|
5525
|
+
async delete(hostId, workspaceId) {
|
|
5526
|
+
return this.http.delete(`${this.base(hostId)}/${workspaceId}`);
|
|
5339
5527
|
}
|
|
5340
5528
|
/**
|
|
5341
5529
|
* Pull the latest changes from the remote repository.
|
|
5342
5530
|
*/
|
|
5343
|
-
async pull(hostId,
|
|
5531
|
+
async pull(hostId, workspaceId) {
|
|
5344
5532
|
return this.http.post(
|
|
5345
|
-
`${this.base(hostId)}/${
|
|
5533
|
+
`${this.base(hostId)}/${workspaceId}/pull`
|
|
5346
5534
|
);
|
|
5347
5535
|
}
|
|
5348
5536
|
/**
|
|
5349
5537
|
* Open a terminal session scoped to the workspace root directory.
|
|
5350
5538
|
* Returns a short-lived WebSocket ticket.
|
|
5351
5539
|
*/
|
|
5352
|
-
async openTerminal(hostId,
|
|
5540
|
+
async openTerminal(hostId, workspaceId) {
|
|
5353
5541
|
return this.http.post(
|
|
5354
|
-
`${this.base(hostId)}/${
|
|
5542
|
+
`${this.base(hostId)}/${workspaceId}/open-terminal`
|
|
5355
5543
|
);
|
|
5356
5544
|
}
|
|
5357
5545
|
/**
|
|
5358
5546
|
* Stream workspace setup / clone / install events.
|
|
5359
5547
|
*/
|
|
5360
|
-
events(hostId,
|
|
5548
|
+
events(hostId, workspaceId) {
|
|
5361
5549
|
return this.http.stream(
|
|
5362
|
-
`${this.base(hostId)}/${
|
|
5550
|
+
`${this.base(hostId)}/${workspaceId}/events`
|
|
5363
5551
|
);
|
|
5364
5552
|
}
|
|
5365
5553
|
};
|
|
@@ -6286,6 +6474,7 @@ var Sandbox = class _Sandbox {
|
|
|
6286
6474
|
port: params.port,
|
|
6287
6475
|
health_check_path: params.healthCheckPath ?? params.health_check_path,
|
|
6288
6476
|
deployment_type: params.deploymentType ?? params.deployment_type,
|
|
6477
|
+
docker_deploy_template_id: params.dockerDeployTemplateId ?? params.docker_deploy_template_id,
|
|
6289
6478
|
type: params.type,
|
|
6290
6479
|
mode: params.mode,
|
|
6291
6480
|
database: params.database,
|
|
@@ -6750,7 +6939,7 @@ function unwrap39(data) {
|
|
|
6750
6939
|
}
|
|
6751
6940
|
return data;
|
|
6752
6941
|
}
|
|
6753
|
-
function
|
|
6942
|
+
function unwrapList13(data) {
|
|
6754
6943
|
if (Array.isArray(data)) return data;
|
|
6755
6944
|
if (data && typeof data === "object") {
|
|
6756
6945
|
const d = data;
|
|
@@ -6769,7 +6958,7 @@ var SnapshotsStandalone = class {
|
|
|
6769
6958
|
const query = Object.fromEntries(
|
|
6770
6959
|
Object.entries(filters).filter(([, v]) => v !== void 0)
|
|
6771
6960
|
);
|
|
6772
|
-
return
|
|
6961
|
+
return unwrapList13(await this.http.get("/admin/snapshots", query));
|
|
6773
6962
|
}
|
|
6774
6963
|
async get(snapshotId) {
|
|
6775
6964
|
return unwrap39(
|
|
@@ -6965,96 +7154,22 @@ var OrgInvites = class {
|
|
|
6965
7154
|
function unwrap41(payload) {
|
|
6966
7155
|
if (payload && typeof payload === "object") {
|
|
6967
7156
|
const p = payload;
|
|
6968
|
-
for (const k of ["data", "tenant", "
|
|
7157
|
+
for (const k of ["data", "tenant", "items"]) {
|
|
6969
7158
|
if (k in p) return p[k];
|
|
6970
7159
|
}
|
|
6971
7160
|
}
|
|
6972
7161
|
return payload;
|
|
6973
7162
|
}
|
|
6974
|
-
var PreviewDomain = class {
|
|
6975
|
-
constructor(http) {
|
|
6976
|
-
this.http = http;
|
|
6977
|
-
}
|
|
6978
|
-
http;
|
|
6979
|
-
/** Get the tenant's white-label preview domain settings. */
|
|
6980
|
-
async get() {
|
|
6981
|
-
const data = await this.http.get("/tenant/preview-domain");
|
|
6982
|
-
return unwrap41(data);
|
|
6983
|
-
}
|
|
6984
|
-
/** Set the tenant's white-label preview domain. */
|
|
6985
|
-
async set(domain) {
|
|
6986
|
-
const data = await this.http.put("/tenant/preview-domain", {
|
|
6987
|
-
preview_domain: domain
|
|
6988
|
-
});
|
|
6989
|
-
return unwrap41(data);
|
|
6990
|
-
}
|
|
6991
|
-
/** Re-run DNS verification for the configured preview domain. */
|
|
6992
|
-
async verify() {
|
|
6993
|
-
const data = await this.http.post(
|
|
6994
|
-
"/tenant/preview-domain/verify",
|
|
6995
|
-
{}
|
|
6996
|
-
);
|
|
6997
|
-
return unwrap41(data);
|
|
6998
|
-
}
|
|
6999
|
-
/** Remove the tenant's custom preview domain. */
|
|
7000
|
-
async delete() {
|
|
7001
|
-
await this.http.delete("/tenant/preview-domain");
|
|
7002
|
-
}
|
|
7003
|
-
};
|
|
7004
|
-
var Branding = class {
|
|
7005
|
-
constructor(http) {
|
|
7006
|
-
this.http = http;
|
|
7007
|
-
}
|
|
7008
|
-
http;
|
|
7009
|
-
/** Get tenant branding used by white-label hosted surfaces. */
|
|
7010
|
-
async get() {
|
|
7011
|
-
const data = await this.http.get("/tenant/branding");
|
|
7012
|
-
return unwrap41(data);
|
|
7013
|
-
}
|
|
7014
|
-
/** Update tenant branding used by white-label hosted surfaces. */
|
|
7015
|
-
async set(params) {
|
|
7016
|
-
const body = Object.fromEntries(
|
|
7017
|
-
Object.entries(params).filter(([, v]) => v !== void 0)
|
|
7018
|
-
);
|
|
7019
|
-
const data = await this.http.put("/tenant/branding", {
|
|
7020
|
-
branding: body
|
|
7021
|
-
});
|
|
7022
|
-
return unwrap41(data);
|
|
7023
|
-
}
|
|
7024
|
-
/** Reset tenant branding to platform defaults. */
|
|
7025
|
-
async delete() {
|
|
7026
|
-
await this.http.delete("/tenant/branding");
|
|
7027
|
-
}
|
|
7028
|
-
};
|
|
7029
7163
|
var Tenant = class {
|
|
7030
|
-
http;
|
|
7031
|
-
preview_domain;
|
|
7032
|
-
branding;
|
|
7033
|
-
/** camelCase alias for SDK consumers that avoid snake_case properties. */
|
|
7034
|
-
previewDomain;
|
|
7035
7164
|
constructor(http) {
|
|
7036
7165
|
this.http = http;
|
|
7037
|
-
this.preview_domain = new PreviewDomain(http);
|
|
7038
|
-
this.previewDomain = this.preview_domain;
|
|
7039
|
-
this.branding = new Branding(http);
|
|
7040
7166
|
}
|
|
7167
|
+
http;
|
|
7041
7168
|
/** Get the current tenant's plan, limits, and live usage counters. */
|
|
7042
7169
|
async current() {
|
|
7043
7170
|
const data = await this.http.get("/tenant/plan");
|
|
7044
7171
|
return unwrap41(data);
|
|
7045
7172
|
}
|
|
7046
|
-
/** Convenience alias for `tenant.branding.get()`. */
|
|
7047
|
-
async getBranding() {
|
|
7048
|
-
return this.branding.get();
|
|
7049
|
-
}
|
|
7050
|
-
/** Convenience alias for `tenant.branding.set(...)`. */
|
|
7051
|
-
async setBranding(params) {
|
|
7052
|
-
return this.branding.set(params);
|
|
7053
|
-
}
|
|
7054
|
-
/** Convenience alias for `tenant.branding.delete()`. */
|
|
7055
|
-
async deleteBranding() {
|
|
7056
|
-
await this.branding.delete();
|
|
7057
|
-
}
|
|
7058
7173
|
};
|
|
7059
7174
|
|
|
7060
7175
|
// src/resources/usage.ts
|
|
@@ -7176,35 +7291,43 @@ function stripUndefined25(input) {
|
|
|
7176
7291
|
function idempotencyKey10(key) {
|
|
7177
7292
|
return key ?? randomUUID();
|
|
7178
7293
|
}
|
|
7179
|
-
function
|
|
7180
|
-
|
|
7181
|
-
|
|
7182
|
-
|
|
7183
|
-
|
|
7184
|
-
|
|
7185
|
-
|
|
7186
|
-
|
|
7187
|
-
|
|
7188
|
-
|
|
7189
|
-
|
|
7190
|
-
|
|
7191
|
-
|
|
7192
|
-
if (!Number.isFinite(unixSeconds)) return false;
|
|
7193
|
-
const ageSec = Math.abs(Date.now() / 1e3 - unixSeconds);
|
|
7194
|
-
if (ageSec > toleranceSec) {
|
|
7195
|
-
throw new Error("webhook timestamp too old");
|
|
7196
|
-
}
|
|
7197
|
-
const rawBody = bodyBuffer(body);
|
|
7198
|
-
const signed = Buffer.concat([Buffer.from(`${timestamp}.`), rawBody]);
|
|
7199
|
-
const expected = createHmac("sha256", secret).update(signed).digest("hex");
|
|
7200
|
-
try {
|
|
7201
|
-
return timingSafeEqual(
|
|
7202
|
-
Buffer.from(expected, "utf8"),
|
|
7203
|
-
Buffer.from(received, "utf8")
|
|
7204
|
-
);
|
|
7205
|
-
} catch {
|
|
7206
|
-
return false;
|
|
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
|
+
}
|
|
7207
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
|
+
});
|
|
7208
7331
|
}
|
|
7209
7332
|
var Webhooks = class {
|
|
7210
7333
|
constructor(http) {
|
|
@@ -7212,6 +7335,7 @@ var Webhooks = class {
|
|
|
7212
7335
|
}
|
|
7213
7336
|
http;
|
|
7214
7337
|
static verifySignature = verifySignature;
|
|
7338
|
+
static verify_signature = verifySignature;
|
|
7215
7339
|
async list(params = {}) {
|
|
7216
7340
|
const query = stripUndefined25({ ...params });
|
|
7217
7341
|
const data = await this.http.get("/webhooks", query);
|
|
@@ -7276,9 +7400,9 @@ var WorkspaceInvites = class {
|
|
|
7276
7400
|
*
|
|
7277
7401
|
* `POST /workspaces/:id/invites`
|
|
7278
7402
|
*/
|
|
7279
|
-
async create(
|
|
7403
|
+
async create(workspaceId, params) {
|
|
7280
7404
|
return this.http.post(
|
|
7281
|
-
`/workspaces/${
|
|
7405
|
+
`/workspaces/${workspaceId}/invites`,
|
|
7282
7406
|
params
|
|
7283
7407
|
);
|
|
7284
7408
|
}
|
|
@@ -7287,9 +7411,9 @@ var WorkspaceInvites = class {
|
|
|
7287
7411
|
*
|
|
7288
7412
|
* `GET /workspaces/:id/invites`
|
|
7289
7413
|
*/
|
|
7290
|
-
async list(
|
|
7414
|
+
async list(workspaceId) {
|
|
7291
7415
|
const res = await this.http.get(
|
|
7292
|
-
`/workspaces/${
|
|
7416
|
+
`/workspaces/${workspaceId}/invites`
|
|
7293
7417
|
);
|
|
7294
7418
|
return res.data ?? [];
|
|
7295
7419
|
}
|
|
@@ -7301,9 +7425,9 @@ var WorkspaceInvites = class {
|
|
|
7301
7425
|
*
|
|
7302
7426
|
* `DELETE /workspaces/:id/invites/:invite_id`
|
|
7303
7427
|
*/
|
|
7304
|
-
async revoke(
|
|
7428
|
+
async revoke(workspaceId, inviteId) {
|
|
7305
7429
|
return this.http.delete(
|
|
7306
|
-
`/workspaces/${
|
|
7430
|
+
`/workspaces/${workspaceId}/invites/${inviteId}`
|
|
7307
7431
|
);
|
|
7308
7432
|
}
|
|
7309
7433
|
/**
|
|
@@ -7357,9 +7481,9 @@ var WorkspaceMembers = class {
|
|
|
7357
7481
|
*
|
|
7358
7482
|
* `GET /workspaces/:id/members`
|
|
7359
7483
|
*/
|
|
7360
|
-
async list(
|
|
7484
|
+
async list(workspaceId) {
|
|
7361
7485
|
const res = await this.http.get(
|
|
7362
|
-
`/workspaces/${
|
|
7486
|
+
`/workspaces/${workspaceId}/members`
|
|
7363
7487
|
);
|
|
7364
7488
|
return res.data ?? res;
|
|
7365
7489
|
}
|
|
@@ -7375,9 +7499,9 @@ var WorkspaceMembers = class {
|
|
|
7375
7499
|
* @throws `MiosaError` with code `NOT_TENANT_MEMBER` if the user is not an
|
|
7376
7500
|
* org member.
|
|
7377
7501
|
*/
|
|
7378
|
-
async add(
|
|
7502
|
+
async add(workspaceId, params) {
|
|
7379
7503
|
const res = await this.http.post(
|
|
7380
|
-
`/workspaces/${
|
|
7504
|
+
`/workspaces/${workspaceId}/members`,
|
|
7381
7505
|
params
|
|
7382
7506
|
);
|
|
7383
7507
|
return res.data ?? res;
|
|
@@ -7387,9 +7511,9 @@ var WorkspaceMembers = class {
|
|
|
7387
7511
|
*
|
|
7388
7512
|
* `PATCH /workspaces/:id/members/:user_id`
|
|
7389
7513
|
*/
|
|
7390
|
-
async updateRole(
|
|
7514
|
+
async updateRole(workspaceId, userId, params) {
|
|
7391
7515
|
const res = await this.http.patch(
|
|
7392
|
-
`/workspaces/${
|
|
7516
|
+
`/workspaces/${workspaceId}/members/${userId}`,
|
|
7393
7517
|
params
|
|
7394
7518
|
);
|
|
7395
7519
|
return res.data ?? res;
|
|
@@ -7404,9 +7528,9 @@ var WorkspaceMembers = class {
|
|
|
7404
7528
|
*
|
|
7405
7529
|
* @throws `MiosaError` with code `LAST_OWNER` if the target is the sole owner.
|
|
7406
7530
|
*/
|
|
7407
|
-
async remove(
|
|
7531
|
+
async remove(workspaceId, userId) {
|
|
7408
7532
|
return this.http.delete(
|
|
7409
|
-
`/workspaces/${
|
|
7533
|
+
`/workspaces/${workspaceId}/members/${userId}`
|
|
7410
7534
|
);
|
|
7411
7535
|
}
|
|
7412
7536
|
};
|
|
@@ -7458,13 +7582,13 @@ var Miosa = class {
|
|
|
7458
7582
|
computers;
|
|
7459
7583
|
/** Sandboxes — native code-execution environments under `/sandboxes`. */
|
|
7460
7584
|
sandboxes;
|
|
7585
|
+
/** Agent device facade — route work across Sandboxes, Computers, and deploy hosts. */
|
|
7586
|
+
devices;
|
|
7461
7587
|
/**
|
|
7462
7588
|
* Deployments — publish from a sandbox to a stable production URL.
|
|
7463
7589
|
* Versions, releases, rollback, custom domains.
|
|
7464
7590
|
*/
|
|
7465
7591
|
deployments;
|
|
7466
|
-
/** Docker Deploy appliance hosts — one always-on workspace host, many apps. */
|
|
7467
|
-
dockerDeploy;
|
|
7468
7592
|
/** Credit balance and usage. */
|
|
7469
7593
|
credits;
|
|
7470
7594
|
/** Admin surface (`/api/v1/admin/*`) — requires an admin credential. */
|
|
@@ -7558,8 +7682,8 @@ var Miosa = class {
|
|
|
7558
7682
|
this.mcp = new Mcp(this.http);
|
|
7559
7683
|
this.computers = new Computers(this.http);
|
|
7560
7684
|
this.sandboxes = new Sandboxes(this.http);
|
|
7685
|
+
this.devices = new Devices(this.http);
|
|
7561
7686
|
this.deployments = new Deployments(this.http);
|
|
7562
|
-
this.dockerDeploy = new DockerDeploy(this.http);
|
|
7563
7687
|
this.credits = new Credits(this.http);
|
|
7564
7688
|
this.admin = new Admin(this.http);
|
|
7565
7689
|
this.openComputers = new OpenComputers(this.http);
|
|
@@ -7589,6 +7713,6 @@ var Miosa = class {
|
|
|
7589
7713
|
}
|
|
7590
7714
|
};
|
|
7591
7715
|
|
|
7592
|
-
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,
|
|
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 };
|
|
7593
7717
|
//# sourceMappingURL=index.js.map
|
|
7594
7718
|
//# sourceMappingURL=index.js.map
|