Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[fixie] Add ability to set default runtime parameters in the CLI #504

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions packages/fixie/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fixie",
"version": "5.2.0",
"version": "5.3.0",
"license": "MIT",
"repository": "fixie-ai/ai-jsx",
"bugs": "https://github.com/fixie-ai/ai-jsx/issues",
Expand All @@ -12,8 +12,8 @@
"build-start": "yarn run build && yarn run start",
"format": "prettier --write .",
"test": "yarn run build && yarn run lint",
"lint": "eslint .",
"lint:fix": "eslint .",
"lint": "eslint . --max-warnings 0",
"lint:fix": "eslint . --fix",
"prepack": "yarn build"
},
"volta": {
Expand Down
28 changes: 17 additions & 11 deletions packages/fixie/src/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -399,12 +399,7 @@ export class FixieAgent {
`
);
const program = TJS.programFromConfig(tsconfigPath, [tempPath]);
const schema = TJS.generateSchema(program, 'RuntimeParameters', settings);
if (schema && schema.type !== 'object') {
throw new Error(`The first argument of your default export must be an object (not ${schema.type})`);
}

return schema;
return TJS.generateSchema(program, 'RuntimeParameters', settings);
}

/** Package the code in the given directory and return the path to the tarball. */
Expand Down Expand Up @@ -600,7 +595,8 @@ export class FixieAgent {
public static async DeployAgent(
client: FixieClient,
agentPath: string,
environmentVariables: Record<string, string> = {}
environmentVariables: Record<string, string> = {},
defaultRuntimeParameters: Record<string, unknown> = {}
): Promise<AgentRevision> {
const config = await FixieAgent.LoadConfig(agentPath);
term('🦊 Deploying agent ').green(config.handle)('...\n');
Expand Down Expand Up @@ -629,7 +625,12 @@ export class FixieAgent {
const runtimeParametersSchema = this.inferRuntimeParametersSchema(agentPath);
const tarball = FixieAgent.getCodePackage(agentPath);
const spinner = ora(' 🚀 Deploying... (hang tight, this takes a minute or two!)').start();
const revision = await agent.createRevision({ tarball, environmentVariables, runtimeParametersSchema });
const revision = await agent.createRevision({
tarball,
environmentVariables,
runtimeParametersSchema,
defaultRuntimeParameters,
});
spinner.succeed(`Agent ${config.handle} is running at: ${agent.agentUrl(client.url)}`);
return revision;
}
Expand All @@ -641,13 +642,15 @@ export class FixieAgent {
tunnel,
port,
environmentVariables,
defaultRuntimeParameters = {},
debug,
}: {
client: FixieClient;
agentPath: string;
tunnel?: boolean;
port: number;
environmentVariables: Record<string, string>;
defaultRuntimeParameters?: Record<string, unknown>;
debug?: boolean;
}) {
const config = await FixieAgent.LoadConfig(agentPath);
Expand Down Expand Up @@ -777,13 +780,16 @@ export class FixieAgent {
await agent.deleteRevision(currentRevision.id);
currentRevision = null;
}
currentRevision = await agent.createRevision({ externalUrl: currentUrl, runtimeParametersSchema });
currentRevision = await agent.createRevision({
externalUrl: currentUrl,
runtimeParametersSchema,
defaultRuntimeParameters,
});
term('🥡 Created temporary agent revision ').green(currentRevision.id)('\n');
term('🥡 Agent ').green(config.handle)(' is running at: ').green(agent.agentUrl(client.url))('\n');
} catch (e: any) {
term('🥡 Got error trying to create agent revision: ').red(e.message)('\n');
console.error(e);
continue;
throw e;
}
}
}
Expand Down
12 changes: 1 addition & 11 deletions packages/fixie/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,7 @@ import { ApolloClient } from '@apollo/client/core/ApolloClient.js';
import { InMemoryCache } from '@apollo/client/cache/inmemory/inMemoryCache.js';
import createUploadLink from 'apollo-upload-client/public/createUploadLink.js';
import type { Jsonifiable } from 'type-fest';
import {
AgentId,
AssistantConversationTurn,
Conversation,
ConversationId,
Metadata,
User,
Team,
Membership,
MembershipRole,
} from './types.js';
import { AgentId, AssistantConversationTurn, Conversation, ConversationId, Metadata, User, Team } from './types.js';
import { encode } from 'base64-arraybuffer';

export class AgentDoesNotExistError extends Error {
Expand Down
82 changes: 60 additions & 22 deletions packages/fixie/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This is a command-line tool to interact with the Fixie platform.
*/

import { Command, Option, program } from 'commander';
import { Command, InvalidArgumentError, Option, program } from 'commander';
import fs from 'fs';
import path from 'path';
import terminal from 'terminal-kit';
Expand Down Expand Up @@ -42,6 +42,18 @@ function parseDate(value: string): Date {
return parsedDate;
}

function parseJsonObject(value: string): Record<string, unknown> {
try {
const parsed = JSON.parse(value);
if (typeof parsed !== 'object') {
throw new Error('Must be an object.');
}
return parsed;
} catch (ex) {
throw new InvalidArgumentError('Not a valid JSON object.');
}
}

/** Deploy an agent from the current directory. */
function registerDeployCommand(command: Command) {
command
Expand All @@ -60,13 +72,28 @@ function registerDeployCommand(command: Command) {
};
}
)
.action(async (path: string | undefined, options: { env: Record<string, string> }) => {
const client = await AuthenticateOrLogIn({ apiUrl: program.opts().url });
await FixieAgent.DeployAgent(client, path ?? process.cwd(), {
FIXIE_API_URL: program.opts().url,
...options.env,
});
});
.option(
'--default-parameters <json>',
'Default runtime parameters to set for this revision. Must conform to the schema defined by the agent.',
parseJsonObject
)
.action(
async (
path: string | undefined,
options: { env: Record<string, string>; defaultParameters?: Record<string, unknown> }
) => {
const client = await AuthenticateOrLogIn({ apiUrl: program.opts().url });
await FixieAgent.DeployAgent(
client,
path ?? process.cwd(),
{
FIXIE_API_URL: program.opts().url,
...options.env,
},
options.defaultParameters
);
}
);
}

/** Run an agent locally. */
Expand All @@ -88,19 +115,30 @@ function registerServeCommand(command: Command) {
};
}
)
.action(async (path: string | undefined, options: { port: string; env: Record<string, string> }) => {
const client = await AuthenticateOrLogIn({ apiUrl: program.opts().url });
await FixieAgent.ServeAgent({
client,
agentPath: path ?? process.cwd(),
port: parseInt(options.port),
tunnel: true,
environmentVariables: {
FIXIE_API_URL: program.opts().url,
...options.env,
},
});
});
.option(
'--default-parameters <json>',
'Default runtime parameters to set for this revision. Must conform to the schema defined by the agent.',
parseJsonObject
)
.action(
async (
path: string | undefined,
options: { port: string; env: Record<string, string>; defaultParameters: Record<string, unknown> }
) => {
const client = await AuthenticateOrLogIn({ apiUrl: program.opts().url });
await FixieAgent.ServeAgent({
client,
agentPath: path ?? process.cwd(),
port: parseInt(options.port),
tunnel: true,
environmentVariables: {
FIXIE_API_URL: program.opts().url,
...options.env,
},
defaultRuntimeParameters: options.defaultParameters,
});
}
);
}

// Get current version of this package.
Expand Down Expand Up @@ -752,7 +790,7 @@ team
.command('remove <teamId> <userId>')
.description('Remove a member from a team')
.action(
catchErrors(async (teamId: string, userId: string, opts) => {
catchErrors(async (teamId: string, userId: string) => {
const client = await AuthenticateOrLogIn({ apiUrl: program.opts().url });
const result = await client.removeTeamMember({
teamId,
Expand Down