@vm0/runner 3.12.1 → 3.12.3
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/index.js +563 -965
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -48,7 +48,9 @@ var runnerPaths = {
|
|
|
48
48
|
/** Check if a directory name is a VM workspace */
|
|
49
49
|
isVmWorkspace: (dirname) => dirname.startsWith(VM_WORKSPACE_PREFIX),
|
|
50
50
|
/** Extract vmId from workspace directory name */
|
|
51
|
-
extractVmId: (dirname) => createVmId(dirname.replace(VM_WORKSPACE_PREFIX, ""))
|
|
51
|
+
extractVmId: (dirname) => createVmId(dirname.replace(VM_WORKSPACE_PREFIX, "")),
|
|
52
|
+
/** VM registry file for proxy IP → run mapping */
|
|
53
|
+
vmRegistry: (baseDir) => path.join(baseDir, "vm-registry.json")
|
|
52
54
|
};
|
|
53
55
|
var vmPaths = {
|
|
54
56
|
/** Firecracker config file (used with --config-file) */
|
|
@@ -73,8 +75,6 @@ var snapshotOutputPaths = {
|
|
|
73
75
|
var tempPaths = {
|
|
74
76
|
/** Default proxy CA directory */
|
|
75
77
|
proxyDir: `${VM0_TMP_PREFIX}-proxy`,
|
|
76
|
-
/** VM registry for proxy */
|
|
77
|
-
vmRegistry: `${VM0_TMP_PREFIX}-vm-registry.json`,
|
|
78
78
|
/** Network log file for a run */
|
|
79
79
|
networkLog: (runId) => `${VM0_TMP_PREFIX}-network-${runId}.jsonl`
|
|
80
80
|
};
|
|
@@ -7896,10 +7896,109 @@ var secretsByNameContract = c11.router({
|
|
|
7896
7896
|
}
|
|
7897
7897
|
});
|
|
7898
7898
|
|
|
7899
|
-
// ../../packages/core/src/contracts/
|
|
7899
|
+
// ../../packages/core/src/contracts/variables.ts
|
|
7900
7900
|
import { z as z19 } from "zod";
|
|
7901
7901
|
var c12 = initContract();
|
|
7902
|
-
var
|
|
7902
|
+
var variableNameSchema = z19.string().min(1, "Variable name is required").max(255, "Variable name must be at most 255 characters").regex(
|
|
7903
|
+
/^[A-Z][A-Z0-9_]*$/,
|
|
7904
|
+
"Variable name must contain only uppercase letters, numbers, and underscores, and must start with a letter (e.g., MY_VAR)"
|
|
7905
|
+
);
|
|
7906
|
+
var variableResponseSchema = z19.object({
|
|
7907
|
+
id: z19.string().uuid(),
|
|
7908
|
+
name: z19.string(),
|
|
7909
|
+
value: z19.string(),
|
|
7910
|
+
description: z19.string().nullable(),
|
|
7911
|
+
createdAt: z19.string(),
|
|
7912
|
+
updatedAt: z19.string()
|
|
7913
|
+
});
|
|
7914
|
+
var variableListResponseSchema = z19.object({
|
|
7915
|
+
variables: z19.array(variableResponseSchema)
|
|
7916
|
+
});
|
|
7917
|
+
var setVariableRequestSchema = z19.object({
|
|
7918
|
+
name: variableNameSchema,
|
|
7919
|
+
value: z19.string().min(1, "Variable value is required"),
|
|
7920
|
+
description: z19.string().max(1e3).optional()
|
|
7921
|
+
});
|
|
7922
|
+
var variablesMainContract = c12.router({
|
|
7923
|
+
/**
|
|
7924
|
+
* GET /api/variables
|
|
7925
|
+
* List all variables for the current user's scope (includes values)
|
|
7926
|
+
*/
|
|
7927
|
+
list: {
|
|
7928
|
+
method: "GET",
|
|
7929
|
+
path: "/api/variables",
|
|
7930
|
+
headers: authHeadersSchema,
|
|
7931
|
+
responses: {
|
|
7932
|
+
200: variableListResponseSchema,
|
|
7933
|
+
401: apiErrorSchema,
|
|
7934
|
+
500: apiErrorSchema
|
|
7935
|
+
},
|
|
7936
|
+
summary: "List all variables (includes values)"
|
|
7937
|
+
},
|
|
7938
|
+
/**
|
|
7939
|
+
* PUT /api/variables
|
|
7940
|
+
* Create or update a variable
|
|
7941
|
+
*/
|
|
7942
|
+
set: {
|
|
7943
|
+
method: "PUT",
|
|
7944
|
+
path: "/api/variables",
|
|
7945
|
+
headers: authHeadersSchema,
|
|
7946
|
+
body: setVariableRequestSchema,
|
|
7947
|
+
responses: {
|
|
7948
|
+
200: variableResponseSchema,
|
|
7949
|
+
201: variableResponseSchema,
|
|
7950
|
+
400: apiErrorSchema,
|
|
7951
|
+
401: apiErrorSchema,
|
|
7952
|
+
500: apiErrorSchema
|
|
7953
|
+
},
|
|
7954
|
+
summary: "Create or update a variable"
|
|
7955
|
+
}
|
|
7956
|
+
});
|
|
7957
|
+
var variablesByNameContract = c12.router({
|
|
7958
|
+
/**
|
|
7959
|
+
* GET /api/variables/:name
|
|
7960
|
+
* Get a variable by name (includes value)
|
|
7961
|
+
*/
|
|
7962
|
+
get: {
|
|
7963
|
+
method: "GET",
|
|
7964
|
+
path: "/api/variables/:name",
|
|
7965
|
+
headers: authHeadersSchema,
|
|
7966
|
+
pathParams: z19.object({
|
|
7967
|
+
name: variableNameSchema
|
|
7968
|
+
}),
|
|
7969
|
+
responses: {
|
|
7970
|
+
200: variableResponseSchema,
|
|
7971
|
+
401: apiErrorSchema,
|
|
7972
|
+
404: apiErrorSchema,
|
|
7973
|
+
500: apiErrorSchema
|
|
7974
|
+
},
|
|
7975
|
+
summary: "Get variable by name"
|
|
7976
|
+
},
|
|
7977
|
+
/**
|
|
7978
|
+
* DELETE /api/variables/:name
|
|
7979
|
+
* Delete a variable by name
|
|
7980
|
+
*/
|
|
7981
|
+
delete: {
|
|
7982
|
+
method: "DELETE",
|
|
7983
|
+
path: "/api/variables/:name",
|
|
7984
|
+
headers: authHeadersSchema,
|
|
7985
|
+
pathParams: z19.object({
|
|
7986
|
+
name: variableNameSchema
|
|
7987
|
+
}),
|
|
7988
|
+
responses: {
|
|
7989
|
+
204: c12.noBody(),
|
|
7990
|
+
401: apiErrorSchema,
|
|
7991
|
+
404: apiErrorSchema,
|
|
7992
|
+
500: apiErrorSchema
|
|
7993
|
+
},
|
|
7994
|
+
summary: "Delete a variable"
|
|
7995
|
+
}
|
|
7996
|
+
});
|
|
7997
|
+
|
|
7998
|
+
// ../../packages/core/src/contracts/model-providers.ts
|
|
7999
|
+
import { z as z20 } from "zod";
|
|
8000
|
+
var c13 = initContract();
|
|
8001
|
+
var modelProviderTypeSchema = z20.enum([
|
|
7903
8002
|
"claude-code-oauth-token",
|
|
7904
8003
|
"anthropic-api-key",
|
|
7905
8004
|
"openrouter-api-key",
|
|
@@ -7910,46 +8009,46 @@ var modelProviderTypeSchema = z19.enum([
|
|
|
7910
8009
|
"azure-foundry",
|
|
7911
8010
|
"aws-bedrock"
|
|
7912
8011
|
]);
|
|
7913
|
-
var modelProviderFrameworkSchema =
|
|
7914
|
-
var modelProviderResponseSchema =
|
|
7915
|
-
id:
|
|
8012
|
+
var modelProviderFrameworkSchema = z20.enum(["claude-code", "codex"]);
|
|
8013
|
+
var modelProviderResponseSchema = z20.object({
|
|
8014
|
+
id: z20.string().uuid(),
|
|
7916
8015
|
type: modelProviderTypeSchema,
|
|
7917
8016
|
framework: modelProviderFrameworkSchema,
|
|
7918
|
-
credentialName:
|
|
8017
|
+
credentialName: z20.string().nullable(),
|
|
7919
8018
|
// Legacy single-credential (deprecated for multi-auth)
|
|
7920
|
-
authMethod:
|
|
8019
|
+
authMethod: z20.string().nullable(),
|
|
7921
8020
|
// For multi-auth providers
|
|
7922
|
-
credentialNames:
|
|
8021
|
+
credentialNames: z20.array(z20.string()).nullable(),
|
|
7923
8022
|
// For multi-auth providers
|
|
7924
|
-
isDefault:
|
|
7925
|
-
selectedModel:
|
|
7926
|
-
createdAt:
|
|
7927
|
-
updatedAt:
|
|
8023
|
+
isDefault: z20.boolean(),
|
|
8024
|
+
selectedModel: z20.string().nullable(),
|
|
8025
|
+
createdAt: z20.string(),
|
|
8026
|
+
updatedAt: z20.string()
|
|
7928
8027
|
});
|
|
7929
|
-
var modelProviderListResponseSchema =
|
|
7930
|
-
modelProviders:
|
|
8028
|
+
var modelProviderListResponseSchema = z20.object({
|
|
8029
|
+
modelProviders: z20.array(modelProviderResponseSchema)
|
|
7931
8030
|
});
|
|
7932
|
-
var upsertModelProviderRequestSchema =
|
|
8031
|
+
var upsertModelProviderRequestSchema = z20.object({
|
|
7933
8032
|
type: modelProviderTypeSchema,
|
|
7934
|
-
credential:
|
|
8033
|
+
credential: z20.string().min(1).optional(),
|
|
7935
8034
|
// Legacy single credential
|
|
7936
|
-
authMethod:
|
|
8035
|
+
authMethod: z20.string().optional(),
|
|
7937
8036
|
// For multi-auth providers
|
|
7938
|
-
credentials:
|
|
8037
|
+
credentials: z20.record(z20.string(), z20.string()).optional(),
|
|
7939
8038
|
// For multi-auth providers
|
|
7940
|
-
convert:
|
|
7941
|
-
selectedModel:
|
|
8039
|
+
convert: z20.boolean().optional(),
|
|
8040
|
+
selectedModel: z20.string().optional()
|
|
7942
8041
|
});
|
|
7943
|
-
var upsertModelProviderResponseSchema =
|
|
8042
|
+
var upsertModelProviderResponseSchema = z20.object({
|
|
7944
8043
|
provider: modelProviderResponseSchema,
|
|
7945
|
-
created:
|
|
8044
|
+
created: z20.boolean()
|
|
7946
8045
|
});
|
|
7947
|
-
var checkCredentialResponseSchema =
|
|
7948
|
-
exists:
|
|
7949
|
-
credentialName:
|
|
7950
|
-
currentType:
|
|
8046
|
+
var checkCredentialResponseSchema = z20.object({
|
|
8047
|
+
exists: z20.boolean(),
|
|
8048
|
+
credentialName: z20.string(),
|
|
8049
|
+
currentType: z20.enum(["user", "model-provider"]).optional()
|
|
7951
8050
|
});
|
|
7952
|
-
var modelProvidersMainContract =
|
|
8051
|
+
var modelProvidersMainContract = c13.router({
|
|
7953
8052
|
list: {
|
|
7954
8053
|
method: "GET",
|
|
7955
8054
|
path: "/api/model-providers",
|
|
@@ -7977,12 +8076,12 @@ var modelProvidersMainContract = c12.router({
|
|
|
7977
8076
|
summary: "Create or update a model provider"
|
|
7978
8077
|
}
|
|
7979
8078
|
});
|
|
7980
|
-
var modelProvidersCheckContract =
|
|
8079
|
+
var modelProvidersCheckContract = c13.router({
|
|
7981
8080
|
check: {
|
|
7982
8081
|
method: "GET",
|
|
7983
8082
|
path: "/api/model-providers/check/:type",
|
|
7984
8083
|
headers: authHeadersSchema,
|
|
7985
|
-
pathParams:
|
|
8084
|
+
pathParams: z20.object({
|
|
7986
8085
|
type: modelProviderTypeSchema
|
|
7987
8086
|
}),
|
|
7988
8087
|
responses: {
|
|
@@ -7993,16 +8092,16 @@ var modelProvidersCheckContract = c12.router({
|
|
|
7993
8092
|
summary: "Check if credential exists for a model provider type"
|
|
7994
8093
|
}
|
|
7995
8094
|
});
|
|
7996
|
-
var modelProvidersByTypeContract =
|
|
8095
|
+
var modelProvidersByTypeContract = c13.router({
|
|
7997
8096
|
delete: {
|
|
7998
8097
|
method: "DELETE",
|
|
7999
8098
|
path: "/api/model-providers/:type",
|
|
8000
8099
|
headers: authHeadersSchema,
|
|
8001
|
-
pathParams:
|
|
8100
|
+
pathParams: z20.object({
|
|
8002
8101
|
type: modelProviderTypeSchema
|
|
8003
8102
|
}),
|
|
8004
8103
|
responses: {
|
|
8005
|
-
204:
|
|
8104
|
+
204: c13.noBody(),
|
|
8006
8105
|
401: apiErrorSchema,
|
|
8007
8106
|
404: apiErrorSchema,
|
|
8008
8107
|
500: apiErrorSchema
|
|
@@ -8010,15 +8109,15 @@ var modelProvidersByTypeContract = c12.router({
|
|
|
8010
8109
|
summary: "Delete a model provider"
|
|
8011
8110
|
}
|
|
8012
8111
|
});
|
|
8013
|
-
var modelProvidersConvertContract =
|
|
8112
|
+
var modelProvidersConvertContract = c13.router({
|
|
8014
8113
|
convert: {
|
|
8015
8114
|
method: "POST",
|
|
8016
8115
|
path: "/api/model-providers/:type/convert",
|
|
8017
8116
|
headers: authHeadersSchema,
|
|
8018
|
-
pathParams:
|
|
8117
|
+
pathParams: z20.object({
|
|
8019
8118
|
type: modelProviderTypeSchema
|
|
8020
8119
|
}),
|
|
8021
|
-
body:
|
|
8120
|
+
body: z20.undefined(),
|
|
8022
8121
|
responses: {
|
|
8023
8122
|
200: modelProviderResponseSchema,
|
|
8024
8123
|
400: apiErrorSchema,
|
|
@@ -8029,15 +8128,15 @@ var modelProvidersConvertContract = c12.router({
|
|
|
8029
8128
|
summary: "Convert existing user credential to model provider"
|
|
8030
8129
|
}
|
|
8031
8130
|
});
|
|
8032
|
-
var modelProvidersSetDefaultContract =
|
|
8131
|
+
var modelProvidersSetDefaultContract = c13.router({
|
|
8033
8132
|
setDefault: {
|
|
8034
8133
|
method: "POST",
|
|
8035
8134
|
path: "/api/model-providers/:type/set-default",
|
|
8036
8135
|
headers: authHeadersSchema,
|
|
8037
|
-
pathParams:
|
|
8136
|
+
pathParams: z20.object({
|
|
8038
8137
|
type: modelProviderTypeSchema
|
|
8039
8138
|
}),
|
|
8040
|
-
body:
|
|
8139
|
+
body: z20.undefined(),
|
|
8041
8140
|
responses: {
|
|
8042
8141
|
200: modelProviderResponseSchema,
|
|
8043
8142
|
401: apiErrorSchema,
|
|
@@ -8047,15 +8146,15 @@ var modelProvidersSetDefaultContract = c12.router({
|
|
|
8047
8146
|
summary: "Set a model provider as default for its framework"
|
|
8048
8147
|
}
|
|
8049
8148
|
});
|
|
8050
|
-
var updateModelRequestSchema =
|
|
8051
|
-
selectedModel:
|
|
8149
|
+
var updateModelRequestSchema = z20.object({
|
|
8150
|
+
selectedModel: z20.string().optional()
|
|
8052
8151
|
});
|
|
8053
|
-
var modelProvidersUpdateModelContract =
|
|
8152
|
+
var modelProvidersUpdateModelContract = c13.router({
|
|
8054
8153
|
updateModel: {
|
|
8055
8154
|
method: "PATCH",
|
|
8056
8155
|
path: "/api/model-providers/:type/model",
|
|
8057
8156
|
headers: authHeadersSchema,
|
|
8058
|
-
pathParams:
|
|
8157
|
+
pathParams: z20.object({
|
|
8059
8158
|
type: modelProviderTypeSchema
|
|
8060
8159
|
}),
|
|
8061
8160
|
body: updateModelRequestSchema,
|
|
@@ -8070,42 +8169,42 @@ var modelProvidersUpdateModelContract = c12.router({
|
|
|
8070
8169
|
});
|
|
8071
8170
|
|
|
8072
8171
|
// ../../packages/core/src/contracts/sessions.ts
|
|
8073
|
-
import { z as
|
|
8074
|
-
var
|
|
8075
|
-
var sessionResponseSchema =
|
|
8076
|
-
id:
|
|
8077
|
-
agentComposeId:
|
|
8078
|
-
agentComposeVersionId:
|
|
8079
|
-
conversationId:
|
|
8080
|
-
artifactName:
|
|
8081
|
-
vars:
|
|
8082
|
-
secretNames:
|
|
8083
|
-
volumeVersions:
|
|
8084
|
-
createdAt:
|
|
8085
|
-
updatedAt:
|
|
8172
|
+
import { z as z21 } from "zod";
|
|
8173
|
+
var c14 = initContract();
|
|
8174
|
+
var sessionResponseSchema = z21.object({
|
|
8175
|
+
id: z21.string(),
|
|
8176
|
+
agentComposeId: z21.string(),
|
|
8177
|
+
agentComposeVersionId: z21.string().nullable(),
|
|
8178
|
+
conversationId: z21.string().nullable(),
|
|
8179
|
+
artifactName: z21.string().nullable(),
|
|
8180
|
+
vars: z21.record(z21.string(), z21.string()).nullable(),
|
|
8181
|
+
secretNames: z21.array(z21.string()).nullable(),
|
|
8182
|
+
volumeVersions: z21.record(z21.string(), z21.string()).nullable(),
|
|
8183
|
+
createdAt: z21.string(),
|
|
8184
|
+
updatedAt: z21.string()
|
|
8086
8185
|
});
|
|
8087
|
-
var agentComposeSnapshotSchema =
|
|
8088
|
-
agentComposeVersionId:
|
|
8089
|
-
vars:
|
|
8090
|
-
secretNames:
|
|
8186
|
+
var agentComposeSnapshotSchema = z21.object({
|
|
8187
|
+
agentComposeVersionId: z21.string(),
|
|
8188
|
+
vars: z21.record(z21.string(), z21.string()).optional(),
|
|
8189
|
+
secretNames: z21.array(z21.string()).optional()
|
|
8091
8190
|
});
|
|
8092
|
-
var artifactSnapshotSchema2 =
|
|
8093
|
-
artifactName:
|
|
8094
|
-
artifactVersion:
|
|
8191
|
+
var artifactSnapshotSchema2 = z21.object({
|
|
8192
|
+
artifactName: z21.string(),
|
|
8193
|
+
artifactVersion: z21.string()
|
|
8095
8194
|
});
|
|
8096
|
-
var volumeVersionsSnapshotSchema2 =
|
|
8097
|
-
versions:
|
|
8195
|
+
var volumeVersionsSnapshotSchema2 = z21.object({
|
|
8196
|
+
versions: z21.record(z21.string(), z21.string())
|
|
8098
8197
|
});
|
|
8099
|
-
var checkpointResponseSchema =
|
|
8100
|
-
id:
|
|
8101
|
-
runId:
|
|
8102
|
-
conversationId:
|
|
8198
|
+
var checkpointResponseSchema = z21.object({
|
|
8199
|
+
id: z21.string(),
|
|
8200
|
+
runId: z21.string(),
|
|
8201
|
+
conversationId: z21.string(),
|
|
8103
8202
|
agentComposeSnapshot: agentComposeSnapshotSchema,
|
|
8104
8203
|
artifactSnapshot: artifactSnapshotSchema2.nullable(),
|
|
8105
8204
|
volumeVersionsSnapshot: volumeVersionsSnapshotSchema2.nullable(),
|
|
8106
|
-
createdAt:
|
|
8205
|
+
createdAt: z21.string()
|
|
8107
8206
|
});
|
|
8108
|
-
var sessionsByIdContract =
|
|
8207
|
+
var sessionsByIdContract = c14.router({
|
|
8109
8208
|
/**
|
|
8110
8209
|
* GET /api/agent/sessions/:id
|
|
8111
8210
|
* Get session by ID
|
|
@@ -8114,8 +8213,8 @@ var sessionsByIdContract = c13.router({
|
|
|
8114
8213
|
method: "GET",
|
|
8115
8214
|
path: "/api/agent/sessions/:id",
|
|
8116
8215
|
headers: authHeadersSchema,
|
|
8117
|
-
pathParams:
|
|
8118
|
-
id:
|
|
8216
|
+
pathParams: z21.object({
|
|
8217
|
+
id: z21.string().min(1, "Session ID is required")
|
|
8119
8218
|
}),
|
|
8120
8219
|
responses: {
|
|
8121
8220
|
200: sessionResponseSchema,
|
|
@@ -8126,7 +8225,7 @@ var sessionsByIdContract = c13.router({
|
|
|
8126
8225
|
summary: "Get session by ID"
|
|
8127
8226
|
}
|
|
8128
8227
|
});
|
|
8129
|
-
var checkpointsByIdContract =
|
|
8228
|
+
var checkpointsByIdContract = c14.router({
|
|
8130
8229
|
/**
|
|
8131
8230
|
* GET /api/agent/checkpoints/:id
|
|
8132
8231
|
* Get checkpoint by ID
|
|
@@ -8135,8 +8234,8 @@ var checkpointsByIdContract = c13.router({
|
|
|
8135
8234
|
method: "GET",
|
|
8136
8235
|
path: "/api/agent/checkpoints/:id",
|
|
8137
8236
|
headers: authHeadersSchema,
|
|
8138
|
-
pathParams:
|
|
8139
|
-
id:
|
|
8237
|
+
pathParams: z21.object({
|
|
8238
|
+
id: z21.string().min(1, "Checkpoint ID is required")
|
|
8140
8239
|
}),
|
|
8141
8240
|
responses: {
|
|
8142
8241
|
200: checkpointResponseSchema,
|
|
@@ -8149,93 +8248,93 @@ var checkpointsByIdContract = c13.router({
|
|
|
8149
8248
|
});
|
|
8150
8249
|
|
|
8151
8250
|
// ../../packages/core/src/contracts/schedules.ts
|
|
8152
|
-
import { z as
|
|
8153
|
-
var
|
|
8154
|
-
var scheduleTriggerSchema =
|
|
8155
|
-
cron:
|
|
8156
|
-
at:
|
|
8157
|
-
timezone:
|
|
8251
|
+
import { z as z22 } from "zod";
|
|
8252
|
+
var c15 = initContract();
|
|
8253
|
+
var scheduleTriggerSchema = z22.object({
|
|
8254
|
+
cron: z22.string().optional(),
|
|
8255
|
+
at: z22.string().optional(),
|
|
8256
|
+
timezone: z22.string().default("UTC")
|
|
8158
8257
|
}).refine((data) => data.cron && !data.at || !data.cron && data.at, {
|
|
8159
8258
|
message: "Exactly one of 'cron' or 'at' must be specified"
|
|
8160
8259
|
});
|
|
8161
|
-
var scheduleRunConfigSchema =
|
|
8162
|
-
agent:
|
|
8163
|
-
prompt:
|
|
8164
|
-
vars:
|
|
8165
|
-
secrets:
|
|
8166
|
-
artifactName:
|
|
8167
|
-
artifactVersion:
|
|
8168
|
-
volumeVersions:
|
|
8260
|
+
var scheduleRunConfigSchema = z22.object({
|
|
8261
|
+
agent: z22.string().min(1, "Agent reference required"),
|
|
8262
|
+
prompt: z22.string().min(1, "Prompt required"),
|
|
8263
|
+
vars: z22.record(z22.string(), z22.string()).optional(),
|
|
8264
|
+
secrets: z22.record(z22.string(), z22.string()).optional(),
|
|
8265
|
+
artifactName: z22.string().optional(),
|
|
8266
|
+
artifactVersion: z22.string().optional(),
|
|
8267
|
+
volumeVersions: z22.record(z22.string(), z22.string()).optional()
|
|
8169
8268
|
});
|
|
8170
|
-
var scheduleDefinitionSchema =
|
|
8269
|
+
var scheduleDefinitionSchema = z22.object({
|
|
8171
8270
|
on: scheduleTriggerSchema,
|
|
8172
8271
|
run: scheduleRunConfigSchema
|
|
8173
8272
|
});
|
|
8174
|
-
var scheduleYamlSchema =
|
|
8175
|
-
version:
|
|
8176
|
-
schedules:
|
|
8177
|
-
});
|
|
8178
|
-
var deployScheduleRequestSchema =
|
|
8179
|
-
name:
|
|
8180
|
-
cronExpression:
|
|
8181
|
-
atTime:
|
|
8182
|
-
timezone:
|
|
8183
|
-
prompt:
|
|
8184
|
-
vars:
|
|
8185
|
-
secrets:
|
|
8186
|
-
artifactName:
|
|
8187
|
-
artifactVersion:
|
|
8188
|
-
volumeVersions:
|
|
8273
|
+
var scheduleYamlSchema = z22.object({
|
|
8274
|
+
version: z22.literal("1.0"),
|
|
8275
|
+
schedules: z22.record(z22.string(), scheduleDefinitionSchema)
|
|
8276
|
+
});
|
|
8277
|
+
var deployScheduleRequestSchema = z22.object({
|
|
8278
|
+
name: z22.string().min(1).max(64, "Schedule name max 64 chars"),
|
|
8279
|
+
cronExpression: z22.string().optional(),
|
|
8280
|
+
atTime: z22.string().optional(),
|
|
8281
|
+
timezone: z22.string().default("UTC"),
|
|
8282
|
+
prompt: z22.string().min(1, "Prompt required"),
|
|
8283
|
+
vars: z22.record(z22.string(), z22.string()).optional(),
|
|
8284
|
+
secrets: z22.record(z22.string(), z22.string()).optional(),
|
|
8285
|
+
artifactName: z22.string().optional(),
|
|
8286
|
+
artifactVersion: z22.string().optional(),
|
|
8287
|
+
volumeVersions: z22.record(z22.string(), z22.string()).optional(),
|
|
8189
8288
|
// Resolved agent compose ID (CLI resolves scope/name:version → composeId)
|
|
8190
|
-
composeId:
|
|
8289
|
+
composeId: z22.string().uuid("Invalid compose ID")
|
|
8191
8290
|
}).refine(
|
|
8192
8291
|
(data) => data.cronExpression && !data.atTime || !data.cronExpression && data.atTime,
|
|
8193
8292
|
{
|
|
8194
8293
|
message: "Exactly one of 'cronExpression' or 'atTime' must be specified"
|
|
8195
8294
|
}
|
|
8196
8295
|
);
|
|
8197
|
-
var scheduleResponseSchema =
|
|
8198
|
-
id:
|
|
8199
|
-
composeId:
|
|
8200
|
-
composeName:
|
|
8201
|
-
scopeSlug:
|
|
8202
|
-
name:
|
|
8203
|
-
cronExpression:
|
|
8204
|
-
atTime:
|
|
8205
|
-
timezone:
|
|
8206
|
-
prompt:
|
|
8207
|
-
vars:
|
|
8296
|
+
var scheduleResponseSchema = z22.object({
|
|
8297
|
+
id: z22.string().uuid(),
|
|
8298
|
+
composeId: z22.string().uuid(),
|
|
8299
|
+
composeName: z22.string(),
|
|
8300
|
+
scopeSlug: z22.string(),
|
|
8301
|
+
name: z22.string(),
|
|
8302
|
+
cronExpression: z22.string().nullable(),
|
|
8303
|
+
atTime: z22.string().nullable(),
|
|
8304
|
+
timezone: z22.string(),
|
|
8305
|
+
prompt: z22.string(),
|
|
8306
|
+
vars: z22.record(z22.string(), z22.string()).nullable(),
|
|
8208
8307
|
// Secret names only (values are never returned)
|
|
8209
|
-
secretNames:
|
|
8210
|
-
artifactName:
|
|
8211
|
-
artifactVersion:
|
|
8212
|
-
volumeVersions:
|
|
8213
|
-
enabled:
|
|
8214
|
-
nextRunAt:
|
|
8215
|
-
lastRunAt:
|
|
8216
|
-
retryStartedAt:
|
|
8217
|
-
createdAt:
|
|
8218
|
-
updatedAt:
|
|
8219
|
-
});
|
|
8220
|
-
var runSummarySchema =
|
|
8221
|
-
id:
|
|
8222
|
-
status:
|
|
8223
|
-
createdAt:
|
|
8224
|
-
completedAt:
|
|
8225
|
-
error:
|
|
8226
|
-
});
|
|
8227
|
-
var scheduleRunsResponseSchema =
|
|
8228
|
-
runs:
|
|
8229
|
-
});
|
|
8230
|
-
var scheduleListResponseSchema =
|
|
8231
|
-
schedules:
|
|
8232
|
-
});
|
|
8233
|
-
var deployScheduleResponseSchema =
|
|
8308
|
+
secretNames: z22.array(z22.string()).nullable(),
|
|
8309
|
+
artifactName: z22.string().nullable(),
|
|
8310
|
+
artifactVersion: z22.string().nullable(),
|
|
8311
|
+
volumeVersions: z22.record(z22.string(), z22.string()).nullable(),
|
|
8312
|
+
enabled: z22.boolean(),
|
|
8313
|
+
nextRunAt: z22.string().nullable(),
|
|
8314
|
+
lastRunAt: z22.string().nullable(),
|
|
8315
|
+
retryStartedAt: z22.string().nullable(),
|
|
8316
|
+
createdAt: z22.string(),
|
|
8317
|
+
updatedAt: z22.string()
|
|
8318
|
+
});
|
|
8319
|
+
var runSummarySchema = z22.object({
|
|
8320
|
+
id: z22.string().uuid(),
|
|
8321
|
+
status: z22.enum(["pending", "running", "completed", "failed", "timeout"]),
|
|
8322
|
+
createdAt: z22.string(),
|
|
8323
|
+
completedAt: z22.string().nullable(),
|
|
8324
|
+
error: z22.string().nullable()
|
|
8325
|
+
});
|
|
8326
|
+
var scheduleRunsResponseSchema = z22.object({
|
|
8327
|
+
runs: z22.array(runSummarySchema)
|
|
8328
|
+
});
|
|
8329
|
+
var scheduleListResponseSchema = z22.object({
|
|
8330
|
+
schedules: z22.array(scheduleResponseSchema)
|
|
8331
|
+
});
|
|
8332
|
+
var deployScheduleResponseSchema = z22.object({
|
|
8234
8333
|
schedule: scheduleResponseSchema,
|
|
8235
|
-
created:
|
|
8334
|
+
created: z22.boolean()
|
|
8236
8335
|
// true if created, false if updated
|
|
8237
8336
|
});
|
|
8238
|
-
var schedulesMainContract =
|
|
8337
|
+
var schedulesMainContract = c15.router({
|
|
8239
8338
|
/**
|
|
8240
8339
|
* POST /api/agent/schedules
|
|
8241
8340
|
* Deploy (create or update) a schedule
|
|
@@ -8273,7 +8372,7 @@ var schedulesMainContract = c14.router({
|
|
|
8273
8372
|
summary: "List all schedules"
|
|
8274
8373
|
}
|
|
8275
8374
|
});
|
|
8276
|
-
var schedulesByNameContract =
|
|
8375
|
+
var schedulesByNameContract = c15.router({
|
|
8277
8376
|
/**
|
|
8278
8377
|
* GET /api/agent/schedules/:name
|
|
8279
8378
|
* Get schedule by name
|
|
@@ -8282,11 +8381,11 @@ var schedulesByNameContract = c14.router({
|
|
|
8282
8381
|
method: "GET",
|
|
8283
8382
|
path: "/api/agent/schedules/:name",
|
|
8284
8383
|
headers: authHeadersSchema,
|
|
8285
|
-
pathParams:
|
|
8286
|
-
name:
|
|
8384
|
+
pathParams: z22.object({
|
|
8385
|
+
name: z22.string().min(1, "Schedule name required")
|
|
8287
8386
|
}),
|
|
8288
|
-
query:
|
|
8289
|
-
composeId:
|
|
8387
|
+
query: z22.object({
|
|
8388
|
+
composeId: z22.string().uuid("Compose ID required")
|
|
8290
8389
|
}),
|
|
8291
8390
|
responses: {
|
|
8292
8391
|
200: scheduleResponseSchema,
|
|
@@ -8303,21 +8402,21 @@ var schedulesByNameContract = c14.router({
|
|
|
8303
8402
|
method: "DELETE",
|
|
8304
8403
|
path: "/api/agent/schedules/:name",
|
|
8305
8404
|
headers: authHeadersSchema,
|
|
8306
|
-
pathParams:
|
|
8307
|
-
name:
|
|
8405
|
+
pathParams: z22.object({
|
|
8406
|
+
name: z22.string().min(1, "Schedule name required")
|
|
8308
8407
|
}),
|
|
8309
|
-
query:
|
|
8310
|
-
composeId:
|
|
8408
|
+
query: z22.object({
|
|
8409
|
+
composeId: z22.string().uuid("Compose ID required")
|
|
8311
8410
|
}),
|
|
8312
8411
|
responses: {
|
|
8313
|
-
204:
|
|
8412
|
+
204: c15.noBody(),
|
|
8314
8413
|
401: apiErrorSchema,
|
|
8315
8414
|
404: apiErrorSchema
|
|
8316
8415
|
},
|
|
8317
8416
|
summary: "Delete schedule"
|
|
8318
8417
|
}
|
|
8319
8418
|
});
|
|
8320
|
-
var schedulesEnableContract =
|
|
8419
|
+
var schedulesEnableContract = c15.router({
|
|
8321
8420
|
/**
|
|
8322
8421
|
* POST /api/agent/schedules/:name/enable
|
|
8323
8422
|
* Enable a disabled schedule
|
|
@@ -8326,11 +8425,11 @@ var schedulesEnableContract = c14.router({
|
|
|
8326
8425
|
method: "POST",
|
|
8327
8426
|
path: "/api/agent/schedules/:name/enable",
|
|
8328
8427
|
headers: authHeadersSchema,
|
|
8329
|
-
pathParams:
|
|
8330
|
-
name:
|
|
8428
|
+
pathParams: z22.object({
|
|
8429
|
+
name: z22.string().min(1, "Schedule name required")
|
|
8331
8430
|
}),
|
|
8332
|
-
body:
|
|
8333
|
-
composeId:
|
|
8431
|
+
body: z22.object({
|
|
8432
|
+
composeId: z22.string().uuid("Compose ID required")
|
|
8334
8433
|
}),
|
|
8335
8434
|
responses: {
|
|
8336
8435
|
200: scheduleResponseSchema,
|
|
@@ -8347,11 +8446,11 @@ var schedulesEnableContract = c14.router({
|
|
|
8347
8446
|
method: "POST",
|
|
8348
8447
|
path: "/api/agent/schedules/:name/disable",
|
|
8349
8448
|
headers: authHeadersSchema,
|
|
8350
|
-
pathParams:
|
|
8351
|
-
name:
|
|
8449
|
+
pathParams: z22.object({
|
|
8450
|
+
name: z22.string().min(1, "Schedule name required")
|
|
8352
8451
|
}),
|
|
8353
|
-
body:
|
|
8354
|
-
composeId:
|
|
8452
|
+
body: z22.object({
|
|
8453
|
+
composeId: z22.string().uuid("Compose ID required")
|
|
8355
8454
|
}),
|
|
8356
8455
|
responses: {
|
|
8357
8456
|
200: scheduleResponseSchema,
|
|
@@ -8361,7 +8460,7 @@ var schedulesEnableContract = c14.router({
|
|
|
8361
8460
|
summary: "Disable schedule"
|
|
8362
8461
|
}
|
|
8363
8462
|
});
|
|
8364
|
-
var scheduleRunsContract =
|
|
8463
|
+
var scheduleRunsContract = c15.router({
|
|
8365
8464
|
/**
|
|
8366
8465
|
* GET /api/agent/schedules/:name/runs
|
|
8367
8466
|
* List recent runs for a schedule
|
|
@@ -8370,12 +8469,12 @@ var scheduleRunsContract = c14.router({
|
|
|
8370
8469
|
method: "GET",
|
|
8371
8470
|
path: "/api/agent/schedules/:name/runs",
|
|
8372
8471
|
headers: authHeadersSchema,
|
|
8373
|
-
pathParams:
|
|
8374
|
-
name:
|
|
8472
|
+
pathParams: z22.object({
|
|
8473
|
+
name: z22.string().min(1, "Schedule name required")
|
|
8375
8474
|
}),
|
|
8376
|
-
query:
|
|
8377
|
-
composeId:
|
|
8378
|
-
limit:
|
|
8475
|
+
query: z22.object({
|
|
8476
|
+
composeId: z22.string().uuid("Compose ID required"),
|
|
8477
|
+
limit: z22.coerce.number().min(0).max(100).default(5)
|
|
8379
8478
|
}),
|
|
8380
8479
|
responses: {
|
|
8381
8480
|
200: scheduleRunsResponseSchema,
|
|
@@ -8387,18 +8486,18 @@ var scheduleRunsContract = c14.router({
|
|
|
8387
8486
|
});
|
|
8388
8487
|
|
|
8389
8488
|
// ../../packages/core/src/contracts/realtime.ts
|
|
8390
|
-
import { z as
|
|
8391
|
-
var
|
|
8392
|
-
var ablyTokenRequestSchema =
|
|
8393
|
-
keyName:
|
|
8394
|
-
ttl:
|
|
8395
|
-
timestamp:
|
|
8396
|
-
capability:
|
|
8397
|
-
clientId:
|
|
8398
|
-
nonce:
|
|
8399
|
-
mac:
|
|
8489
|
+
import { z as z23 } from "zod";
|
|
8490
|
+
var c16 = initContract();
|
|
8491
|
+
var ablyTokenRequestSchema = z23.object({
|
|
8492
|
+
keyName: z23.string(),
|
|
8493
|
+
ttl: z23.number().optional(),
|
|
8494
|
+
timestamp: z23.number(),
|
|
8495
|
+
capability: z23.string(),
|
|
8496
|
+
clientId: z23.string().optional(),
|
|
8497
|
+
nonce: z23.string(),
|
|
8498
|
+
mac: z23.string()
|
|
8400
8499
|
});
|
|
8401
|
-
var realtimeTokenContract =
|
|
8500
|
+
var realtimeTokenContract = c16.router({
|
|
8402
8501
|
/**
|
|
8403
8502
|
* POST /api/realtime/token
|
|
8404
8503
|
* Get an Ably token to subscribe to a run's events channel
|
|
@@ -8407,8 +8506,8 @@ var realtimeTokenContract = c15.router({
|
|
|
8407
8506
|
method: "POST",
|
|
8408
8507
|
path: "/api/realtime/token",
|
|
8409
8508
|
headers: authHeadersSchema,
|
|
8410
|
-
body:
|
|
8411
|
-
runId:
|
|
8509
|
+
body: z23.object({
|
|
8510
|
+
runId: z23.string().uuid("runId must be a valid UUID")
|
|
8412
8511
|
}),
|
|
8413
8512
|
responses: {
|
|
8414
8513
|
200: ablyTokenRequestSchema,
|
|
@@ -8420,7 +8519,7 @@ var realtimeTokenContract = c15.router({
|
|
|
8420
8519
|
summary: "Get Ably token for run event subscription"
|
|
8421
8520
|
}
|
|
8422
8521
|
});
|
|
8423
|
-
var runnerRealtimeTokenContract =
|
|
8522
|
+
var runnerRealtimeTokenContract = c16.router({
|
|
8424
8523
|
/**
|
|
8425
8524
|
* POST /api/runners/realtime/token
|
|
8426
8525
|
* Get an Ably token to subscribe to a runner group's job notification channel
|
|
@@ -8429,7 +8528,7 @@ var runnerRealtimeTokenContract = c15.router({
|
|
|
8429
8528
|
method: "POST",
|
|
8430
8529
|
path: "/api/runners/realtime/token",
|
|
8431
8530
|
headers: authHeadersSchema,
|
|
8432
|
-
body:
|
|
8531
|
+
body: z23.object({
|
|
8433
8532
|
group: runnerGroupSchema
|
|
8434
8533
|
}),
|
|
8435
8534
|
responses: {
|
|
@@ -8443,11 +8542,11 @@ var runnerRealtimeTokenContract = c15.router({
|
|
|
8443
8542
|
});
|
|
8444
8543
|
|
|
8445
8544
|
// ../../packages/core/src/contracts/platform.ts
|
|
8446
|
-
import { z as
|
|
8545
|
+
import { z as z25 } from "zod";
|
|
8447
8546
|
|
|
8448
8547
|
// ../../packages/core/src/contracts/public/common.ts
|
|
8449
|
-
import { z as
|
|
8450
|
-
var publicApiErrorTypeSchema =
|
|
8548
|
+
import { z as z24 } from "zod";
|
|
8549
|
+
var publicApiErrorTypeSchema = z24.enum([
|
|
8451
8550
|
"api_error",
|
|
8452
8551
|
// Internal server error (5xx)
|
|
8453
8552
|
"invalid_request_error",
|
|
@@ -8461,40 +8560,40 @@ var publicApiErrorTypeSchema = z23.enum([
|
|
|
8461
8560
|
"rate_limit_error"
|
|
8462
8561
|
// Rate limit exceeded (429)
|
|
8463
8562
|
]);
|
|
8464
|
-
var publicApiErrorSchema =
|
|
8465
|
-
error:
|
|
8563
|
+
var publicApiErrorSchema = z24.object({
|
|
8564
|
+
error: z24.object({
|
|
8466
8565
|
type: publicApiErrorTypeSchema,
|
|
8467
|
-
code:
|
|
8468
|
-
message:
|
|
8469
|
-
param:
|
|
8470
|
-
docUrl:
|
|
8566
|
+
code: z24.string(),
|
|
8567
|
+
message: z24.string(),
|
|
8568
|
+
param: z24.string().optional(),
|
|
8569
|
+
docUrl: z24.string().url().optional()
|
|
8471
8570
|
})
|
|
8472
8571
|
});
|
|
8473
|
-
var paginationSchema =
|
|
8474
|
-
hasMore:
|
|
8475
|
-
nextCursor:
|
|
8572
|
+
var paginationSchema = z24.object({
|
|
8573
|
+
hasMore: z24.boolean(),
|
|
8574
|
+
nextCursor: z24.string().nullable()
|
|
8476
8575
|
});
|
|
8477
8576
|
function createPaginatedResponseSchema(dataSchema) {
|
|
8478
|
-
return
|
|
8479
|
-
data:
|
|
8577
|
+
return z24.object({
|
|
8578
|
+
data: z24.array(dataSchema),
|
|
8480
8579
|
pagination: paginationSchema
|
|
8481
8580
|
});
|
|
8482
8581
|
}
|
|
8483
|
-
var listQuerySchema =
|
|
8484
|
-
cursor:
|
|
8485
|
-
limit:
|
|
8582
|
+
var listQuerySchema = z24.object({
|
|
8583
|
+
cursor: z24.string().optional(),
|
|
8584
|
+
limit: z24.coerce.number().min(1).max(100).default(20)
|
|
8486
8585
|
});
|
|
8487
|
-
var requestIdSchema =
|
|
8488
|
-
var timestampSchema =
|
|
8586
|
+
var requestIdSchema = z24.string().uuid();
|
|
8587
|
+
var timestampSchema = z24.string().datetime();
|
|
8489
8588
|
|
|
8490
8589
|
// ../../packages/core/src/contracts/platform.ts
|
|
8491
|
-
var
|
|
8492
|
-
var platformPaginationSchema =
|
|
8493
|
-
hasMore:
|
|
8494
|
-
nextCursor:
|
|
8495
|
-
totalPages:
|
|
8590
|
+
var c17 = initContract();
|
|
8591
|
+
var platformPaginationSchema = z25.object({
|
|
8592
|
+
hasMore: z25.boolean(),
|
|
8593
|
+
nextCursor: z25.string().nullable(),
|
|
8594
|
+
totalPages: z25.number()
|
|
8496
8595
|
});
|
|
8497
|
-
var platformLogStatusSchema =
|
|
8596
|
+
var platformLogStatusSchema = z25.enum([
|
|
8498
8597
|
"pending",
|
|
8499
8598
|
"running",
|
|
8500
8599
|
"completed",
|
|
@@ -8502,41 +8601,41 @@ var platformLogStatusSchema = z24.enum([
|
|
|
8502
8601
|
"timeout",
|
|
8503
8602
|
"cancelled"
|
|
8504
8603
|
]);
|
|
8505
|
-
var platformLogEntrySchema =
|
|
8506
|
-
id:
|
|
8507
|
-
sessionId:
|
|
8508
|
-
agentName:
|
|
8509
|
-
framework:
|
|
8604
|
+
var platformLogEntrySchema = z25.object({
|
|
8605
|
+
id: z25.string().uuid(),
|
|
8606
|
+
sessionId: z25.string().nullable(),
|
|
8607
|
+
agentName: z25.string(),
|
|
8608
|
+
framework: z25.string().nullable(),
|
|
8510
8609
|
status: platformLogStatusSchema,
|
|
8511
|
-
createdAt:
|
|
8610
|
+
createdAt: z25.string()
|
|
8512
8611
|
});
|
|
8513
|
-
var platformLogsListResponseSchema =
|
|
8514
|
-
data:
|
|
8612
|
+
var platformLogsListResponseSchema = z25.object({
|
|
8613
|
+
data: z25.array(platformLogEntrySchema),
|
|
8515
8614
|
pagination: platformPaginationSchema
|
|
8516
8615
|
});
|
|
8517
|
-
var artifactSchema =
|
|
8518
|
-
name:
|
|
8519
|
-
version:
|
|
8616
|
+
var artifactSchema = z25.object({
|
|
8617
|
+
name: z25.string().nullable(),
|
|
8618
|
+
version: z25.string().nullable()
|
|
8520
8619
|
});
|
|
8521
|
-
var platformLogDetailSchema =
|
|
8522
|
-
id:
|
|
8523
|
-
sessionId:
|
|
8524
|
-
agentName:
|
|
8525
|
-
framework:
|
|
8620
|
+
var platformLogDetailSchema = z25.object({
|
|
8621
|
+
id: z25.string().uuid(),
|
|
8622
|
+
sessionId: z25.string().nullable(),
|
|
8623
|
+
agentName: z25.string(),
|
|
8624
|
+
framework: z25.string().nullable(),
|
|
8526
8625
|
status: platformLogStatusSchema,
|
|
8527
|
-
prompt:
|
|
8528
|
-
error:
|
|
8529
|
-
createdAt:
|
|
8530
|
-
startedAt:
|
|
8531
|
-
completedAt:
|
|
8626
|
+
prompt: z25.string(),
|
|
8627
|
+
error: z25.string().nullable(),
|
|
8628
|
+
createdAt: z25.string(),
|
|
8629
|
+
startedAt: z25.string().nullable(),
|
|
8630
|
+
completedAt: z25.string().nullable(),
|
|
8532
8631
|
artifact: artifactSchema
|
|
8533
8632
|
});
|
|
8534
|
-
var platformLogsListContract =
|
|
8633
|
+
var platformLogsListContract = c17.router({
|
|
8535
8634
|
list: {
|
|
8536
8635
|
method: "GET",
|
|
8537
8636
|
path: "/api/platform/logs",
|
|
8538
8637
|
query: listQuerySchema.extend({
|
|
8539
|
-
search:
|
|
8638
|
+
search: z25.string().optional()
|
|
8540
8639
|
}),
|
|
8541
8640
|
responses: {
|
|
8542
8641
|
200: platformLogsListResponseSchema,
|
|
@@ -8545,12 +8644,12 @@ var platformLogsListContract = c16.router({
|
|
|
8545
8644
|
summary: "List agent run logs with pagination"
|
|
8546
8645
|
}
|
|
8547
8646
|
});
|
|
8548
|
-
var platformLogsByIdContract =
|
|
8647
|
+
var platformLogsByIdContract = c17.router({
|
|
8549
8648
|
getById: {
|
|
8550
8649
|
method: "GET",
|
|
8551
8650
|
path: "/api/platform/logs/:id",
|
|
8552
|
-
pathParams:
|
|
8553
|
-
id:
|
|
8651
|
+
pathParams: z25.object({
|
|
8652
|
+
id: z25.string().uuid("Invalid log ID")
|
|
8554
8653
|
}),
|
|
8555
8654
|
responses: {
|
|
8556
8655
|
200: platformLogDetailSchema,
|
|
@@ -8560,17 +8659,17 @@ var platformLogsByIdContract = c16.router({
|
|
|
8560
8659
|
summary: "Get agent run log details by ID"
|
|
8561
8660
|
}
|
|
8562
8661
|
});
|
|
8563
|
-
var artifactDownloadResponseSchema =
|
|
8564
|
-
url:
|
|
8565
|
-
expiresAt:
|
|
8662
|
+
var artifactDownloadResponseSchema = z25.object({
|
|
8663
|
+
url: z25.string().url(),
|
|
8664
|
+
expiresAt: z25.string()
|
|
8566
8665
|
});
|
|
8567
|
-
var platformArtifactDownloadContract =
|
|
8666
|
+
var platformArtifactDownloadContract = c17.router({
|
|
8568
8667
|
getDownloadUrl: {
|
|
8569
8668
|
method: "GET",
|
|
8570
8669
|
path: "/api/platform/artifacts/download",
|
|
8571
|
-
query:
|
|
8572
|
-
name:
|
|
8573
|
-
version:
|
|
8670
|
+
query: z25.object({
|
|
8671
|
+
name: z25.string().min(1, "Artifact name is required"),
|
|
8672
|
+
version: z25.string().optional()
|
|
8574
8673
|
}),
|
|
8575
8674
|
responses: {
|
|
8576
8675
|
200: artifactDownloadResponseSchema,
|
|
@@ -8582,29 +8681,29 @@ var platformArtifactDownloadContract = c16.router({
|
|
|
8582
8681
|
});
|
|
8583
8682
|
|
|
8584
8683
|
// ../../packages/core/src/contracts/llm.ts
|
|
8585
|
-
import { z as
|
|
8586
|
-
var
|
|
8587
|
-
var messageRoleSchema =
|
|
8588
|
-
var chatMessageSchema =
|
|
8684
|
+
import { z as z26 } from "zod";
|
|
8685
|
+
var c18 = initContract();
|
|
8686
|
+
var messageRoleSchema = z26.enum(["user", "assistant", "system"]);
|
|
8687
|
+
var chatMessageSchema = z26.object({
|
|
8589
8688
|
role: messageRoleSchema,
|
|
8590
|
-
content:
|
|
8689
|
+
content: z26.string()
|
|
8591
8690
|
});
|
|
8592
|
-
var tokenUsageSchema =
|
|
8593
|
-
promptTokens:
|
|
8594
|
-
completionTokens:
|
|
8595
|
-
totalTokens:
|
|
8691
|
+
var tokenUsageSchema = z26.object({
|
|
8692
|
+
promptTokens: z26.number(),
|
|
8693
|
+
completionTokens: z26.number(),
|
|
8694
|
+
totalTokens: z26.number()
|
|
8596
8695
|
});
|
|
8597
|
-
var llmChatRequestSchema =
|
|
8598
|
-
model:
|
|
8599
|
-
messages:
|
|
8600
|
-
stream:
|
|
8696
|
+
var llmChatRequestSchema = z26.object({
|
|
8697
|
+
model: z26.string().min(1).optional(),
|
|
8698
|
+
messages: z26.array(chatMessageSchema).min(1, "At least one message is required"),
|
|
8699
|
+
stream: z26.boolean().optional().default(false)
|
|
8601
8700
|
});
|
|
8602
|
-
var llmChatResponseSchema =
|
|
8603
|
-
content:
|
|
8604
|
-
model:
|
|
8701
|
+
var llmChatResponseSchema = z26.object({
|
|
8702
|
+
content: z26.string(),
|
|
8703
|
+
model: z26.string(),
|
|
8605
8704
|
usage: tokenUsageSchema
|
|
8606
8705
|
});
|
|
8607
|
-
var llmChatContract =
|
|
8706
|
+
var llmChatContract = c18.router({
|
|
8608
8707
|
chat: {
|
|
8609
8708
|
method: "POST",
|
|
8610
8709
|
path: "/api/llm/chat",
|
|
@@ -8620,28 +8719,28 @@ var llmChatContract = c17.router({
|
|
|
8620
8719
|
});
|
|
8621
8720
|
|
|
8622
8721
|
// ../../packages/core/src/contracts/public/agents.ts
|
|
8623
|
-
import { z as
|
|
8624
|
-
var
|
|
8625
|
-
var publicAgentSchema =
|
|
8626
|
-
id:
|
|
8627
|
-
name:
|
|
8628
|
-
currentVersionId:
|
|
8722
|
+
import { z as z27 } from "zod";
|
|
8723
|
+
var c19 = initContract();
|
|
8724
|
+
var publicAgentSchema = z27.object({
|
|
8725
|
+
id: z27.string(),
|
|
8726
|
+
name: z27.string(),
|
|
8727
|
+
currentVersionId: z27.string().nullable(),
|
|
8629
8728
|
createdAt: timestampSchema,
|
|
8630
8729
|
updatedAt: timestampSchema
|
|
8631
8730
|
});
|
|
8632
|
-
var agentVersionSchema =
|
|
8633
|
-
id:
|
|
8634
|
-
agentId:
|
|
8635
|
-
versionNumber:
|
|
8731
|
+
var agentVersionSchema = z27.object({
|
|
8732
|
+
id: z27.string(),
|
|
8733
|
+
agentId: z27.string(),
|
|
8734
|
+
versionNumber: z27.number(),
|
|
8636
8735
|
createdAt: timestampSchema
|
|
8637
8736
|
});
|
|
8638
8737
|
var publicAgentDetailSchema = publicAgentSchema;
|
|
8639
8738
|
var paginatedAgentsSchema = createPaginatedResponseSchema(publicAgentSchema);
|
|
8640
8739
|
var paginatedAgentVersionsSchema = createPaginatedResponseSchema(agentVersionSchema);
|
|
8641
8740
|
var agentListQuerySchema = listQuerySchema.extend({
|
|
8642
|
-
name:
|
|
8741
|
+
name: z27.string().optional()
|
|
8643
8742
|
});
|
|
8644
|
-
var publicAgentsListContract =
|
|
8743
|
+
var publicAgentsListContract = c19.router({
|
|
8645
8744
|
list: {
|
|
8646
8745
|
method: "GET",
|
|
8647
8746
|
path: "/v1/agents",
|
|
@@ -8656,13 +8755,13 @@ var publicAgentsListContract = c18.router({
|
|
|
8656
8755
|
description: "List all agents in the current scope with pagination. Use the `name` query parameter to filter by agent name."
|
|
8657
8756
|
}
|
|
8658
8757
|
});
|
|
8659
|
-
var publicAgentByIdContract =
|
|
8758
|
+
var publicAgentByIdContract = c19.router({
|
|
8660
8759
|
get: {
|
|
8661
8760
|
method: "GET",
|
|
8662
8761
|
path: "/v1/agents/:id",
|
|
8663
8762
|
headers: authHeadersSchema,
|
|
8664
|
-
pathParams:
|
|
8665
|
-
id:
|
|
8763
|
+
pathParams: z27.object({
|
|
8764
|
+
id: z27.string().min(1, "Agent ID is required")
|
|
8666
8765
|
}),
|
|
8667
8766
|
responses: {
|
|
8668
8767
|
200: publicAgentDetailSchema,
|
|
@@ -8674,13 +8773,13 @@ var publicAgentByIdContract = c18.router({
|
|
|
8674
8773
|
description: "Get agent details by ID"
|
|
8675
8774
|
}
|
|
8676
8775
|
});
|
|
8677
|
-
var publicAgentVersionsContract =
|
|
8776
|
+
var publicAgentVersionsContract = c19.router({
|
|
8678
8777
|
list: {
|
|
8679
8778
|
method: "GET",
|
|
8680
8779
|
path: "/v1/agents/:id/versions",
|
|
8681
8780
|
headers: authHeadersSchema,
|
|
8682
|
-
pathParams:
|
|
8683
|
-
id:
|
|
8781
|
+
pathParams: z27.object({
|
|
8782
|
+
id: z27.string().min(1, "Agent ID is required")
|
|
8684
8783
|
}),
|
|
8685
8784
|
query: listQuerySchema,
|
|
8686
8785
|
responses: {
|
|
@@ -8695,9 +8794,9 @@ var publicAgentVersionsContract = c18.router({
|
|
|
8695
8794
|
});
|
|
8696
8795
|
|
|
8697
8796
|
// ../../packages/core/src/contracts/public/runs.ts
|
|
8698
|
-
import { z as
|
|
8699
|
-
var
|
|
8700
|
-
var publicRunStatusSchema =
|
|
8797
|
+
import { z as z28 } from "zod";
|
|
8798
|
+
var c20 = initContract();
|
|
8799
|
+
var publicRunStatusSchema = z28.enum([
|
|
8701
8800
|
"pending",
|
|
8702
8801
|
"running",
|
|
8703
8802
|
"completed",
|
|
@@ -8705,54 +8804,54 @@ var publicRunStatusSchema = z27.enum([
|
|
|
8705
8804
|
"timeout",
|
|
8706
8805
|
"cancelled"
|
|
8707
8806
|
]);
|
|
8708
|
-
var publicRunSchema =
|
|
8709
|
-
id:
|
|
8710
|
-
agentId:
|
|
8711
|
-
agentName:
|
|
8807
|
+
var publicRunSchema = z28.object({
|
|
8808
|
+
id: z28.string(),
|
|
8809
|
+
agentId: z28.string(),
|
|
8810
|
+
agentName: z28.string(),
|
|
8712
8811
|
status: publicRunStatusSchema,
|
|
8713
|
-
prompt:
|
|
8812
|
+
prompt: z28.string(),
|
|
8714
8813
|
createdAt: timestampSchema,
|
|
8715
8814
|
startedAt: timestampSchema.nullable(),
|
|
8716
8815
|
completedAt: timestampSchema.nullable()
|
|
8717
8816
|
});
|
|
8718
8817
|
var publicRunDetailSchema = publicRunSchema.extend({
|
|
8719
|
-
error:
|
|
8720
|
-
executionTimeMs:
|
|
8721
|
-
checkpointId:
|
|
8722
|
-
sessionId:
|
|
8723
|
-
artifactName:
|
|
8724
|
-
artifactVersion:
|
|
8725
|
-
volumes:
|
|
8818
|
+
error: z28.string().nullable(),
|
|
8819
|
+
executionTimeMs: z28.number().nullable(),
|
|
8820
|
+
checkpointId: z28.string().nullable(),
|
|
8821
|
+
sessionId: z28.string().nullable(),
|
|
8822
|
+
artifactName: z28.string().nullable(),
|
|
8823
|
+
artifactVersion: z28.string().nullable(),
|
|
8824
|
+
volumes: z28.record(z28.string(), z28.string()).optional()
|
|
8726
8825
|
});
|
|
8727
8826
|
var paginatedRunsSchema = createPaginatedResponseSchema(publicRunSchema);
|
|
8728
|
-
var createRunRequestSchema =
|
|
8827
|
+
var createRunRequestSchema = z28.object({
|
|
8729
8828
|
// Agent identification (one of: agent, agentId, sessionId, checkpointId)
|
|
8730
|
-
agent:
|
|
8829
|
+
agent: z28.string().optional(),
|
|
8731
8830
|
// Agent name
|
|
8732
|
-
agentId:
|
|
8831
|
+
agentId: z28.string().optional(),
|
|
8733
8832
|
// Agent ID
|
|
8734
|
-
agentVersion:
|
|
8833
|
+
agentVersion: z28.string().optional(),
|
|
8735
8834
|
// Version specifier (e.g., "latest", "v1", specific ID)
|
|
8736
8835
|
// Continue session
|
|
8737
|
-
sessionId:
|
|
8836
|
+
sessionId: z28.string().optional(),
|
|
8738
8837
|
// Resume from checkpoint
|
|
8739
|
-
checkpointId:
|
|
8838
|
+
checkpointId: z28.string().optional(),
|
|
8740
8839
|
// Required
|
|
8741
|
-
prompt:
|
|
8840
|
+
prompt: z28.string().min(1, "Prompt is required"),
|
|
8742
8841
|
// Optional configuration
|
|
8743
|
-
variables:
|
|
8744
|
-
secrets:
|
|
8745
|
-
artifactName:
|
|
8842
|
+
variables: z28.record(z28.string(), z28.string()).optional(),
|
|
8843
|
+
secrets: z28.record(z28.string(), z28.string()).optional(),
|
|
8844
|
+
artifactName: z28.string().optional(),
|
|
8746
8845
|
// Artifact name to mount
|
|
8747
|
-
artifactVersion:
|
|
8846
|
+
artifactVersion: z28.string().optional(),
|
|
8748
8847
|
// Artifact version (defaults to latest)
|
|
8749
|
-
volumes:
|
|
8848
|
+
volumes: z28.record(z28.string(), z28.string()).optional()
|
|
8750
8849
|
// volume_name -> version
|
|
8751
8850
|
});
|
|
8752
8851
|
var runListQuerySchema = listQuerySchema.extend({
|
|
8753
8852
|
status: publicRunStatusSchema.optional()
|
|
8754
8853
|
});
|
|
8755
|
-
var publicRunsListContract =
|
|
8854
|
+
var publicRunsListContract = c20.router({
|
|
8756
8855
|
list: {
|
|
8757
8856
|
method: "GET",
|
|
8758
8857
|
path: "/v1/runs",
|
|
@@ -8784,13 +8883,13 @@ var publicRunsListContract = c19.router({
|
|
|
8784
8883
|
description: "Create and execute a new agent run. Returns 202 Accepted as runs execute asynchronously."
|
|
8785
8884
|
}
|
|
8786
8885
|
});
|
|
8787
|
-
var publicRunByIdContract =
|
|
8886
|
+
var publicRunByIdContract = c20.router({
|
|
8788
8887
|
get: {
|
|
8789
8888
|
method: "GET",
|
|
8790
8889
|
path: "/v1/runs/:id",
|
|
8791
8890
|
headers: authHeadersSchema,
|
|
8792
|
-
pathParams:
|
|
8793
|
-
id:
|
|
8891
|
+
pathParams: z28.object({
|
|
8892
|
+
id: z28.string().min(1, "Run ID is required")
|
|
8794
8893
|
}),
|
|
8795
8894
|
responses: {
|
|
8796
8895
|
200: publicRunDetailSchema,
|
|
@@ -8802,15 +8901,15 @@ var publicRunByIdContract = c19.router({
|
|
|
8802
8901
|
description: "Get run details by ID"
|
|
8803
8902
|
}
|
|
8804
8903
|
});
|
|
8805
|
-
var publicRunCancelContract =
|
|
8904
|
+
var publicRunCancelContract = c20.router({
|
|
8806
8905
|
cancel: {
|
|
8807
8906
|
method: "POST",
|
|
8808
8907
|
path: "/v1/runs/:id/cancel",
|
|
8809
8908
|
headers: authHeadersSchema,
|
|
8810
|
-
pathParams:
|
|
8811
|
-
id:
|
|
8909
|
+
pathParams: z28.object({
|
|
8910
|
+
id: z28.string().min(1, "Run ID is required")
|
|
8812
8911
|
}),
|
|
8813
|
-
body:
|
|
8912
|
+
body: z28.undefined(),
|
|
8814
8913
|
responses: {
|
|
8815
8914
|
200: publicRunDetailSchema,
|
|
8816
8915
|
400: publicApiErrorSchema,
|
|
@@ -8823,27 +8922,27 @@ var publicRunCancelContract = c19.router({
|
|
|
8823
8922
|
description: "Cancel a pending or running execution"
|
|
8824
8923
|
}
|
|
8825
8924
|
});
|
|
8826
|
-
var logEntrySchema =
|
|
8925
|
+
var logEntrySchema = z28.object({
|
|
8827
8926
|
timestamp: timestampSchema,
|
|
8828
|
-
type:
|
|
8829
|
-
level:
|
|
8830
|
-
message:
|
|
8831
|
-
metadata:
|
|
8927
|
+
type: z28.enum(["agent", "system", "network"]),
|
|
8928
|
+
level: z28.enum(["debug", "info", "warn", "error"]),
|
|
8929
|
+
message: z28.string(),
|
|
8930
|
+
metadata: z28.record(z28.string(), z28.unknown()).optional()
|
|
8832
8931
|
});
|
|
8833
8932
|
var paginatedLogsSchema = createPaginatedResponseSchema(logEntrySchema);
|
|
8834
8933
|
var logsQuerySchema = listQuerySchema.extend({
|
|
8835
|
-
type:
|
|
8934
|
+
type: z28.enum(["agent", "system", "network", "all"]).default("all"),
|
|
8836
8935
|
since: timestampSchema.optional(),
|
|
8837
8936
|
until: timestampSchema.optional(),
|
|
8838
|
-
order:
|
|
8937
|
+
order: z28.enum(["asc", "desc"]).default("asc")
|
|
8839
8938
|
});
|
|
8840
|
-
var publicRunLogsContract =
|
|
8939
|
+
var publicRunLogsContract = c20.router({
|
|
8841
8940
|
getLogs: {
|
|
8842
8941
|
method: "GET",
|
|
8843
8942
|
path: "/v1/runs/:id/logs",
|
|
8844
8943
|
headers: authHeadersSchema,
|
|
8845
|
-
pathParams:
|
|
8846
|
-
id:
|
|
8944
|
+
pathParams: z28.object({
|
|
8945
|
+
id: z28.string().min(1, "Run ID is required")
|
|
8847
8946
|
}),
|
|
8848
8947
|
query: logsQuerySchema,
|
|
8849
8948
|
responses: {
|
|
@@ -8856,30 +8955,30 @@ var publicRunLogsContract = c19.router({
|
|
|
8856
8955
|
description: "Get unified logs for a run. Combines agent, system, and network logs."
|
|
8857
8956
|
}
|
|
8858
8957
|
});
|
|
8859
|
-
var metricPointSchema =
|
|
8958
|
+
var metricPointSchema = z28.object({
|
|
8860
8959
|
timestamp: timestampSchema,
|
|
8861
|
-
cpuPercent:
|
|
8862
|
-
memoryUsedMb:
|
|
8863
|
-
memoryTotalMb:
|
|
8864
|
-
diskUsedMb:
|
|
8865
|
-
diskTotalMb:
|
|
8866
|
-
});
|
|
8867
|
-
var metricsSummarySchema =
|
|
8868
|
-
avgCpuPercent:
|
|
8869
|
-
maxMemoryUsedMb:
|
|
8870
|
-
totalDurationMs:
|
|
8871
|
-
});
|
|
8872
|
-
var metricsResponseSchema2 =
|
|
8873
|
-
data:
|
|
8960
|
+
cpuPercent: z28.number(),
|
|
8961
|
+
memoryUsedMb: z28.number(),
|
|
8962
|
+
memoryTotalMb: z28.number(),
|
|
8963
|
+
diskUsedMb: z28.number(),
|
|
8964
|
+
diskTotalMb: z28.number()
|
|
8965
|
+
});
|
|
8966
|
+
var metricsSummarySchema = z28.object({
|
|
8967
|
+
avgCpuPercent: z28.number(),
|
|
8968
|
+
maxMemoryUsedMb: z28.number(),
|
|
8969
|
+
totalDurationMs: z28.number().nullable()
|
|
8970
|
+
});
|
|
8971
|
+
var metricsResponseSchema2 = z28.object({
|
|
8972
|
+
data: z28.array(metricPointSchema),
|
|
8874
8973
|
summary: metricsSummarySchema
|
|
8875
8974
|
});
|
|
8876
|
-
var publicRunMetricsContract =
|
|
8975
|
+
var publicRunMetricsContract = c20.router({
|
|
8877
8976
|
getMetrics: {
|
|
8878
8977
|
method: "GET",
|
|
8879
8978
|
path: "/v1/runs/:id/metrics",
|
|
8880
8979
|
headers: authHeadersSchema,
|
|
8881
|
-
pathParams:
|
|
8882
|
-
id:
|
|
8980
|
+
pathParams: z28.object({
|
|
8981
|
+
id: z28.string().min(1, "Run ID is required")
|
|
8883
8982
|
}),
|
|
8884
8983
|
responses: {
|
|
8885
8984
|
200: metricsResponseSchema2,
|
|
@@ -8891,7 +8990,7 @@ var publicRunMetricsContract = c19.router({
|
|
|
8891
8990
|
description: "Get CPU, memory, and disk metrics for a run"
|
|
8892
8991
|
}
|
|
8893
8992
|
});
|
|
8894
|
-
var sseEventTypeSchema =
|
|
8993
|
+
var sseEventTypeSchema = z28.enum([
|
|
8895
8994
|
"status",
|
|
8896
8995
|
// Run status change
|
|
8897
8996
|
"output",
|
|
@@ -8903,26 +9002,26 @@ var sseEventTypeSchema = z27.enum([
|
|
|
8903
9002
|
"heartbeat"
|
|
8904
9003
|
// Keep-alive
|
|
8905
9004
|
]);
|
|
8906
|
-
var sseEventSchema =
|
|
9005
|
+
var sseEventSchema = z28.object({
|
|
8907
9006
|
event: sseEventTypeSchema,
|
|
8908
|
-
data:
|
|
8909
|
-
id:
|
|
9007
|
+
data: z28.unknown(),
|
|
9008
|
+
id: z28.string().optional()
|
|
8910
9009
|
// For Last-Event-ID reconnection
|
|
8911
9010
|
});
|
|
8912
|
-
var publicRunEventsContract =
|
|
9011
|
+
var publicRunEventsContract = c20.router({
|
|
8913
9012
|
streamEvents: {
|
|
8914
9013
|
method: "GET",
|
|
8915
9014
|
path: "/v1/runs/:id/events",
|
|
8916
9015
|
headers: authHeadersSchema,
|
|
8917
|
-
pathParams:
|
|
8918
|
-
id:
|
|
9016
|
+
pathParams: z28.object({
|
|
9017
|
+
id: z28.string().min(1, "Run ID is required")
|
|
8919
9018
|
}),
|
|
8920
|
-
query:
|
|
8921
|
-
lastEventId:
|
|
9019
|
+
query: z28.object({
|
|
9020
|
+
lastEventId: z28.string().optional()
|
|
8922
9021
|
// For reconnection
|
|
8923
9022
|
}),
|
|
8924
9023
|
responses: {
|
|
8925
|
-
200:
|
|
9024
|
+
200: z28.any(),
|
|
8926
9025
|
// SSE stream - actual content is text/event-stream
|
|
8927
9026
|
401: publicApiErrorSchema,
|
|
8928
9027
|
404: publicApiErrorSchema,
|
|
@@ -8934,28 +9033,28 @@ var publicRunEventsContract = c19.router({
|
|
|
8934
9033
|
});
|
|
8935
9034
|
|
|
8936
9035
|
// ../../packages/core/src/contracts/public/artifacts.ts
|
|
8937
|
-
import { z as
|
|
8938
|
-
var
|
|
8939
|
-
var publicArtifactSchema =
|
|
8940
|
-
id:
|
|
8941
|
-
name:
|
|
8942
|
-
currentVersionId:
|
|
8943
|
-
size:
|
|
9036
|
+
import { z as z29 } from "zod";
|
|
9037
|
+
var c21 = initContract();
|
|
9038
|
+
var publicArtifactSchema = z29.object({
|
|
9039
|
+
id: z29.string(),
|
|
9040
|
+
name: z29.string(),
|
|
9041
|
+
currentVersionId: z29.string().nullable(),
|
|
9042
|
+
size: z29.number(),
|
|
8944
9043
|
// Total size in bytes
|
|
8945
|
-
fileCount:
|
|
9044
|
+
fileCount: z29.number(),
|
|
8946
9045
|
createdAt: timestampSchema,
|
|
8947
9046
|
updatedAt: timestampSchema
|
|
8948
9047
|
});
|
|
8949
|
-
var artifactVersionSchema =
|
|
8950
|
-
id:
|
|
9048
|
+
var artifactVersionSchema = z29.object({
|
|
9049
|
+
id: z29.string(),
|
|
8951
9050
|
// SHA-256 content hash
|
|
8952
|
-
artifactId:
|
|
8953
|
-
size:
|
|
9051
|
+
artifactId: z29.string(),
|
|
9052
|
+
size: z29.number(),
|
|
8954
9053
|
// Size in bytes
|
|
8955
|
-
fileCount:
|
|
8956
|
-
message:
|
|
9054
|
+
fileCount: z29.number(),
|
|
9055
|
+
message: z29.string().nullable(),
|
|
8957
9056
|
// Optional commit message
|
|
8958
|
-
createdBy:
|
|
9057
|
+
createdBy: z29.string(),
|
|
8959
9058
|
createdAt: timestampSchema
|
|
8960
9059
|
});
|
|
8961
9060
|
var publicArtifactDetailSchema = publicArtifactSchema.extend({
|
|
@@ -8965,7 +9064,7 @@ var paginatedArtifactsSchema = createPaginatedResponseSchema(publicArtifactSchem
|
|
|
8965
9064
|
var paginatedArtifactVersionsSchema = createPaginatedResponseSchema(
|
|
8966
9065
|
artifactVersionSchema
|
|
8967
9066
|
);
|
|
8968
|
-
var publicArtifactsListContract =
|
|
9067
|
+
var publicArtifactsListContract = c21.router({
|
|
8969
9068
|
list: {
|
|
8970
9069
|
method: "GET",
|
|
8971
9070
|
path: "/v1/artifacts",
|
|
@@ -8980,13 +9079,13 @@ var publicArtifactsListContract = c20.router({
|
|
|
8980
9079
|
description: "List all artifacts in the current scope with pagination"
|
|
8981
9080
|
}
|
|
8982
9081
|
});
|
|
8983
|
-
var publicArtifactByIdContract =
|
|
9082
|
+
var publicArtifactByIdContract = c21.router({
|
|
8984
9083
|
get: {
|
|
8985
9084
|
method: "GET",
|
|
8986
9085
|
path: "/v1/artifacts/:id",
|
|
8987
9086
|
headers: authHeadersSchema,
|
|
8988
|
-
pathParams:
|
|
8989
|
-
id:
|
|
9087
|
+
pathParams: z29.object({
|
|
9088
|
+
id: z29.string().min(1, "Artifact ID is required")
|
|
8990
9089
|
}),
|
|
8991
9090
|
responses: {
|
|
8992
9091
|
200: publicArtifactDetailSchema,
|
|
@@ -8998,13 +9097,13 @@ var publicArtifactByIdContract = c20.router({
|
|
|
8998
9097
|
description: "Get artifact details by ID"
|
|
8999
9098
|
}
|
|
9000
9099
|
});
|
|
9001
|
-
var publicArtifactVersionsContract =
|
|
9100
|
+
var publicArtifactVersionsContract = c21.router({
|
|
9002
9101
|
list: {
|
|
9003
9102
|
method: "GET",
|
|
9004
9103
|
path: "/v1/artifacts/:id/versions",
|
|
9005
9104
|
headers: authHeadersSchema,
|
|
9006
|
-
pathParams:
|
|
9007
|
-
id:
|
|
9105
|
+
pathParams: z29.object({
|
|
9106
|
+
id: z29.string().min(1, "Artifact ID is required")
|
|
9008
9107
|
}),
|
|
9009
9108
|
query: listQuerySchema,
|
|
9010
9109
|
responses: {
|
|
@@ -9017,20 +9116,20 @@ var publicArtifactVersionsContract = c20.router({
|
|
|
9017
9116
|
description: "List all versions of an artifact with pagination"
|
|
9018
9117
|
}
|
|
9019
9118
|
});
|
|
9020
|
-
var publicArtifactDownloadContract =
|
|
9119
|
+
var publicArtifactDownloadContract = c21.router({
|
|
9021
9120
|
download: {
|
|
9022
9121
|
method: "GET",
|
|
9023
9122
|
path: "/v1/artifacts/:id/download",
|
|
9024
9123
|
headers: authHeadersSchema,
|
|
9025
|
-
pathParams:
|
|
9026
|
-
id:
|
|
9124
|
+
pathParams: z29.object({
|
|
9125
|
+
id: z29.string().min(1, "Artifact ID is required")
|
|
9027
9126
|
}),
|
|
9028
|
-
query:
|
|
9029
|
-
versionId:
|
|
9127
|
+
query: z29.object({
|
|
9128
|
+
versionId: z29.string().optional()
|
|
9030
9129
|
// Defaults to current version
|
|
9031
9130
|
}),
|
|
9032
9131
|
responses: {
|
|
9033
|
-
302:
|
|
9132
|
+
302: z29.undefined(),
|
|
9034
9133
|
// Redirect to presigned URL
|
|
9035
9134
|
401: publicApiErrorSchema,
|
|
9036
9135
|
404: publicApiErrorSchema,
|
|
@@ -9042,28 +9141,28 @@ var publicArtifactDownloadContract = c20.router({
|
|
|
9042
9141
|
});
|
|
9043
9142
|
|
|
9044
9143
|
// ../../packages/core/src/contracts/public/volumes.ts
|
|
9045
|
-
import { z as
|
|
9046
|
-
var
|
|
9047
|
-
var publicVolumeSchema =
|
|
9048
|
-
id:
|
|
9049
|
-
name:
|
|
9050
|
-
currentVersionId:
|
|
9051
|
-
size:
|
|
9144
|
+
import { z as z30 } from "zod";
|
|
9145
|
+
var c22 = initContract();
|
|
9146
|
+
var publicVolumeSchema = z30.object({
|
|
9147
|
+
id: z30.string(),
|
|
9148
|
+
name: z30.string(),
|
|
9149
|
+
currentVersionId: z30.string().nullable(),
|
|
9150
|
+
size: z30.number(),
|
|
9052
9151
|
// Total size in bytes
|
|
9053
|
-
fileCount:
|
|
9152
|
+
fileCount: z30.number(),
|
|
9054
9153
|
createdAt: timestampSchema,
|
|
9055
9154
|
updatedAt: timestampSchema
|
|
9056
9155
|
});
|
|
9057
|
-
var volumeVersionSchema =
|
|
9058
|
-
id:
|
|
9156
|
+
var volumeVersionSchema = z30.object({
|
|
9157
|
+
id: z30.string(),
|
|
9059
9158
|
// SHA-256 content hash
|
|
9060
|
-
volumeId:
|
|
9061
|
-
size:
|
|
9159
|
+
volumeId: z30.string(),
|
|
9160
|
+
size: z30.number(),
|
|
9062
9161
|
// Size in bytes
|
|
9063
|
-
fileCount:
|
|
9064
|
-
message:
|
|
9162
|
+
fileCount: z30.number(),
|
|
9163
|
+
message: z30.string().nullable(),
|
|
9065
9164
|
// Optional commit message
|
|
9066
|
-
createdBy:
|
|
9165
|
+
createdBy: z30.string(),
|
|
9067
9166
|
createdAt: timestampSchema
|
|
9068
9167
|
});
|
|
9069
9168
|
var publicVolumeDetailSchema = publicVolumeSchema.extend({
|
|
@@ -9071,7 +9170,7 @@ var publicVolumeDetailSchema = publicVolumeSchema.extend({
|
|
|
9071
9170
|
});
|
|
9072
9171
|
var paginatedVolumesSchema = createPaginatedResponseSchema(publicVolumeSchema);
|
|
9073
9172
|
var paginatedVolumeVersionsSchema = createPaginatedResponseSchema(volumeVersionSchema);
|
|
9074
|
-
var publicVolumesListContract =
|
|
9173
|
+
var publicVolumesListContract = c22.router({
|
|
9075
9174
|
list: {
|
|
9076
9175
|
method: "GET",
|
|
9077
9176
|
path: "/v1/volumes",
|
|
@@ -9086,13 +9185,13 @@ var publicVolumesListContract = c21.router({
|
|
|
9086
9185
|
description: "List all volumes in the current scope with pagination"
|
|
9087
9186
|
}
|
|
9088
9187
|
});
|
|
9089
|
-
var publicVolumeByIdContract =
|
|
9188
|
+
var publicVolumeByIdContract = c22.router({
|
|
9090
9189
|
get: {
|
|
9091
9190
|
method: "GET",
|
|
9092
9191
|
path: "/v1/volumes/:id",
|
|
9093
9192
|
headers: authHeadersSchema,
|
|
9094
|
-
pathParams:
|
|
9095
|
-
id:
|
|
9193
|
+
pathParams: z30.object({
|
|
9194
|
+
id: z30.string().min(1, "Volume ID is required")
|
|
9096
9195
|
}),
|
|
9097
9196
|
responses: {
|
|
9098
9197
|
200: publicVolumeDetailSchema,
|
|
@@ -9104,13 +9203,13 @@ var publicVolumeByIdContract = c21.router({
|
|
|
9104
9203
|
description: "Get volume details by ID"
|
|
9105
9204
|
}
|
|
9106
9205
|
});
|
|
9107
|
-
var publicVolumeVersionsContract =
|
|
9206
|
+
var publicVolumeVersionsContract = c22.router({
|
|
9108
9207
|
list: {
|
|
9109
9208
|
method: "GET",
|
|
9110
9209
|
path: "/v1/volumes/:id/versions",
|
|
9111
9210
|
headers: authHeadersSchema,
|
|
9112
|
-
pathParams:
|
|
9113
|
-
id:
|
|
9211
|
+
pathParams: z30.object({
|
|
9212
|
+
id: z30.string().min(1, "Volume ID is required")
|
|
9114
9213
|
}),
|
|
9115
9214
|
query: listQuerySchema,
|
|
9116
9215
|
responses: {
|
|
@@ -9123,20 +9222,20 @@ var publicVolumeVersionsContract = c21.router({
|
|
|
9123
9222
|
description: "List all versions of a volume with pagination"
|
|
9124
9223
|
}
|
|
9125
9224
|
});
|
|
9126
|
-
var publicVolumeDownloadContract =
|
|
9225
|
+
var publicVolumeDownloadContract = c22.router({
|
|
9127
9226
|
download: {
|
|
9128
9227
|
method: "GET",
|
|
9129
9228
|
path: "/v1/volumes/:id/download",
|
|
9130
9229
|
headers: authHeadersSchema,
|
|
9131
|
-
pathParams:
|
|
9132
|
-
id:
|
|
9230
|
+
pathParams: z30.object({
|
|
9231
|
+
id: z30.string().min(1, "Volume ID is required")
|
|
9133
9232
|
}),
|
|
9134
|
-
query:
|
|
9135
|
-
versionId:
|
|
9233
|
+
query: z30.object({
|
|
9234
|
+
versionId: z30.string().optional()
|
|
9136
9235
|
// Defaults to current version
|
|
9137
9236
|
}),
|
|
9138
9237
|
responses: {
|
|
9139
|
-
302:
|
|
9238
|
+
302: z30.undefined(),
|
|
9140
9239
|
// Redirect to presigned URL
|
|
9141
9240
|
401: publicApiErrorSchema,
|
|
9142
9241
|
404: publicApiErrorSchema,
|
|
@@ -9195,11 +9294,10 @@ var ENV_LOADER_PATH = "/usr/local/bin/vm0-agent/env-loader.mjs";
|
|
|
9195
9294
|
// src/lib/proxy/vm-registry.ts
|
|
9196
9295
|
import fs6 from "fs";
|
|
9197
9296
|
var logger5 = createLogger("VMRegistry");
|
|
9198
|
-
var DEFAULT_REGISTRY_PATH = tempPaths.vmRegistry;
|
|
9199
9297
|
var VMRegistry = class {
|
|
9200
9298
|
registryPath;
|
|
9201
9299
|
data;
|
|
9202
|
-
constructor(registryPath
|
|
9300
|
+
constructor(registryPath) {
|
|
9203
9301
|
this.registryPath = registryPath;
|
|
9204
9302
|
this.data = this.load();
|
|
9205
9303
|
}
|
|
@@ -9286,7 +9384,9 @@ var VMRegistry = class {
|
|
|
9286
9384
|
var globalRegistry = null;
|
|
9287
9385
|
function getVMRegistry() {
|
|
9288
9386
|
if (!globalRegistry) {
|
|
9289
|
-
|
|
9387
|
+
throw new Error(
|
|
9388
|
+
"VMRegistry not initialized. Call initVMRegistry(registryPath) first."
|
|
9389
|
+
);
|
|
9290
9390
|
}
|
|
9291
9391
|
return globalRegistry;
|
|
9292
9392
|
}
|
|
@@ -9299,502 +9399,16 @@ function initVMRegistry(registryPath) {
|
|
|
9299
9399
|
import { spawn as spawn2 } from "child_process";
|
|
9300
9400
|
import fs7 from "fs";
|
|
9301
9401
|
import path5 from "path";
|
|
9302
|
-
|
|
9303
|
-
// src/lib/proxy/mitm-addon-script.ts
|
|
9304
|
-
var RUNNER_MITM_ADDON_SCRIPT = `#!/usr/bin/env python3
|
|
9305
|
-
"""
|
|
9306
|
-
mitmproxy addon for VM0 runner-level network security mode.
|
|
9307
|
-
|
|
9308
|
-
This addon runs on the runner HOST (not inside VMs) and:
|
|
9309
|
-
1. Intercepts all HTTPS requests from VMs
|
|
9310
|
-
2. Looks up the source VM's runId and firewall rules from the VM registry
|
|
9311
|
-
3. Evaluates firewall rules (first-match-wins) to ALLOW or DENY
|
|
9312
|
-
4. For MITM mode: Rewrites requests to go through VM0 Proxy endpoint
|
|
9313
|
-
5. For SNI-only mode: Passes through or blocks without decryption
|
|
9314
|
-
6. Logs network activity per-run to JSONL files
|
|
9315
|
-
"""
|
|
9316
|
-
import os
|
|
9317
|
-
import json
|
|
9318
|
-
import time
|
|
9319
|
-
import urllib.parse
|
|
9320
|
-
import ipaddress
|
|
9321
|
-
import socket
|
|
9322
|
-
from mitmproxy import http, ctx, tls
|
|
9323
|
-
|
|
9324
|
-
|
|
9325
|
-
# VM0 Proxy configuration from environment
|
|
9326
|
-
API_URL = os.environ.get("VM0_API_URL", "https://www.vm0.ai")
|
|
9327
|
-
REGISTRY_PATH = os.environ.get("VM0_REGISTRY_PATH", "/tmp/vm0-vm-registry.json")
|
|
9328
|
-
VERCEL_BYPASS = os.environ.get("VERCEL_AUTOMATION_BYPASS_SECRET", "")
|
|
9329
|
-
|
|
9330
|
-
# Construct proxy URL
|
|
9331
|
-
PROXY_URL = f"{API_URL}/api/webhooks/agent/proxy"
|
|
9332
|
-
|
|
9333
|
-
# Cache for VM registry (reloaded periodically)
|
|
9334
|
-
_registry_cache = {}
|
|
9335
|
-
_registry_cache_time = 0
|
|
9336
|
-
REGISTRY_CACHE_TTL = 2 # seconds
|
|
9337
|
-
|
|
9338
|
-
# Track request start times for latency calculation
|
|
9339
|
-
request_start_times = {}
|
|
9340
|
-
|
|
9341
|
-
|
|
9342
|
-
def load_registry() -> dict:
|
|
9343
|
-
"""Load the VM registry from file, with caching."""
|
|
9344
|
-
global _registry_cache, _registry_cache_time
|
|
9345
|
-
|
|
9346
|
-
now = time.time()
|
|
9347
|
-
if now - _registry_cache_time < REGISTRY_CACHE_TTL:
|
|
9348
|
-
return _registry_cache
|
|
9349
|
-
|
|
9350
|
-
try:
|
|
9351
|
-
if os.path.exists(REGISTRY_PATH):
|
|
9352
|
-
with open(REGISTRY_PATH, "r") as f:
|
|
9353
|
-
data = json.load(f)
|
|
9354
|
-
_registry_cache = data.get("vms", {})
|
|
9355
|
-
_registry_cache_time = now
|
|
9356
|
-
return _registry_cache
|
|
9357
|
-
except Exception as e:
|
|
9358
|
-
ctx.log.warn(f"Failed to load VM registry: {e}")
|
|
9359
|
-
|
|
9360
|
-
return _registry_cache
|
|
9361
|
-
|
|
9362
|
-
|
|
9363
|
-
def get_vm_info(client_ip: str) -> dict | None:
|
|
9364
|
-
"""Look up VM info by client IP address."""
|
|
9365
|
-
registry = load_registry()
|
|
9366
|
-
return registry.get(client_ip)
|
|
9367
|
-
|
|
9368
|
-
|
|
9369
|
-
def get_network_log_path(run_id: str) -> str:
|
|
9370
|
-
"""Get the network log file path for a run."""
|
|
9371
|
-
return f"/tmp/vm0-network-{run_id}.jsonl"
|
|
9372
|
-
|
|
9373
|
-
|
|
9374
|
-
def log_network_entry(run_id: str, entry: dict) -> None:
|
|
9375
|
-
"""Write a network log entry to the per-run JSONL file."""
|
|
9376
|
-
if not run_id:
|
|
9377
|
-
return
|
|
9378
|
-
|
|
9379
|
-
log_path = get_network_log_path(run_id)
|
|
9380
|
-
try:
|
|
9381
|
-
fd = os.open(log_path, os.O_CREAT | os.O_APPEND | os.O_WRONLY, 0o644)
|
|
9382
|
-
try:
|
|
9383
|
-
os.write(fd, (json.dumps(entry) + "\\n").encode())
|
|
9384
|
-
finally:
|
|
9385
|
-
os.close(fd)
|
|
9386
|
-
except Exception as e:
|
|
9387
|
-
ctx.log.warn(f"Failed to write network log: {e}")
|
|
9388
|
-
|
|
9389
|
-
|
|
9390
|
-
def get_original_url(flow: http.HTTPFlow) -> str:
|
|
9391
|
-
"""Reconstruct the original target URL from the request."""
|
|
9392
|
-
scheme = "https" if flow.request.port == 443 else "http"
|
|
9393
|
-
host = flow.request.pretty_host
|
|
9394
|
-
port = flow.request.port
|
|
9395
|
-
|
|
9396
|
-
if (scheme == "https" and port != 443) or (scheme == "http" and port != 80):
|
|
9397
|
-
host_with_port = f"{host}:{port}"
|
|
9398
|
-
else:
|
|
9399
|
-
host_with_port = host
|
|
9400
|
-
|
|
9401
|
-
path = flow.request.path
|
|
9402
|
-
return f"{scheme}://{host_with_port}{path}"
|
|
9403
|
-
|
|
9404
|
-
|
|
9405
|
-
# ============================================================================
|
|
9406
|
-
# Firewall Rule Matching
|
|
9407
|
-
# ============================================================================
|
|
9408
|
-
|
|
9409
|
-
def match_domain(pattern: str, hostname: str) -> bool:
|
|
9410
|
-
"""
|
|
9411
|
-
Match hostname against domain pattern.
|
|
9412
|
-
Supports exact match and wildcard prefix (*.example.com).
|
|
9413
|
-
"""
|
|
9414
|
-
if not pattern or not hostname:
|
|
9415
|
-
return False
|
|
9416
|
-
|
|
9417
|
-
pattern = pattern.lower()
|
|
9418
|
-
hostname = hostname.lower()
|
|
9419
|
-
|
|
9420
|
-
if pattern.startswith("*."):
|
|
9421
|
-
# Wildcard: *.example.com matches sub.example.com, www.example.com
|
|
9422
|
-
# Also matches example.com itself (without subdomain)
|
|
9423
|
-
suffix = pattern[1:] # .example.com
|
|
9424
|
-
base = pattern[2:] # example.com
|
|
9425
|
-
return hostname.endswith(suffix) or hostname == base
|
|
9426
|
-
|
|
9427
|
-
return hostname == pattern
|
|
9428
|
-
|
|
9429
|
-
|
|
9430
|
-
def match_ip(cidr: str, ip_str: str) -> bool:
|
|
9431
|
-
"""
|
|
9432
|
-
Match IP address against CIDR range.
|
|
9433
|
-
Supports single IPs (1.2.3.4) and ranges (10.0.0.0/8).
|
|
9434
|
-
"""
|
|
9435
|
-
if not cidr or not ip_str:
|
|
9436
|
-
return False
|
|
9437
|
-
|
|
9438
|
-
try:
|
|
9439
|
-
# Parse CIDR (automatically handles single IPs as /32)
|
|
9440
|
-
if "/" not in cidr:
|
|
9441
|
-
cidr = f"{cidr}/32"
|
|
9442
|
-
network = ipaddress.ip_network(cidr, strict=False)
|
|
9443
|
-
ip = ipaddress.ip_address(ip_str)
|
|
9444
|
-
return ip in network
|
|
9445
|
-
except ValueError:
|
|
9446
|
-
return False
|
|
9447
|
-
|
|
9448
|
-
|
|
9449
|
-
def resolve_hostname_to_ip(hostname: str) -> str | None:
|
|
9450
|
-
"""Resolve hostname to IP address for IP-based rule matching."""
|
|
9451
|
-
try:
|
|
9452
|
-
return socket.gethostbyname(hostname)
|
|
9453
|
-
except socket.gaierror:
|
|
9454
|
-
return None
|
|
9455
|
-
|
|
9456
|
-
|
|
9457
|
-
def evaluate_rules(rules: list, hostname: str, ip_str: str = None) -> tuple[str, str | None]:
|
|
9458
|
-
"""
|
|
9459
|
-
Evaluate firewall rules against hostname/IP.
|
|
9460
|
-
Returns (action, matched_rule_description).
|
|
9461
|
-
|
|
9462
|
-
Rule evaluation is first-match-wins (top to bottom).
|
|
9463
|
-
|
|
9464
|
-
Rule formats:
|
|
9465
|
-
- Domain/IP rule: { domain: "*.example.com", action: "ALLOW" }
|
|
9466
|
-
- Terminal rule: { final: "DENY" }
|
|
9467
|
-
"""
|
|
9468
|
-
if not rules:
|
|
9469
|
-
return ("ALLOW", None) # No rules = allow all
|
|
9470
|
-
|
|
9471
|
-
for rule in rules:
|
|
9472
|
-
# Final/terminal rule - value is the action
|
|
9473
|
-
final_action = rule.get("final")
|
|
9474
|
-
if final_action:
|
|
9475
|
-
return (final_action, "final")
|
|
9476
|
-
|
|
9477
|
-
# Domain rule
|
|
9478
|
-
domain = rule.get("domain")
|
|
9479
|
-
if domain and match_domain(domain, hostname):
|
|
9480
|
-
return (rule.get("action", "DENY"), f"domain:{domain}")
|
|
9481
|
-
|
|
9482
|
-
# IP rule
|
|
9483
|
-
ip_pattern = rule.get("ip")
|
|
9484
|
-
if ip_pattern:
|
|
9485
|
-
target_ip = ip_str
|
|
9486
|
-
if not target_ip:
|
|
9487
|
-
target_ip = resolve_hostname_to_ip(hostname)
|
|
9488
|
-
if target_ip and match_ip(ip_pattern, target_ip):
|
|
9489
|
-
return (rule.get("action", "DENY"), f"ip:{ip_pattern}")
|
|
9490
|
-
|
|
9491
|
-
# No rule matched - default deny (zero-trust)
|
|
9492
|
-
return ("DENY", "default")
|
|
9493
|
-
|
|
9494
|
-
|
|
9495
|
-
# ============================================================================
|
|
9496
|
-
# TLS ClientHello Handler (SNI-only mode)
|
|
9497
|
-
# ============================================================================
|
|
9498
|
-
|
|
9499
|
-
def tls_clienthello(data: tls.ClientHelloData) -> None:
|
|
9500
|
-
"""
|
|
9501
|
-
Handle TLS ClientHello for SNI-based filtering.
|
|
9502
|
-
This is called BEFORE TLS decryption, allowing SNI-only filtering.
|
|
9503
|
-
"""
|
|
9504
|
-
client_ip = data.context.client.peername[0] if data.context.client.peername else None
|
|
9505
|
-
if not client_ip:
|
|
9506
|
-
return
|
|
9507
|
-
|
|
9508
|
-
vm_info = get_vm_info(client_ip)
|
|
9509
|
-
if not vm_info:
|
|
9510
|
-
# Not a registered VM - pass through without MITM interception
|
|
9511
|
-
# This is critical for CIDR-based rules where all VM traffic is redirected
|
|
9512
|
-
data.ignore_connection = True
|
|
9513
|
-
return
|
|
9514
|
-
|
|
9515
|
-
# If MITM is enabled, let the normal flow handle it
|
|
9516
|
-
if vm_info.get("mitmEnabled", False):
|
|
9517
|
-
return
|
|
9518
|
-
|
|
9519
|
-
# SNI-only mode: check rules based on SNI
|
|
9520
|
-
sni = data.context.client.sni
|
|
9521
|
-
run_id = vm_info.get("runId", "")
|
|
9522
|
-
rules = vm_info.get("firewallRules", [])
|
|
9523
|
-
|
|
9524
|
-
# Auto-allow VM0 API requests - the agent MUST be able to communicate with VM0
|
|
9525
|
-
if API_URL and sni:
|
|
9526
|
-
parsed_api = urllib.parse.urlparse(API_URL)
|
|
9527
|
-
api_hostname = parsed_api.hostname.lower() if parsed_api.hostname else ""
|
|
9528
|
-
sni_lower = sni.lower()
|
|
9529
|
-
if api_hostname and (sni_lower == api_hostname or sni_lower.endswith(f".{api_hostname}")):
|
|
9530
|
-
ctx.log.info(f"[{run_id}] SNI-only auto-allow VM0 API: {sni}")
|
|
9531
|
-
log_network_entry(run_id, {
|
|
9532
|
-
"timestamp": time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime()),
|
|
9533
|
-
"mode": "sni",
|
|
9534
|
-
"action": "ALLOW",
|
|
9535
|
-
"host": sni,
|
|
9536
|
-
"port": 443,
|
|
9537
|
-
"rule_matched": "vm0-api",
|
|
9538
|
-
})
|
|
9539
|
-
data.ignore_connection = True # Pass through without MITM
|
|
9540
|
-
return
|
|
9541
|
-
|
|
9542
|
-
if not sni:
|
|
9543
|
-
# No SNI, can't determine target - block for security
|
|
9544
|
-
ctx.log.warn(f"[{run_id}] SNI-only: No SNI in ClientHello, blocking")
|
|
9545
|
-
log_network_entry(run_id, {
|
|
9546
|
-
"timestamp": time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime()),
|
|
9547
|
-
"mode": "sni",
|
|
9548
|
-
"action": "DENY",
|
|
9549
|
-
"host": "",
|
|
9550
|
-
"port": 443,
|
|
9551
|
-
"rule_matched": "no-sni",
|
|
9552
|
-
})
|
|
9553
|
-
# Don't set ignore_connection - mitmproxy will attempt MITM handshake
|
|
9554
|
-
# Since VM doesn't have CA cert (SNI-only mode), TLS will fail immediately
|
|
9555
|
-
return
|
|
9556
|
-
|
|
9557
|
-
# Evaluate rules
|
|
9558
|
-
action, matched_rule = evaluate_rules(rules, sni)
|
|
9559
|
-
|
|
9560
|
-
# Log the connection
|
|
9561
|
-
log_network_entry(run_id, {
|
|
9562
|
-
"timestamp": time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime()),
|
|
9563
|
-
"mode": "sni",
|
|
9564
|
-
"action": action,
|
|
9565
|
-
"host": sni,
|
|
9566
|
-
"port": 443,
|
|
9567
|
-
"rule_matched": matched_rule,
|
|
9568
|
-
})
|
|
9569
|
-
|
|
9570
|
-
if action == "ALLOW":
|
|
9571
|
-
# Pass through without MITM - mitmproxy will relay without decryption
|
|
9572
|
-
ctx.log.info(f"[{run_id}] SNI-only ALLOW: {sni} (rule: {matched_rule})")
|
|
9573
|
-
data.ignore_connection = True
|
|
9574
|
-
else:
|
|
9575
|
-
# Block the connection by NOT setting ignore_connection
|
|
9576
|
-
# mitmproxy will attempt MITM handshake, but since VM doesn't have
|
|
9577
|
-
# our CA certificate installed (SNI-only mode), the TLS handshake
|
|
9578
|
-
# will fail immediately with a certificate error.
|
|
9579
|
-
ctx.log.warn(f"[{run_id}] SNI-only DENY: {sni} (rule: {matched_rule})")
|
|
9580
|
-
# Client will see: SSL certificate problem / certificate verify failed
|
|
9581
|
-
|
|
9582
|
-
|
|
9583
|
-
# ============================================================================
|
|
9584
|
-
# HTTP Request Handler (MITM mode)
|
|
9585
|
-
# ============================================================================
|
|
9586
|
-
|
|
9587
|
-
def request(flow: http.HTTPFlow) -> None:
|
|
9588
|
-
"""
|
|
9589
|
-
Intercept request and apply firewall rules.
|
|
9590
|
-
For MITM mode, rewrites allowed requests to VM0 Proxy.
|
|
9591
|
-
"""
|
|
9592
|
-
# Track request start time
|
|
9593
|
-
request_start_times[flow.id] = time.time()
|
|
9594
|
-
|
|
9595
|
-
# Get client IP (source VM)
|
|
9596
|
-
client_ip = flow.client_conn.peername[0] if flow.client_conn.peername else None
|
|
9597
|
-
|
|
9598
|
-
if not client_ip:
|
|
9599
|
-
ctx.log.warn("No client IP available, passing through")
|
|
9600
|
-
return
|
|
9601
|
-
|
|
9602
|
-
# Look up VM info from registry
|
|
9603
|
-
vm_info = get_vm_info(client_ip)
|
|
9604
|
-
|
|
9605
|
-
if not vm_info:
|
|
9606
|
-
# Not a registered VM, pass through without proxying
|
|
9607
|
-
ctx.log.info(f"No VM registration for {client_ip}, passing through")
|
|
9608
|
-
return
|
|
9609
|
-
|
|
9610
|
-
run_id = vm_info.get("runId", "")
|
|
9611
|
-
sandbox_token = vm_info.get("sandboxToken", "")
|
|
9612
|
-
mitm_enabled = vm_info.get("mitmEnabled", False)
|
|
9613
|
-
rules = vm_info.get("firewallRules", [])
|
|
9614
|
-
|
|
9615
|
-
# Store info for response handler
|
|
9616
|
-
flow.metadata["vm_run_id"] = run_id
|
|
9617
|
-
flow.metadata["vm_client_ip"] = client_ip
|
|
9618
|
-
flow.metadata["vm_mitm_enabled"] = mitm_enabled
|
|
9619
|
-
|
|
9620
|
-
# Get target hostname
|
|
9621
|
-
hostname = flow.request.pretty_host.lower()
|
|
9622
|
-
|
|
9623
|
-
# Auto-allow VM0 API requests - the agent MUST be able to communicate with VM0
|
|
9624
|
-
# This is checked before user firewall rules to ensure agent functionality
|
|
9625
|
-
if API_URL:
|
|
9626
|
-
parsed_api = urllib.parse.urlparse(API_URL)
|
|
9627
|
-
api_hostname = parsed_api.hostname.lower() if parsed_api.hostname else ""
|
|
9628
|
-
if api_hostname and (hostname == api_hostname or hostname.endswith(f".{api_hostname}")):
|
|
9629
|
-
ctx.log.info(f"[{run_id}] Auto-allow VM0 API: {hostname}")
|
|
9630
|
-
flow.metadata["firewall_action"] = "ALLOW"
|
|
9631
|
-
flow.metadata["firewall_rule"] = "vm0-api"
|
|
9632
|
-
# Continue to skip rewrite check below
|
|
9633
|
-
flow.metadata["original_url"] = get_original_url(flow)
|
|
9634
|
-
flow.metadata["skip_rewrite"] = True
|
|
9635
|
-
return
|
|
9636
|
-
|
|
9637
|
-
# Evaluate firewall rules
|
|
9638
|
-
action, matched_rule = evaluate_rules(rules, hostname)
|
|
9639
|
-
flow.metadata["firewall_action"] = action
|
|
9640
|
-
flow.metadata["firewall_rule"] = matched_rule
|
|
9641
|
-
|
|
9642
|
-
if action == "DENY":
|
|
9643
|
-
ctx.log.warn(f"[{run_id}] Firewall DENY: {hostname} (rule: {matched_rule})")
|
|
9644
|
-
# Kill the flow and return error response
|
|
9645
|
-
flow.response = http.Response.make(
|
|
9646
|
-
403,
|
|
9647
|
-
b"Blocked by firewall",
|
|
9648
|
-
{"Content-Type": "text/plain"}
|
|
9649
|
-
)
|
|
9650
|
-
return
|
|
9651
|
-
|
|
9652
|
-
# Request is ALLOWED - proceed with processing
|
|
9653
|
-
|
|
9654
|
-
# Skip if no API URL configured
|
|
9655
|
-
if not API_URL:
|
|
9656
|
-
ctx.log.warn("VM0_API_URL not set, passing through")
|
|
9657
|
-
return
|
|
9658
|
-
|
|
9659
|
-
# Skip rewriting requests already going to VM0 (avoid loops)
|
|
9660
|
-
if API_URL in flow.request.pretty_url:
|
|
9661
|
-
flow.metadata["original_url"] = flow.request.pretty_url
|
|
9662
|
-
flow.metadata["skip_rewrite"] = True
|
|
9663
|
-
return
|
|
9664
|
-
|
|
9665
|
-
# Skip rewriting requests to trusted storage domains (S3, etc.)
|
|
9666
|
-
# S3 presigned URLs have signatures that break when proxied
|
|
9667
|
-
TRUSTED_DOMAINS = [
|
|
9668
|
-
".s3.amazonaws.com",
|
|
9669
|
-
".s3-", # Regional S3 endpoints like s3-us-west-2.amazonaws.com
|
|
9670
|
-
"s3.amazonaws.com",
|
|
9671
|
-
".r2.cloudflarestorage.com",
|
|
9672
|
-
".storage.googleapis.com",
|
|
9673
|
-
]
|
|
9674
|
-
for domain in TRUSTED_DOMAINS:
|
|
9675
|
-
if domain in hostname or hostname.endswith(domain.lstrip(".")):
|
|
9676
|
-
ctx.log.info(f"[{run_id}] Skipping trusted storage domain: {hostname}")
|
|
9677
|
-
flow.metadata["original_url"] = get_original_url(flow)
|
|
9678
|
-
flow.metadata["skip_rewrite"] = True
|
|
9679
|
-
return
|
|
9680
|
-
|
|
9681
|
-
# Get original target URL
|
|
9682
|
-
original_url = get_original_url(flow)
|
|
9683
|
-
flow.metadata["original_url"] = original_url
|
|
9684
|
-
|
|
9685
|
-
# If MITM is not enabled, just allow the request through without rewriting
|
|
9686
|
-
if not mitm_enabled:
|
|
9687
|
-
ctx.log.info(f"[{run_id}] Firewall ALLOW (no MITM): {hostname}")
|
|
9688
|
-
return
|
|
9689
|
-
|
|
9690
|
-
# MITM mode: rewrite to VM0 Proxy
|
|
9691
|
-
ctx.log.info(f"[{run_id}] Proxying via MITM: {original_url}")
|
|
9692
|
-
|
|
9693
|
-
# Parse proxy URL
|
|
9694
|
-
parsed = urllib.parse.urlparse(PROXY_URL)
|
|
9695
|
-
|
|
9696
|
-
# Build query params
|
|
9697
|
-
query_params = {"url": original_url}
|
|
9698
|
-
if run_id:
|
|
9699
|
-
query_params["runId"] = run_id
|
|
9700
|
-
query_string = urllib.parse.urlencode(query_params)
|
|
9701
|
-
|
|
9702
|
-
# Rewrite request to proxy
|
|
9703
|
-
flow.request.host = parsed.hostname
|
|
9704
|
-
flow.request.port = 443 if parsed.scheme == "https" else 80
|
|
9705
|
-
flow.request.scheme = parsed.scheme
|
|
9706
|
-
flow.request.path = f"{parsed.path}?{query_string}"
|
|
9707
|
-
|
|
9708
|
-
# Save original Authorization header before overwriting
|
|
9709
|
-
if "Authorization" in flow.request.headers:
|
|
9710
|
-
flow.request.headers["x-vm0-original-authorization"] = flow.request.headers["Authorization"]
|
|
9711
|
-
|
|
9712
|
-
# Add sandbox authentication token
|
|
9713
|
-
if sandbox_token:
|
|
9714
|
-
flow.request.headers["Authorization"] = f"Bearer {sandbox_token}"
|
|
9715
|
-
|
|
9716
|
-
# Add Vercel bypass header if configured
|
|
9717
|
-
if VERCEL_BYPASS:
|
|
9718
|
-
flow.request.headers["x-vercel-protection-bypass"] = VERCEL_BYPASS
|
|
9719
|
-
|
|
9720
|
-
|
|
9721
|
-
def response(flow: http.HTTPFlow) -> None:
|
|
9722
|
-
"""
|
|
9723
|
-
Handle response and log network activity.
|
|
9724
|
-
"""
|
|
9725
|
-
# Calculate latency
|
|
9726
|
-
start_time = request_start_times.pop(flow.id, None)
|
|
9727
|
-
latency_ms = int((time.time() - start_time) * 1000) if start_time else 0
|
|
9728
|
-
|
|
9729
|
-
# Get stored info
|
|
9730
|
-
run_id = flow.metadata.get("vm_run_id", "")
|
|
9731
|
-
original_url = flow.metadata.get("original_url", flow.request.pretty_url)
|
|
9732
|
-
mitm_enabled = flow.metadata.get("vm_mitm_enabled", False)
|
|
9733
|
-
firewall_action = flow.metadata.get("firewall_action", "ALLOW")
|
|
9734
|
-
firewall_rule = flow.metadata.get("firewall_rule")
|
|
9735
|
-
|
|
9736
|
-
# Calculate sizes
|
|
9737
|
-
request_size = len(flow.request.content) if flow.request.content else 0
|
|
9738
|
-
response_size = len(flow.response.content) if flow.response and flow.response.content else 0
|
|
9739
|
-
status_code = flow.response.status_code if flow.response else 0
|
|
9740
|
-
|
|
9741
|
-
# Parse URL for host
|
|
9742
|
-
try:
|
|
9743
|
-
parsed_url = urllib.parse.urlparse(original_url)
|
|
9744
|
-
host = parsed_url.hostname or flow.request.pretty_host
|
|
9745
|
-
port = parsed_url.port or (443 if parsed_url.scheme == "https" else 80)
|
|
9746
|
-
except:
|
|
9747
|
-
host = flow.request.pretty_host
|
|
9748
|
-
port = flow.request.port
|
|
9749
|
-
|
|
9750
|
-
# Log network entry for this run
|
|
9751
|
-
if run_id:
|
|
9752
|
-
log_entry = {
|
|
9753
|
-
"timestamp": time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime()),
|
|
9754
|
-
"mode": "mitm" if mitm_enabled else "sni",
|
|
9755
|
-
"action": firewall_action,
|
|
9756
|
-
"host": host,
|
|
9757
|
-
"port": port,
|
|
9758
|
-
"rule_matched": firewall_rule,
|
|
9759
|
-
}
|
|
9760
|
-
|
|
9761
|
-
# Add HTTP details only in MITM mode
|
|
9762
|
-
if mitm_enabled:
|
|
9763
|
-
log_entry.update({
|
|
9764
|
-
"method": flow.request.method,
|
|
9765
|
-
"path": flow.request.path.split("?")[0], # Path without query
|
|
9766
|
-
"url": original_url,
|
|
9767
|
-
"status": status_code,
|
|
9768
|
-
"latency_ms": latency_ms,
|
|
9769
|
-
"request_size": request_size,
|
|
9770
|
-
"response_size": response_size,
|
|
9771
|
-
})
|
|
9772
|
-
|
|
9773
|
-
log_network_entry(run_id, log_entry)
|
|
9774
|
-
|
|
9775
|
-
# Log errors to mitmproxy console
|
|
9776
|
-
if flow.response and flow.response.status_code >= 400:
|
|
9777
|
-
ctx.log.warn(
|
|
9778
|
-
f"[{run_id}] Response {flow.response.status_code}: {original_url}"
|
|
9779
|
-
)
|
|
9780
|
-
|
|
9781
|
-
|
|
9782
|
-
# mitmproxy addon registration
|
|
9783
|
-
addons = [tls_clienthello, request, response]
|
|
9784
|
-
`;
|
|
9785
|
-
|
|
9786
|
-
// src/lib/proxy/proxy-manager.ts
|
|
9787
9402
|
var logger6 = createLogger("ProxyManager");
|
|
9788
9403
|
var DEFAULT_PROXY_OPTIONS = {
|
|
9789
|
-
port: 8080
|
|
9790
|
-
registryPath: DEFAULT_REGISTRY_PATH
|
|
9404
|
+
port: 8080
|
|
9791
9405
|
};
|
|
9792
9406
|
var ProxyManager = class {
|
|
9793
9407
|
config;
|
|
9794
9408
|
process = null;
|
|
9795
9409
|
isRunning = false;
|
|
9796
9410
|
constructor(config) {
|
|
9797
|
-
const addonPath = path5.join(config.caDir, "
|
|
9411
|
+
const addonPath = path5.join(config.caDir, "mitm-addon.py");
|
|
9798
9412
|
this.config = {
|
|
9799
9413
|
...DEFAULT_PROXY_OPTIONS,
|
|
9800
9414
|
...config,
|
|
@@ -9817,19 +9431,6 @@ var ProxyManager = class {
|
|
|
9817
9431
|
});
|
|
9818
9432
|
});
|
|
9819
9433
|
}
|
|
9820
|
-
/**
|
|
9821
|
-
* Ensure the addon script exists at the configured path
|
|
9822
|
-
*/
|
|
9823
|
-
ensureAddonScript() {
|
|
9824
|
-
const addonDir = path5.dirname(this.config.addonPath);
|
|
9825
|
-
if (!fs7.existsSync(addonDir)) {
|
|
9826
|
-
fs7.mkdirSync(addonDir, { recursive: true });
|
|
9827
|
-
}
|
|
9828
|
-
fs7.writeFileSync(this.config.addonPath, RUNNER_MITM_ADDON_SCRIPT, {
|
|
9829
|
-
mode: 493
|
|
9830
|
-
});
|
|
9831
|
-
logger6.log(`Addon script written to ${this.config.addonPath}`);
|
|
9832
|
-
}
|
|
9833
9434
|
/**
|
|
9834
9435
|
* Validate proxy configuration
|
|
9835
9436
|
*/
|
|
@@ -9841,7 +9442,9 @@ var ProxyManager = class {
|
|
|
9841
9442
|
if (!fs7.existsSync(caCertPath)) {
|
|
9842
9443
|
throw new Error(`Proxy CA certificate not found: ${caCertPath}`);
|
|
9843
9444
|
}
|
|
9844
|
-
this.
|
|
9445
|
+
if (!fs7.existsSync(this.config.addonPath)) {
|
|
9446
|
+
throw new Error(`Addon script not found: ${this.config.addonPath}`);
|
|
9447
|
+
}
|
|
9845
9448
|
}
|
|
9846
9449
|
/**
|
|
9847
9450
|
* Start mitmproxy
|
|
@@ -9871,17 +9474,15 @@ var ProxyManager = class {
|
|
|
9871
9474
|
String(this.config.port),
|
|
9872
9475
|
"--set",
|
|
9873
9476
|
`confdir=${this.config.caDir}`,
|
|
9477
|
+
"--set",
|
|
9478
|
+
`vm0_api_url=${this.config.apiUrl}`,
|
|
9479
|
+
"--set",
|
|
9480
|
+
`vm0_registry_path=${this.config.registryPath}`,
|
|
9874
9481
|
"--scripts",
|
|
9875
9482
|
this.config.addonPath,
|
|
9876
9483
|
"--quiet"
|
|
9877
9484
|
];
|
|
9878
|
-
const env = {
|
|
9879
|
-
...process.env,
|
|
9880
|
-
VM0_API_URL: this.config.apiUrl,
|
|
9881
|
-
VM0_REGISTRY_PATH: this.config.registryPath
|
|
9882
|
-
};
|
|
9883
9485
|
this.process = spawn2("mitmdump", args, {
|
|
9884
|
-
env,
|
|
9885
9486
|
stdio: ["ignore", "pipe", "pipe"],
|
|
9886
9487
|
detached: false
|
|
9887
9488
|
});
|
|
@@ -10527,14 +10128,6 @@ function checkNetworkPrerequisites() {
|
|
|
10527
10128
|
errors
|
|
10528
10129
|
};
|
|
10529
10130
|
}
|
|
10530
|
-
async function isPortInUse(port) {
|
|
10531
|
-
try {
|
|
10532
|
-
await execAsync3(`ss -tln | grep -q ":${port} "`);
|
|
10533
|
-
return true;
|
|
10534
|
-
} catch {
|
|
10535
|
-
return false;
|
|
10536
|
-
}
|
|
10537
|
-
}
|
|
10538
10131
|
|
|
10539
10132
|
// src/lib/runner/runner-lock.ts
|
|
10540
10133
|
import fs10 from "fs";
|
|
@@ -10588,11 +10181,13 @@ async function setupEnvironment(options) {
|
|
|
10588
10181
|
process.exit(1);
|
|
10589
10182
|
}
|
|
10590
10183
|
logger12.log("Initializing network proxy...");
|
|
10591
|
-
|
|
10184
|
+
const registryPath = runnerPaths.vmRegistry(config.base_dir);
|
|
10185
|
+
initVMRegistry(registryPath);
|
|
10592
10186
|
const proxyManager = initProxyManager({
|
|
10593
10187
|
apiUrl: config.server.url,
|
|
10594
10188
|
port: config.proxy.port,
|
|
10595
|
-
caDir: config.proxy.ca_dir
|
|
10189
|
+
caDir: config.proxy.ca_dir,
|
|
10190
|
+
registryPath
|
|
10596
10191
|
});
|
|
10597
10192
|
let proxyEnabled = false;
|
|
10598
10193
|
try {
|
|
@@ -10942,19 +10537,24 @@ function parseFirecrackerCmdline(cmdline) {
|
|
|
10942
10537
|
}
|
|
10943
10538
|
}
|
|
10944
10539
|
if (!filePath) return null;
|
|
10945
|
-
const
|
|
10946
|
-
if (!
|
|
10947
|
-
|
|
10540
|
+
const vmIdMatch = filePath.match(/vm0-([a-f0-9]+)\//);
|
|
10541
|
+
if (!vmIdMatch?.[1]) return null;
|
|
10542
|
+
const baseDirMatch = filePath.match(/^(.+)\/workspaces\/vm0-[a-f0-9]+\//);
|
|
10543
|
+
if (!baseDirMatch?.[1]) return null;
|
|
10544
|
+
return { vmId: createVmId(vmIdMatch[1]), baseDir: baseDirMatch[1] };
|
|
10948
10545
|
}
|
|
10949
10546
|
function parseMitmproxyCmdline(cmdline) {
|
|
10950
10547
|
if (!cmdline.includes("mitmproxy") && !cmdline.includes("mitmdump")) {
|
|
10951
10548
|
return null;
|
|
10952
10549
|
}
|
|
10953
10550
|
const args = cmdline.split("\0");
|
|
10954
|
-
const
|
|
10955
|
-
|
|
10956
|
-
|
|
10957
|
-
|
|
10551
|
+
for (const arg of args) {
|
|
10552
|
+
const match = arg.match(/^vm0_registry_path=(.+)\/vm-registry\.json$/);
|
|
10553
|
+
if (match?.[1]) {
|
|
10554
|
+
return match[1];
|
|
10555
|
+
}
|
|
10556
|
+
}
|
|
10557
|
+
return null;
|
|
10958
10558
|
}
|
|
10959
10559
|
function findFirecrackerProcesses() {
|
|
10960
10560
|
const processes = [];
|
|
@@ -10972,9 +10572,9 @@ function findFirecrackerProcesses() {
|
|
|
10972
10572
|
if (!existsSync4(cmdlinePath)) continue;
|
|
10973
10573
|
try {
|
|
10974
10574
|
const cmdline = readFileSync2(cmdlinePath, "utf-8");
|
|
10975
|
-
const
|
|
10976
|
-
if (
|
|
10977
|
-
processes.push({ pid, vmId });
|
|
10575
|
+
const parsed = parseFirecrackerCmdline(cmdline);
|
|
10576
|
+
if (parsed) {
|
|
10577
|
+
processes.push({ pid, vmId: parsed.vmId, baseDir: parsed.baseDir });
|
|
10978
10578
|
}
|
|
10979
10579
|
} catch {
|
|
10980
10580
|
continue;
|
|
@@ -11007,13 +10607,14 @@ async function killProcess(pid, timeoutMs = 5e3) {
|
|
|
11007
10607
|
}
|
|
11008
10608
|
return !isProcessRunning(pid);
|
|
11009
10609
|
}
|
|
11010
|
-
function
|
|
10610
|
+
function findMitmproxyProcesses() {
|
|
10611
|
+
const processes = [];
|
|
11011
10612
|
const procDir = "/proc";
|
|
11012
10613
|
let entries;
|
|
11013
10614
|
try {
|
|
11014
10615
|
entries = readdirSync(procDir);
|
|
11015
10616
|
} catch {
|
|
11016
|
-
return
|
|
10617
|
+
return [];
|
|
11017
10618
|
}
|
|
11018
10619
|
for (const entry of entries) {
|
|
11019
10620
|
if (!/^\d+$/.test(entry)) continue;
|
|
@@ -11022,26 +10623,26 @@ function findMitmproxyProcess() {
|
|
|
11022
10623
|
if (!existsSync4(cmdlinePath)) continue;
|
|
11023
10624
|
try {
|
|
11024
10625
|
const cmdline = readFileSync2(cmdlinePath, "utf-8");
|
|
11025
|
-
const
|
|
11026
|
-
if (
|
|
11027
|
-
|
|
10626
|
+
const baseDir = parseMitmproxyCmdline(cmdline);
|
|
10627
|
+
if (baseDir) {
|
|
10628
|
+
processes.push({ pid, baseDir });
|
|
11028
10629
|
}
|
|
11029
10630
|
} catch {
|
|
11030
10631
|
continue;
|
|
11031
10632
|
}
|
|
11032
10633
|
}
|
|
11033
|
-
return
|
|
10634
|
+
return processes;
|
|
11034
10635
|
}
|
|
11035
10636
|
|
|
11036
10637
|
// src/lib/runner/types.ts
|
|
11037
|
-
import { z as
|
|
11038
|
-
var RunnerModeSchema =
|
|
11039
|
-
var RunnerStatusSchema =
|
|
10638
|
+
import { z as z31 } from "zod";
|
|
10639
|
+
var RunnerModeSchema = z31.enum(["running", "draining", "stopping", "stopped"]);
|
|
10640
|
+
var RunnerStatusSchema = z31.object({
|
|
11040
10641
|
mode: RunnerModeSchema,
|
|
11041
|
-
active_runs:
|
|
11042
|
-
active_run_ids:
|
|
11043
|
-
started_at:
|
|
11044
|
-
updated_at:
|
|
10642
|
+
active_runs: z31.number(),
|
|
10643
|
+
active_run_ids: z31.array(z31.string()),
|
|
10644
|
+
started_at: z31.string(),
|
|
10645
|
+
updated_at: z31.string()
|
|
11045
10646
|
});
|
|
11046
10647
|
|
|
11047
10648
|
// src/commands/doctor.ts
|
|
@@ -11083,20 +10684,14 @@ async function checkApiConnectivity(config, warnings) {
|
|
|
11083
10684
|
});
|
|
11084
10685
|
}
|
|
11085
10686
|
}
|
|
11086
|
-
|
|
10687
|
+
function checkNetwork(config, warnings) {
|
|
11087
10688
|
console.log("Network:");
|
|
11088
|
-
const
|
|
11089
|
-
const mitmProc =
|
|
11090
|
-
const portInUse = await isPortInUse(proxyPort);
|
|
10689
|
+
const mitmProcesses = findMitmproxyProcesses();
|
|
10690
|
+
const mitmProc = mitmProcesses.find((p) => p.baseDir === config.base_dir);
|
|
11091
10691
|
if (mitmProc) {
|
|
11092
|
-
console.log(` \u2713 Proxy mitmproxy (PID ${mitmProc.pid}) on :${proxyPort}`);
|
|
11093
|
-
} else if (portInUse) {
|
|
11094
10692
|
console.log(
|
|
11095
|
-
` \
|
|
10693
|
+
` \u2713 Proxy mitmproxy (PID ${mitmProc.pid}) on :${config.proxy.port}`
|
|
11096
10694
|
);
|
|
11097
|
-
warnings.push({
|
|
11098
|
-
message: `Port ${proxyPort} is in use but mitmproxy process not detected`
|
|
11099
|
-
});
|
|
11100
10695
|
} else {
|
|
11101
10696
|
console.log(` \u2717 Proxy mitmproxy not running`);
|
|
11102
10697
|
warnings.push({ message: "Proxy mitmproxy is not running" });
|
|
@@ -11182,7 +10777,8 @@ async function findOrphanNetworkNamespaces(warnings) {
|
|
|
11182
10777
|
return [];
|
|
11183
10778
|
}
|
|
11184
10779
|
}
|
|
11185
|
-
async function detectOrphanResources(jobs,
|
|
10780
|
+
async function detectOrphanResources(jobs, allProcesses, workspaces, statusVmIds, baseDir, warnings) {
|
|
10781
|
+
const processes = allProcesses.filter((p) => p.baseDir === baseDir);
|
|
11186
10782
|
for (const job of jobs) {
|
|
11187
10783
|
if (!job.firecrackerPid) {
|
|
11188
10784
|
warnings.push({
|
|
@@ -11244,7 +10840,7 @@ var doctorCommand = new Command2("doctor").description("Diagnose runner health,
|
|
|
11244
10840
|
console.log("");
|
|
11245
10841
|
await checkApiConnectivity(config, warnings);
|
|
11246
10842
|
console.log("");
|
|
11247
|
-
|
|
10843
|
+
checkNetwork(config, warnings);
|
|
11248
10844
|
console.log("");
|
|
11249
10845
|
const processes = findFirecrackerProcesses();
|
|
11250
10846
|
const workspaces = existsSync5(workspacesDir) ? readdirSync2(workspacesDir).filter(runnerPaths.isVmWorkspace) : [];
|
|
@@ -11256,6 +10852,7 @@ var doctorCommand = new Command2("doctor").description("Diagnose runner health,
|
|
|
11256
10852
|
processes,
|
|
11257
10853
|
workspaces,
|
|
11258
10854
|
statusVmIds,
|
|
10855
|
+
config.base_dir,
|
|
11259
10856
|
warnings
|
|
11260
10857
|
);
|
|
11261
10858
|
displayWarnings(warnings);
|
|
@@ -11502,6 +11099,7 @@ var benchmarkCommand = new Command4("benchmark").description(
|
|
|
11502
11099
|
}
|
|
11503
11100
|
process.exit(1);
|
|
11504
11101
|
}
|
|
11102
|
+
initVMRegistry(runnerPaths.vmRegistry(config.base_dir));
|
|
11505
11103
|
timer.log("Initializing pools...");
|
|
11506
11104
|
const snapshotConfig = config.firecracker.snapshot;
|
|
11507
11105
|
await initOverlayPool({
|
|
@@ -11747,7 +11345,7 @@ var snapshotCommand = new Command5("snapshot").description("Generate a Firecrack
|
|
|
11747
11345
|
);
|
|
11748
11346
|
|
|
11749
11347
|
// src/index.ts
|
|
11750
|
-
var version = true ? "3.12.
|
|
11348
|
+
var version = true ? "3.12.3" : "0.1.0";
|
|
11751
11349
|
program.name("vm0-runner").version(version).description("Self-hosted runner for VM0 agents");
|
|
11752
11350
|
program.addCommand(startCommand);
|
|
11753
11351
|
program.addCommand(doctorCommand);
|