Skip to content

Commit

Permalink
Merge pull request #89 from nevermined-io/fix/optional_query_opts
Browse files Browse the repository at this point in the history
fix: making optional query opts
  • Loading branch information
aaitor authored Dec 11, 2024
2 parents bd4445d + f3525b5 commit 109cb1d
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 62 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nevermined-io/payments",
"version": "0.7.5",
"version": "0.8.0",
"description": "Typescript SDK to interact with the Nevermined Payments Protocol",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion src/api/nvm-backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export const DefaultSubscriptionOptions = {
}

export class NVMBackendApi {
private opts: BackendApiOptions
protected opts: BackendApiOptions
private socketClient: any
private userRoomId: string | undefined = undefined
private taskCallbacks: Map<string, TaskCallback> = new Map()
Expand Down
67 changes: 58 additions & 9 deletions src/api/query-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ export class AIQueryOptions {
* This API is oriented for AI Builders providing AI Agents and AI Subscribers interacting with them.
*/
export class AIQueryApi extends NVMBackendApi {
queryOptionsCache = new Map<string, AIQueryOptions>()

constructor(opts: BackendApiOptions) {
super(opts)
}
Expand Down Expand Up @@ -95,6 +97,43 @@ export class AIQueryApi extends NVMBackendApi {
await super.connectTasksSocket(_callback, tasks, history)
}

/**
* Get the required configuration for accessing a remote service agent.
* This configuration includes:
* - The JWT access token
* - The Proxy url that can be used to query the agent/service.
*
* @example
* ```
* const accessConfig = await payments.query.getServiceAccessConfig(agentDID)
* console.log(`Agent JWT Token: ${accessConfig.accessToken}`)
* console.log(`Agent Proxy URL: ${accessConfig.neverminedProxyUri}`)
* ```
*
* @param did - The DID of the agent/service.
* @returns A promise that resolves to the service token.
*/
public async getServiceAccessConfig(did: string): Promise<{
accessToken: string
neverminedProxyUri: string
}> {
const options = {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${this.opts.apiKey}`,
},
}
const url = new URL(`/api/v1/payments/service/token/${did}`, this.opts.backendHost)
const response = await fetch(url, options)
if (!response.ok) {
throw Error(`${response.statusText} - ${await response.text()}`)
}

return (await response.json()).token
}

/**
* Subscribers can create an AI Task for an Agent. The task must contain the input query that will be used by the AI Agent.
* @see https://docs.nevermined.io/docs/protocol/query-protocol
Expand All @@ -107,7 +146,7 @@ export class AIQueryApi extends NVMBackendApi {
*
* @example
* ```
* const accessConfig = await payments.getServiceAccessConfig(agentDID)
* const accessConfig = await payments.query.getServiceAccessConfig(agentDID)
* const queryOpts = {
* accessToken: accessConfig.accessToken,
* proxyHost: accessConfig.neverminedProxyUri
Expand All @@ -129,21 +168,26 @@ 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 queryOpts - The query options @see {@link Payments.query.getServiceAccessConfig}
* @param _callback - The callback to execute when a new task log event is received (optional)
* @returns The result of the operation
*/
async createTask(
did: string,
task: CreateTaskDto,
queryOpts: AIQueryOptions,
queryOpts?: AIQueryOptions,
_callback?: (err?: any) => any,
) {
if (!queryOpts || !queryOpts.accessToken) {
queryOpts = this.queryOptionsCache.has(did)
? this.queryOptionsCache.get(did)
: await this.getServiceAccessConfig(did)
}
const endpoint = TASK_ENDPOINT.replace('{did}', did)
const reqOptions: HTTPRequestOptions = {
sendThroughProxy: true,
...(queryOpts.neverminedProxyUri && { proxyHost: queryOpts.neverminedProxyUri }),
...(queryOpts.accessToken && {
...(queryOpts?.neverminedProxyUri && { proxyHost: queryOpts.neverminedProxyUri }),
...(queryOpts?.accessToken && {
headers: { Authorization: `Bearer ${queryOpts.accessToken}` },
}),
}
Expand All @@ -165,7 +209,7 @@ export class AIQueryApi extends NVMBackendApi {
*
* @example
* ```
* const accessConfig = await payments.getServiceAccessConfig(agentDID)
* const accessConfig = await payments.query.getServiceAccessConfig(agentDID)
* const queryOpts = {
* accessToken: accessConfig.accessToken,
* proxyHost: accessConfig.neverminedProxyUri
Expand All @@ -182,11 +226,16 @@ export class AIQueryApi extends NVMBackendApi {
* @param taskId - Task ID
* @returns The task with the steps
*/
async getTaskWithSteps(did: string, taskId: string, queryOpts: AIQueryOptions) {
async getTaskWithSteps(did: string, taskId: string, queryOpts?: AIQueryOptions) {
if (!queryOpts || !queryOpts.accessToken) {
queryOpts = this.queryOptionsCache.has(did)
? this.queryOptionsCache.get(did)
: await this.getServiceAccessConfig(did)
}
const reqOptions: HTTPRequestOptions = {
sendThroughProxy: true,
...(queryOpts.neverminedProxyUri && { proxyHost: queryOpts.neverminedProxyUri }),
...(queryOpts.accessToken && {
...(queryOpts?.neverminedProxyUri && { proxyHost: queryOpts.neverminedProxyUri }),
...(queryOpts?.accessToken && {
headers: { Authorization: `Bearer ${queryOpts.accessToken}` },
}),
}
Expand Down
37 changes: 0 additions & 37 deletions src/payments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1029,43 +1029,6 @@ export class Payments {
return response.json()
}

/**
* Get the required configuration for accessing a remote service agent.
* This configuration includes:
* - The JWT access token
* - The Proxy url that can be used to query the agent/service.
*
* @example
* ```
* const accessConfig = await payments.getServiceAccessConfig(agentDID)
* console.log(`Agent JWT Token: ${accessConfig.accessToken}`)
* console.log(`Agent Proxy URL: ${accessConfig.neverminedProxyUri}`)
* ```
*
* @param did - The DID of the agent/service.
* @returns A promise that resolves to the service token.
*/
public async getServiceAccessConfig(did: string): Promise<{
accessToken: string
neverminedProxyUri: string
}> {
const options = {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${this.nvmApiKey}`,
},
}
const url = new URL(`/api/v1/payments/service/token/${did}`, this.environment.backend)
const response = await fetch(url, options)
if (!response.ok) {
throw Error(`${response.statusText} - ${await response.text()}`)
}

return (await response.json()).token
}

/**
* Orders a Payment Plan. The user needs to have enough balance in the token selected by the owner of the Payment Plan.
*
Expand Down
28 changes: 14 additions & 14 deletions tests/e2e/payments.e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ describe('Payments API (e2e)', () => {
// "artifacts": []
// }

// const accessConfig = await paymentsSubscriber.getServiceAccessConfig(agentDID)
// const accessConfig = await paymentsSubscriber.query.getServiceAccessConfig(agentDID)
// const queryOpts = {
// accessToken: accessConfig.accessToken,
// proxyHost: accessConfig.neverminedProxyUri
Expand Down Expand Up @@ -229,7 +229,7 @@ describe('Payments API (e2e)', () => {
additional_params: [],
artifacts: [],
}
subscriberQueryOpts = await paymentsSubscriber.getServiceAccessConfig(agentDID)
subscriberQueryOpts = await paymentsSubscriber.query.getServiceAccessConfig(agentDID)

const taskResult = await paymentsSubscriber.query.createTask(
agentDID,
Expand Down Expand Up @@ -328,13 +328,13 @@ describe('Payments API (e2e)', () => {
additional_params: [],
artifacts: [],
}
const accessConfig = await paymentsSubscriber.getServiceAccessConfig(agentDID)
const queryOpts = {
accessToken: accessConfig.accessToken,
proxyHost: accessConfig.neverminedProxyUri,
}
// const accessConfig = await paymentsSubscriber.query.getServiceAccessConfig(agentDID)
// const queryOpts = {
// accessToken: accessConfig.accessToken,
// proxyHost: accessConfig.neverminedProxyUri,
// }

const taskResult = await paymentsSubscriber.query.createTask(agentDID, aiTask, queryOpts)
const taskResult = await paymentsSubscriber.query.createTask(agentDID, aiTask) //, queryOpts)

expect(taskResult).toBeDefined()
expect(taskResult.status).toBe(201)
Expand All @@ -358,14 +358,14 @@ describe('Payments API (e2e)', () => {
additional_params: [],
artifacts: [],
}
const accessConfig = await paymentsSubscriber.getServiceAccessConfig(agentDID)
const queryOpts = {
accessToken: accessConfig.accessToken,
proxyHost: accessConfig.neverminedProxyUri,
}
// const accessConfig = await paymentsSubscriber.query.getServiceAccessConfig(agentDID)
// const queryOpts = {
// accessToken: accessConfig.accessToken,
// proxyHost: accessConfig.neverminedProxyUri,
// }

let logsReceived = 0
const taskResult = await paymentsSubscriber.query.createTask(agentDID, aiTask, queryOpts, async (data) => {
const taskResult = await paymentsSubscriber.query.createTask(agentDID, aiTask, undefined, async (data) => {
console.log('New Task Log received', data)
logsReceived++
})
Expand Down

0 comments on commit 109cb1d

Please sign in to comment.