Skip to content

Commit

Permalink
Allow CLI to run without a graph if the main graph is specified in th…
Browse files Browse the repository at this point in the history
…e project, build fix
  • Loading branch information
abrenneke committed Oct 31, 2023
1 parent 74ed7c0 commit 63c6aef
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 103 deletions.
98 changes: 52 additions & 46 deletions packages/cli/bin/cli.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { createProcessor, loadProjectFromFile, runGraphInFile } from '@ironclad/rivet-node';
import { createProcessor, loadProjectFromFile } from '@ironclad/rivet-node';
import { resolve } from 'node:path';
import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';
await yargs(hideBin(process.argv))
.command('run <projectFile> [graphName]', 'Run a graph in a project file', (y) => y
.command('run <projectFile> [graphName]', 'Run a graph in a project file, or the main graph if graphName is not specified.', (y) => y
.positional('projectFile', {
describe: 'The project file to run',
type: 'string',
Expand Down Expand Up @@ -38,58 +38,64 @@ await yargs(hideBin(process.argv))
.demandCommand()
.parseAsync();
async function run(args) {
const projectPath = resolve(process.cwd(), args.projectFile);
const project = await loadProjectFromFile(projectPath);
if (!args.graphName) {
const validGraphs = Object.values(project.graphs).map((graph) => [graph.metadata.id, graph.metadata.name]);
const validGraphNames = validGraphs.map(([id, name]) => `• "${name}" (${id})`);
console.error(`No graph name provided. Valid graphs are: \n${validGraphNames.join('\n')}\n\n Use either the graph's name or its ID.`);
process.exit(1);
}
let inputs = {};
if (args.inputsStdin) {
// Read json from stdin
const stdin = process.stdin;
stdin.setEncoding('utf8');
let input = '';
for await (const chunk of stdin) {
input += chunk;
try {
const projectPath = resolve(process.cwd(), args.projectFile);
const project = await loadProjectFromFile(projectPath);
if (!args.graphName && !project.metadata.mainGraphId) {
const validGraphs = Object.values(project.graphs).map((graph) => [graph.metadata.id, graph.metadata.name]);
const validGraphNames = validGraphs.map(([id, name]) => `• "${name}" (${id})`);
console.error(`No graph name provided, and project does not specify a main graph. Valid graphs are: \n${validGraphNames.join('\n')}\n\n Use either the graph's name or its ID. For example, \`rivet run my-project.rivet-project my-graph\` or \`rivet run my-project.rivet-project 1234abcd\``);
process.exit(1);
}
try {
inputs = JSON.parse(input);
let inputs = {};
if (args.inputsStdin) {
// Read json from stdin
const stdin = process.stdin;
stdin.setEncoding('utf8');
let input = '';
for await (const chunk of stdin) {
input += chunk;
}
try {
inputs = JSON.parse(input);
}
catch (err) {
console.error('Failed to parse input JSON');
console.error(err);
process.exit(1);
}
}
catch (err) {
console.error('Failed to parse input JSON');
console.error(err);
process.exit(1);
else {
inputs = Object.fromEntries(args.input.map((input) => {
const [key, value] = input.split('=');
if (!key || !value) {
console.error(`Invalid input value: ${input}`);
process.exit(1);
}
return [key, value];
}));
}
}
else {
inputs = Object.fromEntries(args.input.map((input) => {
const [key, value] = input.split('=');
const contextValues = Object.fromEntries(args.context.map((context) => {
const [key, value] = context.split('=');
if (!key || !value) {
console.error(`Invalid input value: ${input}`);
console.error(`Invalid context value: ${context}`);
process.exit(1);
}
return [key, value];
}));
}
const contextValues = Object.fromEntries(args.context.map((context) => {
const [key, value] = context.split('=');
if (!key || !value) {
console.error(`Invalid context value: ${context}`);
process.exit(1);
const { run } = createProcessor(project, {
graph: args.graphName,
inputs,
context: contextValues,
});
const outputs = await run();
if (!args.includeCost) {
delete outputs.cost;
}
return [key, value];
}));
const { run } = createProcessor(project, {
graph: args.graphName,
inputs,
context: contextValues,
});
const outputs = await run();
if (!args.includeCost) {
delete outputs.cost;
console.log(outputs);
}
catch (err) {
console.error(err);
process.exit(1);
}
console.log(outputs);
}
3 changes: 3 additions & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,8 @@
},
"volta": {
"node": "20.4.0"
},
"engines": {
"node": ">=18.0.0"
}
}
115 changes: 60 additions & 55 deletions packages/cli/src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { createProcessor, loadProjectFromFile, runGraphInFile, type LooseDataValue } from '@ironclad/rivet-node';
import { createProcessor, loadProjectFromFile, type LooseDataValue } from '@ironclad/rivet-node';
import { resolve } from 'node:path';
import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';

await yargs(hideBin(process.argv))
.command(
'run <projectFile> [graphName]',
'Run a graph in a project file',
'Run a graph in a project file, or the main graph if graphName is not specified.',
(y) =>
y
.positional('projectFile', {
Expand Down Expand Up @@ -53,75 +53,80 @@ async function run(args: {
context: string[];
input: string[];
}) {
const projectPath = resolve(process.cwd(), args.projectFile);
try {
const projectPath = resolve(process.cwd(), args.projectFile);

const project = await loadProjectFromFile(projectPath);
const project = await loadProjectFromFile(projectPath);

if (!args.graphName) {
const validGraphs = Object.values(project.graphs).map((graph) => [graph.metadata!.id!, graph.metadata!.name!]);
const validGraphNames = validGraphs.map(([id, name]) => `• "${name}" (${id})`);
if (!args.graphName && !project.metadata.mainGraphId) {
const validGraphs = Object.values(project.graphs).map((graph) => [graph.metadata!.id!, graph.metadata!.name!]);
const validGraphNames = validGraphs.map(([id, name]) => `• "${name}" (${id})`);

console.error(
`No graph name provided. Valid graphs are: \n${validGraphNames.join(
'\n',
)}\n\n Use either the graph's name or its ID.`,
);
process.exit(1);
}
console.error(
`No graph name provided, and project does not specify a main graph. Valid graphs are: \n${validGraphNames.join(
'\n',
)}\n\n Use either the graph's name or its ID. For example, \`rivet run my-project.rivet-project my-graph\` or \`rivet run my-project.rivet-project 1234abcd\``,
);
process.exit(1);
}

let inputs: Record<string, LooseDataValue> = {};
if (args.inputsStdin) {
// Read json from stdin
const stdin = process.stdin;
stdin.setEncoding('utf8');
let inputs: Record<string, LooseDataValue> = {};
if (args.inputsStdin) {
// Read json from stdin
const stdin = process.stdin;
stdin.setEncoding('utf8');

let input = '';
for await (const chunk of stdin) {
input += chunk;
}
let input = '';
for await (const chunk of stdin) {
input += chunk;
}

try {
inputs = JSON.parse(input);
} catch (err) {
console.error('Failed to parse input JSON');
console.error(err);
process.exit(1);
try {
inputs = JSON.parse(input);
} catch (err) {
console.error('Failed to parse input JSON');
console.error(err);
process.exit(1);
}
} else {
inputs = Object.fromEntries(
args.input.map((input) => {
const [key, value] = input.split('=');
if (!key || !value) {
console.error(`Invalid input value: ${input}`);
process.exit(1);
}
return [key, value];
}),
);
}
} else {
inputs = Object.fromEntries(
args.input.map((input) => {
const [key, value] = input.split('=');

const contextValues = Object.fromEntries(
args.context.map((context) => {
const [key, value] = context.split('=');
if (!key || !value) {
console.error(`Invalid input value: ${input}`);
console.error(`Invalid context value: ${context}`);
process.exit(1);
}
return [key, value];
}),
);
}

const contextValues = Object.fromEntries(
args.context.map((context) => {
const [key, value] = context.split('=');
if (!key || !value) {
console.error(`Invalid context value: ${context}`);
process.exit(1);
}
return [key, value];
}),
);
const { run } = createProcessor(project, {
graph: args.graphName,
inputs,
context: contextValues,
});

const { run } = createProcessor(project, {
graph: args.graphName,
inputs,
context: contextValues,
});
const outputs = await run();

const outputs = await run();
if (!args.includeCost) {
delete outputs.cost;
}

if (!args.includeCost) {
delete outputs.cost;
console.log(outputs);
} catch (err) {
console.error(err);
process.exit(1);
}

console.log(outputs);
}
1 change: 1 addition & 0 deletions packages/core/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ export * from './newId.js';
export * from './serialization/serializationUtils.js';
export * from './handleEscapeCharacters.js';
export * from './compatibility.js';
export * from './defaults.js';
2 changes: 1 addition & 1 deletion packages/node/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ import {
loadProjectFromString,
loadProjectAndAttachedDataFromString,
type RunGraphOptions,
DEFAULT_CHAT_NODE_TIMEOUT,
} from '@ironclad/rivet-core';

import { readFile } from 'node:fs/promises';
import { type RivetDebuggerServer, type Settings } from './index.js';
import { NodeNativeApi } from './native/NodeNativeApi.js';
import * as events from 'node:events';
import { DEFAULT_CHAT_NODE_TIMEOUT } from '../../core/src/utils/defaults.js';

export async function loadProjectFromFile(path: string): Promise<Project> {
const content = await readFile(path, { encoding: 'utf8' });
Expand Down
2 changes: 1 addition & 1 deletion packages/trivet/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
type Settings,
type GraphOutputNode,
inferType,
DEFAULT_CHAT_NODE_TIMEOUT,
} from '@ironclad/rivet-core';
import { cloneDeep, keyBy, mapValues, omit } from 'lodash-es';
import {
Expand All @@ -15,7 +16,6 @@ import {
type TrivetResults,
type TrivetTestCaseResult,
} from './trivetTypes.js';
import { DEFAULT_CHAT_NODE_TIMEOUT } from '../../core/src/utils/defaults.js';

const TRUTHY_STRINGS = new Set(['true', 'TRUE']);

Expand Down

0 comments on commit 63c6aef

Please sign in to comment.