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

feat: add getSteps API #22

Merged
Merged
Show file tree
Hide file tree
Changes from all 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
78 changes: 73 additions & 5 deletions src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import {
ParticipantsFilter,
ScoresFilter,
ScoresOrderBy,
StepsFilter,
StepsOrderBy,
ThreadsFilter,
ThreadsOrderBy
} from './filter';
Expand All @@ -30,6 +32,7 @@ import {
Prompt,
Score,
Step,
StepConstructor,
StepType,
User,
Utils
Expand Down Expand Up @@ -437,6 +440,71 @@ export class API {
return this.makeGqlCall(query, variables);
}

/**
* Retrieves a paginated list of steps (runs) based on the provided criteria.
*
* @param variables - The parameters to filter and paginate the steps.
* @param variables.first - The number of steps to retrieve after the cursor. (Optional)
* @param variables.after - The cursor to start retrieving steps after. (Optional)
* @param variables.before - The cursor to start retrieving steps before. (Optional)
* @param variables.filters - The filters to apply on the steps retrieval. (Optional)
* @param variables.orderBy - The order in which to retrieve the steps. (Optional)
* @returns A promise that resolves to a paginated response of steps.
*/
async getSteps(variables: {
first?: Maybe<number>;
after?: Maybe<string>;
before?: Maybe<string>;
filters?: StepsFilter[];
orderBy?: StepsOrderBy;
}): Promise<PaginatedResponse<OmitUtils<StepConstructor>>> {
const query = `
query GetSteps(
$after: ID,
$before: ID,
$cursorAnchor: DateTime,
$filters: [stepsInputType!],
$orderBy: StepsOrderByInput,
$first: Int,
$last: Int,
$projectId: String,
) {
steps(
after: $after,
before: $before,
cursorAnchor: $cursorAnchor,
filters: $filters,
orderBy: $orderBy,
first: $first,
last: $last,
projectId: $projectId,
) {
pageInfo {
startCursor
endCursor
hasNextPage
hasPreviousPage
}
totalCount
edges {
cursor
node {
${stepFields}
}
}
}
}`;

const result = await this.makeGqlCall(query, variables);

const response = result.data.steps;

response.data = response.edges.map((x: any) => x.node);
delete response.edges;

return response;
}

/**
* Retrieves a step by its ID.
*
Expand All @@ -448,12 +516,12 @@ export class API {
*/
async getStep(id: string): Promise<Maybe<Step>> {
const query = `
query GetStep($id: String!) {
step(id: $id) {
${stepFields}
query GetStep($id: String!) {
step(id: $id) {
${stepFields}
}
}
}
`;
`;

const variables = { id };

Expand Down
16 changes: 16 additions & 0 deletions src/filter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,22 @@ type OrderBy<Cols extends string> = {
direction: 'ASC' | 'DESC';
};

export type StepsFilter =
| Filter<'id', 'string'>
| Filter<'name', 'string', true>
| Filter<'input', 'json', true>
| Filter<'output', 'json', true>
| Filter<'participantIdentifiers', 'stringList', true>
| Filter<'startTime', 'datetime', true>
| Filter<'endTime', 'datetime', true>
| Filter<'metadata', 'json', true>
| Filter<'parentId', 'string', true>
| Filter<'threadId', 'string'>
| Filter<'error', 'string', true>
| Filter<'tags', 'stringList', true>;

export type StepsOrderBy = OrderBy<'createdAt'>;

export type ThreadsFilter =
| Filter<'id', 'string'>
| Filter<'createdAt', 'datetime'>
Expand Down
34 changes: 34 additions & 0 deletions tests/integration/api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,40 @@ describe('End to end tests for the SDK', function () {
expect(deletedStep).toBeNull();
});

it('should test steps', async function () {
const thread = await client.thread({ id: uuidv4() });
const step = await thread
.step({
name: 'test',
type: 'run',
tags: ['to_score']
})
.send();

if (!step.id) {
throw new Error('Step id is null');
}

const steps = await client.api.getSteps({
filters: [
{
field: 'id',
operator: 'eq',
value: step.id
},
{
field: 'tags',
operator: 'in',
value: ['to_score']

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't testing without any 'ids' in the query, risky ?

As in, there can be an existing step with that tag from any other test run, and that would make that test fail.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I will add a filter on the id here!

}
]
});
expect(steps.data.length).toBe(1);
expect(steps.data[0].id).toBe(step.id);

await client.api.deleteThread(thread.id);
});

it('should test score', async function () {
const thread = await client.thread({ id: uuidv4() });
const step = await thread
Expand Down
Loading