@hasna/machines 0.0.23 → 0.0.25
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 +49 -5
- package/dist/agent/index.js +1 -1
- package/dist/cli/index.js +272 -41
- package/dist/commands/apps.d.ts.map +1 -1
- package/dist/commands/manifest.d.ts.map +1 -1
- package/dist/commands/screen.d.ts +35 -0
- package/dist/commands/screen.d.ts.map +1 -0
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/consumer-schema.d.ts +21 -0
- package/dist/consumer-schema.d.ts.map +1 -0
- package/dist/consumer.d.ts +4 -2
- package/dist/consumer.d.ts.map +1 -1
- package/dist/consumer.js +499 -13
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +339 -31
- package/dist/manifests.d.ts.map +1 -1
- package/dist/mcp/index.js +146 -37
- package/dist/topology.d.ts +117 -1
- package/dist/topology.d.ts.map +1 -1
- package/package.json +2 -1
- package/schemas/machines-consumer.schema.json +47 -0
- package/scripts/consumer-conformance.mjs +27 -2
package/dist/consumer.js
CHANGED
|
@@ -4264,6 +4264,7 @@ function writeManifest(manifest, path = getManifestPath()) {
|
|
|
4264
4264
|
generatedAt: new Date().toISOString(),
|
|
4265
4265
|
machines: normalizeMachines(manifest.machines)
|
|
4266
4266
|
};
|
|
4267
|
+
fleetSchema.parse(payload);
|
|
4267
4268
|
writeFileSync(path, `${JSON.stringify(payload, null, 2)}
|
|
4268
4269
|
`, "utf8");
|
|
4269
4270
|
return path;
|
|
@@ -4312,29 +4313,78 @@ function getPackageVersion() {
|
|
|
4312
4313
|
var MACHINES_CONSUMER_CONTRACT_VERSION = 1;
|
|
4313
4314
|
var MACHINES_PACKAGE_NAME = "@hasna/machines";
|
|
4314
4315
|
var MACHINES_CONSUMER_ENTRYPOINT = "@hasna/machines/consumer";
|
|
4316
|
+
var MACHINES_CONSUMER_SCHEMA_URI = "https://schemas.hasna.xyz/machines/consumer/v1/machines-consumer.schema.json";
|
|
4317
|
+
var MACHINES_CONSUMER_SCHEMA_ARTIFACT = "schemas/machines-consumer.schema.json";
|
|
4318
|
+
var DEFAULT_MACHINE_RESOLVER_TTL_MS = 24 * 60 * 60 * 1000;
|
|
4315
4319
|
var MACHINES_CONSUMER_CAPABILITIES = {
|
|
4316
4320
|
topology: true,
|
|
4317
4321
|
compatibility: true,
|
|
4318
4322
|
route_resolution: true,
|
|
4319
4323
|
cli_json_fallback: true,
|
|
4320
4324
|
workspace_path_mapping: true,
|
|
4321
|
-
workspace_diagnostics: true
|
|
4325
|
+
workspace_diagnostics: true,
|
|
4326
|
+
schema_artifacts: true,
|
|
4327
|
+
cacheability_metadata: true,
|
|
4328
|
+
resolver_snapshots: true,
|
|
4329
|
+
field_capability_descriptors: true
|
|
4330
|
+
};
|
|
4331
|
+
var MACHINES_CONSUMER_FIELD_CAPABILITIES = {
|
|
4332
|
+
topology: {
|
|
4333
|
+
machine_identity: true,
|
|
4334
|
+
route_hints: true,
|
|
4335
|
+
tailscale_status: true,
|
|
4336
|
+
manifest_metadata: true
|
|
4337
|
+
},
|
|
4338
|
+
route: {
|
|
4339
|
+
cacheability: true,
|
|
4340
|
+
confidence: true,
|
|
4341
|
+
resolver_evidence: true
|
|
4342
|
+
},
|
|
4343
|
+
workspace: {
|
|
4344
|
+
cacheability: true,
|
|
4345
|
+
path_mapping: true,
|
|
4346
|
+
diagnostics: true,
|
|
4347
|
+
repair_hints: true,
|
|
4348
|
+
trust_auth: true
|
|
4349
|
+
},
|
|
4350
|
+
compatibility: {
|
|
4351
|
+
commands: true,
|
|
4352
|
+
packages: true,
|
|
4353
|
+
workspaces: true
|
|
4354
|
+
},
|
|
4355
|
+
resolver_snapshot: {
|
|
4356
|
+
cacheability: true,
|
|
4357
|
+
redacted_provenance: true
|
|
4358
|
+
}
|
|
4322
4359
|
};
|
|
4323
4360
|
var MACHINES_CONSUMER_CONTRACT = {
|
|
4324
4361
|
schema_version: MACHINES_CONSUMER_CONTRACT_VERSION,
|
|
4325
4362
|
package_name: MACHINES_PACKAGE_NAME,
|
|
4326
4363
|
entrypoint: MACHINES_CONSUMER_ENTRYPOINT,
|
|
4364
|
+
schema_uri: MACHINES_CONSUMER_SCHEMA_URI,
|
|
4365
|
+
schema_artifact: MACHINES_CONSUMER_SCHEMA_ARTIFACT,
|
|
4327
4366
|
capabilities: MACHINES_CONSUMER_CAPABILITIES,
|
|
4328
|
-
|
|
4367
|
+
field_capabilities: MACHINES_CONSUMER_FIELD_CAPABILITIES,
|
|
4368
|
+
cacheability: {
|
|
4369
|
+
default_ttl_ms: DEFAULT_MACHINE_RESOLVER_TTL_MS,
|
|
4370
|
+
stale_requires_refresh: true
|
|
4371
|
+
},
|
|
4372
|
+
envelopes: ["topology", "route", "workspace", "compatibility", "resolver_snapshot"],
|
|
4329
4373
|
stable_exports: [
|
|
4330
4374
|
"MACHINES_CONSUMER_CONTRACT",
|
|
4331
4375
|
"MACHINES_CONSUMER_CONTRACT_VERSION",
|
|
4332
4376
|
"MACHINES_CONSUMER_CAPABILITIES",
|
|
4377
|
+
"MACHINES_CONSUMER_FIELD_CAPABILITIES",
|
|
4378
|
+
"MACHINES_CONSUMER_SCHEMA_BUNDLE",
|
|
4379
|
+
"MACHINES_CONSUMER_SCHEMA_URI",
|
|
4333
4380
|
"MACHINES_PACKAGE_NAME",
|
|
4334
4381
|
"discoverMachineTopology",
|
|
4335
4382
|
"getLocalMachineTopology",
|
|
4336
4383
|
"resolveMachineRoute",
|
|
4337
4384
|
"resolveMachineWorkspace",
|
|
4385
|
+
"createMachineResolverSnapshot",
|
|
4386
|
+
"getMachinesConsumerSchemaBundle",
|
|
4387
|
+
"validateMachinesConsumerEnvelope",
|
|
4338
4388
|
"checkMachineCompatibility",
|
|
4339
4389
|
"resolveMachineCommand",
|
|
4340
4390
|
"runMachineCommand",
|
|
@@ -4612,11 +4662,100 @@ function routeConfidence(input) {
|
|
|
4612
4662
|
return "low";
|
|
4613
4663
|
return "none";
|
|
4614
4664
|
}
|
|
4665
|
+
function addMilliseconds(date, milliseconds) {
|
|
4666
|
+
return new Date(date.getTime() + milliseconds).toISOString();
|
|
4667
|
+
}
|
|
4668
|
+
function routeAuthority(input) {
|
|
4669
|
+
if (!input.machine)
|
|
4670
|
+
return "unresolved";
|
|
4671
|
+
if (input.matchedBy === "fallback")
|
|
4672
|
+
return "fallback";
|
|
4673
|
+
if (input.selectedHint?.kind === "local")
|
|
4674
|
+
return "live_topology";
|
|
4675
|
+
if (input.selectedHint?.kind === "tailscale" || input.machine.tailscale.online !== null)
|
|
4676
|
+
return "live_topology";
|
|
4677
|
+
if (input.machine.manifest_declared)
|
|
4678
|
+
return "manifest";
|
|
4679
|
+
return "open-machines";
|
|
4680
|
+
}
|
|
4681
|
+
function workspaceAuthority(paths) {
|
|
4682
|
+
const sources = [paths.workspace_root.source, paths.project_root.source, paths.open_files_root.source];
|
|
4683
|
+
if (sources.some((source) => source === "argument"))
|
|
4684
|
+
return "argument";
|
|
4685
|
+
if (sources.some((source) => source === "manifest_metadata"))
|
|
4686
|
+
return "manifest_metadata";
|
|
4687
|
+
if (sources.some((source) => source === "manifest"))
|
|
4688
|
+
return "manifest";
|
|
4689
|
+
if (sources.some((source) => source === "inferred"))
|
|
4690
|
+
return "inferred";
|
|
4691
|
+
if (sources.every((source) => source === "unresolved"))
|
|
4692
|
+
return "unresolved";
|
|
4693
|
+
return "open-machines";
|
|
4694
|
+
}
|
|
4695
|
+
function cacheability(input) {
|
|
4696
|
+
const ttlMs = input.ttlMs === undefined ? DEFAULT_MACHINE_RESOLVER_TTL_MS : input.ttlMs;
|
|
4697
|
+
const expiresAt = typeof ttlMs === "number" && ttlMs > 0 ? addMilliseconds(input.observedAt, ttlMs) : null;
|
|
4698
|
+
const stale = expiresAt ? input.now.getTime() > new Date(expiresAt).getTime() : false;
|
|
4699
|
+
const confidenceCacheable = input.confidence !== "none" && input.confidence !== "low";
|
|
4700
|
+
const cacheable = input.ok && confidenceCacheable && !stale && input.authority !== "unresolved";
|
|
4701
|
+
const reasons = [...input.reasons];
|
|
4702
|
+
if (!input.ok)
|
|
4703
|
+
reasons.push("resolver_not_ok");
|
|
4704
|
+
if (!confidenceCacheable)
|
|
4705
|
+
reasons.push(`low_confidence:${input.confidence}`);
|
|
4706
|
+
if (stale)
|
|
4707
|
+
reasons.push("stale");
|
|
4708
|
+
if (input.authority === "unresolved")
|
|
4709
|
+
reasons.push("unresolved_authority");
|
|
4710
|
+
return {
|
|
4711
|
+
observed_at: input.observedAt.toISOString(),
|
|
4712
|
+
verified_at: input.ok ? input.now.toISOString() : null,
|
|
4713
|
+
expires_at: expiresAt,
|
|
4714
|
+
ttl_ms: typeof ttlMs === "number" && ttlMs > 0 ? ttlMs : null,
|
|
4715
|
+
source_authority: input.authority,
|
|
4716
|
+
confidence: input.confidence,
|
|
4717
|
+
cacheable,
|
|
4718
|
+
stale,
|
|
4719
|
+
reasons: [...new Set(reasons)].sort()
|
|
4720
|
+
};
|
|
4721
|
+
}
|
|
4722
|
+
function worstConfidence(values) {
|
|
4723
|
+
const rank = {
|
|
4724
|
+
exact: 0,
|
|
4725
|
+
high: 1,
|
|
4726
|
+
medium: 2,
|
|
4727
|
+
low: 3,
|
|
4728
|
+
none: 4
|
|
4729
|
+
};
|
|
4730
|
+
return [...values].sort((left, right) => rank[right] - rank[left])[0] ?? "none";
|
|
4731
|
+
}
|
|
4732
|
+
function mergeAuthorities(values) {
|
|
4733
|
+
const filtered = values.filter((value) => value !== "unknown");
|
|
4734
|
+
if (filtered.length === 0)
|
|
4735
|
+
return "unknown";
|
|
4736
|
+
const first = filtered[0];
|
|
4737
|
+
return filtered.every((value) => value === first) ? first : "mixed";
|
|
4738
|
+
}
|
|
4739
|
+
function mergeCacheability(input) {
|
|
4740
|
+
const confidence = worstConfidence(input.cacheabilities.map((entry) => entry.confidence));
|
|
4741
|
+
const reasons = input.cacheabilities.flatMap((entry) => entry.reasons);
|
|
4742
|
+
const ok = input.cacheabilities.every((entry) => entry.cacheable);
|
|
4743
|
+
return cacheability({
|
|
4744
|
+
ok,
|
|
4745
|
+
observedAt: input.observedAt,
|
|
4746
|
+
now: input.now,
|
|
4747
|
+
ttlMs: input.ttlMs,
|
|
4748
|
+
authority: mergeAuthorities(input.authorities),
|
|
4749
|
+
confidence,
|
|
4750
|
+
reasons
|
|
4751
|
+
});
|
|
4752
|
+
}
|
|
4615
4753
|
function resolveMachineRoute(machineId, options = {}) {
|
|
4754
|
+
const now = options.now ?? new Date;
|
|
4616
4755
|
const topology = options.topology ?? discoverMachineTopology(options);
|
|
4617
4756
|
const warnings = [...topology.warnings];
|
|
4618
4757
|
const { machine, matchedBy } = findRouteMachine(topology, machineId);
|
|
4619
|
-
const generatedAt =
|
|
4758
|
+
const generatedAt = now.toISOString();
|
|
4620
4759
|
if (!machine) {
|
|
4621
4760
|
warnings.push(`machine_not_found:${machineId}`);
|
|
4622
4761
|
return {
|
|
@@ -4640,16 +4779,27 @@ function resolveMachineRoute(machineId, options = {}) {
|
|
|
4640
4779
|
tailscale_online: null,
|
|
4641
4780
|
selected_hint: null
|
|
4642
4781
|
},
|
|
4782
|
+
cacheability: cacheability({
|
|
4783
|
+
ok: false,
|
|
4784
|
+
observedAt: now,
|
|
4785
|
+
now,
|
|
4786
|
+
ttlMs: options.resolverTtlMs,
|
|
4787
|
+
authority: "unresolved",
|
|
4788
|
+
confidence: "none",
|
|
4789
|
+
reasons: [`machine_not_found:${machineId}`]
|
|
4790
|
+
}),
|
|
4643
4791
|
warnings
|
|
4644
4792
|
};
|
|
4645
4793
|
}
|
|
4646
4794
|
const selectedHint = selectRouteHint(machine.route_hints);
|
|
4647
4795
|
const route = selectedHint?.kind ?? machine.ssh.route ?? "unknown";
|
|
4648
4796
|
const local = route === "local" || machine.machine_id === topology.local_machine_id;
|
|
4797
|
+
const confidence = routeConfidence({ machine, hint: selectedHint, matchedBy });
|
|
4798
|
+
const ok = Boolean(selectedHint?.target);
|
|
4649
4799
|
return {
|
|
4650
4800
|
schema_version: MACHINES_CONSUMER_CONTRACT_VERSION,
|
|
4651
4801
|
package: topology.package,
|
|
4652
|
-
ok
|
|
4802
|
+
ok,
|
|
4653
4803
|
machine_id: machine.machine_id,
|
|
4654
4804
|
requested_machine_id: machineId,
|
|
4655
4805
|
generated_at: generatedAt,
|
|
@@ -4657,7 +4807,7 @@ function resolveMachineRoute(machineId, options = {}) {
|
|
|
4657
4807
|
source: route,
|
|
4658
4808
|
target: selectedHint?.target ?? null,
|
|
4659
4809
|
command_target: selectedHint?.target ?? null,
|
|
4660
|
-
confidence
|
|
4810
|
+
confidence,
|
|
4661
4811
|
local,
|
|
4662
4812
|
evidence: {
|
|
4663
4813
|
topology: true,
|
|
@@ -4667,6 +4817,15 @@ function resolveMachineRoute(machineId, options = {}) {
|
|
|
4667
4817
|
tailscale_online: machine.tailscale.online,
|
|
4668
4818
|
selected_hint: selectedHint
|
|
4669
4819
|
},
|
|
4820
|
+
cacheability: cacheability({
|
|
4821
|
+
ok,
|
|
4822
|
+
observedAt: now,
|
|
4823
|
+
now,
|
|
4824
|
+
ttlMs: options.resolverTtlMs,
|
|
4825
|
+
authority: routeAuthority({ machine, selectedHint, matchedBy }),
|
|
4826
|
+
confidence,
|
|
4827
|
+
reasons: selectedHint ? [] : ["route_target_unresolved"]
|
|
4828
|
+
}),
|
|
4670
4829
|
warnings
|
|
4671
4830
|
};
|
|
4672
4831
|
}
|
|
@@ -4963,10 +5122,11 @@ function metadataKeysForDiagnostics(metadata) {
|
|
|
4963
5122
|
return Object.keys(metadata).filter((key) => !/(secret|token|key|password|credential)/i.test(key)).sort();
|
|
4964
5123
|
}
|
|
4965
5124
|
function resolveMachineWorkspace(options) {
|
|
5125
|
+
const now = options.now ?? new Date;
|
|
4966
5126
|
const topology = options.topology ?? discoverMachineTopology(options);
|
|
4967
5127
|
const warnings = [...topology.warnings];
|
|
4968
5128
|
const { machine, matchedBy } = findRouteMachine(topology, options.machineId);
|
|
4969
|
-
const generatedAt =
|
|
5129
|
+
const generatedAt = now.toISOString();
|
|
4970
5130
|
const repoName = options.repoName ?? options.projectId;
|
|
4971
5131
|
const openFilesRepoName = options.openFilesRepoName ?? "open-files";
|
|
4972
5132
|
if (!machine) {
|
|
@@ -4993,6 +5153,15 @@ function resolveMachineWorkspace(options) {
|
|
|
4993
5153
|
manifest_declared: null,
|
|
4994
5154
|
metadata_keys: []
|
|
4995
5155
|
},
|
|
5156
|
+
cacheability: cacheability({
|
|
5157
|
+
ok: false,
|
|
5158
|
+
observedAt: now,
|
|
5159
|
+
now,
|
|
5160
|
+
ttlMs: options.resolverTtlMs,
|
|
5161
|
+
authority: "unresolved",
|
|
5162
|
+
confidence: "none",
|
|
5163
|
+
reasons: [`machine_not_found:${options.machineId}`]
|
|
5164
|
+
}),
|
|
4996
5165
|
warnings
|
|
4997
5166
|
};
|
|
4998
5167
|
const diagnostics2 = workspaceDiagnostics({
|
|
@@ -5024,10 +5193,16 @@ function resolveMachineWorkspace(options) {
|
|
|
5024
5193
|
warnings.push(`open_files_root_inferred:${options.projectId}`);
|
|
5025
5194
|
if (!projectRootPath)
|
|
5026
5195
|
warnings.push(`project_root_unresolved:${options.projectId}`);
|
|
5196
|
+
const workspacePaths = {
|
|
5197
|
+
workspace_root: { path: workspaceRootPath, source: workspaceRootSource },
|
|
5198
|
+
project_root: { path: projectRootPath, source: projectRootSource },
|
|
5199
|
+
open_files_root: { path: openFilesRootPath, source: openFilesRootSource }
|
|
5200
|
+
};
|
|
5201
|
+
const workspaceOk = Boolean(projectRootPath);
|
|
5027
5202
|
const resolution = {
|
|
5028
5203
|
schema_version: MACHINES_CONSUMER_CONTRACT_VERSION,
|
|
5029
5204
|
package: topology.package,
|
|
5030
|
-
ok:
|
|
5205
|
+
ok: workspaceOk,
|
|
5031
5206
|
requested_machine_id: options.machineId,
|
|
5032
5207
|
machine_id: machine.machine_id,
|
|
5033
5208
|
generated_at: generatedAt,
|
|
@@ -5042,11 +5217,7 @@ function resolveMachineWorkspace(options) {
|
|
|
5042
5217
|
trust_status: trustStatus(machine),
|
|
5043
5218
|
auth_status: authStatus(machine)
|
|
5044
5219
|
},
|
|
5045
|
-
paths:
|
|
5046
|
-
workspace_root: { path: workspaceRootPath, source: workspaceRootSource },
|
|
5047
|
-
project_root: { path: projectRootPath, source: projectRootSource },
|
|
5048
|
-
open_files_root: { path: openFilesRootPath, source: openFilesRootSource }
|
|
5049
|
-
},
|
|
5220
|
+
paths: workspacePaths,
|
|
5050
5221
|
diagnostics: [],
|
|
5051
5222
|
repair_hints: [],
|
|
5052
5223
|
evidence: {
|
|
@@ -5055,6 +5226,15 @@ function resolveMachineWorkspace(options) {
|
|
|
5055
5226
|
manifest_declared: machine.manifest_declared,
|
|
5056
5227
|
metadata_keys: metadataKeysForDiagnostics(metadata)
|
|
5057
5228
|
},
|
|
5229
|
+
cacheability: cacheability({
|
|
5230
|
+
ok: workspaceOk,
|
|
5231
|
+
observedAt: now,
|
|
5232
|
+
now,
|
|
5233
|
+
ttlMs: options.resolverTtlMs,
|
|
5234
|
+
authority: workspaceAuthority(workspacePaths),
|
|
5235
|
+
confidence: workspaceOk ? "medium" : "none",
|
|
5236
|
+
reasons: projectRootPath ? [] : [`project_root_unresolved:${options.projectId}`]
|
|
5237
|
+
}),
|
|
5058
5238
|
warnings
|
|
5059
5239
|
};
|
|
5060
5240
|
const diagnostics = workspaceDiagnostics({
|
|
@@ -5069,6 +5249,73 @@ function resolveMachineWorkspace(options) {
|
|
|
5069
5249
|
repair_hints: diagnostics.repairHints
|
|
5070
5250
|
};
|
|
5071
5251
|
}
|
|
5252
|
+
function createMachineResolverSnapshot(options) {
|
|
5253
|
+
const now = options.now ?? new Date;
|
|
5254
|
+
const routeObservedAt = new Date(options.route.generated_at);
|
|
5255
|
+
const workspaceObservedAt = options.workspace ? new Date(options.workspace.generated_at) : null;
|
|
5256
|
+
const observedAt = new Date(Math.max(Number.isNaN(routeObservedAt.getTime()) ? 0 : routeObservedAt.getTime(), workspaceObservedAt && !Number.isNaN(workspaceObservedAt.getTime()) ? workspaceObservedAt.getTime() : 0));
|
|
5257
|
+
const cacheabilities = [options.route.cacheability, options.workspace?.cacheability].filter((entry) => Boolean(entry));
|
|
5258
|
+
const authorities = cacheabilities.map((entry) => entry.source_authority);
|
|
5259
|
+
const warnings = [...new Set([
|
|
5260
|
+
...options.route.warnings,
|
|
5261
|
+
...options.workspace?.warnings ?? [],
|
|
5262
|
+
...cacheabilities.flatMap((entry) => entry.reasons)
|
|
5263
|
+
])].sort();
|
|
5264
|
+
return {
|
|
5265
|
+
schema_version: MACHINES_CONSUMER_CONTRACT_VERSION,
|
|
5266
|
+
package: options.route.package,
|
|
5267
|
+
generated_at: now.toISOString(),
|
|
5268
|
+
requested_machine_id: options.route.requested_machine_id,
|
|
5269
|
+
machine_id: options.route.machine_id ?? options.workspace?.machine_id ?? null,
|
|
5270
|
+
route: {
|
|
5271
|
+
ok: options.route.ok,
|
|
5272
|
+
source: options.route.source,
|
|
5273
|
+
route: options.route.route,
|
|
5274
|
+
target: options.route.target,
|
|
5275
|
+
command_target: options.route.command_target,
|
|
5276
|
+
confidence: options.route.confidence,
|
|
5277
|
+
local: options.route.local,
|
|
5278
|
+
cacheability: options.route.cacheability
|
|
5279
|
+
},
|
|
5280
|
+
workspace: options.workspace ? {
|
|
5281
|
+
ok: options.workspace.ok,
|
|
5282
|
+
project: options.workspace.project,
|
|
5283
|
+
machine: options.workspace.machine,
|
|
5284
|
+
paths: options.workspace.paths,
|
|
5285
|
+
diagnostics: options.workspace.diagnostics,
|
|
5286
|
+
repair_hints: options.workspace.repair_hints,
|
|
5287
|
+
cacheability: options.workspace.cacheability
|
|
5288
|
+
} : null,
|
|
5289
|
+
cacheability: mergeCacheability({
|
|
5290
|
+
observedAt: observedAt.getTime() > 0 ? observedAt : now,
|
|
5291
|
+
now,
|
|
5292
|
+
ttlMs: options.resolverTtlMs,
|
|
5293
|
+
authorities,
|
|
5294
|
+
cacheabilities
|
|
5295
|
+
}),
|
|
5296
|
+
warnings,
|
|
5297
|
+
provenance: {
|
|
5298
|
+
route: {
|
|
5299
|
+
schema_version: options.route.schema_version,
|
|
5300
|
+
generated_at: options.route.generated_at,
|
|
5301
|
+
evidence: {
|
|
5302
|
+
matched_by: options.route.evidence.matched_by,
|
|
5303
|
+
manifest_declared: options.route.evidence.manifest_declared,
|
|
5304
|
+
heartbeat_status: options.route.evidence.heartbeat_status,
|
|
5305
|
+
tailscale_online: options.route.evidence.tailscale_online,
|
|
5306
|
+
selected_hint_kind: options.route.evidence.selected_hint?.kind ?? null
|
|
5307
|
+
}
|
|
5308
|
+
},
|
|
5309
|
+
workspace: options.workspace ? {
|
|
5310
|
+
schema_version: options.workspace.schema_version,
|
|
5311
|
+
generated_at: options.workspace.generated_at,
|
|
5312
|
+
metadata_keys: options.workspace.evidence.metadata_keys,
|
|
5313
|
+
matched_by: options.workspace.evidence.matched_by,
|
|
5314
|
+
manifest_declared: options.workspace.evidence.manifest_declared
|
|
5315
|
+
} : null
|
|
5316
|
+
}
|
|
5317
|
+
};
|
|
5318
|
+
}
|
|
5072
5319
|
function getLocalMachineTopology(options = {}) {
|
|
5073
5320
|
const topology = discoverMachineTopology(options);
|
|
5074
5321
|
return topology.machines.find((machine) => machine.machine_id === topology.local_machine_id) ?? {
|
|
@@ -5088,6 +5335,237 @@ function getLocalMachineTopology(options = {}) {
|
|
|
5088
5335
|
metadata: {}
|
|
5089
5336
|
};
|
|
5090
5337
|
}
|
|
5338
|
+
// src/consumer-schema.ts
|
|
5339
|
+
var MACHINES_CONSUMER_SCHEMA_BUNDLE = {
|
|
5340
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
5341
|
+
$id: MACHINES_CONSUMER_SCHEMA_URI,
|
|
5342
|
+
title: "@hasna/machines consumer contract schema bundle",
|
|
5343
|
+
type: "object",
|
|
5344
|
+
$defs: {
|
|
5345
|
+
cacheability: {
|
|
5346
|
+
type: "object",
|
|
5347
|
+
required: ["observed_at", "verified_at", "expires_at", "ttl_ms", "source_authority", "confidence", "cacheable", "stale", "reasons"],
|
|
5348
|
+
properties: {
|
|
5349
|
+
observed_at: { type: "string", format: "date-time" },
|
|
5350
|
+
verified_at: { type: ["string", "null"], format: "date-time" },
|
|
5351
|
+
expires_at: { type: ["string", "null"], format: "date-time" },
|
|
5352
|
+
ttl_ms: { type: ["number", "null"] },
|
|
5353
|
+
source_authority: { enum: ["open-machines", "manifest", "manifest_metadata", "live_topology", "argument", "inferred", "fallback", "unresolved", "mixed", "unknown"] },
|
|
5354
|
+
confidence: { enum: ["exact", "high", "medium", "low", "none"] },
|
|
5355
|
+
cacheable: { type: "boolean" },
|
|
5356
|
+
stale: { type: "boolean" },
|
|
5357
|
+
reasons: { type: "array", items: { type: "string" } }
|
|
5358
|
+
}
|
|
5359
|
+
},
|
|
5360
|
+
contract: {
|
|
5361
|
+
type: "object",
|
|
5362
|
+
required: ["schema_version", "package_name", "entrypoint", "schema_uri", "schema_artifact", "capabilities", "field_capabilities", "cacheability", "envelopes", "stable_exports"],
|
|
5363
|
+
properties: {
|
|
5364
|
+
schema_version: { const: MACHINES_CONSUMER_CONTRACT_VERSION },
|
|
5365
|
+
package_name: { const: "@hasna/machines" },
|
|
5366
|
+
entrypoint: { const: "@hasna/machines/consumer" },
|
|
5367
|
+
schema_uri: { const: MACHINES_CONSUMER_SCHEMA_URI },
|
|
5368
|
+
schema_artifact: { const: "schemas/machines-consumer.schema.json" },
|
|
5369
|
+
capabilities: { type: "object" },
|
|
5370
|
+
field_capabilities: { type: "object" },
|
|
5371
|
+
cacheability: { type: "object" },
|
|
5372
|
+
envelopes: { type: "array", items: { enum: ["topology", "route", "workspace", "compatibility", "resolver_snapshot"] } },
|
|
5373
|
+
stable_exports: { type: "array", items: { type: "string" } }
|
|
5374
|
+
}
|
|
5375
|
+
},
|
|
5376
|
+
topology: {
|
|
5377
|
+
type: "object",
|
|
5378
|
+
required: ["schema_version", "package", "capabilities", "generated_at", "local_machine_id", "machines", "warnings"],
|
|
5379
|
+
properties: {
|
|
5380
|
+
schema_version: { const: MACHINES_CONSUMER_CONTRACT_VERSION },
|
|
5381
|
+
package: { type: "object" },
|
|
5382
|
+
capabilities: { type: "object" },
|
|
5383
|
+
generated_at: { type: "string", format: "date-time" },
|
|
5384
|
+
local_machine_id: { type: "string" },
|
|
5385
|
+
machines: { type: "array" },
|
|
5386
|
+
warnings: { type: "array", items: { type: "string" } }
|
|
5387
|
+
}
|
|
5388
|
+
},
|
|
5389
|
+
route: {
|
|
5390
|
+
type: "object",
|
|
5391
|
+
required: ["schema_version", "package", "ok", "machine_id", "requested_machine_id", "generated_at", "route", "source", "target", "command_target", "confidence", "local", "evidence", "cacheability", "warnings"],
|
|
5392
|
+
properties: {
|
|
5393
|
+
schema_version: { const: MACHINES_CONSUMER_CONTRACT_VERSION },
|
|
5394
|
+
package: { type: "object" },
|
|
5395
|
+
ok: { type: "boolean" },
|
|
5396
|
+
machine_id: { type: ["string", "null"] },
|
|
5397
|
+
requested_machine_id: { type: "string" },
|
|
5398
|
+
generated_at: { type: "string", format: "date-time" },
|
|
5399
|
+
route: { enum: ["local", "lan", "tailscale", "ssh", "unknown"] },
|
|
5400
|
+
source: { enum: ["local", "lan", "tailscale", "ssh", "unknown"] },
|
|
5401
|
+
target: { type: ["string", "null"] },
|
|
5402
|
+
command_target: { type: ["string", "null"] },
|
|
5403
|
+
confidence: { enum: ["exact", "high", "medium", "low", "none"] },
|
|
5404
|
+
local: { type: "boolean" },
|
|
5405
|
+
evidence: { type: "object" },
|
|
5406
|
+
cacheability: { $ref: "#/$defs/cacheability" },
|
|
5407
|
+
warnings: { type: "array", items: { type: "string" } }
|
|
5408
|
+
}
|
|
5409
|
+
},
|
|
5410
|
+
workspace: {
|
|
5411
|
+
type: "object",
|
|
5412
|
+
required: ["schema_version", "package", "ok", "requested_machine_id", "machine_id", "generated_at", "project", "machine", "paths", "diagnostics", "repair_hints", "evidence", "cacheability", "warnings"],
|
|
5413
|
+
properties: {
|
|
5414
|
+
schema_version: { const: MACHINES_CONSUMER_CONTRACT_VERSION },
|
|
5415
|
+
package: { type: "object" },
|
|
5416
|
+
ok: { type: "boolean" },
|
|
5417
|
+
requested_machine_id: { type: "string" },
|
|
5418
|
+
machine_id: { type: ["string", "null"] },
|
|
5419
|
+
generated_at: { type: "string", format: "date-time" },
|
|
5420
|
+
project: { type: "object" },
|
|
5421
|
+
machine: {
|
|
5422
|
+
type: "object",
|
|
5423
|
+
required: ["current", "primary", "trust_status", "auth_status"],
|
|
5424
|
+
properties: {
|
|
5425
|
+
current: { type: "boolean" },
|
|
5426
|
+
primary: { type: "boolean" },
|
|
5427
|
+
trust_status: { enum: ["trusted", "untrusted", "unknown"] },
|
|
5428
|
+
auth_status: { enum: ["authenticated", "unauthenticated", "unknown"] }
|
|
5429
|
+
}
|
|
5430
|
+
},
|
|
5431
|
+
paths: { type: "object" },
|
|
5432
|
+
diagnostics: { type: "array" },
|
|
5433
|
+
repair_hints: { type: "array" },
|
|
5434
|
+
evidence: { type: "object" },
|
|
5435
|
+
cacheability: { $ref: "#/$defs/cacheability" },
|
|
5436
|
+
warnings: { type: "array", items: { type: "string" } }
|
|
5437
|
+
}
|
|
5438
|
+
},
|
|
5439
|
+
compatibility: {
|
|
5440
|
+
type: "object",
|
|
5441
|
+
required: ["schema_version", "package", "capabilities", "ok", "machine_id", "source", "generated_at", "checks", "summary"],
|
|
5442
|
+
properties: {
|
|
5443
|
+
schema_version: { const: MACHINES_CONSUMER_CONTRACT_VERSION },
|
|
5444
|
+
package: { type: "object" },
|
|
5445
|
+
capabilities: { type: "object" },
|
|
5446
|
+
ok: { type: "boolean" },
|
|
5447
|
+
machine_id: { type: "string" },
|
|
5448
|
+
source: { type: "string" },
|
|
5449
|
+
generated_at: { type: "string", format: "date-time" },
|
|
5450
|
+
checks: { type: "array" },
|
|
5451
|
+
summary: { type: "object" }
|
|
5452
|
+
}
|
|
5453
|
+
},
|
|
5454
|
+
resolver_snapshot: {
|
|
5455
|
+
type: "object",
|
|
5456
|
+
required: ["schema_version", "package", "generated_at", "requested_machine_id", "machine_id", "route", "workspace", "cacheability", "warnings", "provenance"],
|
|
5457
|
+
properties: {
|
|
5458
|
+
schema_version: { const: MACHINES_CONSUMER_CONTRACT_VERSION },
|
|
5459
|
+
package: { type: "object" },
|
|
5460
|
+
generated_at: { type: "string", format: "date-time" },
|
|
5461
|
+
requested_machine_id: { type: "string" },
|
|
5462
|
+
machine_id: { type: ["string", "null"] },
|
|
5463
|
+
route: { type: "object" },
|
|
5464
|
+
workspace: { type: ["object", "null"] },
|
|
5465
|
+
cacheability: { $ref: "#/$defs/cacheability" },
|
|
5466
|
+
warnings: { type: "array", items: { type: "string" } },
|
|
5467
|
+
provenance: { type: "object" }
|
|
5468
|
+
}
|
|
5469
|
+
}
|
|
5470
|
+
}
|
|
5471
|
+
};
|
|
5472
|
+
function isRecord2(value) {
|
|
5473
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
5474
|
+
}
|
|
5475
|
+
function hasString(value, key) {
|
|
5476
|
+
return typeof value[key] === "string" && value[key].length > 0;
|
|
5477
|
+
}
|
|
5478
|
+
function hasObject(value, key) {
|
|
5479
|
+
return isRecord2(value[key]);
|
|
5480
|
+
}
|
|
5481
|
+
function hasArray(value, key) {
|
|
5482
|
+
return Array.isArray(value[key]);
|
|
5483
|
+
}
|
|
5484
|
+
function hasCacheability(value, key = "cacheability") {
|
|
5485
|
+
const cache = value[key];
|
|
5486
|
+
return isRecord2(cache) && hasString(cache, "observed_at") && typeof cache.cacheable === "boolean" && typeof cache.stale === "boolean" && hasArray(cache, "reasons");
|
|
5487
|
+
}
|
|
5488
|
+
function requireFields(value, fields, errors2) {
|
|
5489
|
+
for (const field of fields) {
|
|
5490
|
+
if (!(field in value))
|
|
5491
|
+
errors2.push(`missing:${field}`);
|
|
5492
|
+
}
|
|
5493
|
+
}
|
|
5494
|
+
function getMachinesConsumerSchemaBundle() {
|
|
5495
|
+
return JSON.parse(JSON.stringify(MACHINES_CONSUMER_SCHEMA_BUNDLE));
|
|
5496
|
+
}
|
|
5497
|
+
function validateMachinesConsumerEnvelope(envelope, value) {
|
|
5498
|
+
const errors2 = [];
|
|
5499
|
+
if (!isRecord2(value)) {
|
|
5500
|
+
return { ok: false, envelope, schema_id: MACHINES_CONSUMER_SCHEMA_URI, errors: ["not_object"] };
|
|
5501
|
+
}
|
|
5502
|
+
if (value.schema_version !== MACHINES_CONSUMER_CONTRACT_VERSION)
|
|
5503
|
+
errors2.push(`schema_version:${String(value.schema_version)}`);
|
|
5504
|
+
if (envelope === "contract") {
|
|
5505
|
+
requireFields(value, ["package_name", "entrypoint", "schema_uri", "schema_artifact", "capabilities", "field_capabilities", "cacheability", "envelopes", "stable_exports"], errors2);
|
|
5506
|
+
if (value.package_name !== "@hasna/machines")
|
|
5507
|
+
errors2.push("package_name");
|
|
5508
|
+
if (value.entrypoint !== "@hasna/machines/consumer")
|
|
5509
|
+
errors2.push("entrypoint");
|
|
5510
|
+
if (!hasObject(value, "capabilities"))
|
|
5511
|
+
errors2.push("capabilities");
|
|
5512
|
+
if (!hasObject(value, "field_capabilities"))
|
|
5513
|
+
errors2.push("field_capabilities");
|
|
5514
|
+
if (!hasArray(value, "envelopes"))
|
|
5515
|
+
errors2.push("envelopes");
|
|
5516
|
+
if (!hasArray(value, "stable_exports"))
|
|
5517
|
+
errors2.push("stable_exports");
|
|
5518
|
+
} else if (envelope === "topology") {
|
|
5519
|
+
requireFields(value, ["package", "capabilities", "generated_at", "local_machine_id", "machines", "warnings"], errors2);
|
|
5520
|
+
if (!hasArray(value, "machines"))
|
|
5521
|
+
errors2.push("machines");
|
|
5522
|
+
if (!hasArray(value, "warnings"))
|
|
5523
|
+
errors2.push("warnings");
|
|
5524
|
+
} else if (envelope === "route") {
|
|
5525
|
+
requireFields(value, ["package", "ok", "machine_id", "requested_machine_id", "generated_at", "route", "source", "target", "command_target", "confidence", "local", "evidence", "cacheability", "warnings"], errors2);
|
|
5526
|
+
if (typeof value.ok !== "boolean")
|
|
5527
|
+
errors2.push("ok");
|
|
5528
|
+
if (!hasObject(value, "evidence"))
|
|
5529
|
+
errors2.push("evidence");
|
|
5530
|
+
if (!hasCacheability(value))
|
|
5531
|
+
errors2.push("cacheability");
|
|
5532
|
+
if (!hasArray(value, "warnings"))
|
|
5533
|
+
errors2.push("warnings");
|
|
5534
|
+
} else if (envelope === "workspace") {
|
|
5535
|
+
requireFields(value, ["package", "ok", "requested_machine_id", "machine_id", "generated_at", "project", "machine", "paths", "diagnostics", "repair_hints", "evidence", "cacheability", "warnings"], errors2);
|
|
5536
|
+
if (typeof value.ok !== "boolean")
|
|
5537
|
+
errors2.push("ok");
|
|
5538
|
+
if (!hasObject(value, "machine"))
|
|
5539
|
+
errors2.push("machine");
|
|
5540
|
+
if (!hasObject(value, "paths"))
|
|
5541
|
+
errors2.push("paths");
|
|
5542
|
+
if (!hasArray(value, "diagnostics"))
|
|
5543
|
+
errors2.push("diagnostics");
|
|
5544
|
+
if (!hasArray(value, "repair_hints"))
|
|
5545
|
+
errors2.push("repair_hints");
|
|
5546
|
+
if (!hasCacheability(value))
|
|
5547
|
+
errors2.push("cacheability");
|
|
5548
|
+
} else if (envelope === "compatibility") {
|
|
5549
|
+
requireFields(value, ["package", "capabilities", "ok", "machine_id", "source", "generated_at", "checks", "summary"], errors2);
|
|
5550
|
+
if (typeof value.ok !== "boolean")
|
|
5551
|
+
errors2.push("ok");
|
|
5552
|
+
if (!hasArray(value, "checks"))
|
|
5553
|
+
errors2.push("checks");
|
|
5554
|
+
if (!hasObject(value, "summary"))
|
|
5555
|
+
errors2.push("summary");
|
|
5556
|
+
} else if (envelope === "resolver_snapshot") {
|
|
5557
|
+
requireFields(value, ["package", "generated_at", "requested_machine_id", "machine_id", "route", "workspace", "cacheability", "warnings", "provenance"], errors2);
|
|
5558
|
+
if (!hasObject(value, "route"))
|
|
5559
|
+
errors2.push("route");
|
|
5560
|
+
if (!hasCacheability(value))
|
|
5561
|
+
errors2.push("cacheability");
|
|
5562
|
+
if (!hasArray(value, "warnings"))
|
|
5563
|
+
errors2.push("warnings");
|
|
5564
|
+
if (!hasObject(value, "provenance"))
|
|
5565
|
+
errors2.push("provenance");
|
|
5566
|
+
}
|
|
5567
|
+
return { ok: errors2.length === 0, envelope, schema_id: MACHINES_CONSUMER_SCHEMA_URI, errors: errors2 };
|
|
5568
|
+
}
|
|
5091
5569
|
// src/remote.ts
|
|
5092
5570
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
5093
5571
|
import { hostname as hostname4 } from "os";
|
|
@@ -5397,20 +5875,28 @@ function checkMachineCompatibility(options = {}) {
|
|
|
5397
5875
|
};
|
|
5398
5876
|
}
|
|
5399
5877
|
export {
|
|
5878
|
+
validateMachinesConsumerEnvelope,
|
|
5400
5879
|
runMachineCommand,
|
|
5401
5880
|
resolveSshTarget,
|
|
5402
5881
|
resolveMachineWorkspace,
|
|
5403
5882
|
resolveMachineRoute,
|
|
5404
5883
|
resolveMachineCommand,
|
|
5405
5884
|
getPackageVersion,
|
|
5885
|
+
getMachinesConsumerSchemaBundle,
|
|
5406
5886
|
getMachinesConsumerCapabilities,
|
|
5407
5887
|
getLocalMachineTopology,
|
|
5408
5888
|
discoverMachineTopology,
|
|
5889
|
+
createMachineResolverSnapshot,
|
|
5409
5890
|
checkMachineCompatibility,
|
|
5410
5891
|
buildSshCommand,
|
|
5411
5892
|
MACHINES_PACKAGE_NAME,
|
|
5893
|
+
MACHINES_CONSUMER_SCHEMA_URI,
|
|
5894
|
+
MACHINES_CONSUMER_SCHEMA_BUNDLE,
|
|
5895
|
+
MACHINES_CONSUMER_SCHEMA_ARTIFACT,
|
|
5896
|
+
MACHINES_CONSUMER_FIELD_CAPABILITIES,
|
|
5412
5897
|
MACHINES_CONSUMER_ENTRYPOINT,
|
|
5413
5898
|
MACHINES_CONSUMER_CONTRACT_VERSION,
|
|
5414
5899
|
MACHINES_CONSUMER_CONTRACT,
|
|
5415
|
-
MACHINES_CONSUMER_CAPABILITIES
|
|
5900
|
+
MACHINES_CONSUMER_CAPABILITIES,
|
|
5901
|
+
DEFAULT_MACHINE_RESOLVER_TTL_MS
|
|
5416
5902
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export * from "./commands/self-test.js";
|
|
|
21
21
|
export * from "./commands/serve.js";
|
|
22
22
|
export * from "./commands/setup.js";
|
|
23
23
|
export * from "./commands/ssh.js";
|
|
24
|
+
export * from "./commands/screen.js";
|
|
24
25
|
export * from "./commands/sync.js";
|
|
25
26
|
export * from "./commands/status.js";
|
|
26
27
|
export * from "./commands/workspace.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,0BAA0B,CAAC;AACzC,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,OAAO,EACL,oBAAoB,EACpB,6BAA6B,EAC7B,yBAAyB,EACzB,kCAAkC,EAClC,uBAAuB,EACvB,oBAAoB,EACpB,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,oBAAoB,EACpB,WAAW,EACX,WAAW,EACX,WAAW,GACZ,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,QAAQ,EAAE,UAAU,IAAI,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtH,cAAc,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,0BAA0B,CAAC;AACzC,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,OAAO,EACL,oBAAoB,EACpB,6BAA6B,EAC7B,yBAAyB,EACzB,kCAAkC,EAClC,uBAAuB,EACvB,oBAAoB,EACpB,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,oBAAoB,EACpB,WAAW,EACX,WAAW,EACX,WAAW,GACZ,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,QAAQ,EAAE,UAAU,IAAI,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtH,cAAc,cAAc,CAAC"}
|