Skip to content

Commit

Permalink
Merge branch 'main' into juberti/webrtc-chat
Browse files Browse the repository at this point in the history
  • Loading branch information
juberti authored Nov 14, 2023
2 parents 0467ae6 + 7d4b0d0 commit 73c6b91
Show file tree
Hide file tree
Showing 5 changed files with 393 additions and 8 deletions.
2 changes: 1 addition & 1 deletion packages/fixie/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fixie",
"version": "5.0.0",
"version": "5.2.0",
"license": "MIT",
"repository": "fixie-ai/ai-jsx",
"bugs": "https://github.com/fixie-ai/ai-jsx/issues",
Expand Down
45 changes: 42 additions & 3 deletions packages/fixie/src/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -303,9 +303,48 @@ export class FixieAgent {
}

/** Return logs for this Agent. Returns the last 15 minutes of agent logs. */
async getLogs(): Promise<AgentLogEntry[]> {
// TODO: Expand parameters here to specify start/end times, deal with pagination, etc.
const retval = await this.client.request(`/api/v1/agents/${this.metadata.uuid}/logs`);
async getLogs({
start,
end,
limit,
offset,
minSeverity,
conversationId,
messageId,
}: {
start?: Date;
end?: Date;
limit?: number;
offset?: number;
minSeverity?: number;
conversationId?: string;
messageId?: string;
}): Promise<AgentLogEntry[]> {
// We don't actually care about the full URL here. We're only using the
// URL to build up the query parameters.
const url = new URL('http://localhost/');
if (start) {
url.searchParams.append('startTimestamp', Math.floor(start.getTime() / 1000).toString());
}
if (end) {
url.searchParams.append('endTimestamp', Math.floor(end.getTime() / 1000).toString());
}
if (limit) {
url.searchParams.append('limit', limit.toString());
}
if (offset) {
url.searchParams.append('offset', offset.toString());
}
if (minSeverity) {
url.searchParams.append('minSeverity', minSeverity.toString());
}
if (conversationId) {
url.searchParams.append('conversationId', conversationId);
}
if (messageId) {
url.searchParams.append('messageId', messageId);
}
const retval = await this.client.request(`/api/v1/agents/${this.metadata.uuid}/logs${url.search}`);
if (retval.status !== 200) {
return [];
}
Expand Down
167 changes: 166 additions & 1 deletion packages/fixie/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,17 @@ 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 } from './types.js';
import {
AgentId,
AssistantConversationTurn,
Conversation,
ConversationId,
Metadata,
User,
Team,
Membership,
MembershipRole,
} from './types.js';
import { encode } from 'base64-arraybuffer';

export class AgentDoesNotExistError extends Error {
Expand Down Expand Up @@ -746,4 +756,159 @@ export class FixieClient {
'POST'
);
}

/** Return information about a given user. */
async getUser({ userId }: { userId: string }): Promise<User> {
const rawUserInfo: { user: User } = await this.requestJson(`/api/v1/users/${userId}`);
return rawUserInfo.user;
}

/** Create a new team. */
async createTeam({
displayName,
description,
avatarUrl,
}: {
displayName?: string;
description?: string;
avatarUrl?: string;
}): Promise<Team> {
const response: { team: Team } = await this.requestJson('/api/v1/teams', {
team: {
displayName,
description,
avatarUrl,
},
});
return response.team;
}

/** Get the given team. */
async getTeam({ teamId }: { teamId: string }): Promise<Team> {
const response: { team: Team } = await this.requestJson(`/api/v1/teams/${teamId}`);
return response.team;
}

/** Delete the given team. */
deleteTeam({ teamId }: { teamId: string }): Promise<Jsonifiable> {
return this.requestJson(`/api/v1/teams/${teamId}`, undefined, 'DELETE');
}

/**
* List the teams visible to the current user.
*
* @param options.offset The offset into the list of teams to return.
* @param options.limit The maximum number of teams to return.
*/
listTeams({ offset = 0, limit = 100 }: { offset?: number; limit?: number }): Promise<Jsonifiable> {
return this.requestJson(`/api/v1/teams?offset=${offset}&limit=${limit}`);
}

/**
* Update the given team's metadata.
*
* @param options.displayName The new display name for the team.
* @param options.description The new description for the team.
*/
async updateTeam({
teamId,
displayName,
description,
}: {
teamId: string;
displayName?: string;
description?: string;
}): Promise<Team> {
if (!displayName && !description) {
throw new Error('Must specify either displayName or description');
}
const fieldMask: string[] = [];
if (displayName !== undefined) {
fieldMask.push('displayName');
}
if (description !== undefined) {
fieldMask.push('description');
}
const body = {
team: {
displayName,
description,
},
updateMask: fieldMask.join(','),
};
const response: { team: Team } = await this.requestJson(`/api/v1/teams/${teamId}`, body, 'PUT');
return response.team;
}

/**
* Invite a new member to a team.
*
* @param options.teamId The ID of the team to invite the member to.
* @param options.email The email address of the member to invite.
* @param options.isAdmin Whether the member should be a team admin.
*/
inviteTeamMember({
teamId,
email,
isAdmin,
}: {
teamId: string;
email: string;
isAdmin?: boolean;
}): Promise<Jsonifiable> {
const body = {
teamId,
email,
role: {
isAdmin,
},
};
return this.requestJson(`/api/v1/teams/${teamId}/invite`, body, 'POST');
}

/**
* Cancel a pending invitation to a team.
*
* @param options.teamId The ID of the team to cancel the invitation for.
* @param options.email The email address of the member to cancel the invitation for.
*/
cancelInvitation({ teamId, email }: { teamId: string; email: string }): Promise<Jsonifiable> {
return this.requestJson(`/api/v1/teams/${teamId}/invite/${email}`, null, 'DELETE');
}

/**
* Remove a member from a team.
*
* @param options.teamId The ID of the team to invite the member to.
* @param options.userId The user ID of the member to remove.
*/
removeTeamMember({ teamId, userId }: { teamId: string; userId: string }): Promise<Jsonifiable> {
return this.requestJson(`/api/v1/teams/${teamId}/members/${userId}`, null, 'DELETE');
}

/**
* Update a user's role on a team.
*
* @param options.teamId The ID of the team to update.
* @param options.userId The user ID of the member to update.
* @param options.isAdmin Set the admin role for this user.
*/
updateTeamMember({
teamId,
userId,
isAdmin,
}: {
teamId: string;
userId: string;
isAdmin: boolean;
}): Promise<Jsonifiable> {
const body = {
teamId,
userId,
role: {
isAdmin,
},
};
return this.requestJson(`/api/v1/teams/${teamId}/members/${userId}`, body, 'PUT');
}
}
Loading

0 comments on commit 73c6b91

Please sign in to comment.