@hasna/machines 0.0.20 → 0.0.22
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 +17 -0
- package/dist/cli/index.js +417 -15
- package/dist/commands/workspace.d.ts +37 -0
- package/dist/commands/workspace.d.ts.map +1 -0
- package/dist/consumer.d.ts +1 -1
- package/dist/consumer.d.ts.map +1 -1
- package/dist/consumer.js +201 -10
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +354 -14
- package/dist/mcp/index.js +205 -14
- package/dist/topology.d.ts +21 -0
- package/dist/topology.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11117,7 +11117,8 @@ var MACHINES_CONSUMER_CAPABILITIES = {
|
|
|
11117
11117
|
compatibility: true,
|
|
11118
11118
|
route_resolution: true,
|
|
11119
11119
|
cli_json_fallback: true,
|
|
11120
|
-
workspace_path_mapping: true
|
|
11120
|
+
workspace_path_mapping: true,
|
|
11121
|
+
workspace_diagnostics: true
|
|
11121
11122
|
};
|
|
11122
11123
|
var MACHINES_CONSUMER_CONTRACT = {
|
|
11123
11124
|
schema_version: MACHINES_CONSUMER_CONTRACT_VERSION,
|
|
@@ -11531,6 +11532,170 @@ function inferRepoRoot(workspaceRoot, repoName) {
|
|
|
11531
11532
|
}
|
|
11532
11533
|
return joinPath(root, repoName);
|
|
11533
11534
|
}
|
|
11535
|
+
function shellQuote(value) {
|
|
11536
|
+
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
11537
|
+
}
|
|
11538
|
+
function shellCommand(command) {
|
|
11539
|
+
return command.map(shellQuote).join(" ");
|
|
11540
|
+
}
|
|
11541
|
+
function canCheckPathForMachine(machine, localMachineId) {
|
|
11542
|
+
if (!machine)
|
|
11543
|
+
return false;
|
|
11544
|
+
if (machine.machine_id === localMachineId)
|
|
11545
|
+
return true;
|
|
11546
|
+
return machine.route_hints.some((hint) => hint.kind === "local");
|
|
11547
|
+
}
|
|
11548
|
+
function checkedPathExists(path, check) {
|
|
11549
|
+
if (!path || !check)
|
|
11550
|
+
return null;
|
|
11551
|
+
return existsSync4(path);
|
|
11552
|
+
}
|
|
11553
|
+
function repairHint(input) {
|
|
11554
|
+
const command = [
|
|
11555
|
+
"machines",
|
|
11556
|
+
"workspace",
|
|
11557
|
+
"repair",
|
|
11558
|
+
"--machine",
|
|
11559
|
+
input.machineId,
|
|
11560
|
+
"--project",
|
|
11561
|
+
input.projectId
|
|
11562
|
+
];
|
|
11563
|
+
if (input.repoName)
|
|
11564
|
+
command.push("--repo", input.repoName);
|
|
11565
|
+
if (input.openFilesRepoName)
|
|
11566
|
+
command.push("--open-files-repo", input.openFilesRepoName);
|
|
11567
|
+
command.push("--json");
|
|
11568
|
+
const applyCommand = [...command.slice(0, -1), "--apply", "--json"];
|
|
11569
|
+
return {
|
|
11570
|
+
id: `repair:${input.machineId}:${input.projectId}`,
|
|
11571
|
+
reason: input.reason,
|
|
11572
|
+
command,
|
|
11573
|
+
shell_command: shellCommand(command),
|
|
11574
|
+
apply_command: applyCommand,
|
|
11575
|
+
apply_shell_command: shellCommand(applyCommand)
|
|
11576
|
+
};
|
|
11577
|
+
}
|
|
11578
|
+
function pathDiagnostic(input) {
|
|
11579
|
+
if (!input.path.path) {
|
|
11580
|
+
return {
|
|
11581
|
+
id: input.id,
|
|
11582
|
+
status: "missing",
|
|
11583
|
+
severity: input.required ? "fail" : "warn",
|
|
11584
|
+
message: `${input.label} is unresolved.`,
|
|
11585
|
+
path: null,
|
|
11586
|
+
source: input.path.source,
|
|
11587
|
+
path_exists: null
|
|
11588
|
+
};
|
|
11589
|
+
}
|
|
11590
|
+
if (input.pathExists === false) {
|
|
11591
|
+
return {
|
|
11592
|
+
id: input.id,
|
|
11593
|
+
status: "stale",
|
|
11594
|
+
severity: "fail",
|
|
11595
|
+
message: `${input.label} points to a path that does not exist on this machine.`,
|
|
11596
|
+
path: input.path.path,
|
|
11597
|
+
source: input.path.source,
|
|
11598
|
+
path_exists: false
|
|
11599
|
+
};
|
|
11600
|
+
}
|
|
11601
|
+
if (input.path.source === "inferred") {
|
|
11602
|
+
return {
|
|
11603
|
+
id: input.id,
|
|
11604
|
+
status: "inferred",
|
|
11605
|
+
severity: "warn",
|
|
11606
|
+
message: `${input.label} was inferred from the workspace root; write an explicit manifest mapping for repeatable downstream sync.`,
|
|
11607
|
+
path: input.path.path,
|
|
11608
|
+
source: input.path.source,
|
|
11609
|
+
path_exists: input.pathExists
|
|
11610
|
+
};
|
|
11611
|
+
}
|
|
11612
|
+
return {
|
|
11613
|
+
id: input.id,
|
|
11614
|
+
status: "ok",
|
|
11615
|
+
severity: "ok",
|
|
11616
|
+
message: `${input.label} is explicit enough for downstream sync.`,
|
|
11617
|
+
path: input.path.path,
|
|
11618
|
+
source: input.path.source,
|
|
11619
|
+
path_exists: input.pathExists
|
|
11620
|
+
};
|
|
11621
|
+
}
|
|
11622
|
+
function workspaceDiagnostics(input) {
|
|
11623
|
+
const checkPaths = canCheckPathForMachine(input.machine, input.localMachineId);
|
|
11624
|
+
const diagnostics = [];
|
|
11625
|
+
if (!input.machine) {
|
|
11626
|
+
diagnostics.push({
|
|
11627
|
+
id: "manifest",
|
|
11628
|
+
status: "missing_manifest",
|
|
11629
|
+
severity: "fail",
|
|
11630
|
+
message: "Machine is not present in topology or manifest.",
|
|
11631
|
+
path: null,
|
|
11632
|
+
source: "manifest",
|
|
11633
|
+
path_exists: null
|
|
11634
|
+
});
|
|
11635
|
+
} else if (!input.resolution.evidence.manifest_declared) {
|
|
11636
|
+
diagnostics.push({
|
|
11637
|
+
id: "manifest",
|
|
11638
|
+
status: "missing_manifest",
|
|
11639
|
+
severity: "warn",
|
|
11640
|
+
message: "Machine came from live topology but is not declared in the manifest.",
|
|
11641
|
+
path: null,
|
|
11642
|
+
source: "manifest",
|
|
11643
|
+
path_exists: null
|
|
11644
|
+
});
|
|
11645
|
+
}
|
|
11646
|
+
diagnostics.push(pathDiagnostic({
|
|
11647
|
+
id: "workspace_root",
|
|
11648
|
+
label: "Workspace root",
|
|
11649
|
+
path: input.resolution.paths.workspace_root,
|
|
11650
|
+
pathExists: checkedPathExists(input.resolution.paths.workspace_root.path, checkPaths),
|
|
11651
|
+
required: false
|
|
11652
|
+
}));
|
|
11653
|
+
diagnostics.push(pathDiagnostic({
|
|
11654
|
+
id: "project_root",
|
|
11655
|
+
label: "Project root",
|
|
11656
|
+
path: input.resolution.paths.project_root,
|
|
11657
|
+
pathExists: checkedPathExists(input.resolution.paths.project_root.path, checkPaths),
|
|
11658
|
+
required: true
|
|
11659
|
+
}));
|
|
11660
|
+
diagnostics.push(pathDiagnostic({
|
|
11661
|
+
id: "open_files_root",
|
|
11662
|
+
label: "Open-files root",
|
|
11663
|
+
path: input.resolution.paths.open_files_root,
|
|
11664
|
+
pathExists: checkedPathExists(input.resolution.paths.open_files_root.path, checkPaths),
|
|
11665
|
+
required: false
|
|
11666
|
+
}));
|
|
11667
|
+
if (input.resolution.machine.trust_status !== "trusted") {
|
|
11668
|
+
diagnostics.push({
|
|
11669
|
+
id: "trust",
|
|
11670
|
+
status: "untrusted",
|
|
11671
|
+
severity: "warn",
|
|
11672
|
+
message: `Machine trust status is ${input.resolution.machine.trust_status}; manifest repair apply requires trust or --allow-untrusted.`,
|
|
11673
|
+
path: null,
|
|
11674
|
+
source: "trust",
|
|
11675
|
+
path_exists: null
|
|
11676
|
+
});
|
|
11677
|
+
}
|
|
11678
|
+
if (input.resolution.machine.auth_status !== "authenticated") {
|
|
11679
|
+
diagnostics.push({
|
|
11680
|
+
id: "auth",
|
|
11681
|
+
status: "unknown_auth",
|
|
11682
|
+
severity: "warn",
|
|
11683
|
+
message: `Machine auth status is ${input.resolution.machine.auth_status}; remote sync may still fail if SSH is unavailable.`,
|
|
11684
|
+
path: null,
|
|
11685
|
+
source: "auth",
|
|
11686
|
+
path_exists: null
|
|
11687
|
+
});
|
|
11688
|
+
}
|
|
11689
|
+
const needsRepair = diagnostics.some((entry) => (entry.id === "project_root" || entry.id === "open_files_root") && (entry.status === "missing" || entry.status === "inferred" || entry.status === "stale"));
|
|
11690
|
+
const repairHints = needsRepair ? [repairHint({
|
|
11691
|
+
machineId: input.resolution.machine_id ?? input.resolution.requested_machine_id,
|
|
11692
|
+
projectId: input.resolution.project.project_id,
|
|
11693
|
+
repoName: input.resolution.project.repo_name,
|
|
11694
|
+
openFilesRepoName: input.openFilesRepoName,
|
|
11695
|
+
reason: "Write explicit workspace_paths and open_files_roots manifest metadata."
|
|
11696
|
+
})] : [];
|
|
11697
|
+
return { diagnostics, repairHints };
|
|
11698
|
+
}
|
|
11534
11699
|
function projectPathFromMetadata(metadata, projectId, repoName) {
|
|
11535
11700
|
const keys = [projectId, repoName].filter((value) => Boolean(value));
|
|
11536
11701
|
return readMappedPath({
|
|
@@ -11606,7 +11771,7 @@ function resolveMachineWorkspace(options) {
|
|
|
11606
11771
|
const openFilesRepoName = options.openFilesRepoName ?? "open-files";
|
|
11607
11772
|
if (!machine) {
|
|
11608
11773
|
warnings.push(`machine_not_found:${options.machineId}`);
|
|
11609
|
-
|
|
11774
|
+
const resolution2 = {
|
|
11610
11775
|
schema_version: MACHINES_CONSUMER_CONTRACT_VERSION,
|
|
11611
11776
|
package: topology.package,
|
|
11612
11777
|
ok: false,
|
|
@@ -11620,6 +11785,8 @@ function resolveMachineWorkspace(options) {
|
|
|
11620
11785
|
project_root: { path: null, source: "unresolved" },
|
|
11621
11786
|
open_files_root: { path: null, source: "unresolved" }
|
|
11622
11787
|
},
|
|
11788
|
+
diagnostics: [],
|
|
11789
|
+
repair_hints: [],
|
|
11623
11790
|
evidence: {
|
|
11624
11791
|
topology: true,
|
|
11625
11792
|
matched_by: matchedBy,
|
|
@@ -11628,6 +11795,17 @@ function resolveMachineWorkspace(options) {
|
|
|
11628
11795
|
},
|
|
11629
11796
|
warnings
|
|
11630
11797
|
};
|
|
11798
|
+
const diagnostics2 = workspaceDiagnostics({
|
|
11799
|
+
machine,
|
|
11800
|
+
localMachineId: topology.local_machine_id,
|
|
11801
|
+
resolution: resolution2,
|
|
11802
|
+
openFilesRepoName
|
|
11803
|
+
});
|
|
11804
|
+
return {
|
|
11805
|
+
...resolution2,
|
|
11806
|
+
diagnostics: diagnostics2.diagnostics,
|
|
11807
|
+
repair_hints: diagnostics2.repairHints
|
|
11808
|
+
};
|
|
11631
11809
|
}
|
|
11632
11810
|
const metadata = machine.metadata;
|
|
11633
11811
|
const workspaceRootPath = options.workspaceRoot ?? machine.workspace_path;
|
|
@@ -11646,7 +11824,7 @@ function resolveMachineWorkspace(options) {
|
|
|
11646
11824
|
warnings.push(`open_files_root_inferred:${options.projectId}`);
|
|
11647
11825
|
if (!projectRootPath)
|
|
11648
11826
|
warnings.push(`project_root_unresolved:${options.projectId}`);
|
|
11649
|
-
|
|
11827
|
+
const resolution = {
|
|
11650
11828
|
schema_version: MACHINES_CONSUMER_CONTRACT_VERSION,
|
|
11651
11829
|
package: topology.package,
|
|
11652
11830
|
ok: Boolean(projectRootPath),
|
|
@@ -11669,6 +11847,8 @@ function resolveMachineWorkspace(options) {
|
|
|
11669
11847
|
project_root: { path: projectRootPath, source: projectRootSource },
|
|
11670
11848
|
open_files_root: { path: openFilesRootPath, source: openFilesRootSource }
|
|
11671
11849
|
},
|
|
11850
|
+
diagnostics: [],
|
|
11851
|
+
repair_hints: [],
|
|
11672
11852
|
evidence: {
|
|
11673
11853
|
topology: true,
|
|
11674
11854
|
matched_by: matchedBy,
|
|
@@ -11677,6 +11857,17 @@ function resolveMachineWorkspace(options) {
|
|
|
11677
11857
|
},
|
|
11678
11858
|
warnings
|
|
11679
11859
|
};
|
|
11860
|
+
const diagnostics = workspaceDiagnostics({
|
|
11861
|
+
machine,
|
|
11862
|
+
localMachineId: topology.local_machine_id,
|
|
11863
|
+
resolution,
|
|
11864
|
+
openFilesRepoName
|
|
11865
|
+
});
|
|
11866
|
+
return {
|
|
11867
|
+
...resolution,
|
|
11868
|
+
diagnostics: diagnostics.diagnostics,
|
|
11869
|
+
repair_hints: diagnostics.repairHints
|
|
11870
|
+
};
|
|
11680
11871
|
}
|
|
11681
11872
|
function getLocalMachineTopology(options = {}) {
|
|
11682
11873
|
const topology = discoverMachineTopology(options);
|
|
@@ -11702,7 +11893,7 @@ import { spawnSync as spawnSync2 } from "child_process";
|
|
|
11702
11893
|
import { hostname as hostname4 } from "os";
|
|
11703
11894
|
|
|
11704
11895
|
// src/commands/ssh.ts
|
|
11705
|
-
function
|
|
11896
|
+
function shellQuote2(value) {
|
|
11706
11897
|
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
11707
11898
|
}
|
|
11708
11899
|
function resolveSshTarget(machineId, options = {}) {
|
|
@@ -11723,11 +11914,11 @@ function resolveSshTarget(machineId, options = {}) {
|
|
|
11723
11914
|
}
|
|
11724
11915
|
function buildSshCommand(machineId, remoteCommand, options = {}) {
|
|
11725
11916
|
const resolved = resolveSshTarget(machineId, options);
|
|
11726
|
-
return remoteCommand ? `ssh ${resolved.target} ${
|
|
11917
|
+
return remoteCommand ? `ssh ${resolved.target} ${shellQuote2(remoteCommand)}` : `ssh ${resolved.target}`;
|
|
11727
11918
|
}
|
|
11728
11919
|
|
|
11729
11920
|
// src/remote.ts
|
|
11730
|
-
function
|
|
11921
|
+
function shellQuote3(value) {
|
|
11731
11922
|
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
11732
11923
|
}
|
|
11733
11924
|
function machineIsLocal(machineId, localMachineId) {
|
|
@@ -11745,7 +11936,7 @@ function resolveMachineCommand(machineId, command, localMachineId = getLocalMach
|
|
|
11745
11936
|
} catch (error) {
|
|
11746
11937
|
const message = String(error.message ?? error);
|
|
11747
11938
|
if (message.includes("Machine route not found") || message.includes("Machine not found in manifest")) {
|
|
11748
|
-
return { source: "ssh", shellCommand: `ssh ${
|
|
11939
|
+
return { source: "ssh", shellCommand: `ssh ${shellQuote3(machineId)} ${shellQuote3(command)}` };
|
|
11749
11940
|
}
|
|
11750
11941
|
throw error;
|
|
11751
11942
|
}
|
|
@@ -11773,7 +11964,7 @@ var DEFAULT_COMMANDS = [
|
|
|
11773
11964
|
function defaultPackages() {
|
|
11774
11965
|
return [{ name: "@hasna/machines", command: "machines", expectedVersion: getPackageVersion(), required: true }];
|
|
11775
11966
|
}
|
|
11776
|
-
function
|
|
11967
|
+
function shellQuote4(value) {
|
|
11777
11968
|
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
11778
11969
|
}
|
|
11779
11970
|
function commandId(value) {
|
|
@@ -11824,7 +12015,7 @@ function defaultRunner2(machineId, command) {
|
|
|
11824
12015
|
return runMachineCommand(machineId, command);
|
|
11825
12016
|
}
|
|
11826
12017
|
function inspectCommand(machineId, spec, runner) {
|
|
11827
|
-
const command =
|
|
12018
|
+
const command = shellQuote4(spec.command);
|
|
11828
12019
|
const versionArgs = spec.versionArgs ?? "--version";
|
|
11829
12020
|
const script = [
|
|
11830
12021
|
`cmd=${command}`,
|
|
@@ -11853,7 +12044,7 @@ function fieldCommand(field) {
|
|
|
11853
12044
|
}
|
|
11854
12045
|
function inspectWorkspace(machineId, spec, runner) {
|
|
11855
12046
|
const script = [
|
|
11856
|
-
`path=${
|
|
12047
|
+
`path=${shellQuote4(spec.path)}`,
|
|
11857
12048
|
'printf "exists=%s\\n" "$(test -d "$path" && printf yes || printf no)"',
|
|
11858
12049
|
'pkg="$path/package.json"',
|
|
11859
12050
|
'printf "package_json=%s\\n" "$(test -f "$pkg" && printf yes || printf no)"',
|
|
@@ -12148,7 +12339,7 @@ function getAppManager(machine, app) {
|
|
|
12148
12339
|
return "winget";
|
|
12149
12340
|
return "apt";
|
|
12150
12341
|
}
|
|
12151
|
-
function
|
|
12342
|
+
function shellQuote5(value) {
|
|
12152
12343
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
12153
12344
|
}
|
|
12154
12345
|
function buildAppCommand(machine, app) {
|
|
@@ -12169,7 +12360,7 @@ function buildAppCommand(machine, app) {
|
|
|
12169
12360
|
return `sudo apt-get install -y ${packageName}`;
|
|
12170
12361
|
}
|
|
12171
12362
|
function buildAppProbeCommand(machine, app) {
|
|
12172
|
-
const packageName =
|
|
12363
|
+
const packageName = shellQuote5(getPackageName(app));
|
|
12173
12364
|
const manager = getAppManager(machine, app);
|
|
12174
12365
|
if (manager === "custom") {
|
|
12175
12366
|
return `if command -v ${packageName} >/dev/null 2>&1; then printf 'installed=1\\nversion=custom\\n'; else printf 'installed=0\\n'; fi`;
|
|
@@ -12705,7 +12896,7 @@ var notificationConfigSchema = exports_external.object({
|
|
|
12705
12896
|
function sortChannels(channels) {
|
|
12706
12897
|
return [...channels].sort((left, right) => left.id.localeCompare(right.id));
|
|
12707
12898
|
}
|
|
12708
|
-
function
|
|
12899
|
+
function shellQuote6(value) {
|
|
12709
12900
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
12710
12901
|
}
|
|
12711
12902
|
function hasCommand2(binary) {
|
|
@@ -12752,7 +12943,7 @@ ${message}
|
|
|
12752
12943
|
};
|
|
12753
12944
|
}
|
|
12754
12945
|
if (hasCommand2("mail")) {
|
|
12755
|
-
const command = `printf %s ${
|
|
12946
|
+
const command = `printf %s ${shellQuote6(message)} | mail -s ${shellQuote6(subject)} ${shellQuote6(channel.target)}`;
|
|
12756
12947
|
const result = Bun.spawnSync(["bash", "-lc", command], {
|
|
12757
12948
|
stdout: "pipe",
|
|
12758
12949
|
stderr: "pipe",
|
|
@@ -13568,6 +13759,154 @@ function runSync(machineId, options = {}) {
|
|
|
13568
13759
|
recordSyncRun(plan.machineId, "completed", summary);
|
|
13569
13760
|
return summary;
|
|
13570
13761
|
}
|
|
13762
|
+
// src/commands/workspace.ts
|
|
13763
|
+
function isRecord2(value) {
|
|
13764
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
13765
|
+
}
|
|
13766
|
+
function cloneMetadata(metadata) {
|
|
13767
|
+
return isRecord2(metadata) ? { ...metadata } : {};
|
|
13768
|
+
}
|
|
13769
|
+
function mappedPath(metadata, field, key) {
|
|
13770
|
+
const container = metadata[field];
|
|
13771
|
+
if (!isRecord2(container))
|
|
13772
|
+
return null;
|
|
13773
|
+
const value = container[key];
|
|
13774
|
+
if (typeof value === "string" && value.trim())
|
|
13775
|
+
return value.trim();
|
|
13776
|
+
if (isRecord2(value)) {
|
|
13777
|
+
const nested = value["path"] ?? value["root"] ?? value["workspacePath"] ?? value["workspace_path"];
|
|
13778
|
+
if (typeof nested === "string" && nested.trim())
|
|
13779
|
+
return nested.trim();
|
|
13780
|
+
}
|
|
13781
|
+
return null;
|
|
13782
|
+
}
|
|
13783
|
+
function writeMappedPath(metadata, field, key, path) {
|
|
13784
|
+
const existing = metadata[field];
|
|
13785
|
+
const container = isRecord2(existing) ? { ...existing } : {};
|
|
13786
|
+
container[key] = path;
|
|
13787
|
+
metadata[field] = container;
|
|
13788
|
+
}
|
|
13789
|
+
function buildPatch(input) {
|
|
13790
|
+
const previous = mappedPath(input.metadata, input.field, input.key);
|
|
13791
|
+
if (!input.path) {
|
|
13792
|
+
return {
|
|
13793
|
+
field: input.field,
|
|
13794
|
+
key: input.key,
|
|
13795
|
+
path: null,
|
|
13796
|
+
previous_path: previous,
|
|
13797
|
+
status: "unresolved"
|
|
13798
|
+
};
|
|
13799
|
+
}
|
|
13800
|
+
const status = previous === input.path ? "unchanged" : input.apply ? "written" : "would_write";
|
|
13801
|
+
return {
|
|
13802
|
+
field: input.field,
|
|
13803
|
+
key: input.key,
|
|
13804
|
+
path: input.path,
|
|
13805
|
+
previous_path: previous,
|
|
13806
|
+
status
|
|
13807
|
+
};
|
|
13808
|
+
}
|
|
13809
|
+
function upsertMachineMetadata(manifest, machineId, metadata) {
|
|
13810
|
+
return {
|
|
13811
|
+
...manifest,
|
|
13812
|
+
machines: manifest.machines.map((machine) => machine.id === machineId ? { ...machine, metadata } : machine)
|
|
13813
|
+
};
|
|
13814
|
+
}
|
|
13815
|
+
function repairWorkspaceManifestMappings(options) {
|
|
13816
|
+
const projectId = options.projectId;
|
|
13817
|
+
const repoName = options.repoName ?? projectId;
|
|
13818
|
+
const openFilesRepoName = options.openFilesRepoName ?? "open-files";
|
|
13819
|
+
const apply = options.apply === true;
|
|
13820
|
+
const resolution = resolveMachineWorkspace({
|
|
13821
|
+
machineId: options.machineId,
|
|
13822
|
+
projectId,
|
|
13823
|
+
repoName,
|
|
13824
|
+
openFilesRepoName,
|
|
13825
|
+
projectRoot: options.projectRoot,
|
|
13826
|
+
openFilesRoot: options.openFilesRoot,
|
|
13827
|
+
workspaceRoot: options.workspaceRoot,
|
|
13828
|
+
includeTailscale: options.includeTailscale,
|
|
13829
|
+
now: options.now
|
|
13830
|
+
});
|
|
13831
|
+
const warnings = [...resolution.warnings];
|
|
13832
|
+
const manifest = readManifest();
|
|
13833
|
+
const manifestMachineId = resolution.machine_id ?? options.machineId;
|
|
13834
|
+
const machine = manifest.machines.find((entry) => entry.id === manifestMachineId) ?? null;
|
|
13835
|
+
const trusted = resolution.machine.trust_status === "trusted" || options.allowUntrusted === true;
|
|
13836
|
+
if (!machine) {
|
|
13837
|
+
warnings.push(`manifest_machine_missing:${manifestMachineId}`);
|
|
13838
|
+
return {
|
|
13839
|
+
ok: false,
|
|
13840
|
+
applied: false,
|
|
13841
|
+
manifest_path: getManifestPath(),
|
|
13842
|
+
machine_id: resolution.machine_id,
|
|
13843
|
+
project_id: projectId,
|
|
13844
|
+
repo_name: repoName,
|
|
13845
|
+
open_files_repo_name: openFilesRepoName,
|
|
13846
|
+
trusted,
|
|
13847
|
+
resolution,
|
|
13848
|
+
patches: [],
|
|
13849
|
+
warnings
|
|
13850
|
+
};
|
|
13851
|
+
}
|
|
13852
|
+
const metadata = cloneMetadata(machine.metadata);
|
|
13853
|
+
const patches = [
|
|
13854
|
+
buildPatch({
|
|
13855
|
+
metadata,
|
|
13856
|
+
field: "workspace_paths",
|
|
13857
|
+
key: projectId,
|
|
13858
|
+
path: options.projectRoot ?? resolution.paths.project_root.path,
|
|
13859
|
+
apply
|
|
13860
|
+
}),
|
|
13861
|
+
buildPatch({
|
|
13862
|
+
metadata,
|
|
13863
|
+
field: "open_files_roots",
|
|
13864
|
+
key: projectId,
|
|
13865
|
+
path: options.openFilesRoot ?? resolution.paths.open_files_root.path,
|
|
13866
|
+
apply
|
|
13867
|
+
})
|
|
13868
|
+
];
|
|
13869
|
+
const hasUnresolved = patches.some((patch) => patch.status === "unresolved");
|
|
13870
|
+
const hasWrites = patches.some((patch) => patch.status === "would_write" || patch.status === "written");
|
|
13871
|
+
if (apply && hasWrites && !trusted) {
|
|
13872
|
+
warnings.push(`manifest_repair_requires_trusted_machine:${manifestMachineId}`);
|
|
13873
|
+
return {
|
|
13874
|
+
ok: false,
|
|
13875
|
+
applied: false,
|
|
13876
|
+
manifest_path: getManifestPath(),
|
|
13877
|
+
machine_id: manifestMachineId,
|
|
13878
|
+
project_id: projectId,
|
|
13879
|
+
repo_name: repoName,
|
|
13880
|
+
open_files_repo_name: openFilesRepoName,
|
|
13881
|
+
trusted,
|
|
13882
|
+
resolution,
|
|
13883
|
+
patches: patches.map((patch) => patch.status === "written" ? { ...patch, status: "would_write" } : patch),
|
|
13884
|
+
warnings
|
|
13885
|
+
};
|
|
13886
|
+
}
|
|
13887
|
+
let applied = false;
|
|
13888
|
+
if (apply && !hasUnresolved && hasWrites) {
|
|
13889
|
+
for (const patch of patches) {
|
|
13890
|
+
if (patch.path && patch.status === "written")
|
|
13891
|
+
writeMappedPath(metadata, patch.field, patch.key, patch.path);
|
|
13892
|
+
}
|
|
13893
|
+
writeManifest(upsertMachineMetadata(manifest, manifestMachineId, metadata));
|
|
13894
|
+
applied = true;
|
|
13895
|
+
}
|
|
13896
|
+
return {
|
|
13897
|
+
ok: resolution.ok && !hasUnresolved && (!apply || applied || !hasWrites),
|
|
13898
|
+
applied,
|
|
13899
|
+
manifest_path: getManifestPath(),
|
|
13900
|
+
machine_id: manifestMachineId,
|
|
13901
|
+
project_id: projectId,
|
|
13902
|
+
repo_name: repoName,
|
|
13903
|
+
open_files_repo_name: openFilesRepoName,
|
|
13904
|
+
trusted,
|
|
13905
|
+
resolution,
|
|
13906
|
+
patches,
|
|
13907
|
+
warnings
|
|
13908
|
+
};
|
|
13909
|
+
}
|
|
13571
13910
|
// node_modules/zod/v4/core/core.js
|
|
13572
13911
|
var NEVER2 = Object.freeze({
|
|
13573
13912
|
status: "aborted"
|
|
@@ -22725,6 +23064,7 @@ export {
|
|
|
22725
23064
|
resolveMachineWorkspace,
|
|
22726
23065
|
resolveMachineRoute,
|
|
22727
23066
|
resolveBackupTarget,
|
|
23067
|
+
repairWorkspaceManifestMappings,
|
|
22728
23068
|
renderDomainMapping,
|
|
22729
23069
|
renderDashboardHtml,
|
|
22730
23070
|
removeNotificationChannel,
|