Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | 3x 15x 12x 3x 1x 2x 1x 1x 3x 15x 3x 35x 35x 35x 20x 5x 15x 15x 15x 15x 15x 15x 15x 12x 12x 12x 15x 15x 35x 2x 1x 1x 35x 2x 1x 1x 35x 2x 1x 1x 35x 2x 1x 1x 35x 2x 1x 1x 35x | import { stringify } from '@metamask/kernel-utils';
import type {
VatConfig,
VatId,
Subcluster,
KernelStatus,
} from '@metamask/ocap-kernel';
import { useCallback, useMemo, useState } from 'react';
import { usePanelContext } from '../context/PanelContext.tsx';
import type { VatRecord } from '../types.ts';
export type Subclusters = (Subcluster & { vatRecords: VatRecord[] })[];
const getSourceFromConfig = (config: VatConfig): string => {
if ('bundleSpec' in config) {
return config.bundleSpec;
}
if ('sourceSpec' in config) {
return config.sourceSpec;
}
if ('bundleName' in config) {
return config.bundleName;
}
return 'unknown';
};
const transformVatData = (
vatData: KernelStatus['vats'][number],
): VatRecord => ({
id: vatData.id,
source: getSourceFromConfig(vatData.config),
parameters: stringify(vatData.config?.parameters ?? {}, 0),
creationOptions: stringify(vatData.config?.creationOptions ?? {}, 0),
subclusterId: vatData.subclusterId,
});
/**
* Hook to manage the vats state, grouped by subcluster.
*
* @returns An object containing the grouped vats and functions to interact with them.
*/
export const useVats = (): {
subclusters: Subclusters;
pingVat: (id: VatId) => void;
restartVat: (id: VatId) => void;
terminateVat: (id: VatId) => void;
terminateSubcluster: (id: string) => void;
reloadSubcluster: (id: string) => void;
hasVats: boolean;
} => {
const { callKernelMethod, status, logMessage } = usePanelContext();
const [hasVats, setHasVats] = useState(false);
const subclusters = useMemo<Subclusters>(() => {
if (!status) {
return [];
}
setHasVats(status.vats.length > 0);
// Create a map of vat records for quick lookup
const vatRecords = new Map<VatId, VatRecord>();
const subclusterVats = new Map<string, VatRecord[]>();
// First pass: transform all vats and group them by subcluster
for (const vat of status.vats) {
const vatRecord = transformVatData(vat);
vatRecords.set(vat.id, vatRecord);
if (vat.subclusterId) {
const vats = subclusterVats.get(vat.subclusterId) ?? [];
vats.push(vatRecord);
subclusterVats.set(vat.subclusterId, vats);
}
}
// Second pass: create subclusters with their vat records
const subclustersWithVats = status.subclusters.map((subcluster) => ({
...subcluster,
vatRecords: subclusterVats.get(subcluster.id) ?? [],
}));
return subclustersWithVats;
}, [status]);
const pingVat = useCallback(
(id: VatId) => {
callKernelMethod({
method: 'pingVat',
params: { id },
})
.then((result) => logMessage(stringify(result), 'success'))
.catch((error) => logMessage(error.message, 'error'));
},
[callKernelMethod, logMessage],
);
const restartVat = useCallback(
(id: VatId) => {
callKernelMethod({
method: 'restartVat',
params: { id },
})
.then(() => logMessage(`Restarted vat "${id}"`, 'success'))
.catch(() => logMessage(`Failed to restart vat "${id}"`, 'error'));
},
[callKernelMethod, logMessage],
);
const terminateVat = useCallback(
(id: VatId) => {
callKernelMethod({
method: 'terminateVat',
params: { id },
})
.then(() => logMessage(`Terminated vat "${id}"`, 'success'))
.catch(() => logMessage(`Failed to terminate vat "${id}"`, 'error'));
},
[callKernelMethod, logMessage],
);
const terminateSubcluster = useCallback(
(id: string) => {
callKernelMethod({
method: 'terminateSubcluster',
params: { id },
})
.then(() => logMessage(`Terminated subcluster "${id}"`, 'success'))
.catch(() =>
logMessage(`Failed to terminate subcluster "${id}"`, 'error'),
);
},
[callKernelMethod, logMessage],
);
const reloadSubcluster = useCallback(
(id: string) => {
callKernelMethod({
method: 'reloadSubcluster',
params: { id },
})
.then(() => logMessage(`Reloaded subcluster "${id}"`, 'success'))
.catch(() =>
logMessage(`Failed to reload subcluster "${id}"`, 'error'),
);
},
[callKernelMethod, logMessage],
);
return {
hasVats,
subclusters,
pingVat,
restartVat,
terminateVat,
terminateSubcluster,
reloadSubcluster,
};
};
|