From 6256409392d630e6bf7b75ca4e86a47e6b4bc990 Mon Sep 17 00:00:00 2001 From: Aitor <1726644+aaitor@users.noreply.github.com> Date: Tue, 12 Nov 2024 09:13:59 +0100 Subject: [PATCH 1/6] fix: new authentication --- src/api/nvm-backend.ts | 42 ++++++++++++++++++---------------- tests/e2e/payments.e2e.test.ts | 13 ++++++----- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/api/nvm-backend.ts b/src/api/nvm-backend.ts index 265c196..f97c7b2 100644 --- a/src/api/nvm-backend.ts +++ b/src/api/nvm-backend.ts @@ -41,14 +41,19 @@ export interface BackendApiOptions { export interface BackendWebSocketOptions { /** - * The path to connect to the websocket server + * The websocket transports to use */ - path?: string + transports: string[] /** - * The websocket transports to use + * Authentication parameters */ - transports?: string[] + auth: { token: string } + + /** + * The path to connect to the websocket server + */ + path?: string /** * The bearer token to use in the websocket connection @@ -89,11 +94,12 @@ export class NVMBackendApi { private _defaultSocketOptions: BackendWebSocketOptions = { // path: '', transports: ['websocket'], - transportOptions: { - websocket: { - extraHeaders: {}, - }, - }, + auth: { token: '' }, + // transportOptions: { + // websocket: { + // extraHeaders: {}, + // }, + // }, } constructor(opts: BackendApiOptions) { @@ -106,22 +112,16 @@ export class NVMBackendApi { if (opts.webSocketOptions?.bearerToken) { // If the user pass a specific websocketoptions bearer token we use that one opts.webSocketOptions = { + ...this._defaultSocketOptions, ...opts.webSocketOptions, - transportOptions: { - websocket: { - extraHeaders: { Authorization: `Bearer ${opts.webSocketOptions!.bearerToken}` }, - }, - }, + auth: { token: `Bearer ${opts.webSocketOptions!.bearerToken}` }, } } else if (opts.apiKey) { // If not use the api key opts.webSocketOptions = { + ...this._defaultSocketOptions, ...opts.webSocketOptions, - transportOptions: { - websocket: { - extraHeaders: { Authorization: `Bearer ${opts.apiKey}` }, - }, - }, + auth: { token: `Bearer ${opts.apiKey}` }, } } @@ -137,7 +137,6 @@ export class NVMBackendApi { try { if (this.opts.apiKey && this.opts.apiKey.length > 0) { const jwt = decodeJwt(this.opts.apiKey) - // if (jwt.sub && !jwt.sub.match(/^0x[a-fA-F0-9]{40}$/)) { if (isEthereumAddress(jwt.sub)) { this.userRoomId = `room:${jwt.sub}` this.hasKey = true @@ -167,6 +166,9 @@ export class NVMBackendApi { } try { // nvm-backend:: Connecting to websocket server: ${this.opts.webSocketHost} + console.log( + `nvm-backend:: Connecting to websocket server: ${JSON.stringify(this.opts.webSocketOptions)}`, + ) this.socketClient = io(this.opts.webSocketHost!, this.opts.webSocketOptions) await this.socketClient.connect() await this.socketClient.on('_connected', async () => { diff --git a/tests/e2e/payments.e2e.test.ts b/tests/e2e/payments.e2e.test.ts index 7ecff1c..1a97f71 100644 --- a/tests/e2e/payments.e2e.test.ts +++ b/tests/e2e/payments.e2e.test.ts @@ -13,7 +13,8 @@ describe('Payments API (e2e)', () => { 'eyJhbGciOiJFUzI1NksifQ.eyJpc3MiOiIweDU4MzhCNTUxMmNGOWYxMkZFOWYyYmVjY0IyMGViNDcyMTFGOUIwYmMiLCJzdWIiOiIweDFCMDZDRkIyMkYwODMyZmI5MjU1NDE1MmRiYjVGOWM5NzU2ZTkzN2QiLCJqdGkiOiIweDlmMGRkNmZhODNkMDY3ZDRiYzFkNzEyN2Q3ZWE0M2EwYmUwNzc1NWJmNjMxMTVmYzJhODhmOTQwZmY4MjQ1NGQiLCJleHAiOjE3NTk4NzQwMDEsImlhdCI6MTcyODMxNjQwMn0.SqlcnMvdIjpZdBDs8FBsruYUIVpS75My-l5VfVwsFdU_3Xz5DuYt1frdF0QZq8isx9NOsNgRSeG8sBVtvAl-vRw' const builderNvmApiKeyHash = process.env.TEST_BUILDER_API_KEY || - 'eyJhbGciOiJFUzI1NksifQ.eyJpc3MiOiIweDU4MzhCNTUxMmNGOWYxMkZFOWYyYmVjY0IyMGViNDcyMTFGOUIwYmMiLCJzdWIiOiIweDdmRTNFZTA4OGQwY2IzRjQ5ZmREMjBlMTk0RjIzRDY4MzhhY2NjODIiLCJqdGkiOiIweGY2ZDcyMmIzYWY5ZmNhOWY2MTQ2OGI5YjlhNGNmZjk3Yjg5NjE5Yzc1ZjRkYWEyMmY4NTA3Yjc2ODQzM2JkYWQiLCJleHAiOjE3NTk2MDU0MTMsImlhdCI6MTcyODA0NzgxNn0.1JDNV7yT8i1_1DXxC4z_jzMLJQns4XqujaJOEFmLdtwFam7bi-3s8oOF-dbTBObzNY98ddZZFifaCEvJUImYOBw' + // 'eyJhbGciOiJFUzI1NksifQ.eyJpc3MiOiIweDU4MzhCNTUxMmNGOWYxMkZFOWYyYmVjY0IyMGViNDcyMTFGOUIwYmMiLCJzdWIiOiIweDdmRTNFZTA4OGQwY2IzRjQ5ZmREMjBlMTk0RjIzRDY4MzhhY2NjODIiLCJqdGkiOiIweGY2ZDcyMmIzYWY5ZmNhOWY2MTQ2OGI5YjlhNGNmZjk3Yjg5NjE5Yzc1ZjRkYWEyMmY4NTA3Yjc2ODQzM2JkYWQiLCJleHAiOjE3NTk2MDU0MTMsImlhdCI6MTcyODA0NzgxNn0.1JDNV7yT8i1_1DXxC4z_jzMLJQns4XqujaJOEFmLdtwFam7bi-3s8oOF-dbTBObzNY98ddZZFifaCEvJUImYOBw' + 'eyJhbGciOiJFUzI1NksifQ.eyJpc3MiOiIweDU4MzhCNTUxMmNGOWYxMkZFOWYyYmVjY0IyMGViNDcyMTFGOUIwYmMiLCJzdWIiOiIweDdmRTNFZTA4OGQwY2IzRjQ5ZmREMjBlMTk0RjIzRDY4MzhhY2NjODIiLCJqdGkiOiIweGRhMWNmYTFjMzQ5NTE3MDkwOWQ2ZjY1Mjk3MzlhNWMyZDQ3NTNiMzE4N2JhZDc2ZjU3NGU4ZjQ1NTA0ZGUxYjIiLCJleHAiOjE3NjI5NTYwNjksImlhdCI6MTczMTM5ODQ3MH0.3fHX0Ngptob__kXC8CVUwuVJ-TyMEdxRJwohXCNLO9UzCQOIxwHK9c6uIwUkF-vls4oC2G9lNiqPgVey3KnMSRs' const testingEnvironment = process.env.TEST_ENVIRONMENT || 'staging' const _SLEEP_DURATION = 3_000 const ERC20_ADDRESS = '0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d' @@ -387,7 +388,7 @@ describe('Payments API (e2e)', () => { expect(taskResult).toBeDefined() expect(taskResult.status).toBe(201) - console.log('Task Result', taskResult.data) + //console.log('Task Result', taskResult.data) failedTaskDID = taskResult.data.task.did failedTaskId = taskResult.data.task.task_id console.log(`Failed Task DID: ${failedTaskDID}`) @@ -403,7 +404,7 @@ describe('Payments API (e2e)', () => { subscriberQueryOpts, ) expect(result).toBeDefined() - console.log('Task with Steps', result) + //console.log('Task with Steps', result) expect(result.status).toBe(200) // console.log('Task with Steps', result.data) // expect(result.data.task.cost).toBeDefined() @@ -435,6 +436,6 @@ describe('Payments API (e2e)', () => { }) }) -const stepReceived = (data: any) => { - console.log('Step received', data) -} +// const stepReceived = (data: any) => { +// console.log('Step received', data) +// } From 0515b316eda2c96ca6932a3d6b6f61efb914d9c7 Mon Sep 17 00:00:00 2001 From: Aitor <1726644+aaitor@users.noreply.github.com> Date: Tue, 12 Nov 2024 13:22:37 +0100 Subject: [PATCH 2/6] feat: logging task messages --- src/api/nvm-backend.ts | 72 +++++++++++++++++++++++++++------- src/api/query-api.ts | 34 +++++++++++++++- tests/e2e/payments.e2e.test.ts | 47 +++++++++++++++++++--- 3 files changed, 133 insertions(+), 20 deletions(-) diff --git a/src/api/nvm-backend.ts b/src/api/nvm-backend.ts index f97c7b2..3a5e2fd 100644 --- a/src/api/nvm-backend.ts +++ b/src/api/nvm-backend.ts @@ -4,6 +4,8 @@ import { io } from 'socket.io-client' import { sleep } from '../common/helper' import { AgentExecutionStatus } from '../common/types' import { isEthereumAddress } from '../utils' +import { PaymentsError } from '../common/payments.error' +import { TaskLogMessage } from './query-api' export interface BackendApiOptions { /** @@ -156,35 +158,73 @@ export class NVMBackendApi { } } - public async connectSocket(_callback: (err?: any) => any, opts: SubscriptionOptions) { + private async _connectInternalSocketClient() { if (!this.hasKey) throw new Error('Unable to subscribe to the server becase a key was not provided') - if (this.socketClient && this.socketClient.connected) { - // nvm-backend:: Already connected to the websocket server + if (this.isWebSocketConnected()) { + console.log( + `_connectInternalSocketClient:: Already connected to the websocket server with id ${this.socketClient.id}`, + ) return } + + this.socketClient = io(this.opts.webSocketHost!, this.opts.webSocketOptions) + await this.socketClient.connect() + for (let i = 0; i < 10; i++) { + if (this.isWebSocketConnected()) return + await sleep(500) + } + if (!this.isWebSocketConnected()) { + throw new Error('Unable to connect to the websocket server') + } + } + + protected async connectSocketSubscriber( + _callback: (err?: any) => any, + opts: SubscriptionOptions, + ) { try { // nvm-backend:: Connecting to websocket server: ${this.opts.webSocketHost} console.log( `nvm-backend:: Connecting to websocket server: ${JSON.stringify(this.opts.webSocketOptions)}`, ) - this.socketClient = io(this.opts.webSocketHost!, this.opts.webSocketOptions) - await this.socketClient.connect() + this._connectInternalSocketClient() + await this.socketClient.on('_connected', async () => { this._subscribe(_callback, opts) }) - for (let i = 0; i < 5; i++) { - await sleep(1_000) - if (this.socketClient.connected) { - break - } - } - if (!this.socketClient.connected) { - throw new Error('Unable to connect to the websocket server') + } catch (error) { + throw new PaymentsError( + `Unable to initialize websocket client: ${this.opts.webSocketHost} - ${(error as Error).message}`, + ) + } + } + + protected async connectTasksSocket(_callback: (err?: any) => any, tasks: string[]) { + try { + if (tasks.length === 0) { + throw new Error('No task rooms to join in configuration') } + + console.log( + `connectTasksSocket:: Connecting to websocket server: ${JSON.stringify(this.opts.webSocketOptions)}`, + ) + this._connectInternalSocketClient() + + console.log(`connectTasksSocket:: Is connected? ${this.isWebSocketConnected()}`) + + await this.socketClient.on('_connected', async () => { + console.log(`connectTasksSocket:: Joining tasks: ${JSON.stringify(tasks)}`) + await this.socketClient.emit('_join-tasks', JSON.stringify({ tasks })) + await this.socketClient.on('task-log', (data: any) => { + _callback(data) + }) + }) + + console.log(`connectTasksSocket:: ending`) } catch (error) { - throw new Error( + throw new PaymentsError( `Unable to initialize websocket client: ${this.opts.webSocketHost} - ${(error as Error).message}`, ) } @@ -233,6 +273,10 @@ export class NVMBackendApi { this.socketClient.emit('_emit-steps', JSON.stringify(message)) } + protected async _emitTaskLog(logMessage: TaskLogMessage) { + this.socketClient.emit('task-log', JSON.stringify(logMessage)) + } + disconnect() { this.disconnectSocket() // nvm-backend:: Disconnected from the server diff --git a/src/api/query-api.ts b/src/api/query-api.ts index 374cc89..b5a915f 100644 --- a/src/api/query-api.ts +++ b/src/api/query-api.ts @@ -37,6 +37,14 @@ export interface SearchSteps { offset?: number } +export interface TaskLogMessage { + level: 'info' | 'error' | 'warning' | 'debug' + task_id: string + task_status: AgentExecutionStatus + message: string + step_id?: string +} + /** * Options required for interacting with an external AI Agent/Service. */ @@ -78,7 +86,20 @@ export class AIQueryApi extends NVMBackendApi { _callback: (err?: any) => any, opts: SubscriptionOptions = DefaultSubscriptionOptions, ) { - await super.connectSocket(_callback, opts) + await super.connectSocketSubscriber(_callback, opts) + } + + /** + * It subscribes to receive the logs generated during the execution of a task/s + * + * @remarks + * This method is used by users/subscribers of AI agents after they create a task on them + * + * @param _callback - The callback to execute when a new task log event is received + * @param tasks - The list of tasks to subscribe to + */ + async subscribeTasksLogs(_callback: (err?: any) => any, tasks: string[]) { + await super.connectTasksSocket(_callback, tasks) } /** @@ -334,4 +355,15 @@ export class AIQueryApi extends NVMBackendApi { async getTasksFromAgents() { return this.get(GET_AGENTS_ENDPOINT, { sendThroughProxy: false }) } + + /** + * It emits a log message related to a task + * + * @remarks + * This method is used by the AI Agent to emit log messages + * + */ + async logTask(logMessage: TaskLogMessage) { + super._emitTaskLog(logMessage) + } } diff --git a/tests/e2e/payments.e2e.test.ts b/tests/e2e/payments.e2e.test.ts index 1a97f71..3d56786 100644 --- a/tests/e2e/payments.e2e.test.ts +++ b/tests/e2e/payments.e2e.test.ts @@ -1,3 +1,4 @@ +import { TaskLogMessage } from '../../src/api/query-api' import { sleep } from '../../src/common/helper' import { AgentExecutionStatus, Step } from '../../src/common/types' import { EnvironmentName } from '../../src/environments' @@ -33,6 +34,7 @@ describe('Payments API (e2e)', () => { // let proxyHost: string let subscriberQueryOpts = {} let balanceBefore: bigint + let createdTaskId: string let completedTaskId: string let completedTaskDID: string let failedTaskId: string @@ -244,6 +246,9 @@ describe('Payments API (e2e)', () => { expect(taskResult).toBeDefined() expect(taskResult.status).toBe(201) console.log('Task Result', taskResult.data) + createdTaskId = taskResult.data.task.task_id + expect(createdTaskId).toBeDefined() + }, TEST_TIMEOUT, ) @@ -258,8 +263,19 @@ describe('Payments API (e2e)', () => { expect(steps.data.steps.length).toBeGreaterThan(0) }) + it.skip('Builder should be able to send logs', async () => { + const logMessage: TaskLogMessage = { + level: 'info', + task_status: AgentExecutionStatus.Pending, + task_id: createdTaskId, + message: 'This is a log message', + } + await paymentsBuilder.query.logTask(logMessage) + expect(true).toBeTruthy() // If the emitTaskLog does not throw an error, it is working + }) + it( - 'I should be able to subscribe and process pending tasks', + 'Builder should be able to subscribe and process pending tasks', async () => { let stepsReceived = 0 const opts = { @@ -337,7 +353,28 @@ describe('Payments API (e2e)', () => { TEST_TIMEOUT, ) - it('I should be able to validate an AI task is completed', async () => { + it('Subscriber should be able to receive logs', async () => { + let logsReceived = 0 + await paymentsSubscriber.query.subscribeTasksLogs(async (data) => { + console.log('Task Log received', data) + logsReceived++ + }, [completedTaskId]) + await sleep(5_000) + + const logMessage: TaskLogMessage = { + level: 'info', + task_status: AgentExecutionStatus.Completed, + task_id: completedTaskId, + message: 'This is a log message', + } + await paymentsBuilder.query.logTask(logMessage) + + await sleep(2_000) + expect(logsReceived).toBeGreaterThan(0) + + }, TEST_TIMEOUT) + + it.skip('Subscriber should be able to validate an AI task is completed', async () => { console.log(`@@@@@ getting task with steps: ${completedTaskDID} - ${completedTaskId}`) console.log(JSON.stringify(subscriberQueryOpts)) const result = await paymentsSubscriber.query.getTaskWithSteps( @@ -353,7 +390,7 @@ describe('Payments API (e2e)', () => { expect(taskCost).toBeGreaterThan(0) }) - it('I should be able to check that I consumed some credits', async () => { + it.skip('Subscriber should be able to check that I consumed some credits', async () => { const balanceResult = await paymentsSubscriber.getPlanBalance(planDID) expect(balanceResult).toBeDefined() const balanceAfter = BigInt(balanceResult.balance) @@ -367,10 +404,10 @@ describe('Payments API (e2e)', () => { expect(balanceAfter).toBeLessThan(balanceBefore) }) - it.skip('I should be able to end a task with a failure', () => {}) + // it.skip('I should be able to end a task with a failure', () => {}) }) - describe('Failed tasks are free of charge', () => { + describe.skip('Failed tasks are free of charge', () => { it( 'I should be able to create a wrong AI Task', async () => { From 08e94a520d12473b90f167ff4149e696f574bea3 Mon Sep 17 00:00:00 2001 From: Aitor <1726644+aaitor@users.noreply.github.com> Date: Tue, 12 Nov 2024 14:46:59 +0100 Subject: [PATCH 3/6] feat: subscribing to logs on createTask --- src/api/nvm-backend.ts | 2 +- src/api/query-api.ts | 13 +++++++++++-- tests/e2e/payments.e2e.test.ts | 32 ++++++++++++++------------------ 3 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/api/nvm-backend.ts b/src/api/nvm-backend.ts index 3a5e2fd..0d8e1b5 100644 --- a/src/api/nvm-backend.ts +++ b/src/api/nvm-backend.ts @@ -274,7 +274,7 @@ export class NVMBackendApi { } protected async _emitTaskLog(logMessage: TaskLogMessage) { - this.socketClient.emit('task-log', JSON.stringify(logMessage)) + this.socketClient.emit('_task-log', JSON.stringify(logMessage)) } disconnect() { diff --git a/src/api/query-api.ts b/src/api/query-api.ts index b5a915f..d078315 100644 --- a/src/api/query-api.ts +++ b/src/api/query-api.ts @@ -139,7 +139,12 @@ export class AIQueryApi extends NVMBackendApi { * @param queryOpts - The query options @see {@link Payments.getServiceAccessConfig} * @returns The result of the operation */ - async createTask(did: string, task: any, queryOpts: AIQueryOptions) { + async createTask( + did: string, + task: any, + queryOpts: AIQueryOptions, + _callback?: (err?: any) => any, + ) { const endpoint = TASK_ENDPOINT.replace('{did}', did) const reqOptions: HTTPRequestOptions = { sendThroughProxy: true, @@ -148,7 +153,11 @@ export class AIQueryApi extends NVMBackendApi { headers: { Authorization: `Bearer ${queryOpts.accessToken}` }, }), } - return this.post(endpoint, task, reqOptions) + const result = await this.post(endpoint, task, reqOptions) + if (result.status === 201 && _callback) { + await this.subscribeTasksLogs(_callback, [result.data.task.task_id]) + } + return result } /** diff --git a/tests/e2e/payments.e2e.test.ts b/tests/e2e/payments.e2e.test.ts index 3d56786..d154e67 100644 --- a/tests/e2e/payments.e2e.test.ts +++ b/tests/e2e/payments.e2e.test.ts @@ -1,3 +1,4 @@ +import { log } from 'console' import { TaskLogMessage } from '../../src/api/query-api' import { sleep } from '../../src/common/helper' import { AgentExecutionStatus, Step } from '../../src/common/types' @@ -39,6 +40,8 @@ describe('Payments API (e2e)', () => { let completedTaskDID: string let failedTaskId: string let failedTaskDID: string + let logsReceived = 0 + describe('Payments Setup', () => { it('The Payments client can be initialized correctly', () => { paymentsSubscriber = Payments.getInstance({ @@ -230,17 +233,15 @@ describe('Payments API (e2e)', () => { artifacts: [], } subscriberQueryOpts = await paymentsSubscriber.getServiceAccessConfig(agentDID) - // accessToken = accessConfig.accessToken - // proxyHost = accessConfig.neverminedProxyUri - // subscriberQueryOpts = { - // accessToken, - // proxyHost - // } const taskResult = await paymentsSubscriber.query.createTask( agentDID, aiTask, subscriberQueryOpts, + async (data) => { + console.log('Task Log received', data) + logsReceived++ + } ) expect(taskResult).toBeDefined() @@ -259,7 +260,7 @@ describe('Payments API (e2e)', () => { it('Builder should be able to fetch pending tasks', async () => { const steps = await paymentsBuilder.query.getSteps(AgentExecutionStatus.Pending) expect(steps).toBeDefined() - console.log(steps.data) + //console.log(steps.data) expect(steps.data.steps.length).toBeGreaterThan(0) }) @@ -354,19 +355,14 @@ describe('Payments API (e2e)', () => { ) it('Subscriber should be able to receive logs', async () => { - let logsReceived = 0 - await paymentsSubscriber.query.subscribeTasksLogs(async (data) => { - console.log('Task Log received', data) - logsReceived++ - }, [completedTaskId]) - await sleep(5_000) - + const logMessage: TaskLogMessage = { level: 'info', task_status: AgentExecutionStatus.Completed, - task_id: completedTaskId, + task_id: createdTaskId, message: 'This is a log message', } + console.log(`Sending log message for task ${logMessage.task_id}`) await paymentsBuilder.query.logTask(logMessage) await sleep(2_000) @@ -374,7 +370,7 @@ describe('Payments API (e2e)', () => { }, TEST_TIMEOUT) - it.skip('Subscriber should be able to validate an AI task is completed', async () => { + it('Subscriber should be able to validate an AI task is completed', async () => { console.log(`@@@@@ getting task with steps: ${completedTaskDID} - ${completedTaskId}`) console.log(JSON.stringify(subscriberQueryOpts)) const result = await paymentsSubscriber.query.getTaskWithSteps( @@ -390,7 +386,7 @@ describe('Payments API (e2e)', () => { expect(taskCost).toBeGreaterThan(0) }) - it.skip('Subscriber should be able to check that I consumed some credits', async () => { + it('Subscriber should be able to check that I consumed some credits', async () => { const balanceResult = await paymentsSubscriber.getPlanBalance(planDID) expect(balanceResult).toBeDefined() const balanceAfter = BigInt(balanceResult.balance) @@ -407,7 +403,7 @@ describe('Payments API (e2e)', () => { // it.skip('I should be able to end a task with a failure', () => {}) }) - describe.skip('Failed tasks are free of charge', () => { + describe('Failed tasks are free of charge', () => { it( 'I should be able to create a wrong AI Task', async () => { From e6db64b22920fb310b7105cadc86fc2198494d14 Mon Sep 17 00:00:00 2001 From: Aitor <1726644+aaitor@users.noreply.github.com> Date: Tue, 12 Nov 2024 15:19:51 +0100 Subject: [PATCH 4/6] chore: format, version and docs --- package.json | 2 +- src/api/nvm-backend.ts | 16 +++------------- src/api/query-api.ts | 1 + 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 3496655..5119a64 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@nevermined-io/payments", - "version": "0.6.1", + "version": "0.7.0", "description": "Typescript SDK to interact with the Nevermined Payments Protocol", "main": "./dist/index.js", "types": "./dist/index.d.ts", diff --git a/src/api/nvm-backend.ts b/src/api/nvm-backend.ts index 0d8e1b5..6d5a3d4 100644 --- a/src/api/nvm-backend.ts +++ b/src/api/nvm-backend.ts @@ -163,9 +163,7 @@ export class NVMBackendApi { throw new Error('Unable to subscribe to the server becase a key was not provided') if (this.isWebSocketConnected()) { - console.log( - `_connectInternalSocketClient:: Already connected to the websocket server with id ${this.socketClient.id}`, - ) + // `_connectInternalSocketClient:: Already connected to the websocket server with id ${this.socketClient.id}`, return } @@ -186,9 +184,6 @@ export class NVMBackendApi { ) { try { // nvm-backend:: Connecting to websocket server: ${this.opts.webSocketHost} - console.log( - `nvm-backend:: Connecting to websocket server: ${JSON.stringify(this.opts.webSocketOptions)}`, - ) this._connectInternalSocketClient() await this.socketClient.on('_connected', async () => { @@ -207,22 +202,17 @@ export class NVMBackendApi { throw new Error('No task rooms to join in configuration') } - console.log( - `connectTasksSocket:: Connecting to websocket server: ${JSON.stringify(this.opts.webSocketOptions)}`, - ) this._connectInternalSocketClient() - console.log(`connectTasksSocket:: Is connected? ${this.isWebSocketConnected()}`) + // `connectTasksSocket:: Is connected? ${this.isWebSocketConnected()}` await this.socketClient.on('_connected', async () => { - console.log(`connectTasksSocket:: Joining tasks: ${JSON.stringify(tasks)}`) + // `connectTasksSocket:: Joining tasks: ${JSON.stringify(tasks)}` await this.socketClient.emit('_join-tasks', JSON.stringify({ tasks })) await this.socketClient.on('task-log', (data: any) => { _callback(data) }) }) - - console.log(`connectTasksSocket:: ending`) } catch (error) { throw new PaymentsError( `Unable to initialize websocket client: ${this.opts.webSocketHost} - ${(error as Error).message}`, diff --git a/src/api/query-api.ts b/src/api/query-api.ts index d078315..72253cb 100644 --- a/src/api/query-api.ts +++ b/src/api/query-api.ts @@ -137,6 +137,7 @@ export class AIQueryApi extends NVMBackendApi { * @param did - Agent DID * @param task - Task object. The task object should contain the query to execute and the name of the task. All the attributes here: @see https://docs.nevermined.io/docs/protocol/query-protocol#tasks-attributes * @param queryOpts - The query options @see {@link Payments.getServiceAccessConfig} + * @param _callback - The callback to execute when a new task log event is received (optional) * @returns The result of the operation */ async createTask( From 9400af299fbda8be53b43cf08b540647d0ea651a Mon Sep 17 00:00:00 2001 From: Aitor <1726644+aaitor@users.noreply.github.com> Date: Tue, 12 Nov 2024 15:23:48 +0100 Subject: [PATCH 5/6] chore: adding v0.7.0 Changelog updates --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e58e013..585c5e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [v0.7.0](https://github.com/nevermined-io/payments/compare/v0.6.1...v0.7.0) + +> 12 November 2024 + +- Automated docs update [`c3884b0`](https://github.com/nevermined-io/payments/commit/c3884b0d309b7350185e4f7b76e24e7c0ca8e6c3) +- feat: logging task messages [`0515b31`](https://github.com/nevermined-io/payments/commit/0515b316eda2c96ca6932a3d6b6f61efb914d9c7) +- fix: new authentication [`6256409`](https://github.com/nevermined-io/payments/commit/6256409392d630e6bf7b75ca4e86a47e6b4bc990) + #### [v0.6.1](https://github.com/nevermined-io/payments/compare/v0.6.0...v0.6.1) > 29 October 2024 From 3c05540ef16cce1918cd367fefa38c0905f23ee1 Mon Sep 17 00:00:00 2001 From: Aitor <1726644+aaitor@users.noreply.github.com> Date: Tue, 12 Nov 2024 17:37:02 +0100 Subject: [PATCH 6/6] chore: pr comments --- package.json | 2 +- src/api/nvm-backend.ts | 8 +----- src/api/query-api.ts | 12 ++------- src/common/types.ts | 49 ++++++++++++++++++++++++++++++++++ tests/e2e/payments.e2e.test.ts | 6 ++--- 5 files changed, 55 insertions(+), 22 deletions(-) diff --git a/package.json b/package.json index 5119a64..a4a118c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@nevermined-io/payments", - "version": "0.7.0", + "version": "0.7.1", "description": "Typescript SDK to interact with the Nevermined Payments Protocol", "main": "./dist/index.js", "types": "./dist/index.d.ts", diff --git a/src/api/nvm-backend.ts b/src/api/nvm-backend.ts index 6d5a3d4..6009531 100644 --- a/src/api/nvm-backend.ts +++ b/src/api/nvm-backend.ts @@ -2,10 +2,9 @@ import axios from 'axios' import { decodeJwt } from 'jose' import { io } from 'socket.io-client' import { sleep } from '../common/helper' -import { AgentExecutionStatus } from '../common/types' +import { AgentExecutionStatus, TaskLogMessage } from '../common/types' import { isEthereumAddress } from '../utils' import { PaymentsError } from '../common/payments.error' -import { TaskLogMessage } from './query-api' export interface BackendApiOptions { /** @@ -97,11 +96,6 @@ export class NVMBackendApi { // path: '', transports: ['websocket'], auth: { token: '' }, - // transportOptions: { - // websocket: { - // extraHeaders: {}, - // }, - // }, } constructor(opts: BackendApiOptions) { diff --git a/src/api/query-api.ts b/src/api/query-api.ts index 72253cb..baa6bdf 100644 --- a/src/api/query-api.ts +++ b/src/api/query-api.ts @@ -1,4 +1,4 @@ -import { AgentExecutionStatus, Step } from '../common/types' +import { AgentExecutionStatus, CreateTaskDto, Step, TaskLogMessage } from '../common/types' import { isStepIdValid } from '../utils' import { BackendApiOptions, @@ -37,14 +37,6 @@ export interface SearchSteps { offset?: number } -export interface TaskLogMessage { - level: 'info' | 'error' | 'warning' | 'debug' - task_id: string - task_status: AgentExecutionStatus - message: string - step_id?: string -} - /** * Options required for interacting with an external AI Agent/Service. */ @@ -142,7 +134,7 @@ export class AIQueryApi extends NVMBackendApi { */ async createTask( did: string, - task: any, + task: CreateTaskDto, queryOpts: AIQueryOptions, _callback?: (err?: any) => any, ) { diff --git a/src/common/types.ts b/src/common/types.ts index 4e42587..0a04cdf 100644 --- a/src/common/types.ts +++ b/src/common/types.ts @@ -164,3 +164,52 @@ export interface Artifact { */ url: string } + +export interface TaskLogMessage { + /** + * Log level + */ + level: 'info' | 'error' | 'warning' | 'debug' + + /** + * The log message + */ + message: string + + /** + * Identifier of the task associated with the log + */ + task_id: string + + /** + * The status of the task + */ + task_status?: AgentExecutionStatus + + /** + * The step id associated with the log message if any + */ + step_id?: string +} + +export interface CreateTaskDto { + /** + * The query parameter for the task + */ + query: string + + /** + * The name of the task + */ + name?: string + + /** + * Additional parameters required for the task + */ + additional_params?: { [name: string]: string }[] + + /** + * Additional artifacts required for the task + */ + artifacts?: Artifact[] +} diff --git a/tests/e2e/payments.e2e.test.ts b/tests/e2e/payments.e2e.test.ts index d154e67..4ca35c3 100644 --- a/tests/e2e/payments.e2e.test.ts +++ b/tests/e2e/payments.e2e.test.ts @@ -1,7 +1,5 @@ -import { log } from 'console' -import { TaskLogMessage } from '../../src/api/query-api' import { sleep } from '../../src/common/helper' -import { AgentExecutionStatus, Step } from '../../src/common/types' +import { AgentExecutionStatus, CreateTaskDto, Step, TaskLogMessage } from '../../src/common/types' import { EnvironmentName } from '../../src/environments' import { Payments } from '../../src/payments' // import { getQueryProtocolEndpoints } from "../../src/utils" @@ -326,7 +324,7 @@ describe('Payments API (e2e)', () => { } }, opts) - const aiTask = { + const aiTask: CreateTaskDto = { query: 'https://www.youtube.com/watch?v=0tZFQs7qBfQ', name: 'transcribe', additional_params: [],