Skip to content

Commit

Permalink
chore(commands): move command to separate modules (#30)
Browse files Browse the repository at this point in the history
Signed-off-by: Tomas Pilar <tomas.pilar@ibm.com>
  • Loading branch information
pilartomas authored Sep 21, 2023
1 parent 0e71bb9 commit 7575f28
Show file tree
Hide file tree
Showing 35 changed files with 1,290 additions and 1,110 deletions.
7 changes: 7 additions & 0 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,10 @@ rules:
"import/order":
- error
- newlines-between: always
"import/extensions":
- error
- ignorePackages
- js: always
"quote-props":
- error
- consistent
1 change: 1 addition & 0 deletions .prettierrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
quoteProps: "consistent"
55 changes: 55 additions & 0 deletions src/commands/config/default.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { stdin, stdout } from "node:process";
import { createInterface } from "node:readline";
import { promisify } from "node:util";

import { DEFAULT_ENDPOINT } from "../../utils/constants.js";
import { mergeConfig } from "../../utils/config.js";

export const defaultCommandDefinition = [
"$0",
"Modify configuration",
{},
async (args) => {
const rl = createInterface({
input: stdin,
output: stdout,
});
const question = promisify(rl.question).bind(rl);
rl.on("close", () => {
console.log();
});

const config = {
configuration: {},
credentials: {},
};
if (args.profile) {
config.configuration.profiles = { [args.profile]: {} };
config.credentials.profiles = { [args.profile]: {} };
}

const endpoint = await question(
`Endpoint (${
args.endpoint ?? process.env.GENAI_ENDPOINT ?? DEFAULT_ENDPOINT
}): `
);
if (endpoint) {
if (args.profile) {
config.configuration.profiles[args.profile].endpoint = endpoint;
} else {
config.configuration.endpoint = endpoint;
}
}
const apiKey = await question(`API Key (${args.apiKey ?? "none"}): `);
if (apiKey) {
if (args.profile) {
config.credentials.profiles[args.profile].apiKey = apiKey;
} else {
config.credentials.apiKey = apiKey;
}
}

rl.close();
mergeConfig(config);
},
];
15 changes: 15 additions & 0 deletions src/commands/config/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { defaultCommandDefinition } from "./default.js";
import { profilesCommandDefinition } from "./profiles.js";
import { removeCommandDefinition } from "./remove.js";
import { showCommandDefinition } from "./show.js";

export const configCommandDefinition = [
"config",
"Manage CLI configuration",
(yargs) =>
yargs
.command(...defaultCommandDefinition)
.command(...showCommandDefinition)
.command(...profilesCommandDefinition)
.command(...removeCommandDefinition),
];
13 changes: 13 additions & 0 deletions src/commands/config/profiles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { allProfiles } from "../../utils/config.js";

export const profilesCommandDefinition = [
"profiles",
"List configuration profiles",
{},
() => {
const profiles = allProfiles();
profiles.forEach((profile) => {
console.log(profile);
});
},
];
10 changes: 10 additions & 0 deletions src/commands/config/remove.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { deleteProfileConfig } from "../../utils/config.js";

export const removeCommandDefinition = [
"remove",
"Remove configuration",
{},
(args) => {
deleteProfileConfig(args.profile);
},
];
12 changes: 12 additions & 0 deletions src/commands/config/show.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { loadProfileConfig } from "../../utils/config.js";
import { prettyPrint } from "../../utils/print.js";

export const showCommandDefinition = [
"show",
"Show configuration",
{},
(args) => {
const config = loadProfileConfig(args.profile);
prettyPrint(config);
},
];
12 changes: 12 additions & 0 deletions src/commands/files/delete.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export const deleteCommandDefinition = [
"delete <id>",
"Delete a file",
(yargs) =>
yargs.positional("id", {
type: "string",
description: "Identifier of the file to be deleted",
}),
async (args) => {
await args.client.file({ id: args.id }, { delete: true });
},
];
35 changes: 35 additions & 0 deletions src/commands/files/download.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { stdout } from "node:process";
import { createWriteStream } from "node:fs";
import { pipeline } from "node:stream/promises";

import { groupOptions } from "../../utils/yargs.js";

export const downloadCommandDefinition = [
"download <id>",
"Download a file",
(yargs) =>
yargs
.positional("id", {
type: "string",
description: "Identifier of the file to download",
})
.options(
groupOptions({
output: {
alias: "o",
describe: "Filepath to write the file to",
type: "string",
normalize: true,
requiresArg: true,
coerce: (output) => createWriteStream(output),
},
})
),
async (args) => {
const { download } = await args.client.file({
id: args.id,
});
const readable = await download();
await pipeline(readable, args.output ?? stdout);
},
];
21 changes: 21 additions & 0 deletions src/commands/files/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { clientMiddleware } from "../../middleware/client.js";

import { deleteCommandDefinition } from "./delete.js";
import { downloadCommandDefinition } from "./download.js";
import { infoCommandDefinition } from "./info.js";
import { listCommandDefinition } from "./list.js";
import { uploadCommandDefinition } from "./upload.js";

export const filesCommandDefinition = [
"files",
"Upload and manage files",
(yargs) =>
yargs
.middleware(clientMiddleware)
.command(...listCommandDefinition)
.command(...infoCommandDefinition)
.command(...uploadCommandDefinition)
.command(...downloadCommandDefinition)
.command(...deleteCommandDefinition)
.demandCommand(1, 1, "Please choose a command"),
];
17 changes: 17 additions & 0 deletions src/commands/files/info.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { prettyPrint } from "../../utils/print.js";

export const infoCommandDefinition = [
"info <id>",
"Show detailed information about a file",
(yargs) =>
yargs.positional("id", {
type: "string",
description: "Identifier of the file",
}),
async (args) => {
const { id, file_name, purpose, created_at } = await args.client.file({
id: args.id,
});
prettyPrint({ id, name: file_name, purpose, created_at });
},
];
24 changes: 24 additions & 0 deletions src/commands/files/list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { FilePurposeSchema } from "@ibm-generative-ai/node-sdk";

import { groupOptions } from "../../utils/yargs.js";

export const listCommandDefinition = [
"list",
"List all files",
groupOptions({
purpose: {
alias: "p",
type: "array",
description: "Filter listed by purpose",
requiresArg: true,
choices: FilePurposeSchema.options,
},
}),
async (args) => {
for await (const file of args.client.files()) {
if (!args.purpose || args.purpose.includes(file.purpose)) {
console.log(`${file.id} (${file.file_name})`);
}
}
},
];
44 changes: 44 additions & 0 deletions src/commands/files/upload.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { createReadStream } from "node:fs";
import path from "node:path";

import { FilePurposeSchema } from "@ibm-generative-ai/node-sdk";

import { groupOptions } from "../../utils/yargs.js";
import { prettyPrint } from "../../utils/print.js";

export const uploadCommandDefinition = [
"upload <file>",
"Upload a file",
(yargs) =>
yargs
.positional("file", {
type: "string",
describe: "Filepath to the file to be uploaded",
normalize: true,
})
.options(
groupOptions({
purpose: {
alias: "p",
description: "Purpose of the file",
requiresArg: true,
demandOption: true,
choices: FilePurposeSchema.options,
},
name: {
alias: "n",
type: "string",
description: "Name of the file",
requiresArg: true,
},
})
),
async (args) => {
const { id, file_name, purpose, created_at } = await args.client.file({
purpose: args.purpose,
filename: args.name ?? path.parse(args.file).base,
file: createReadStream(args.file),
});
prettyPrint({ id, name: file_name, purpose, created_at });
},
];
94 changes: 94 additions & 0 deletions src/commands/generate/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import isEmpty from "lodash/isEmpty.js";
import merge from "lodash/merge.js";

import { pickDefined } from "../../utils/common.js";
import { prettyPrint } from "../../utils/print.js";
import { groupOptions } from "../../utils/yargs.js";

export const configCommandDefinition = [
"config",
"Read and modify generate configuration",
(yargs) =>
yargs
.options(
groupOptions(
{
"input-text": {
type: "boolean",
description: "Include input text",
},
"generated-tokens": {
type: "boolean",
description: "Include the list of individual generated tokens",
},
"input-tokens": {
type: "boolean",
description: "Include the list of input tokens",
},
"token-logprobs": {
type: "boolean",
description: "Include logprob for each token",
},
"token-ranks": {
type: "boolean",
description: "Include rank of each returned token",
},
"top-n-tokens": {
type: "number",
requiresArg: true,
nargs: 1,
description:
"Include top n candidate tokens at the position of each returned token",
},
},
"Configuration:"
)
)
.middleware((args) => {
const return_options = pickDefined({
input_text: args.inputText,
generated_tokens: args.generatedTokens,
input_tokens: args.inputTokens,
token_logprobs: args.tokenLogprobs,
input_ranks: args.tokenRanks,
top_n_tokens: args.topNTokens,
});
args.parameters = !isEmpty(return_options)
? merge({}, args.parameters, { return_options })
: args.parameters;
})
.options(
groupOptions({
reset: {
describe: "Reset the config",
type: "boolean",
},
replace: {
describe: "Replace the entire config",
type: "boolean",
conflicts: "reset",
},
})
),
async (args) => {
const hasInput = args.model || args.parameters;

const output = hasInput
? await args.client.generateConfig(
{
model_id: args.model,
parameters: args.parameters,
},
{
strategy: args.replace ? "replace" : "merge",
timeout: args.timeout,
}
)
: await args.client.generateConfig({
reset: args.reset,
timeout: args.timeout,
});

prettyPrint(output);
},
];
Loading

0 comments on commit 7575f28

Please sign in to comment.