@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/cli/index.js
CHANGED
|
@@ -993,7 +993,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
993
993
|
this._exitCallback = (err) => {
|
|
994
994
|
if (err.code !== "commander.executeSubCommandAsync") {
|
|
995
995
|
throw err;
|
|
996
|
-
}
|
|
996
|
+
}
|
|
997
997
|
};
|
|
998
998
|
}
|
|
999
999
|
return this;
|
|
@@ -2601,6 +2601,9 @@ var {
|
|
|
2601
2601
|
Help
|
|
2602
2602
|
} = import__.default;
|
|
2603
2603
|
|
|
2604
|
+
// src/cli/index.ts
|
|
2605
|
+
import { execFileSync } from "child_process";
|
|
2606
|
+
|
|
2604
2607
|
// node_modules/chalk/source/vendor/ansi-styles/index.js
|
|
2605
2608
|
var ANSI_BACKGROUND_OFFSET = 10;
|
|
2606
2609
|
var wrapAnsi16 = (offset = 0) => (code) => `\x1B[${code + offset}m`;
|
|
@@ -7165,6 +7168,7 @@ function writeManifest(manifest, path = getManifestPath()) {
|
|
|
7165
7168
|
generatedAt: new Date().toISOString(),
|
|
7166
7169
|
machines: normalizeMachines(manifest.machines)
|
|
7167
7170
|
};
|
|
7171
|
+
fleetSchema.parse(payload);
|
|
7168
7172
|
writeFileSync(path, `${JSON.stringify(payload, null, 2)}
|
|
7169
7173
|
`, "utf8");
|
|
7170
7174
|
return path;
|
|
@@ -7200,9 +7204,10 @@ function manifestList() {
|
|
|
7200
7204
|
return readManifest();
|
|
7201
7205
|
}
|
|
7202
7206
|
function manifestAdd(machine) {
|
|
7207
|
+
const validatedMachine = machineSchema.parse(machine);
|
|
7203
7208
|
const manifest = readManifest();
|
|
7204
|
-
const nextMachines = manifest.machines.filter((entry) => entry.id !==
|
|
7205
|
-
nextMachines.push(
|
|
7209
|
+
const nextMachines = manifest.machines.filter((entry) => entry.id !== validatedMachine.id);
|
|
7210
|
+
nextMachines.push(validatedMachine);
|
|
7206
7211
|
const nextManifest = { ...manifest, machines: nextMachines };
|
|
7207
7212
|
writeManifest(nextManifest);
|
|
7208
7213
|
return nextManifest;
|
|
@@ -7227,6 +7232,7 @@ function manifestValidate() {
|
|
|
7227
7232
|
}
|
|
7228
7233
|
|
|
7229
7234
|
// src/commands/setup.ts
|
|
7235
|
+
import { homedir as homedir2 } from "os";
|
|
7230
7236
|
init_db();
|
|
7231
7237
|
function quote(value) {
|
|
7232
7238
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
@@ -7275,11 +7281,11 @@ function buildPackageSteps(machine) {
|
|
|
7275
7281
|
const manager = pkg.manager || (machine.platform === "macos" ? "brew" : "apt");
|
|
7276
7282
|
let command = pkg.name;
|
|
7277
7283
|
if (manager === "bun") {
|
|
7278
|
-
command = `bun install -g ${pkg.name}`;
|
|
7284
|
+
command = `bun install -g ${quote(pkg.name)}`;
|
|
7279
7285
|
} else if (manager === "brew") {
|
|
7280
|
-
command = `brew install ${pkg.name}`;
|
|
7286
|
+
command = `brew install ${quote(pkg.name)}`;
|
|
7281
7287
|
} else if (manager === "apt") {
|
|
7282
|
-
command = `sudo apt-get install -y ${pkg.name}`;
|
|
7288
|
+
command = `sudo apt-get install -y ${quote(pkg.name)}`;
|
|
7283
7289
|
}
|
|
7284
7290
|
return {
|
|
7285
7291
|
id: `package-${index + 1}`,
|
|
@@ -7297,7 +7303,7 @@ function buildSetupPlan(machineId) {
|
|
|
7297
7303
|
const target = selected || {
|
|
7298
7304
|
id: currentMachineId,
|
|
7299
7305
|
platform: "linux",
|
|
7300
|
-
workspacePath:
|
|
7306
|
+
workspacePath: `${homedir2()}/workspace`
|
|
7301
7307
|
};
|
|
7302
7308
|
const steps = [...buildBaseSteps(target), ...buildPackageSteps(target)];
|
|
7303
7309
|
return {
|
|
@@ -7343,7 +7349,7 @@ function runSetup(machineId, options = {}) {
|
|
|
7343
7349
|
}
|
|
7344
7350
|
|
|
7345
7351
|
// src/commands/backup.ts
|
|
7346
|
-
import { homedir as
|
|
7352
|
+
import { homedir as homedir3, hostname as hostname3 } from "os";
|
|
7347
7353
|
import { join as join3 } from "path";
|
|
7348
7354
|
var MACHINES_BACKUP_BUCKET_ENV = "HASNA_MACHINES_S3_BUCKET";
|
|
7349
7355
|
var MACHINES_BACKUP_BUCKET_FALLBACK_ENV = "MACHINES_S3_BUCKET";
|
|
@@ -7392,7 +7398,7 @@ function resolveBackupTarget(options = {}) {
|
|
|
7392
7398
|
};
|
|
7393
7399
|
}
|
|
7394
7400
|
function defaultBackupSources() {
|
|
7395
|
-
const home =
|
|
7401
|
+
const home = homedir3();
|
|
7396
7402
|
return [
|
|
7397
7403
|
join3(home, ".hasna"),
|
|
7398
7404
|
join3(home, ".ssh"),
|
|
@@ -7401,7 +7407,7 @@ function defaultBackupSources() {
|
|
|
7401
7407
|
}
|
|
7402
7408
|
function buildBackupPlan(bucket, prefix) {
|
|
7403
7409
|
const target = resolveBackupTarget({ bucket, prefix });
|
|
7404
|
-
const archivePath = join3(
|
|
7410
|
+
const archivePath = join3(homedir3(), ".hasna", "machines", "backup.tgz");
|
|
7405
7411
|
const sources = defaultBackupSources();
|
|
7406
7412
|
const steps = [
|
|
7407
7413
|
{
|
|
@@ -7413,7 +7419,7 @@ function buildBackupPlan(bucket, prefix) {
|
|
|
7413
7419
|
{
|
|
7414
7420
|
id: "backup-upload",
|
|
7415
7421
|
title: "Upload archive to S3",
|
|
7416
|
-
command: `aws s3 cp ${quote2(archivePath)} s3://${target.bucket}/${target.prefix}/$(
|
|
7422
|
+
command: `aws s3 cp ${quote2(archivePath)} ${quote2(`s3://${target.bucket}/${target.prefix}/${hostname3()}-backup.tgz`)}`,
|
|
7417
7423
|
manager: "custom"
|
|
7418
7424
|
}
|
|
7419
7425
|
];
|
|
@@ -7452,13 +7458,13 @@ function runBackup(bucket, prefix, options = {}) {
|
|
|
7452
7458
|
}
|
|
7453
7459
|
|
|
7454
7460
|
// src/commands/cert.ts
|
|
7455
|
-
import { homedir as
|
|
7461
|
+
import { homedir as homedir4, platform as platform2 } from "os";
|
|
7456
7462
|
import { join as join4 } from "path";
|
|
7457
7463
|
function quote3(value) {
|
|
7458
7464
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
7459
7465
|
}
|
|
7460
7466
|
function certDir() {
|
|
7461
|
-
return join4(
|
|
7467
|
+
return join4(homedir4(), ".hasna", "machines", "certs");
|
|
7462
7468
|
}
|
|
7463
7469
|
function buildCertPlan(domains) {
|
|
7464
7470
|
if (domains.length === 0) {
|
|
@@ -7618,23 +7624,28 @@ function diffMachines(leftMachineId, rightMachineId) {
|
|
|
7618
7624
|
// src/remote.ts
|
|
7619
7625
|
init_db();
|
|
7620
7626
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
7621
|
-
import { hostname as
|
|
7627
|
+
import { hostname as hostname5 } from "os";
|
|
7622
7628
|
|
|
7623
7629
|
// src/topology.ts
|
|
7624
7630
|
init_db();
|
|
7625
7631
|
import { existsSync as existsSync5 } from "fs";
|
|
7626
|
-
import { arch as arch2, hostname as
|
|
7632
|
+
import { arch as arch2, hostname as hostname4, platform as platform3, userInfo as userInfo2 } from "os";
|
|
7627
7633
|
import { spawnSync } from "child_process";
|
|
7628
7634
|
init_paths();
|
|
7629
7635
|
var MACHINES_CONSUMER_CONTRACT_VERSION = 1;
|
|
7630
7636
|
var MACHINES_PACKAGE_NAME = "@hasna/machines";
|
|
7637
|
+
var DEFAULT_MACHINE_RESOLVER_TTL_MS = 24 * 60 * 60 * 1000;
|
|
7631
7638
|
var MACHINES_CONSUMER_CAPABILITIES = {
|
|
7632
7639
|
topology: true,
|
|
7633
7640
|
compatibility: true,
|
|
7634
7641
|
route_resolution: true,
|
|
7635
7642
|
cli_json_fallback: true,
|
|
7636
7643
|
workspace_path_mapping: true,
|
|
7637
|
-
workspace_diagnostics: true
|
|
7644
|
+
workspace_diagnostics: true,
|
|
7645
|
+
schema_artifacts: true,
|
|
7646
|
+
cacheability_metadata: true,
|
|
7647
|
+
resolver_snapshots: true,
|
|
7648
|
+
field_capability_descriptors: true
|
|
7638
7649
|
};
|
|
7639
7650
|
function getMachinesConsumerCapabilities() {
|
|
7640
7651
|
return { ...MACHINES_CONSUMER_CAPABILITIES };
|
|
@@ -7842,7 +7853,7 @@ function discoverMachineTopology(options = {}) {
|
|
|
7842
7853
|
capabilities: getMachinesConsumerCapabilities(),
|
|
7843
7854
|
generated_at: now.toISOString(),
|
|
7844
7855
|
local_machine_id: localMachineId,
|
|
7845
|
-
local_hostname:
|
|
7856
|
+
local_hostname: hostname4(),
|
|
7846
7857
|
current_platform: normalizePlatform2(),
|
|
7847
7858
|
manifest_path_known: existsSync5(getManifestPath()),
|
|
7848
7859
|
machines,
|
|
@@ -7867,7 +7878,7 @@ function routeTargetMatches(machine, requested) {
|
|
|
7867
7878
|
}
|
|
7868
7879
|
function findRouteMachine(topology, requestedMachineId) {
|
|
7869
7880
|
const requested = normalizeMachineAlias(requestedMachineId);
|
|
7870
|
-
if (requested === "local" || requested === "localhost" || requested === normalizeMachineAlias(
|
|
7881
|
+
if (requested === "local" || requested === "localhost" || requested === normalizeMachineAlias(hostname4()) || requested === normalizeMachineAlias(topology.local_machine_id)) {
|
|
7871
7882
|
return {
|
|
7872
7883
|
machine: topology.machines.find((machine) => machine.machine_id === topology.local_machine_id) ?? null,
|
|
7873
7884
|
matchedBy: "local_alias"
|
|
@@ -7905,11 +7916,69 @@ function routeConfidence(input) {
|
|
|
7905
7916
|
return "low";
|
|
7906
7917
|
return "none";
|
|
7907
7918
|
}
|
|
7919
|
+
function addMilliseconds(date, milliseconds) {
|
|
7920
|
+
return new Date(date.getTime() + milliseconds).toISOString();
|
|
7921
|
+
}
|
|
7922
|
+
function routeAuthority(input) {
|
|
7923
|
+
if (!input.machine)
|
|
7924
|
+
return "unresolved";
|
|
7925
|
+
if (input.matchedBy === "fallback")
|
|
7926
|
+
return "fallback";
|
|
7927
|
+
if (input.selectedHint?.kind === "local")
|
|
7928
|
+
return "live_topology";
|
|
7929
|
+
if (input.selectedHint?.kind === "tailscale" || input.machine.tailscale.online !== null)
|
|
7930
|
+
return "live_topology";
|
|
7931
|
+
if (input.machine.manifest_declared)
|
|
7932
|
+
return "manifest";
|
|
7933
|
+
return "open-machines";
|
|
7934
|
+
}
|
|
7935
|
+
function workspaceAuthority(paths) {
|
|
7936
|
+
const sources = [paths.workspace_root.source, paths.project_root.source, paths.open_files_root.source];
|
|
7937
|
+
if (sources.some((source) => source === "argument"))
|
|
7938
|
+
return "argument";
|
|
7939
|
+
if (sources.some((source) => source === "manifest_metadata"))
|
|
7940
|
+
return "manifest_metadata";
|
|
7941
|
+
if (sources.some((source) => source === "manifest"))
|
|
7942
|
+
return "manifest";
|
|
7943
|
+
if (sources.some((source) => source === "inferred"))
|
|
7944
|
+
return "inferred";
|
|
7945
|
+
if (sources.every((source) => source === "unresolved"))
|
|
7946
|
+
return "unresolved";
|
|
7947
|
+
return "open-machines";
|
|
7948
|
+
}
|
|
7949
|
+
function cacheability(input) {
|
|
7950
|
+
const ttlMs = input.ttlMs === undefined ? DEFAULT_MACHINE_RESOLVER_TTL_MS : input.ttlMs;
|
|
7951
|
+
const expiresAt = typeof ttlMs === "number" && ttlMs > 0 ? addMilliseconds(input.observedAt, ttlMs) : null;
|
|
7952
|
+
const stale = expiresAt ? input.now.getTime() > new Date(expiresAt).getTime() : false;
|
|
7953
|
+
const confidenceCacheable = input.confidence !== "none" && input.confidence !== "low";
|
|
7954
|
+
const cacheable = input.ok && confidenceCacheable && !stale && input.authority !== "unresolved";
|
|
7955
|
+
const reasons = [...input.reasons];
|
|
7956
|
+
if (!input.ok)
|
|
7957
|
+
reasons.push("resolver_not_ok");
|
|
7958
|
+
if (!confidenceCacheable)
|
|
7959
|
+
reasons.push(`low_confidence:${input.confidence}`);
|
|
7960
|
+
if (stale)
|
|
7961
|
+
reasons.push("stale");
|
|
7962
|
+
if (input.authority === "unresolved")
|
|
7963
|
+
reasons.push("unresolved_authority");
|
|
7964
|
+
return {
|
|
7965
|
+
observed_at: input.observedAt.toISOString(),
|
|
7966
|
+
verified_at: input.ok ? input.now.toISOString() : null,
|
|
7967
|
+
expires_at: expiresAt,
|
|
7968
|
+
ttl_ms: typeof ttlMs === "number" && ttlMs > 0 ? ttlMs : null,
|
|
7969
|
+
source_authority: input.authority,
|
|
7970
|
+
confidence: input.confidence,
|
|
7971
|
+
cacheable,
|
|
7972
|
+
stale,
|
|
7973
|
+
reasons: [...new Set(reasons)].sort()
|
|
7974
|
+
};
|
|
7975
|
+
}
|
|
7908
7976
|
function resolveMachineRoute(machineId, options = {}) {
|
|
7977
|
+
const now = options.now ?? new Date;
|
|
7909
7978
|
const topology = options.topology ?? discoverMachineTopology(options);
|
|
7910
7979
|
const warnings = [...topology.warnings];
|
|
7911
7980
|
const { machine, matchedBy } = findRouteMachine(topology, machineId);
|
|
7912
|
-
const generatedAt =
|
|
7981
|
+
const generatedAt = now.toISOString();
|
|
7913
7982
|
if (!machine) {
|
|
7914
7983
|
warnings.push(`machine_not_found:${machineId}`);
|
|
7915
7984
|
return {
|
|
@@ -7933,16 +8002,27 @@ function resolveMachineRoute(machineId, options = {}) {
|
|
|
7933
8002
|
tailscale_online: null,
|
|
7934
8003
|
selected_hint: null
|
|
7935
8004
|
},
|
|
8005
|
+
cacheability: cacheability({
|
|
8006
|
+
ok: false,
|
|
8007
|
+
observedAt: now,
|
|
8008
|
+
now,
|
|
8009
|
+
ttlMs: options.resolverTtlMs,
|
|
8010
|
+
authority: "unresolved",
|
|
8011
|
+
confidence: "none",
|
|
8012
|
+
reasons: [`machine_not_found:${machineId}`]
|
|
8013
|
+
}),
|
|
7936
8014
|
warnings
|
|
7937
8015
|
};
|
|
7938
8016
|
}
|
|
7939
8017
|
const selectedHint = selectRouteHint(machine.route_hints);
|
|
7940
8018
|
const route = selectedHint?.kind ?? machine.ssh.route ?? "unknown";
|
|
7941
8019
|
const local = route === "local" || machine.machine_id === topology.local_machine_id;
|
|
8020
|
+
const confidence = routeConfidence({ machine, hint: selectedHint, matchedBy });
|
|
8021
|
+
const ok = Boolean(selectedHint?.target);
|
|
7942
8022
|
return {
|
|
7943
8023
|
schema_version: MACHINES_CONSUMER_CONTRACT_VERSION,
|
|
7944
8024
|
package: topology.package,
|
|
7945
|
-
ok
|
|
8025
|
+
ok,
|
|
7946
8026
|
machine_id: machine.machine_id,
|
|
7947
8027
|
requested_machine_id: machineId,
|
|
7948
8028
|
generated_at: generatedAt,
|
|
@@ -7950,7 +8030,7 @@ function resolveMachineRoute(machineId, options = {}) {
|
|
|
7950
8030
|
source: route,
|
|
7951
8031
|
target: selectedHint?.target ?? null,
|
|
7952
8032
|
command_target: selectedHint?.target ?? null,
|
|
7953
|
-
confidence
|
|
8033
|
+
confidence,
|
|
7954
8034
|
local,
|
|
7955
8035
|
evidence: {
|
|
7956
8036
|
topology: true,
|
|
@@ -7960,6 +8040,15 @@ function resolveMachineRoute(machineId, options = {}) {
|
|
|
7960
8040
|
tailscale_online: machine.tailscale.online,
|
|
7961
8041
|
selected_hint: selectedHint
|
|
7962
8042
|
},
|
|
8043
|
+
cacheability: cacheability({
|
|
8044
|
+
ok,
|
|
8045
|
+
observedAt: now,
|
|
8046
|
+
now,
|
|
8047
|
+
ttlMs: options.resolverTtlMs,
|
|
8048
|
+
authority: routeAuthority({ machine, selectedHint, matchedBy }),
|
|
8049
|
+
confidence,
|
|
8050
|
+
reasons: selectedHint ? [] : ["route_target_unresolved"]
|
|
8051
|
+
}),
|
|
7963
8052
|
warnings
|
|
7964
8053
|
};
|
|
7965
8054
|
}
|
|
@@ -8256,10 +8345,11 @@ function metadataKeysForDiagnostics(metadata) {
|
|
|
8256
8345
|
return Object.keys(metadata).filter((key) => !/(secret|token|key|password|credential)/i.test(key)).sort();
|
|
8257
8346
|
}
|
|
8258
8347
|
function resolveMachineWorkspace(options) {
|
|
8348
|
+
const now = options.now ?? new Date;
|
|
8259
8349
|
const topology = options.topology ?? discoverMachineTopology(options);
|
|
8260
8350
|
const warnings = [...topology.warnings];
|
|
8261
8351
|
const { machine, matchedBy } = findRouteMachine(topology, options.machineId);
|
|
8262
|
-
const generatedAt =
|
|
8352
|
+
const generatedAt = now.toISOString();
|
|
8263
8353
|
const repoName = options.repoName ?? options.projectId;
|
|
8264
8354
|
const openFilesRepoName = options.openFilesRepoName ?? "open-files";
|
|
8265
8355
|
if (!machine) {
|
|
@@ -8286,6 +8376,15 @@ function resolveMachineWorkspace(options) {
|
|
|
8286
8376
|
manifest_declared: null,
|
|
8287
8377
|
metadata_keys: []
|
|
8288
8378
|
},
|
|
8379
|
+
cacheability: cacheability({
|
|
8380
|
+
ok: false,
|
|
8381
|
+
observedAt: now,
|
|
8382
|
+
now,
|
|
8383
|
+
ttlMs: options.resolverTtlMs,
|
|
8384
|
+
authority: "unresolved",
|
|
8385
|
+
confidence: "none",
|
|
8386
|
+
reasons: [`machine_not_found:${options.machineId}`]
|
|
8387
|
+
}),
|
|
8289
8388
|
warnings
|
|
8290
8389
|
};
|
|
8291
8390
|
const diagnostics2 = workspaceDiagnostics({
|
|
@@ -8317,10 +8416,16 @@ function resolveMachineWorkspace(options) {
|
|
|
8317
8416
|
warnings.push(`open_files_root_inferred:${options.projectId}`);
|
|
8318
8417
|
if (!projectRootPath)
|
|
8319
8418
|
warnings.push(`project_root_unresolved:${options.projectId}`);
|
|
8419
|
+
const workspacePaths = {
|
|
8420
|
+
workspace_root: { path: workspaceRootPath, source: workspaceRootSource },
|
|
8421
|
+
project_root: { path: projectRootPath, source: projectRootSource },
|
|
8422
|
+
open_files_root: { path: openFilesRootPath, source: openFilesRootSource }
|
|
8423
|
+
};
|
|
8424
|
+
const workspaceOk = Boolean(projectRootPath);
|
|
8320
8425
|
const resolution = {
|
|
8321
8426
|
schema_version: MACHINES_CONSUMER_CONTRACT_VERSION,
|
|
8322
8427
|
package: topology.package,
|
|
8323
|
-
ok:
|
|
8428
|
+
ok: workspaceOk,
|
|
8324
8429
|
requested_machine_id: options.machineId,
|
|
8325
8430
|
machine_id: machine.machine_id,
|
|
8326
8431
|
generated_at: generatedAt,
|
|
@@ -8335,11 +8440,7 @@ function resolveMachineWorkspace(options) {
|
|
|
8335
8440
|
trust_status: trustStatus(machine),
|
|
8336
8441
|
auth_status: authStatus(machine)
|
|
8337
8442
|
},
|
|
8338
|
-
paths:
|
|
8339
|
-
workspace_root: { path: workspaceRootPath, source: workspaceRootSource },
|
|
8340
|
-
project_root: { path: projectRootPath, source: projectRootSource },
|
|
8341
|
-
open_files_root: { path: openFilesRootPath, source: openFilesRootSource }
|
|
8342
|
-
},
|
|
8443
|
+
paths: workspacePaths,
|
|
8343
8444
|
diagnostics: [],
|
|
8344
8445
|
repair_hints: [],
|
|
8345
8446
|
evidence: {
|
|
@@ -8348,6 +8449,15 @@ function resolveMachineWorkspace(options) {
|
|
|
8348
8449
|
manifest_declared: machine.manifest_declared,
|
|
8349
8450
|
metadata_keys: metadataKeysForDiagnostics(metadata)
|
|
8350
8451
|
},
|
|
8452
|
+
cacheability: cacheability({
|
|
8453
|
+
ok: workspaceOk,
|
|
8454
|
+
observedAt: now,
|
|
8455
|
+
now,
|
|
8456
|
+
ttlMs: options.resolverTtlMs,
|
|
8457
|
+
authority: workspaceAuthority(workspacePaths),
|
|
8458
|
+
confidence: workspaceOk ? "medium" : "none",
|
|
8459
|
+
reasons: projectRootPath ? [] : [`project_root_unresolved:${options.projectId}`]
|
|
8460
|
+
}),
|
|
8351
8461
|
warnings
|
|
8352
8462
|
};
|
|
8353
8463
|
const diagnostics = workspaceDiagnostics({
|
|
@@ -8393,7 +8503,7 @@ function shellQuote3(value) {
|
|
|
8393
8503
|
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
8394
8504
|
}
|
|
8395
8505
|
function machineIsLocal(machineId, localMachineId) {
|
|
8396
|
-
return machineId === "local" || machineId === "localhost" || machineId === localMachineId || machineId ===
|
|
8506
|
+
return machineId === "local" || machineId === "localhost" || machineId === localMachineId || machineId === hostname5();
|
|
8397
8507
|
}
|
|
8398
8508
|
function resolveMachineCommand(machineId, command, localMachineId = getLocalMachineId()) {
|
|
8399
8509
|
if (machineIsLocal(machineId, localMachineId)) {
|
|
@@ -8445,20 +8555,21 @@ function shellQuote4(value) {
|
|
|
8445
8555
|
}
|
|
8446
8556
|
function buildAppCommand(machine, app) {
|
|
8447
8557
|
const packageName = getPackageName(app);
|
|
8558
|
+
const quotedPackageName = shellQuote4(packageName);
|
|
8448
8559
|
const manager = getAppManager(machine, app);
|
|
8449
8560
|
if (manager === "custom") {
|
|
8450
8561
|
return packageName;
|
|
8451
8562
|
}
|
|
8452
8563
|
if (machine.platform === "macos") {
|
|
8453
8564
|
if (manager === "cask") {
|
|
8454
|
-
return `brew install --cask ${
|
|
8565
|
+
return `brew install --cask ${quotedPackageName}`;
|
|
8455
8566
|
}
|
|
8456
|
-
return `brew install ${
|
|
8567
|
+
return `brew install ${quotedPackageName}`;
|
|
8457
8568
|
}
|
|
8458
8569
|
if (machine.platform === "windows") {
|
|
8459
|
-
return `winget install ${
|
|
8570
|
+
return `winget install ${quotedPackageName}`;
|
|
8460
8571
|
}
|
|
8461
|
-
return `sudo apt-get install -y ${
|
|
8572
|
+
return `sudo apt-get install -y ${quotedPackageName}`;
|
|
8462
8573
|
}
|
|
8463
8574
|
function buildAppProbeCommand(machine, app) {
|
|
8464
8575
|
const packageName = shellQuote4(getPackageName(app));
|
|
@@ -9041,8 +9152,55 @@ function listPorts(machineId) {
|
|
|
9041
9152
|
};
|
|
9042
9153
|
}
|
|
9043
9154
|
|
|
9155
|
+
// src/commands/screen.ts
|
|
9156
|
+
function shellQuote6(value) {
|
|
9157
|
+
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
9158
|
+
}
|
|
9159
|
+
function splitTarget(target) {
|
|
9160
|
+
const at = target.indexOf("@");
|
|
9161
|
+
if (at === -1)
|
|
9162
|
+
return [null, target];
|
|
9163
|
+
return [target.slice(0, at), target.slice(at + 1)];
|
|
9164
|
+
}
|
|
9165
|
+
function resolveScreenTarget(machineId, options = {}) {
|
|
9166
|
+
const resolved = resolveMachineRoute(machineId, options);
|
|
9167
|
+
if (!resolved.ok || !resolved.target) {
|
|
9168
|
+
throw new Error(`Machine route not found: ${machineId}`);
|
|
9169
|
+
}
|
|
9170
|
+
if (resolved.route === "unknown") {
|
|
9171
|
+
throw new Error(`Machine route is not reachable for screen sharing: ${machineId}`);
|
|
9172
|
+
}
|
|
9173
|
+
let [user, host] = splitTarget(resolved.target);
|
|
9174
|
+
if (!user) {
|
|
9175
|
+
const topology = options.topology ?? discoverMachineTopology(options);
|
|
9176
|
+
const entry = topology.machines.find((m) => m.machine_id === (resolved.machine_id ?? machineId));
|
|
9177
|
+
user = entry?.user ?? null;
|
|
9178
|
+
}
|
|
9179
|
+
const url = user ? `vnc://${user}@${host}` : `vnc://${host}`;
|
|
9180
|
+
return {
|
|
9181
|
+
machineId: resolved.machine_id ?? machineId,
|
|
9182
|
+
user,
|
|
9183
|
+
host,
|
|
9184
|
+
url,
|
|
9185
|
+
route: resolved.route,
|
|
9186
|
+
confidence: resolved.confidence,
|
|
9187
|
+
warnings: resolved.warnings
|
|
9188
|
+
};
|
|
9189
|
+
}
|
|
9190
|
+
function buildScreenEnableRemoteCommand(user, vncPassword) {
|
|
9191
|
+
const kickstart = "/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart";
|
|
9192
|
+
const lines = [
|
|
9193
|
+
`dseditgroup -o edit -a ${shellQuote6(user)} -t user com.apple.access_screensharing 2>/dev/null || true`,
|
|
9194
|
+
"defaults write /Library/Preferences/com.apple.RemoteManagement AllowSRPForNetworkNodes -bool true",
|
|
9195
|
+
`${kickstart} -configure -clientopts -setvnclegacy -vnclegacy yes -setvncpw -vncpw ${shellQuote6(vncPassword)}`,
|
|
9196
|
+
`${kickstart} -activate -configure -access -on -users ${shellQuote6(user)} -privs -all -restart -agent -menu`
|
|
9197
|
+
];
|
|
9198
|
+
return lines.join(" && ");
|
|
9199
|
+
}
|
|
9200
|
+
|
|
9044
9201
|
// src/commands/sync.ts
|
|
9045
9202
|
import { existsSync as existsSync7, lstatSync, readFileSync as readFileSync5, symlinkSync, copyFileSync } from "fs";
|
|
9203
|
+
import { homedir as homedir5 } from "os";
|
|
9046
9204
|
init_paths();
|
|
9047
9205
|
init_db();
|
|
9048
9206
|
function quote4(value) {
|
|
@@ -9062,13 +9220,13 @@ function packageCheckCommand(machine, packageName, manager = machine.platform ==
|
|
|
9062
9220
|
}
|
|
9063
9221
|
function packageInstallCommand(machine, packageName, manager = machine.platform === "macos" ? "brew" : "apt") {
|
|
9064
9222
|
if (manager === "bun") {
|
|
9065
|
-
return `bun install -g ${packageName}`;
|
|
9223
|
+
return `bun install -g ${quote4(packageName)}`;
|
|
9066
9224
|
}
|
|
9067
9225
|
if (manager === "brew") {
|
|
9068
|
-
return `brew install ${packageName}`;
|
|
9226
|
+
return `brew install ${quote4(packageName)}`;
|
|
9069
9227
|
}
|
|
9070
9228
|
if (manager === "apt") {
|
|
9071
|
-
return `sudo apt-get install -y ${packageName}`;
|
|
9229
|
+
return `sudo apt-get install -y ${quote4(packageName)}`;
|
|
9072
9230
|
}
|
|
9073
9231
|
return packageName;
|
|
9074
9232
|
}
|
|
@@ -9121,7 +9279,7 @@ function buildSyncPlan(machineId) {
|
|
|
9121
9279
|
const target = selected || {
|
|
9122
9280
|
id: currentMachineId,
|
|
9123
9281
|
platform: "linux",
|
|
9124
|
-
workspacePath:
|
|
9282
|
+
workspacePath: `${homedir5()}/workspace`
|
|
9125
9283
|
};
|
|
9126
9284
|
const actions = [
|
|
9127
9285
|
...detectPackageActions(target),
|
|
@@ -9388,7 +9546,7 @@ var DEFAULT_COMMANDS = [
|
|
|
9388
9546
|
function defaultPackages() {
|
|
9389
9547
|
return [{ name: "@hasna/machines", command: "machines", expectedVersion: getPackageVersion(), required: true }];
|
|
9390
9548
|
}
|
|
9391
|
-
function
|
|
9549
|
+
function shellQuote7(value) {
|
|
9392
9550
|
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
9393
9551
|
}
|
|
9394
9552
|
function commandId(value) {
|
|
@@ -9439,7 +9597,7 @@ function defaultRunner2(machineId, command) {
|
|
|
9439
9597
|
return runMachineCommand(machineId, command);
|
|
9440
9598
|
}
|
|
9441
9599
|
function inspectCommand(machineId, spec, runner) {
|
|
9442
|
-
const command =
|
|
9600
|
+
const command = shellQuote7(spec.command);
|
|
9443
9601
|
const versionArgs = spec.versionArgs ?? "--version";
|
|
9444
9602
|
const script = [
|
|
9445
9603
|
`cmd=${command}`,
|
|
@@ -9468,7 +9626,7 @@ function fieldCommand(field) {
|
|
|
9468
9626
|
}
|
|
9469
9627
|
function inspectWorkspace(machineId, spec, runner) {
|
|
9470
9628
|
const script = [
|
|
9471
|
-
`path=${
|
|
9629
|
+
`path=${shellQuote7(spec.path)}`,
|
|
9472
9630
|
'printf "exists=%s\\n" "$(test -d "$path" && printf yes || printf no)"',
|
|
9473
9631
|
'pkg="$path/package.json"',
|
|
9474
9632
|
'printf "package_json=%s\\n" "$(test -f "$pkg" && printf yes || printf no)"',
|
|
@@ -11214,6 +11372,11 @@ manifestCommand.command("add").description("Add or replace a machine in the flee
|
|
|
11214
11372
|
console.log(JSON.stringify(manifestAdd(machine2), null, 2));
|
|
11215
11373
|
return;
|
|
11216
11374
|
}
|
|
11375
|
+
for (const key of ["id", "platform", "workspacePath"]) {
|
|
11376
|
+
if (typeof options[key] !== "string" || !options[key].trim()) {
|
|
11377
|
+
throw new Error(`manifest add requires --${key === "workspacePath" ? "workspace-path" : key} unless --from-stdin is used`);
|
|
11378
|
+
}
|
|
11379
|
+
}
|
|
11217
11380
|
const packages = Array.isArray(options["package"]) ? options["package"].map((name) => ({ name: String(name) })) : undefined;
|
|
11218
11381
|
const files = Array.isArray(options["file"]) ? options["file"].map((value) => {
|
|
11219
11382
|
const [source, target, mode] = String(value).split(":");
|
|
@@ -11519,6 +11682,68 @@ program2.command("ssh").description("Choose the best SSH route for a machine").r
|
|
|
11519
11682
|
}
|
|
11520
11683
|
console.log(buildSshCommand(options.machine, options.cmd));
|
|
11521
11684
|
});
|
|
11685
|
+
program2.command("screen").description("Open Screen Sharing (VNC) to a machine using its best live route").argument("[machine]", "Machine identifier").option("--machine <id>", "Machine identifier (alternative to positional arg)").option("--all", "Open every reachable machine", false).option("--print", "Print the vnc:// URL instead of opening it", false).option("-j, --json", "Print JSON output", false).action((machineArg, options) => {
|
|
11686
|
+
if (options.all) {
|
|
11687
|
+
const topology = discoverMachineTopology();
|
|
11688
|
+
const results = topology.machines.map((m) => {
|
|
11689
|
+
try {
|
|
11690
|
+
const resolved2 = resolveScreenTarget(m.machine_id, { topology });
|
|
11691
|
+
return { machine: m.machine_id, ok: true, url: resolved2.url, route: resolved2.route };
|
|
11692
|
+
} catch (error) {
|
|
11693
|
+
return { machine: m.machine_id, ok: false, error: error instanceof Error ? error.message : String(error) };
|
|
11694
|
+
}
|
|
11695
|
+
});
|
|
11696
|
+
if (options.json) {
|
|
11697
|
+
console.log(JSON.stringify(results, null, 2));
|
|
11698
|
+
return;
|
|
11699
|
+
}
|
|
11700
|
+
for (const r of results) {
|
|
11701
|
+
if (r.ok && r.url) {
|
|
11702
|
+
if (!options.print)
|
|
11703
|
+
execFileSync("open", [r.url], { stdio: "ignore" });
|
|
11704
|
+
console.log(`${r.ok ? "\u2713" : "\u2717"} ${r.machine.padEnd(14)} ${r.url ?? r.error}`);
|
|
11705
|
+
} else {
|
|
11706
|
+
console.log(`\u2717 ${r.machine.padEnd(14)} ${r.error}`);
|
|
11707
|
+
}
|
|
11708
|
+
}
|
|
11709
|
+
return;
|
|
11710
|
+
}
|
|
11711
|
+
const machineId = machineArg ?? options.machine;
|
|
11712
|
+
if (!machineId) {
|
|
11713
|
+
console.error("Provide a machine: machines screen <id> (or --all)");
|
|
11714
|
+
process.exitCode = 1;
|
|
11715
|
+
return;
|
|
11716
|
+
}
|
|
11717
|
+
const resolved = resolveScreenTarget(machineId);
|
|
11718
|
+
if (options.json) {
|
|
11719
|
+
console.log(JSON.stringify(resolved, null, 2));
|
|
11720
|
+
return;
|
|
11721
|
+
}
|
|
11722
|
+
if (options.print) {
|
|
11723
|
+
console.log(resolved.url);
|
|
11724
|
+
return;
|
|
11725
|
+
}
|
|
11726
|
+
execFileSync("open", [resolved.url], { stdio: "ignore" });
|
|
11727
|
+
console.log(`Opening Screen Sharing \u2192 ${resolved.url} (route: ${resolved.route})`);
|
|
11728
|
+
});
|
|
11729
|
+
program2.command("screen-enable").description("Enable Remote Management / Screen Sharing on a macOS machine over SSH").requiredOption("--machine <id>", "Machine identifier").option("--user <user>", "macOS user to grant screen-sharing (overrides manifest)").option("--vnc-password <pw>", "Legacy VNC password (<=8 chars honored)", "").option("--print", "Print the remote command instead of running it", false).action((options) => {
|
|
11730
|
+
const screen = resolveScreenTarget(options.machine);
|
|
11731
|
+
const user = options.user ?? screen.user;
|
|
11732
|
+
if (!user) {
|
|
11733
|
+
console.error(`No SSH user known for ${options.machine}; pass --user <name> or set metadata.user in the manifest.`);
|
|
11734
|
+
process.exitCode = 1;
|
|
11735
|
+
return;
|
|
11736
|
+
}
|
|
11737
|
+
const vncPw = (options.vncPassword || "").slice(0, 8);
|
|
11738
|
+
const remoteCmd = buildScreenEnableRemoteCommand(user, vncPw);
|
|
11739
|
+
const sshCmd = buildSshCommand(options.machine, `sudo -p '' bash -c ${JSON.stringify(remoteCmd)}`);
|
|
11740
|
+
if (options.print) {
|
|
11741
|
+
console.log(sshCmd);
|
|
11742
|
+
return;
|
|
11743
|
+
}
|
|
11744
|
+
console.log(`Run this to enable Screen Sharing on ${options.machine} (will prompt for sudo on the target):`);
|
|
11745
|
+
console.log(` ${sshCmd}`);
|
|
11746
|
+
});
|
|
11522
11747
|
program2.command("ports").description("List listening ports on a machine").option("--machine <id>", "Machine identifier").option("-j, --json", "Print JSON output", false).action((options) => {
|
|
11523
11748
|
const result = listPorts(options.machine);
|
|
11524
11749
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -11683,4 +11908,10 @@ healCommand.command("uninstall").description("Remove the systemd watchdog servic
|
|
|
11683
11908
|
}
|
|
11684
11909
|
console.log(renderList("uninstall", uninstallHealService()));
|
|
11685
11910
|
});
|
|
11686
|
-
|
|
11911
|
+
try {
|
|
11912
|
+
await program2.parseAsync(process.argv);
|
|
11913
|
+
} catch (error) {
|
|
11914
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
11915
|
+
console.error(source_default.red(message));
|
|
11916
|
+
process.exit(1);
|
|
11917
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apps.d.ts","sourceRoot":"","sources":["../../src/commands/apps.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAGhB,eAAe,EACf,WAAW,EAEZ,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"apps.d.ts","sourceRoot":"","sources":["../../src/commands/apps.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAGhB,eAAe,EACf,WAAW,EAEZ,MAAM,aAAa,CAAC;AA+FrB,wBAAgB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,eAAe,EAAE,CAAA;CAAE,CAM3F;AAED,wBAAgB,aAAa,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,WAAW,CAQ7D;AAED,wBAAgB,aAAa,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAWlE;AAED,wBAAgB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,cAAc,CAO3D;AAED,wBAAgB,cAAc,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,WAAW,CA0BhH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/commands/manifest.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/commands/manifest.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAElE,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,wBAAgB,YAAY,IAAI,aAAa,CAE5C;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,eAAe,GAAG,aAAa,CAQnE;AAED,wBAAgB,+BAA+B,IAAI,aAAa,CAE/D;AAED,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAErE;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,CAQ/D;AAED,wBAAgB,gBAAgB,IAAI,aAAa,CAEhD"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type MachineRouteOptions, type MachineRouteKind, type MachineRouteConfidence } from "../topology.js";
|
|
2
|
+
export interface ResolvedScreenTarget {
|
|
3
|
+
machineId: string;
|
|
4
|
+
user: string | null;
|
|
5
|
+
host: string;
|
|
6
|
+
url: string;
|
|
7
|
+
route: MachineRouteKind;
|
|
8
|
+
confidence: MachineRouteConfidence;
|
|
9
|
+
warnings: string[];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Resolve the best screen-sharing (VNC) target for a machine.
|
|
13
|
+
* Prefers the live LAN route over Tailscale (lower latency for screen sharing),
|
|
14
|
+
* and always produces a `vnc://user@host` URL when a user is known.
|
|
15
|
+
*/
|
|
16
|
+
export declare function resolveScreenTarget(machineId: string, options?: MachineRouteOptions): ResolvedScreenTarget;
|
|
17
|
+
/**
|
|
18
|
+
* Build the macOS command that opens Screen Sharing to a machine.
|
|
19
|
+
* `open vnc://user@host` launches Screen Sharing.app pointed at the resolved route.
|
|
20
|
+
*/
|
|
21
|
+
export declare function buildScreenCommand(machineId: string, options?: MachineRouteOptions): string;
|
|
22
|
+
/**
|
|
23
|
+
* Build the remote command that ENABLES Remote Management / Screen Sharing on a
|
|
24
|
+
* macOS target via `kickstart`, plus the SRP + legacy-VNC password tweaks that
|
|
25
|
+
* make user-password auth work reliably from Screen Sharing.app and ARD.
|
|
26
|
+
*
|
|
27
|
+
* `vncPassword` is truncated to 8 chars by the VNC protocol; callers should pass
|
|
28
|
+
* an <=8 char value (or accept that only the first 8 chars are honored by legacy
|
|
29
|
+
* VNC clients).
|
|
30
|
+
*
|
|
31
|
+
* Returns the shell command to run AS ROOT on the target (caller pipes the sudo
|
|
32
|
+
* password or runs under an already-root context).
|
|
33
|
+
*/
|
|
34
|
+
export declare function buildScreenEnableRemoteCommand(user: string, vncPassword: string): string;
|
|
35
|
+
//# sourceMappingURL=screen.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screen.d.ts","sourceRoot":"","sources":["../../src/commands/screen.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgD,KAAK,mBAAmB,EAAE,KAAK,gBAAgB,EAAE,KAAK,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAE5J,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,gBAAgB,CAAC;IACxB,UAAU,EAAE,sBAAsB,CAAC;IACnC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAgBD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,GAAG,oBAAoB,CA+B9G;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,GAAG,MAAM,CAG/F;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAcxF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAmB,WAAW,EAAa,MAAM,aAAa,CAAC;AAsE3E,wBAAgB,cAAc,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,WAAW,CAqB9D;AAED,wBAAgB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,WAAW,CAoC1G"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAA+B,UAAU,EAAE,MAAM,aAAa,CAAC;AAiF3E,wBAAgB,aAAa,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,UAAU,CAwB5D;AAwBD,wBAAgB,OAAO,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,UAAU,CAyCxG"}
|