@miosa/sdk 1.2.4 → 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 +429 -343
- 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 +117 -114
- package/src/resources/deployments.ts +314 -166
- 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,47 +3621,41 @@ 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
|
-
|
|
3627
|
+
deployment_product: "docker_deploy",
|
|
3628
|
+
docker_deploy_template_id: templateId
|
|
3629
|
+
});
|
|
3647
3630
|
}
|
|
3648
|
-
function
|
|
3649
|
-
return
|
|
3631
|
+
function isRecord(value) {
|
|
3632
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
3650
3633
|
}
|
|
3651
|
-
function
|
|
3652
|
-
|
|
3653
|
-
return deployment.docker_deploy_host_id ?? (typeof metadataHost === "string" ? metadataHost : null);
|
|
3634
|
+
function stringValue(value) {
|
|
3635
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
3654
3636
|
}
|
|
3655
|
-
function
|
|
3656
|
-
const
|
|
3657
|
-
|
|
3658
|
-
|
|
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();
|
|
3659
3646
|
}
|
|
3660
|
-
function
|
|
3661
|
-
const url = app?.["url"];
|
|
3662
|
-
if (typeof url !== "string") return null;
|
|
3647
|
+
function looksLikeMiosaGatewayJson(body) {
|
|
3663
3648
|
try {
|
|
3664
|
-
const parsed =
|
|
3665
|
-
|
|
3666
|
-
return Number.isInteger(port) ? port : null;
|
|
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));
|
|
3667
3651
|
} catch {
|
|
3668
|
-
return
|
|
3652
|
+
return false;
|
|
3669
3653
|
}
|
|
3670
3654
|
}
|
|
3671
|
-
function addDoctorCheck(checks, name, ok, message,
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
return Boolean(
|
|
3676
|
-
host && host.status === "active" && host.appliance_status === "healthy"
|
|
3677
|
-
);
|
|
3678
|
-
}
|
|
3679
|
-
function probeUrl(publicUrl, probePath) {
|
|
3680
|
-
const url = new URL(publicUrl);
|
|
3681
|
-
url.pathname = probePath.startsWith("/") ? probePath : `/${probePath}`;
|
|
3682
|
-
return url.toString();
|
|
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);
|
|
3683
3659
|
}
|
|
3684
3660
|
var DeploymentVersions = class {
|
|
3685
3661
|
constructor(http, deploymentId) {
|
|
@@ -3853,6 +3829,7 @@ var Deployments = class {
|
|
|
3853
3829
|
run_command: params.runCommand ?? params.run_command,
|
|
3854
3830
|
auto_deploy: params.autoDeploy ?? params.auto_deploy,
|
|
3855
3831
|
database: params.database,
|
|
3832
|
+
docker_deploy_template_id: params.dockerDeployTemplateId ?? params.docker_deploy_template_id,
|
|
3856
3833
|
metadata: params.metadata,
|
|
3857
3834
|
...attributionBody(params)
|
|
3858
3835
|
});
|
|
@@ -3869,140 +3846,181 @@ var Deployments = class {
|
|
|
3869
3846
|
* deployment so the control plane attaches it to the workspace Docker host.
|
|
3870
3847
|
*/
|
|
3871
3848
|
async createDockerDeploy(params) {
|
|
3849
|
+
const templateId = params.dockerDeployTemplateId ?? params.docker_deploy_template_id;
|
|
3872
3850
|
return this.create({
|
|
3873
3851
|
...params,
|
|
3874
|
-
metadata: dockerDeployMetadata(params.metadata)
|
|
3852
|
+
metadata: dockerDeployMetadata(params.metadata, templateId)
|
|
3875
3853
|
});
|
|
3876
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
|
+
}
|
|
3877
3882
|
/**
|
|
3878
|
-
* Verify a Docker Deploy deployment
|
|
3879
|
-
*
|
|
3880
|
-
*
|
|
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.
|
|
3881
3889
|
*/
|
|
3882
3890
|
async doctorDockerDeploy(deploymentId, params = {}) {
|
|
3883
3891
|
const checks = [];
|
|
3884
3892
|
const deployment = await this.get(deploymentId);
|
|
3885
|
-
const metadata = deployment.metadata
|
|
3886
|
-
const product =
|
|
3887
|
-
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);
|
|
3888
3896
|
addDoctorCheck(
|
|
3889
3897
|
checks,
|
|
3890
3898
|
"deployment_product",
|
|
3891
3899
|
product === "docker_deploy",
|
|
3892
|
-
product === "docker_deploy" ? "Deployment is marked
|
|
3893
|
-
{
|
|
3900
|
+
product === "docker_deploy" ? "Deployment is marked as Docker Deploy." : `Expected deployment_product=docker_deploy, got ${product ?? "missing"}.`,
|
|
3901
|
+
{ product: product ?? null }
|
|
3894
3902
|
);
|
|
3895
3903
|
addDoctorCheck(
|
|
3896
3904
|
checks,
|
|
3897
3905
|
"docker_deploy_host_id",
|
|
3898
|
-
|
|
3899
|
-
hostId ? "Deployment
|
|
3900
|
-
{ 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 }
|
|
3901
3909
|
);
|
|
3902
3910
|
let host;
|
|
3903
3911
|
if (hostId) {
|
|
3904
3912
|
try {
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
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));
|
|
3909
3919
|
addDoctorCheck(
|
|
3910
3920
|
checks,
|
|
3911
3921
|
"docker_deploy_host_health",
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
{
|
|
3915
|
-
status: host.status,
|
|
3916
|
-
appliance_status: host.appliance_status
|
|
3917
|
-
}
|
|
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 }
|
|
3918
3925
|
);
|
|
3919
|
-
} catch (
|
|
3926
|
+
} catch (err) {
|
|
3920
3927
|
addDoctorCheck(
|
|
3921
3928
|
checks,
|
|
3922
3929
|
"docker_deploy_host_health",
|
|
3923
3930
|
false,
|
|
3924
|
-
|
|
3931
|
+
`Could not fetch Docker Deploy host ${hostId}: ${err instanceof Error ? err.message : String(err)}`
|
|
3925
3932
|
);
|
|
3926
3933
|
}
|
|
3927
3934
|
}
|
|
3928
|
-
const
|
|
3929
|
-
const
|
|
3930
|
-
const
|
|
3935
|
+
const runtime = runtimeMetadata(metadata);
|
|
3936
|
+
const runtimeIp = runtime ? stringValue(runtime.ip) ?? stringValue(runtime.ip_address) : void 0;
|
|
3937
|
+
const runtimePort = runtime?.port;
|
|
3931
3938
|
addDoctorCheck(
|
|
3932
3939
|
checks,
|
|
3933
|
-
"
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
status: app["status"],
|
|
3940
|
-
url: app["url"],
|
|
3941
|
-
expected_port: appPort
|
|
3942
|
-
} : void 0
|
|
3943
|
-
);
|
|
3944
|
-
const runtime = metadata["runtime"];
|
|
3945
|
-
const hasRuntimeRoute = typeof runtime === "object" && runtime !== null && typeof runtime["ip"] === "string" && typeof runtime["port"] === "number";
|
|
3946
|
-
const runtimeRecord = hasRuntimeRoute && typeof runtime === "object" ? runtime : void 0;
|
|
3947
|
-
const routeMatchesContainerPort = hasRuntimeRoute && (appPort === null || runtimeRecord?.["port"] === appPort);
|
|
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);
|
|
3948
3946
|
addDoctorCheck(
|
|
3949
3947
|
checks,
|
|
3950
|
-
"
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
...runtimeRecord,
|
|
3955
|
-
expected_port: appPort,
|
|
3956
|
-
docker_deploy_url: app?.["url"]
|
|
3957
|
-
} : void 0
|
|
3948
|
+
"public_url",
|
|
3949
|
+
!!publicUrl,
|
|
3950
|
+
publicUrl ? "Deployment has a public URL." : "Deployment has no public URL to probe.",
|
|
3951
|
+
{ public_url: publicUrl ?? null }
|
|
3958
3952
|
);
|
|
3959
3953
|
let probe;
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
const url = probeUrl(publicUrl, path);
|
|
3954
|
+
if (params.probe !== false && publicUrl) {
|
|
3955
|
+
const fetchImpl = params.fetchImpl ?? fetch;
|
|
3956
|
+
const url = publicProbeUrl(publicUrl, params.probePath ?? "/");
|
|
3964
3957
|
const controller = new AbortController();
|
|
3965
|
-
const
|
|
3966
|
-
() => controller.abort(),
|
|
3967
|
-
params.timeoutMs ?? params.timeout_ms ?? 1e4
|
|
3968
|
-
);
|
|
3958
|
+
const timer = setTimeout(() => controller.abort(), params.timeoutMs ?? 2e4);
|
|
3969
3959
|
try {
|
|
3970
|
-
const response = await
|
|
3971
|
-
|
|
3960
|
+
const response = await fetchImpl(url, {
|
|
3961
|
+
headers: { Accept: "*/*" },
|
|
3972
3962
|
signal: controller.signal
|
|
3973
3963
|
});
|
|
3974
|
-
|
|
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;
|
|
3975
3974
|
addDoctorCheck(
|
|
3976
3975
|
checks,
|
|
3977
3976
|
"public_url_probe",
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
{
|
|
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 }
|
|
3981
3980
|
);
|
|
3982
|
-
} catch (
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
ok: false,
|
|
3986
|
-
error: error instanceof Error ? error.message : String(error)
|
|
3987
|
-
};
|
|
3981
|
+
} catch (err) {
|
|
3982
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
3983
|
+
probe = { url, status: null, ok: false, responseSnippet: message };
|
|
3988
3984
|
addDoctorCheck(
|
|
3989
3985
|
checks,
|
|
3990
3986
|
"public_url_probe",
|
|
3991
3987
|
false,
|
|
3992
|
-
|
|
3993
|
-
{ url }
|
|
3988
|
+
`Public URL probe failed: ${message}`
|
|
3994
3989
|
);
|
|
3995
3990
|
} finally {
|
|
3996
|
-
clearTimeout(
|
|
3991
|
+
clearTimeout(timer);
|
|
3997
3992
|
}
|
|
3998
3993
|
}
|
|
3999
|
-
|
|
3994
|
+
const result = {
|
|
4000
3995
|
ok: checks.every((check) => check.ok),
|
|
4001
3996
|
deployment,
|
|
4002
|
-
|
|
4003
|
-
checks,
|
|
4004
|
-
...probe ? { probe } : {}
|
|
3997
|
+
checks
|
|
4005
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);
|
|
4006
4024
|
}
|
|
4007
4025
|
async update(deploymentId, params) {
|
|
4008
4026
|
const body = stripUndefined10({
|
|
@@ -4026,7 +4044,15 @@ var Deployments = class {
|
|
|
4026
4044
|
source_sandbox_id: params.sourceSandboxId ?? params.source_sandbox_id,
|
|
4027
4045
|
output_path: params.outputPath ?? params.output_path,
|
|
4028
4046
|
entrypoint: params.entrypoint,
|
|
4029
|
-
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)
|
|
4030
4056
|
});
|
|
4031
4057
|
const data = await this.http.request(
|
|
4032
4058
|
`/deployments/${deploymentId}/publish`,
|
|
@@ -4051,7 +4077,15 @@ var Deployments = class {
|
|
|
4051
4077
|
source_snapshot_path: params.sourceSnapshotPath ?? params.source_snapshot_path,
|
|
4052
4078
|
entrypoint: params.entrypoint,
|
|
4053
4079
|
domain: params.domain,
|
|
4054
|
-
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)
|
|
4055
4089
|
});
|
|
4056
4090
|
const data = await this.http.request(
|
|
4057
4091
|
`/sandboxes/${sandboxId}/deploy`,
|
|
@@ -4120,89 +4154,205 @@ var Deployments = class {
|
|
|
4120
4154
|
}
|
|
4121
4155
|
};
|
|
4122
4156
|
|
|
4123
|
-
// src/resources/
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
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;
|
|
4153
4240
|
constructor(http) {
|
|
4154
4241
|
this.http = http;
|
|
4155
4242
|
}
|
|
4156
|
-
http;
|
|
4157
4243
|
/**
|
|
4158
|
-
*
|
|
4159
|
-
*
|
|
4160
|
-
* Pass a workspace ID to inspect the dedicated always-on appliance machine
|
|
4161
|
-
* 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.
|
|
4162
4246
|
*/
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
"/docker-deploy/hosts",
|
|
4166
|
-
{ workspace_id: workspaceId(params) }
|
|
4167
|
-
);
|
|
4168
|
-
return res.data ?? res.hosts ?? [];
|
|
4247
|
+
catalog() {
|
|
4248
|
+
return DEVICE_CATALOG.map((entry) => ({ ...entry }));
|
|
4169
4249
|
}
|
|
4170
4250
|
/**
|
|
4171
|
-
*
|
|
4172
|
-
*
|
|
4173
|
-
*
|
|
4174
|
-
* this call. Treat `status === "active"` and `appliance_status === "healthy"`
|
|
4175
|
-
* 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.
|
|
4176
4254
|
*/
|
|
4177
|
-
async
|
|
4178
|
-
const
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
)
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
/** Fetch one Docker Deploy starter template by ID. */
|
|
4199
|
-
async getTemplate(templateId) {
|
|
4200
|
-
const res = await this.http.get(
|
|
4201
|
-
`/docker-deploy/templates/${encodeURIComponent(templateId)}`
|
|
4202
|
-
);
|
|
4203
|
-
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 };
|
|
4204
4276
|
}
|
|
4205
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
|
+
}
|
|
4206
4356
|
|
|
4207
4357
|
// src/resources/email.ts
|
|
4208
4358
|
function unwrap24(data) {
|
|
@@ -4221,7 +4371,7 @@ function unwrap24(data) {
|
|
|
4221
4371
|
}
|
|
4222
4372
|
return data;
|
|
4223
4373
|
}
|
|
4224
|
-
function
|
|
4374
|
+
function unwrapList12(data) {
|
|
4225
4375
|
if (Array.isArray(data)) return data;
|
|
4226
4376
|
if (data && typeof data === "object") {
|
|
4227
4377
|
const d = data;
|
|
@@ -4249,7 +4399,7 @@ var EmailCampaigns = class {
|
|
|
4249
4399
|
}
|
|
4250
4400
|
http;
|
|
4251
4401
|
async list(filters = {}) {
|
|
4252
|
-
return
|
|
4402
|
+
return unwrapList12(
|
|
4253
4403
|
await this.http.get(
|
|
4254
4404
|
"/admin/email-campaigns",
|
|
4255
4405
|
filters
|
|
@@ -4285,7 +4435,7 @@ var EmailCampaigns = class {
|
|
|
4285
4435
|
);
|
|
4286
4436
|
}
|
|
4287
4437
|
async deliveries(campaignId, filters = {}) {
|
|
4288
|
-
return
|
|
4438
|
+
return unwrapList12(
|
|
4289
4439
|
await this.http.get(
|
|
4290
4440
|
`/admin/email-campaigns/${campaignId}/deliveries`,
|
|
4291
4441
|
filters
|
|
@@ -4299,7 +4449,7 @@ var EmailTemplates = class {
|
|
|
4299
4449
|
}
|
|
4300
4450
|
http;
|
|
4301
4451
|
async list(filters = {}) {
|
|
4302
|
-
return
|
|
4452
|
+
return unwrapList12(
|
|
4303
4453
|
await this.http.get("/admin/email-templates", filters)
|
|
4304
4454
|
);
|
|
4305
4455
|
}
|
|
@@ -4331,7 +4481,7 @@ var EmailInbox = class {
|
|
|
4331
4481
|
}
|
|
4332
4482
|
http;
|
|
4333
4483
|
async list(filters = {}) {
|
|
4334
|
-
return
|
|
4484
|
+
return unwrapList12(
|
|
4335
4485
|
await this.http.get("/admin/email-inbox", filters)
|
|
4336
4486
|
);
|
|
4337
4487
|
}
|
|
@@ -5355,49 +5505,49 @@ var OcWorkspaces = class {
|
|
|
5355
5505
|
/**
|
|
5356
5506
|
* Fetch a single workspace.
|
|
5357
5507
|
*/
|
|
5358
|
-
async get(hostId,
|
|
5508
|
+
async get(hostId, workspaceId) {
|
|
5359
5509
|
return this.http.get(
|
|
5360
|
-
`${this.base(hostId)}/${
|
|
5510
|
+
`${this.base(hostId)}/${workspaceId}`
|
|
5361
5511
|
);
|
|
5362
5512
|
}
|
|
5363
5513
|
/**
|
|
5364
5514
|
* Update workspace metadata (name, branch).
|
|
5365
5515
|
*/
|
|
5366
|
-
async update(hostId,
|
|
5516
|
+
async update(hostId, workspaceId, params) {
|
|
5367
5517
|
return this.http.patch(
|
|
5368
|
-
`${this.base(hostId)}/${
|
|
5518
|
+
`${this.base(hostId)}/${workspaceId}`,
|
|
5369
5519
|
params
|
|
5370
5520
|
);
|
|
5371
5521
|
}
|
|
5372
5522
|
/**
|
|
5373
5523
|
* Delete a workspace.
|
|
5374
5524
|
*/
|
|
5375
|
-
async delete(hostId,
|
|
5376
|
-
return this.http.delete(`${this.base(hostId)}/${
|
|
5525
|
+
async delete(hostId, workspaceId) {
|
|
5526
|
+
return this.http.delete(`${this.base(hostId)}/${workspaceId}`);
|
|
5377
5527
|
}
|
|
5378
5528
|
/**
|
|
5379
5529
|
* Pull the latest changes from the remote repository.
|
|
5380
5530
|
*/
|
|
5381
|
-
async pull(hostId,
|
|
5531
|
+
async pull(hostId, workspaceId) {
|
|
5382
5532
|
return this.http.post(
|
|
5383
|
-
`${this.base(hostId)}/${
|
|
5533
|
+
`${this.base(hostId)}/${workspaceId}/pull`
|
|
5384
5534
|
);
|
|
5385
5535
|
}
|
|
5386
5536
|
/**
|
|
5387
5537
|
* Open a terminal session scoped to the workspace root directory.
|
|
5388
5538
|
* Returns a short-lived WebSocket ticket.
|
|
5389
5539
|
*/
|
|
5390
|
-
async openTerminal(hostId,
|
|
5540
|
+
async openTerminal(hostId, workspaceId) {
|
|
5391
5541
|
return this.http.post(
|
|
5392
|
-
`${this.base(hostId)}/${
|
|
5542
|
+
`${this.base(hostId)}/${workspaceId}/open-terminal`
|
|
5393
5543
|
);
|
|
5394
5544
|
}
|
|
5395
5545
|
/**
|
|
5396
5546
|
* Stream workspace setup / clone / install events.
|
|
5397
5547
|
*/
|
|
5398
|
-
events(hostId,
|
|
5548
|
+
events(hostId, workspaceId) {
|
|
5399
5549
|
return this.http.stream(
|
|
5400
|
-
`${this.base(hostId)}/${
|
|
5550
|
+
`${this.base(hostId)}/${workspaceId}/events`
|
|
5401
5551
|
);
|
|
5402
5552
|
}
|
|
5403
5553
|
};
|
|
@@ -6324,6 +6474,7 @@ var Sandbox = class _Sandbox {
|
|
|
6324
6474
|
port: params.port,
|
|
6325
6475
|
health_check_path: params.healthCheckPath ?? params.health_check_path,
|
|
6326
6476
|
deployment_type: params.deploymentType ?? params.deployment_type,
|
|
6477
|
+
docker_deploy_template_id: params.dockerDeployTemplateId ?? params.docker_deploy_template_id,
|
|
6327
6478
|
type: params.type,
|
|
6328
6479
|
mode: params.mode,
|
|
6329
6480
|
database: params.database,
|
|
@@ -6788,7 +6939,7 @@ function unwrap39(data) {
|
|
|
6788
6939
|
}
|
|
6789
6940
|
return data;
|
|
6790
6941
|
}
|
|
6791
|
-
function
|
|
6942
|
+
function unwrapList13(data) {
|
|
6792
6943
|
if (Array.isArray(data)) return data;
|
|
6793
6944
|
if (data && typeof data === "object") {
|
|
6794
6945
|
const d = data;
|
|
@@ -6807,7 +6958,7 @@ var SnapshotsStandalone = class {
|
|
|
6807
6958
|
const query = Object.fromEntries(
|
|
6808
6959
|
Object.entries(filters).filter(([, v]) => v !== void 0)
|
|
6809
6960
|
);
|
|
6810
|
-
return
|
|
6961
|
+
return unwrapList13(await this.http.get("/admin/snapshots", query));
|
|
6811
6962
|
}
|
|
6812
6963
|
async get(snapshotId) {
|
|
6813
6964
|
return unwrap39(
|
|
@@ -7003,96 +7154,22 @@ var OrgInvites = class {
|
|
|
7003
7154
|
function unwrap41(payload) {
|
|
7004
7155
|
if (payload && typeof payload === "object") {
|
|
7005
7156
|
const p = payload;
|
|
7006
|
-
for (const k of ["data", "tenant", "
|
|
7157
|
+
for (const k of ["data", "tenant", "items"]) {
|
|
7007
7158
|
if (k in p) return p[k];
|
|
7008
7159
|
}
|
|
7009
7160
|
}
|
|
7010
7161
|
return payload;
|
|
7011
7162
|
}
|
|
7012
|
-
var PreviewDomain = class {
|
|
7013
|
-
constructor(http) {
|
|
7014
|
-
this.http = http;
|
|
7015
|
-
}
|
|
7016
|
-
http;
|
|
7017
|
-
/** Get the tenant's white-label preview domain settings. */
|
|
7018
|
-
async get() {
|
|
7019
|
-
const data = await this.http.get("/tenant/preview-domain");
|
|
7020
|
-
return unwrap41(data);
|
|
7021
|
-
}
|
|
7022
|
-
/** Set the tenant's white-label preview domain. */
|
|
7023
|
-
async set(domain) {
|
|
7024
|
-
const data = await this.http.put("/tenant/preview-domain", {
|
|
7025
|
-
preview_domain: domain
|
|
7026
|
-
});
|
|
7027
|
-
return unwrap41(data);
|
|
7028
|
-
}
|
|
7029
|
-
/** Re-run DNS verification for the configured preview domain. */
|
|
7030
|
-
async verify() {
|
|
7031
|
-
const data = await this.http.post(
|
|
7032
|
-
"/tenant/preview-domain/verify",
|
|
7033
|
-
{}
|
|
7034
|
-
);
|
|
7035
|
-
return unwrap41(data);
|
|
7036
|
-
}
|
|
7037
|
-
/** Remove the tenant's custom preview domain. */
|
|
7038
|
-
async delete() {
|
|
7039
|
-
await this.http.delete("/tenant/preview-domain");
|
|
7040
|
-
}
|
|
7041
|
-
};
|
|
7042
|
-
var Branding = class {
|
|
7043
|
-
constructor(http) {
|
|
7044
|
-
this.http = http;
|
|
7045
|
-
}
|
|
7046
|
-
http;
|
|
7047
|
-
/** Get tenant branding used by white-label hosted surfaces. */
|
|
7048
|
-
async get() {
|
|
7049
|
-
const data = await this.http.get("/tenant/branding");
|
|
7050
|
-
return unwrap41(data);
|
|
7051
|
-
}
|
|
7052
|
-
/** Update tenant branding used by white-label hosted surfaces. */
|
|
7053
|
-
async set(params) {
|
|
7054
|
-
const body = Object.fromEntries(
|
|
7055
|
-
Object.entries(params).filter(([, v]) => v !== void 0)
|
|
7056
|
-
);
|
|
7057
|
-
const data = await this.http.put("/tenant/branding", {
|
|
7058
|
-
branding: body
|
|
7059
|
-
});
|
|
7060
|
-
return unwrap41(data);
|
|
7061
|
-
}
|
|
7062
|
-
/** Reset tenant branding to platform defaults. */
|
|
7063
|
-
async delete() {
|
|
7064
|
-
await this.http.delete("/tenant/branding");
|
|
7065
|
-
}
|
|
7066
|
-
};
|
|
7067
7163
|
var Tenant = class {
|
|
7068
|
-
http;
|
|
7069
|
-
preview_domain;
|
|
7070
|
-
branding;
|
|
7071
|
-
/** camelCase alias for SDK consumers that avoid snake_case properties. */
|
|
7072
|
-
previewDomain;
|
|
7073
7164
|
constructor(http) {
|
|
7074
7165
|
this.http = http;
|
|
7075
|
-
this.preview_domain = new PreviewDomain(http);
|
|
7076
|
-
this.previewDomain = this.preview_domain;
|
|
7077
|
-
this.branding = new Branding(http);
|
|
7078
7166
|
}
|
|
7167
|
+
http;
|
|
7079
7168
|
/** Get the current tenant's plan, limits, and live usage counters. */
|
|
7080
7169
|
async current() {
|
|
7081
7170
|
const data = await this.http.get("/tenant/plan");
|
|
7082
7171
|
return unwrap41(data);
|
|
7083
7172
|
}
|
|
7084
|
-
/** Convenience alias for `tenant.branding.get()`. */
|
|
7085
|
-
async getBranding() {
|
|
7086
|
-
return this.branding.get();
|
|
7087
|
-
}
|
|
7088
|
-
/** Convenience alias for `tenant.branding.set(...)`. */
|
|
7089
|
-
async setBranding(params) {
|
|
7090
|
-
return this.branding.set(params);
|
|
7091
|
-
}
|
|
7092
|
-
/** Convenience alias for `tenant.branding.delete()`. */
|
|
7093
|
-
async deleteBranding() {
|
|
7094
|
-
await this.branding.delete();
|
|
7095
|
-
}
|
|
7096
7173
|
};
|
|
7097
7174
|
|
|
7098
7175
|
// src/resources/usage.ts
|
|
@@ -7214,35 +7291,43 @@ function stripUndefined25(input) {
|
|
|
7214
7291
|
function idempotencyKey10(key) {
|
|
7215
7292
|
return key ?? randomUUID();
|
|
7216
7293
|
}
|
|
7217
|
-
function
|
|
7218
|
-
|
|
7219
|
-
|
|
7220
|
-
|
|
7221
|
-
|
|
7222
|
-
|
|
7223
|
-
|
|
7224
|
-
|
|
7225
|
-
|
|
7226
|
-
|
|
7227
|
-
|
|
7228
|
-
|
|
7229
|
-
|
|
7230
|
-
if (!Number.isFinite(unixSeconds)) return false;
|
|
7231
|
-
const ageSec = Math.abs(Date.now() / 1e3 - unixSeconds);
|
|
7232
|
-
if (ageSec > toleranceSec) {
|
|
7233
|
-
throw new Error("webhook timestamp too old");
|
|
7234
|
-
}
|
|
7235
|
-
const rawBody = bodyBuffer(body);
|
|
7236
|
-
const signed = Buffer.concat([Buffer.from(`${timestamp}.`), rawBody]);
|
|
7237
|
-
const expected = createHmac("sha256", secret).update(signed).digest("hex");
|
|
7238
|
-
try {
|
|
7239
|
-
return timingSafeEqual(
|
|
7240
|
-
Buffer.from(expected, "utf8"),
|
|
7241
|
-
Buffer.from(received, "utf8")
|
|
7242
|
-
);
|
|
7243
|
-
} catch {
|
|
7244
|
-
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
|
+
}
|
|
7245
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
|
+
});
|
|
7246
7331
|
}
|
|
7247
7332
|
var Webhooks = class {
|
|
7248
7333
|
constructor(http) {
|
|
@@ -7250,6 +7335,7 @@ var Webhooks = class {
|
|
|
7250
7335
|
}
|
|
7251
7336
|
http;
|
|
7252
7337
|
static verifySignature = verifySignature;
|
|
7338
|
+
static verify_signature = verifySignature;
|
|
7253
7339
|
async list(params = {}) {
|
|
7254
7340
|
const query = stripUndefined25({ ...params });
|
|
7255
7341
|
const data = await this.http.get("/webhooks", query);
|
|
@@ -7314,9 +7400,9 @@ var WorkspaceInvites = class {
|
|
|
7314
7400
|
*
|
|
7315
7401
|
* `POST /workspaces/:id/invites`
|
|
7316
7402
|
*/
|
|
7317
|
-
async create(
|
|
7403
|
+
async create(workspaceId, params) {
|
|
7318
7404
|
return this.http.post(
|
|
7319
|
-
`/workspaces/${
|
|
7405
|
+
`/workspaces/${workspaceId}/invites`,
|
|
7320
7406
|
params
|
|
7321
7407
|
);
|
|
7322
7408
|
}
|
|
@@ -7325,9 +7411,9 @@ var WorkspaceInvites = class {
|
|
|
7325
7411
|
*
|
|
7326
7412
|
* `GET /workspaces/:id/invites`
|
|
7327
7413
|
*/
|
|
7328
|
-
async list(
|
|
7414
|
+
async list(workspaceId) {
|
|
7329
7415
|
const res = await this.http.get(
|
|
7330
|
-
`/workspaces/${
|
|
7416
|
+
`/workspaces/${workspaceId}/invites`
|
|
7331
7417
|
);
|
|
7332
7418
|
return res.data ?? [];
|
|
7333
7419
|
}
|
|
@@ -7339,9 +7425,9 @@ var WorkspaceInvites = class {
|
|
|
7339
7425
|
*
|
|
7340
7426
|
* `DELETE /workspaces/:id/invites/:invite_id`
|
|
7341
7427
|
*/
|
|
7342
|
-
async revoke(
|
|
7428
|
+
async revoke(workspaceId, inviteId) {
|
|
7343
7429
|
return this.http.delete(
|
|
7344
|
-
`/workspaces/${
|
|
7430
|
+
`/workspaces/${workspaceId}/invites/${inviteId}`
|
|
7345
7431
|
);
|
|
7346
7432
|
}
|
|
7347
7433
|
/**
|
|
@@ -7395,9 +7481,9 @@ var WorkspaceMembers = class {
|
|
|
7395
7481
|
*
|
|
7396
7482
|
* `GET /workspaces/:id/members`
|
|
7397
7483
|
*/
|
|
7398
|
-
async list(
|
|
7484
|
+
async list(workspaceId) {
|
|
7399
7485
|
const res = await this.http.get(
|
|
7400
|
-
`/workspaces/${
|
|
7486
|
+
`/workspaces/${workspaceId}/members`
|
|
7401
7487
|
);
|
|
7402
7488
|
return res.data ?? res;
|
|
7403
7489
|
}
|
|
@@ -7413,9 +7499,9 @@ var WorkspaceMembers = class {
|
|
|
7413
7499
|
* @throws `MiosaError` with code `NOT_TENANT_MEMBER` if the user is not an
|
|
7414
7500
|
* org member.
|
|
7415
7501
|
*/
|
|
7416
|
-
async add(
|
|
7502
|
+
async add(workspaceId, params) {
|
|
7417
7503
|
const res = await this.http.post(
|
|
7418
|
-
`/workspaces/${
|
|
7504
|
+
`/workspaces/${workspaceId}/members`,
|
|
7419
7505
|
params
|
|
7420
7506
|
);
|
|
7421
7507
|
return res.data ?? res;
|
|
@@ -7425,9 +7511,9 @@ var WorkspaceMembers = class {
|
|
|
7425
7511
|
*
|
|
7426
7512
|
* `PATCH /workspaces/:id/members/:user_id`
|
|
7427
7513
|
*/
|
|
7428
|
-
async updateRole(
|
|
7514
|
+
async updateRole(workspaceId, userId, params) {
|
|
7429
7515
|
const res = await this.http.patch(
|
|
7430
|
-
`/workspaces/${
|
|
7516
|
+
`/workspaces/${workspaceId}/members/${userId}`,
|
|
7431
7517
|
params
|
|
7432
7518
|
);
|
|
7433
7519
|
return res.data ?? res;
|
|
@@ -7442,9 +7528,9 @@ var WorkspaceMembers = class {
|
|
|
7442
7528
|
*
|
|
7443
7529
|
* @throws `MiosaError` with code `LAST_OWNER` if the target is the sole owner.
|
|
7444
7530
|
*/
|
|
7445
|
-
async remove(
|
|
7531
|
+
async remove(workspaceId, userId) {
|
|
7446
7532
|
return this.http.delete(
|
|
7447
|
-
`/workspaces/${
|
|
7533
|
+
`/workspaces/${workspaceId}/members/${userId}`
|
|
7448
7534
|
);
|
|
7449
7535
|
}
|
|
7450
7536
|
};
|
|
@@ -7496,13 +7582,13 @@ var Miosa = class {
|
|
|
7496
7582
|
computers;
|
|
7497
7583
|
/** Sandboxes — native code-execution environments under `/sandboxes`. */
|
|
7498
7584
|
sandboxes;
|
|
7585
|
+
/** Agent device facade — route work across Sandboxes, Computers, and deploy hosts. */
|
|
7586
|
+
devices;
|
|
7499
7587
|
/**
|
|
7500
7588
|
* Deployments — publish from a sandbox to a stable production URL.
|
|
7501
7589
|
* Versions, releases, rollback, custom domains.
|
|
7502
7590
|
*/
|
|
7503
7591
|
deployments;
|
|
7504
|
-
/** Docker Deploy appliance hosts — one always-on workspace host, many apps. */
|
|
7505
|
-
dockerDeploy;
|
|
7506
7592
|
/** Credit balance and usage. */
|
|
7507
7593
|
credits;
|
|
7508
7594
|
/** Admin surface (`/api/v1/admin/*`) — requires an admin credential. */
|
|
@@ -7596,8 +7682,8 @@ var Miosa = class {
|
|
|
7596
7682
|
this.mcp = new Mcp(this.http);
|
|
7597
7683
|
this.computers = new Computers(this.http);
|
|
7598
7684
|
this.sandboxes = new Sandboxes(this.http);
|
|
7685
|
+
this.devices = new Devices(this.http);
|
|
7599
7686
|
this.deployments = new Deployments(this.http);
|
|
7600
|
-
this.dockerDeploy = new DockerDeploy(this.http);
|
|
7601
7687
|
this.credits = new Credits(this.http);
|
|
7602
7688
|
this.admin = new Admin(this.http);
|
|
7603
7689
|
this.openComputers = new OpenComputers(this.http);
|
|
@@ -7627,6 +7713,6 @@ var Miosa = class {
|
|
|
7627
7713
|
}
|
|
7628
7714
|
};
|
|
7629
7715
|
|
|
7630
|
-
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 };
|
|
7631
7717
|
//# sourceMappingURL=index.js.map
|
|
7632
7718
|
//# sourceMappingURL=index.js.map
|