alwaysai
Version:
The alwaysAI command-line interface (CLI)
143 lines (127 loc) • 4.58 kB
text/typescript
import { CliLeaf, CliOneOfInput, CliStringInput } from '@alwaysai/alwayscli';
import { yesCliInput } from '../../cli-inputs';
import { checkUserIsLoggedInComponent } from '../../components/user';
import { getModels } from '../../core/model';
import { echo } from '../../util';
export const modelList = CliLeaf({
name: 'list',
description: 'List models',
namedInputs: {
yes: yesCliInput,
owner: CliStringInput({
description: 'Filter by the owner of the model.'
}),
filter: CliStringInput({
description: 'Filter by a custom string in the id of the model.'
}),
sortBy: CliOneOfInput({
description: 'Sort the results.',
required: false,
values: ['ascending', 'descending', 'oldest', 'latest']
})
},
async action(_, { yes, owner, filter, sortBy }) {
await checkUserIsLoggedInComponent({ yes });
const models = await getModels({ yes });
const modelTable: { id: string; version: number; updated_at: string }[] =
[];
// Create an array of models dropping the other parameters
for (const model of models) {
modelTable.push({
id: model.id,
version: model.version,
updated_at: formatUpdatedAt(model.updated_at)
});
}
// Group models by ids and select the one with the highest version for each group
const latestModels = Object.values(
modelTable.reduce((acc, model) => {
// If this is the first model or a newer version, update the model in the accumulator
if (!acc[model.id] || acc[model.id].version < model.version) {
acc[model.id] = model;
}
return acc;
}, {})
);
// Filter data if filter provided
const filteredData = filterModels(latestModels, { owner, id: filter });
// Sort data if sort flag provided, otherwise use latest.
sortBy = sortBy || 'latest';
const sortedData = sortModels(filteredData, sortBy);
// Transform data for display
const transformedData = sortedData.map((item) => ({
id: item.id,
version: item.version,
updated_at: item.updated_at.toLocaleString()
}));
// Inform user of chosen filters and how many results are given
if (owner || filter) {
const filterBy: string[] = [];
if (owner) filterBy.push(`owner: '${owner}'`);
if (filter) filterBy.push(`id: '${filter}'`);
echo(`Filtering by ${filterBy.join(' and ')}`);
}
if (transformedData.length < 1) {
echo(`Did not find any matching results. Try using a different filter`);
} else {
echo(
`Displaying ${transformedData.length}/${latestModels.length} models in the ${sortBy} order.`
);
console.table(transformedData);
}
}
});
// Filter by ID and description
function filterModels(modelTable, filter: { owner?: string; id?: string }) {
return modelTable.filter((model) => {
// Split the model.id into owner and id
const owner = model.id.split('/')[0];
const id = model.id.split('/')[1];
// Filter the results
const matchesOwner = filter.owner ? owner.includes(filter.owner) : true;
const matchesId = filter.id ? id.includes(filter.id) : true;
return matchesOwner && matchesId;
});
}
// Sort models by sorting flag
function sortModels(models, sortBy: string) {
let sortedModels = [...models]; // Create a shallow copy to avoid modifying the original array
switch (sortBy) {
case 'ascending':
sortedModels = sortedModels.sort((a, b) =>
a.id.localeCompare(b.id, undefined, { sensitivity: 'accent' })
);
break;
case 'descending':
sortedModels = sortedModels.sort((a, b) =>
b.id.localeCompare(a.id, undefined, { sensitivity: 'accent' })
);
break;
case 'oldest':
sortedModels = sortedModels.sort((a, b) => a.updated_at - b.updated_at);
break;
case 'latest':
sortedModels = sortedModels.sort((a, b) => b.updated_at - a.updated_at);
break;
default:
console.log('Invalid sorting option');
}
return sortedModels;
}
function formatUpdatedAt(updatedAt: string): string {
let date;
// Try to convert to a Date object
if (!isNaN(Number(updatedAt))) {
// If the value is a numeric string (timestamp in milliseconds)
date = new Date(Number(updatedAt));
} else {
// Otherwise, treat it as an ISO string (e.g., '2022-05-12T21:18:26.596Z')
date = new Date(updatedAt);
}
// If the date is valid, format it as a readable string
if (!isNaN(date.getTime())) {
return date;
} else {
return 'Invalid Date';
}
}