@forgezero/agent 0.1.74 → 0.1.75
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +126 -17
- package/dist/agent-heartbeat.d.ts +25 -1
- package/dist/agent-heartbeat.js +45 -5
- package/dist/bootstrap.js +1 -1
- package/dist/community-rehearsal-host.js +208 -9
- package/dist/credential-schema.d.ts +1 -1
- package/dist/credential-schema.js +1 -1
- package/dist/definition.js +206 -7
- package/dist/deploy-actions.d.ts +7 -0
- package/dist/deploy-compiler.js +191 -10
- package/dist/deploy-file.js +206 -7
- package/dist/deploy-plan-runner.d.ts +3 -0
- package/dist/deploy-plan-runner.js +190 -9
- package/dist/deploy-plan.js +187 -8
- package/dist/deploy-providers.d.ts +19 -0
- package/dist/deploy.d.ts +89 -3
- package/dist/deploy.js +49 -2
- package/dist/deployment-connectivity.d.ts +63 -0
- package/dist/deployment-connectivity.js +148 -0
- package/dist/deployment-pull.d.ts +2 -0
- package/dist/deployment-targets.d.ts +9 -0
- package/dist/deployment-targets.js +141 -0
- package/dist/deployment.d.ts +69 -0
- package/dist/fz-agent.js +1111 -301
- package/dist/fz.js +220 -15
- package/dist/index.d.ts +1 -0
- package/dist/metal-bootstrap.js +1 -1
- package/dist/metal-helper-socket.js +210 -11
- package/dist/metal-provision.js +210 -11
- package/dist/operator-bootstrap.js +1 -1
- package/dist/platform-bootstrap-runtime.js +209 -10
- package/dist/platform-fleet-verification.js +515 -149
- package/dist/platform-genesis.js +206 -7
- package/dist/provision.js +465 -99
- package/dist/service-supervisor.d.ts +6 -0
- package/dist/software-helper.d.ts +3 -0
- package/dist/software-helper.js +465 -98
- package/dist/software.d.ts +4 -1
- package/dist/software.js +210 -8
- package/dist/ubuntu.js +206 -7
- package/dist/version.d.ts +1 -1
- package/package.json +12 -4
package/README.md
CHANGED
|
@@ -63,6 +63,8 @@ Every row links to the detailed explanation and named-import/example area below.
|
|
|
63
63
|
| @forgezero/agent/credential-schema | Canonical systemd credential names and validation shared by bootstrap and services. | Bun/Node host | [Reference + usage](#forgezero-agent-credential-schema) |
|
|
64
64
|
| @forgezero/agent/definition | Legacy version 3 JSON deployment compatibility contract. | Bun/Node host | [Reference + usage](#forgezero-agent-definition) |
|
|
65
65
|
| @forgezero/agent/deploy | Typed deployment authoring builders, built-in provider requirements and versioned action constructors. | Bun/Node host | [Reference + usage](#forgezero-agent-deploy) |
|
|
66
|
+
| @forgezero/agent/deployment-targets | Bounded input resolution and stable compute-target assignment for typed plans; emits requirements and slots rather than physical hostnames. | Bun/Node host | [Reference + usage](#forgezero-agent-deployment-targets) |
|
|
67
|
+
| @forgezero/agent/deployment-connectivity | Root-owned application of per-target Cloudflare Tunnel or WARP connector capabilities without exposing the project management token to a compute. | Bun/Node host | [Reference + usage](#forgezero-agent-deployment-connectivity) |
|
|
66
68
|
| @forgezero/agent/deploy-plan | Runtime validation, canonicalization and semantic digest for inert deployment plans. | Bun/Node host | [Reference + usage](#forgezero-agent-deploy-plan) |
|
|
67
69
|
| @forgezero/agent/deploy-plan-runner | Conditional DAG execution with bounded retry, compensation and failure policy over injected action handlers. | Bun/Node host | [Reference + usage](#forgezero-agent-deploy-plan-runner) |
|
|
68
70
|
| @forgezero/agent/deploy-compiler | Explicit developer/CI compiler from forgezero.deploy.ts to canonical .fz/deploy.plan.json; never used to execute project TypeScript in production. | Bun/Node host | [Reference + usage](#forgezero-agent-deploy-compiler) |
|
|
@@ -495,7 +497,7 @@ export const selectedCapability = PipelineError;
|
|
|
495
497
|
<a id="forgezero-agent-agent-heartbeat"></a>
|
|
496
498
|
## @forgezero/agent/agent-heartbeat
|
|
497
499
|
|
|
498
|
-
Signed node health publication with bounded renewal and shutdown withdrawal. This entry exposes 3 named value exports and
|
|
500
|
+
Signed node health publication with bounded renewal and shutdown withdrawal. This entry exposes 3 named value exports and 4 named type exports. The generated import block lists one name per line for scanning and copying; keep only the names used by your file.
|
|
499
501
|
|
|
500
502
|
```text
|
|
501
503
|
import {
|
|
@@ -507,6 +509,7 @@ import {
|
|
|
507
509
|
import type {
|
|
508
510
|
AgentHeartbeatOptions,
|
|
509
511
|
AgentHeartbeatResponse,
|
|
512
|
+
AgentHostMetrics,
|
|
510
513
|
AgentObservation,
|
|
511
514
|
} from '@forgezero/agent/agent-heartbeat';
|
|
512
515
|
```
|
|
@@ -1064,7 +1067,7 @@ export const selectedCapability = DEPLOY_SCHEMA_URL;
|
|
|
1064
1067
|
<a id="forgezero-agent-deploy"></a>
|
|
1065
1068
|
## @forgezero/agent/deploy
|
|
1066
1069
|
|
|
1067
|
-
Typed deployment authoring builders, built-in provider requirements and versioned action constructors. This entry exposes 14 named value exports and
|
|
1070
|
+
Typed deployment authoring builders, built-in provider requirements and versioned action constructors. This entry exposes 14 named value exports and 41 named type exports. The generated import block lists one name per line for scanning and copying; keep only the names used by your file.
|
|
1068
1071
|
|
|
1069
1072
|
```text
|
|
1070
1073
|
import {
|
|
@@ -1091,17 +1094,22 @@ import type {
|
|
|
1091
1094
|
BunProviderConfig,
|
|
1092
1095
|
CloudflaredProviderConfig,
|
|
1093
1096
|
ComponentDefinition,
|
|
1097
|
+
ComputeConnectivityDefinition,
|
|
1098
|
+
ComputePoolDefinition,
|
|
1094
1099
|
Condition,
|
|
1095
1100
|
ConditionOperand,
|
|
1101
|
+
ContainerdProviderConfig,
|
|
1096
1102
|
CredentialDefinition,
|
|
1097
1103
|
DatabaseComponent,
|
|
1098
1104
|
DeploymentSource,
|
|
1099
1105
|
DockerProviderConfig,
|
|
1100
1106
|
HealthDefinition,
|
|
1101
1107
|
InputDefinition,
|
|
1108
|
+
IntegerValue,
|
|
1102
1109
|
JsonObject,
|
|
1103
1110
|
JsonPrimitive,
|
|
1104
1111
|
JsonValue,
|
|
1112
|
+
KataProviderConfig,
|
|
1105
1113
|
NetworkDefinition,
|
|
1106
1114
|
NginxProviderConfig,
|
|
1107
1115
|
OpenSshProviderConfig,
|
|
@@ -1113,6 +1121,7 @@ import type {
|
|
|
1113
1121
|
StageDefinition,
|
|
1114
1122
|
StepScope,
|
|
1115
1123
|
StorageMount,
|
|
1124
|
+
StringValue,
|
|
1116
1125
|
SystemdProviderConfig,
|
|
1117
1126
|
TargetDefinition,
|
|
1118
1127
|
UfwProviderConfig,
|
|
@@ -1123,16 +1132,19 @@ import type {
|
|
|
1123
1132
|
} from '@forgezero/agent/deploy';
|
|
1124
1133
|
```
|
|
1125
1134
|
|
|
1126
|
-
## @forgezero/agent/deploy — Author a typed
|
|
1135
|
+
## @forgezero/agent/deploy — Author a typed, placed containerd deployment
|
|
1127
1136
|
|
|
1128
|
-
TypeScript is authoring only. The checked-in canonical plan is what Agents validate and execute.
|
|
1137
|
+
TypeScript is authoring only. The checked-in canonical plan is what Agents validate and execute. Targets declare bounded resource/cardinality intent, not hostnames. The API reserves eligible project capacity or provisions only under the reviewed plan and spend ceiling, assigns stable slots, and the Agent runs only its exact assignment. runc containers must declare hard CPU, memory and PID limits, bounded storage, loopback ingress and a health-gated rollout; select Kata QEMU SNP when the workload needs host isolation.
|
|
1129
1138
|
|
|
1130
1139
|
```text
|
|
1131
1140
|
import {
|
|
1132
1141
|
actions,
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1142
|
+
application,
|
|
1143
|
+
credential,
|
|
1144
|
+
defineDeployment,
|
|
1145
|
+
input,
|
|
1146
|
+
providers,
|
|
1147
|
+
ref,
|
|
1136
1148
|
stage,
|
|
1137
1149
|
target,
|
|
1138
1150
|
workflow,
|
|
@@ -1142,24 +1154,117 @@ export default defineDeployment({
|
|
|
1142
1154
|
apiVersion: 'deploy.forgezero.net/v1', kind: 'Deployment',
|
|
1143
1155
|
metadata: { name: 'orders-api' },
|
|
1144
1156
|
spec: {
|
|
1145
|
-
|
|
1146
|
-
|
|
1157
|
+
inputs: {
|
|
1158
|
+
replicas: input.integer({ minimum: 1, maximum: 16, default: 1 }),
|
|
1159
|
+
cpuCores: input.integer({ minimum: 1, maximum: 32, default: 1 }),
|
|
1160
|
+
memoryMiB: input.integer({ minimum: 256, maximum: 131072, default: 512 }),
|
|
1161
|
+
storageGiB: input.integer({ minimum: 4, maximum: 2048, default: 8 })
|
|
1162
|
+
},
|
|
1163
|
+
credentials: {
|
|
1164
|
+
cloudflare: credential.vault({ schema: 'forgezero.cloudflare/management@1', name: 'cloudflare-management' })
|
|
1165
|
+
},
|
|
1166
|
+
targets: { api: target.compute({
|
|
1167
|
+
profiles: ['api'], replicas: { minimum: 1, desired: input.ref('replicas'), maximum: 16 },
|
|
1168
|
+
resources: { cpuCores: input.ref('cpuCores'), memoryMiB: input.ref('memoryMiB'), storageGiB: input.ref('storageGiB') },
|
|
1169
|
+
os: 'ubuntu-24.04', runtime: 'oci-runc', sharing: 'shared', reuse: 'prefer',
|
|
1170
|
+
provisioning: {
|
|
1171
|
+
planKey: 'app-small', regionKey: 'default', imageKey: 'ubuntu-24.04-x64',
|
|
1172
|
+
environmentKey: 'production', ownership: 'platform', maxMonthlySpendMinor: '25000'
|
|
1173
|
+
},
|
|
1174
|
+
connectivity: {
|
|
1175
|
+
private: { mode: 'private-lan' },
|
|
1176
|
+
public: { mode: 'cloudflare-tunnel', credential: 'cloudflare', zone: 'example.com', hostname: { mode: 'indexed', prefix: 'api' } }
|
|
1177
|
+
}
|
|
1178
|
+
}) },
|
|
1179
|
+
requirements: {
|
|
1180
|
+
containerd: providers.containerd.require(), nginx: providers.nginx.require(),
|
|
1181
|
+
cloudflared: providers.cloudflared.require()
|
|
1182
|
+
},
|
|
1147
1183
|
components: {
|
|
1148
1184
|
api: application({
|
|
1149
1185
|
target: 'api',
|
|
1150
|
-
|
|
1186
|
+
runtime: { kind: 'container', provider: 'forgezero.containerd', requirement: 'containerd', runtimeClass: 'runc', image: { source: { kind: 'build', context: '.', dockerfile: 'Dockerfile' } }, security: { privileged: false, noNewPrivileges: true, root: 'read-only', dropCapabilities: ['ALL'] } },
|
|
1151
1187
|
service: { protocol: 'http', port: 3000, health: { protocol: 'http', method: 'GET', path: '/health', expectedStatus: [200], timeoutMs: 2000 } },
|
|
1152
|
-
|
|
1188
|
+
resources: { cpu: { limit: 1 }, memory: { limitMiB: 512, swap: 'disabled' }, pids: { limit: 256 } },
|
|
1153
1189
|
storage: [{ class: 'ephemeral', path: '/tmp', type: 'tmpfs', sizeMiB: 128 }],
|
|
1154
|
-
|
|
1190
|
+
network: {
|
|
1191
|
+
ingress: { exposure: 'public', stablePort: 3000 },
|
|
1192
|
+
public: { mode: 'cloudflare-tunnel' },
|
|
1193
|
+
container: { mode: 'bridge', network: 'api' }
|
|
1194
|
+
},
|
|
1155
1195
|
rollout: { strategy: 'blue-green', proxy: 'nginx', automaticRollback: true }
|
|
1156
1196
|
})
|
|
1157
1197
|
},
|
|
1158
|
-
|
|
1198
|
+
workflows: { deploy: workflow({ stages: {
|
|
1199
|
+
prepare: stage({ strategy: { mode: 'sequential' }, steps: {
|
|
1200
|
+
software: actions.software.ensure({ requirements: ['containerd', 'nginx', 'cloudflared'] }, { scope: { kind: 'each-target', target: 'api' } }),
|
|
1201
|
+
network: actions.network.ensure({ target: 'api' }, { scope: { kind: 'each-target', target: 'api' } }),
|
|
1202
|
+
image: actions.container.build({ component: 'api' }, { scope: { kind: 'each-target', target: 'api' } })
|
|
1203
|
+
} }),
|
|
1204
|
+
release: stage({ dependsOn: ['prepare'], strategy: { mode: 'blue-green' }, steps: {
|
|
1205
|
+
promote: actions.service.promote({ component: 'api', imageDigest: ref.stepOutput('image', 'digest') }, { scope: { kind: 'each-target', target: 'api' } })
|
|
1206
|
+
} })
|
|
1207
|
+
} }) }
|
|
1159
1208
|
}
|
|
1160
1209
|
});
|
|
1161
1210
|
```
|
|
1162
1211
|
|
|
1212
|
+
<a id="forgezero-agent-deployment-targets"></a>
|
|
1213
|
+
## @forgezero/agent/deployment-targets
|
|
1214
|
+
|
|
1215
|
+
Bounded input resolution and stable compute-target assignment for typed plans; emits requirements and slots rather than physical hostnames. This entry exposes 3 named value exports and 0 named type exports. The generated import block lists one name per line for scanning and copying; keep only the names used by your file.
|
|
1216
|
+
|
|
1217
|
+
```text
|
|
1218
|
+
import {
|
|
1219
|
+
DeploymentInputError,
|
|
1220
|
+
resolveDeploymentInputs,
|
|
1221
|
+
resolveDeploymentTargets,
|
|
1222
|
+
} from '@forgezero/agent/deployment-targets';
|
|
1223
|
+
```
|
|
1224
|
+
|
|
1225
|
+
## @forgezero/agent/deployment-targets — Use this entry point
|
|
1226
|
+
|
|
1227
|
+
This minimal executable use imports one concrete value from this exact entry point without a wildcard or package-root detour. Keep the value or values the application actually needs; the full named inventory remains directly above it.
|
|
1228
|
+
|
|
1229
|
+
```text
|
|
1230
|
+
import {
|
|
1231
|
+
DeploymentInputError,
|
|
1232
|
+
} from '@forgezero/agent/deployment-targets';
|
|
1233
|
+
|
|
1234
|
+
export const selectedCapability = DeploymentInputError;
|
|
1235
|
+
```
|
|
1236
|
+
|
|
1237
|
+
<a id="forgezero-agent-deployment-connectivity"></a>
|
|
1238
|
+
## @forgezero/agent/deployment-connectivity
|
|
1239
|
+
|
|
1240
|
+
Root-owned application of per-target Cloudflare Tunnel or WARP connector capabilities without exposing the project management token to a compute. This entry exposes 1 named value export and 5 named type exports. The generated import block lists one name per line for scanning and copying; keep only the names used by your file.
|
|
1241
|
+
|
|
1242
|
+
```text
|
|
1243
|
+
import {
|
|
1244
|
+
applyDeploymentConnectivity,
|
|
1245
|
+
} from '@forgezero/agent/deployment-connectivity';
|
|
1246
|
+
|
|
1247
|
+
import type {
|
|
1248
|
+
DeploymentConnectivityCapabilities,
|
|
1249
|
+
DeploymentConnectivityEvidence,
|
|
1250
|
+
DeploymentConnectivityHost,
|
|
1251
|
+
DeploymentConnectivityIntent,
|
|
1252
|
+
DeploymentConnectivityRequest,
|
|
1253
|
+
} from '@forgezero/agent/deployment-connectivity';
|
|
1254
|
+
```
|
|
1255
|
+
|
|
1256
|
+
## @forgezero/agent/deployment-connectivity — Use this entry point
|
|
1257
|
+
|
|
1258
|
+
This minimal executable use imports one concrete value from this exact entry point without a wildcard or package-root detour. Keep the value or values the application actually needs; the full named inventory remains directly above it.
|
|
1259
|
+
|
|
1260
|
+
```text
|
|
1261
|
+
import {
|
|
1262
|
+
applyDeploymentConnectivity,
|
|
1263
|
+
} from '@forgezero/agent/deployment-connectivity';
|
|
1264
|
+
|
|
1265
|
+
export const selectedCapability = applyDeploymentConnectivity;
|
|
1266
|
+
```
|
|
1267
|
+
|
|
1163
1268
|
<a id="forgezero-agent-deploy-plan"></a>
|
|
1164
1269
|
## @forgezero/agent/deploy-plan
|
|
1165
1270
|
|
|
@@ -1540,11 +1645,14 @@ if (!validate(deploymentDefinition)) throw new Error(JSON.stringify(validate.err
|
|
|
1540
1645
|
<a id="forgezero-agent-software"></a>
|
|
1541
1646
|
## @forgezero/agent/software
|
|
1542
1647
|
|
|
1543
|
-
Exact managed-software inventory, requirement and evidence contracts. This entry exposes
|
|
1648
|
+
Exact managed-software inventory, requirement and evidence contracts. This entry exposes 13 named value exports and 10 named type exports. The generated import block lists one name per line for scanning and copying; keep only the names used by your file.
|
|
1544
1649
|
|
|
1545
1650
|
```text
|
|
1546
1651
|
import {
|
|
1652
|
+
BUILDKIT_VERSION,
|
|
1547
1653
|
BUN_RELEASE_SHA256,
|
|
1654
|
+
KATA_CONTAINERS_VERSION,
|
|
1655
|
+
NERDCTL_VERSION,
|
|
1548
1656
|
OS_CATALOG,
|
|
1549
1657
|
PINNED_BUN_VERSION,
|
|
1550
1658
|
SOFTWARE_CATALOG,
|
|
@@ -1576,16 +1684,16 @@ This minimal executable use imports one concrete value from this exact entry poi
|
|
|
1576
1684
|
|
|
1577
1685
|
```text
|
|
1578
1686
|
import {
|
|
1579
|
-
|
|
1687
|
+
BUILDKIT_VERSION,
|
|
1580
1688
|
} from '@forgezero/agent/software';
|
|
1581
1689
|
|
|
1582
|
-
export const selectedCapability =
|
|
1690
|
+
export const selectedCapability = BUILDKIT_VERSION;
|
|
1583
1691
|
```
|
|
1584
1692
|
|
|
1585
1693
|
<a id="forgezero-agent-software-helper"></a>
|
|
1586
1694
|
## @forgezero/agent/software-helper
|
|
1587
1695
|
|
|
1588
|
-
Root-owned fixed installation/update boundary for declared software. This entry exposes
|
|
1696
|
+
Root-owned fixed installation/update boundary for declared software. This entry exposes 9 named value exports and 0 named type exports. The generated import block lists one name per line for scanning and copying; keep only the names used by your file.
|
|
1589
1697
|
|
|
1590
1698
|
```text
|
|
1591
1699
|
import {
|
|
@@ -1594,6 +1702,7 @@ import {
|
|
|
1594
1702
|
SOFTWARE_HELPER_UNIT_PATH,
|
|
1595
1703
|
requestContainerActivation,
|
|
1596
1704
|
requestContainerBuild,
|
|
1705
|
+
requestDeploymentConnectivity,
|
|
1597
1706
|
requestServiceActivation,
|
|
1598
1707
|
requestSoftware,
|
|
1599
1708
|
startSoftwareHelper,
|
|
@@ -10,6 +10,22 @@ export interface AgentObservation {
|
|
|
10
10
|
};
|
|
11
11
|
architecture: string;
|
|
12
12
|
mode: 'attested' | 'enrolled';
|
|
13
|
+
runtimeCapabilities?: {
|
|
14
|
+
native: true;
|
|
15
|
+
ociRunc: boolean;
|
|
16
|
+
kataQemuSnp: boolean;
|
|
17
|
+
};
|
|
18
|
+
/** Signed host evidence. Placement still reserves declared capacity; it never chases transient utilization. */
|
|
19
|
+
capacity?: {
|
|
20
|
+
logicalCpu: number;
|
|
21
|
+
memoryMiB: number;
|
|
22
|
+
storageGiB: number;
|
|
23
|
+
};
|
|
24
|
+
utilization?: {
|
|
25
|
+
load1mMilli: number;
|
|
26
|
+
memoryUsedMiB: number;
|
|
27
|
+
storageUsedGiB: number;
|
|
28
|
+
};
|
|
13
29
|
update?: AgentUpdateReceipt;
|
|
14
30
|
deploymentIntake?: {
|
|
15
31
|
generation: number;
|
|
@@ -32,6 +48,14 @@ export interface AgentHeartbeatResponse {
|
|
|
32
48
|
state: 'running' | 'paused';
|
|
33
49
|
};
|
|
34
50
|
}
|
|
51
|
+
export interface AgentHostMetrics {
|
|
52
|
+
logicalCpu: number;
|
|
53
|
+
memoryBytes: number;
|
|
54
|
+
memoryFreeBytes: number;
|
|
55
|
+
storageBytes: number;
|
|
56
|
+
storageFreeBytes: number;
|
|
57
|
+
load1m: number;
|
|
58
|
+
}
|
|
35
59
|
export interface AgentHeartbeatOptions {
|
|
36
60
|
apiUrl: string;
|
|
37
61
|
nodeKey: string;
|
|
@@ -58,7 +82,7 @@ export interface AgentHeartbeatOptions {
|
|
|
58
82
|
onEvent?: (event: string, detail?: unknown) => void;
|
|
59
83
|
telemetry?: AgentOperationTelemetry;
|
|
60
84
|
}
|
|
61
|
-
export declare function observeAgentHost(version?: string, mode?: AgentObservation['mode'], osRelease?: string, architecture?: NodeJS.Architecture): AgentObservation;
|
|
85
|
+
export declare function observeAgentHost(version?: string, mode?: AgentObservation['mode'], osRelease?: string, architecture?: NodeJS.Architecture, metrics?: AgentHostMetrics): AgentObservation;
|
|
62
86
|
/** One PQ-authenticated observation and optional supervised update decision. */
|
|
63
87
|
export declare function heartbeatAgentOnce(options: AgentHeartbeatOptions): Promise<AgentHeartbeatResponse>;
|
|
64
88
|
/** Server-paced heartbeat; stopping waits for the active PQ request/update handoff. */
|
package/dist/agent-heartbeat.js
CHANGED
|
@@ -677,7 +677,8 @@ function requestAgentUpdate(request, socketPath = DEFAULT_AGENT_UPDATE_SOCKET, t
|
|
|
677
677
|
}
|
|
678
678
|
|
|
679
679
|
// src/agent-heartbeat.ts
|
|
680
|
-
import { readFileSync as readFileSync3 } from "node:fs";
|
|
680
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, statfsSync } from "node:fs";
|
|
681
|
+
import { cpus, freemem, loadavg, totalmem } from "node:os";
|
|
681
682
|
|
|
682
683
|
// src/signed-node-http.ts
|
|
683
684
|
import {
|
|
@@ -749,25 +750,64 @@ async function postSignedNode(options, path, body) {
|
|
|
749
750
|
}
|
|
750
751
|
|
|
751
752
|
// src/version.ts
|
|
752
|
-
var VERSION3 = "0.1.
|
|
753
|
+
var VERSION3 = "0.1.75";
|
|
753
754
|
|
|
754
755
|
// src/agent-heartbeat.ts
|
|
756
|
+
function readAgentHostMetrics() {
|
|
757
|
+
const filesystem = statfsSync("/");
|
|
758
|
+
return {
|
|
759
|
+
logicalCpu: cpus().length,
|
|
760
|
+
memoryBytes: totalmem(),
|
|
761
|
+
memoryFreeBytes: freemem(),
|
|
762
|
+
storageBytes: Number(filesystem.blocks) * Number(filesystem.bsize),
|
|
763
|
+
storageFreeBytes: Number(filesystem.bavail) * Number(filesystem.bsize),
|
|
764
|
+
load1m: loadavg()[0]
|
|
765
|
+
};
|
|
766
|
+
}
|
|
755
767
|
var unquote = (value) => value.replace(/^['"]|['"]$/g, "");
|
|
756
768
|
var remoteOutcome = (cause) => cause instanceof SignedNodeHttpError && cause.status < 500 ? "refused" : cause instanceof SignedNodeHttpError ? "retryable" : "failed";
|
|
757
769
|
|
|
758
770
|
class AgentUpdateRefusedError extends Error {
|
|
759
771
|
}
|
|
760
|
-
function observeAgentHost(version = VERSION3, mode = "enrolled", osRelease = readFileSync3("/etc/os-release", "utf8"), architecture = process.arch) {
|
|
772
|
+
function observeAgentHost(version = VERSION3, mode = "enrolled", osRelease = readFileSync3("/etc/os-release", "utf8"), architecture = process.arch, metrics = readAgentHostMetrics()) {
|
|
761
773
|
const values = Object.fromEntries(osRelease.split(`
|
|
762
774
|
`).flatMap((line) => {
|
|
763
775
|
const separator = line.indexOf("=");
|
|
764
776
|
return separator > 0 ? [[line.slice(0, separator), unquote(line.slice(separator + 1))]] : [];
|
|
765
777
|
}));
|
|
778
|
+
const osId = (values.ID ?? "unknown").toLowerCase();
|
|
779
|
+
const osVersion = values.VERSION_ID ?? "unknown";
|
|
780
|
+
const ubuntuX64 = osId === "ubuntu" && ["24.04", "26.04"].includes(osVersion) && architecture === "x64";
|
|
781
|
+
const enabled = (path) => {
|
|
782
|
+
try {
|
|
783
|
+
return /^(?:1|y)$/i.test(readFileSync3(path, "utf8").trim());
|
|
784
|
+
} catch {
|
|
785
|
+
return false;
|
|
786
|
+
}
|
|
787
|
+
};
|
|
788
|
+
const gib = 1024 ** 3;
|
|
789
|
+
const mib = 1024 ** 2;
|
|
790
|
+
const storageGiB = Math.max(1, Math.floor(metrics.storageBytes / gib));
|
|
766
791
|
return {
|
|
767
792
|
version,
|
|
768
|
-
os: { id:
|
|
793
|
+
os: { id: osId, versionId: osVersion },
|
|
769
794
|
architecture,
|
|
770
|
-
mode
|
|
795
|
+
mode,
|
|
796
|
+
runtimeCapabilities: {
|
|
797
|
+
native: true,
|
|
798
|
+
ociRunc: ubuntuX64,
|
|
799
|
+
kataQemuSnp: ubuntuX64 && osVersion === "26.04" && existsSync3("/dev/kvm") && existsSync3("/dev/sev") && enabled("/sys/module/kvm_amd/parameters/sev") && enabled("/sys/module/kvm_amd/parameters/sev_snp")
|
|
800
|
+
},
|
|
801
|
+
capacity: {
|
|
802
|
+
logicalCpu: Math.max(1, metrics.logicalCpu),
|
|
803
|
+
memoryMiB: Math.max(1, Math.floor(metrics.memoryBytes / mib)),
|
|
804
|
+
storageGiB
|
|
805
|
+
},
|
|
806
|
+
utilization: {
|
|
807
|
+
load1mMilli: Math.max(0, Math.round(metrics.load1m * 1000)),
|
|
808
|
+
memoryUsedMiB: Math.max(0, Math.floor((metrics.memoryBytes - metrics.memoryFreeBytes) / mib)),
|
|
809
|
+
storageUsedGiB: Math.max(0, Math.min(storageGiB, Math.ceil((metrics.storageBytes - metrics.storageFreeBytes) / gib)))
|
|
810
|
+
}
|
|
771
811
|
};
|
|
772
812
|
}
|
|
773
813
|
async function heartbeatAgentOnce(options) {
|
package/dist/bootstrap.js
CHANGED