Skip to content

Feat/acp nego feature #10

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
61 changes: 51 additions & 10 deletions src/acpClient.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
import { Address, parseEther } from "viem";
import { io } from "socket.io-client";
import AcpContractClient, { AcpJobPhases, MemoType } from "./acpContractClient";
import AcpContractClient, {
AcpJobPhases,
AcpNegoStatus,
MemoType,
} from "./acpContractClient";
import { AcpAgent } from "../interfaces";
import AcpJob from "./acpJob";
import AcpMemo from "./acpMemo";
import AcpJobOffering from "./acpJobOffering";
import AcpMessage from "./acpMessage";
import {
IAcpClientOptions,
IAcpJob,
IAcpJobResponse,
IAcpMemo,
} from "./interfaces";

enum SocketEvents {
export interface IDeliverable {
type: string;
value: string;
}

export enum SocketEvents {
ROOM_JOINED = "roomJoined",
ON_EVALUATE = "onEvaluate",
ON_NEW_TASK = "onNewTask",
ON_NEW_MSG = "onNewMsg",
ON_CREATE_MSG = "onCreateMsg",
}
export class EvaluateResult {
isApproved: boolean;
Expand All @@ -29,15 +41,16 @@ export class EvaluateResult {

class AcpClient {
private acpUrl;
private acpJob: AcpJob | null = null;
public acpContractClient: AcpContractClient;
private onNewTask?: (job: AcpJob) => void;
private onEvaluate?: (job: AcpJob) => void;

private onNewMsg?: (msg: AcpMessage, job: AcpJob) => void;
constructor(options: IAcpClientOptions) {
this.acpContractClient = options.acpContractClient;
this.onNewTask = options.onNewTask;
this.onEvaluate = options.onEvaluate || this.defaultOnEvaluate;

this.onNewMsg = options.onNewMsg;
this.acpUrl = this.acpContractClient.config.acpUrl;
this.init();
}
Expand Down Expand Up @@ -84,9 +97,12 @@ class AcpClient {
memo.nextPhase
);
}),
data.phase
data.phase,
data.negoStatus
);

this.acpJob = job;

this.onEvaluate(job);
}
}
Expand All @@ -113,14 +129,35 @@ class AcpClient {
memo.nextPhase
);
}),
data.phase
data.phase,
data.negoStatus
);

this.acpJob = job;

this.onNewTask(job);
}
}
);

socket.on(SocketEvents.ON_NEW_MSG, (data, callback) => {
callback(true);

if (this.onNewMsg && this.acpJob) {
this.acpJob.negoStatus = AcpNegoStatus.PENDING;

const msg = new AcpMessage(
data.id,
data.messages ?? [],
socket,
this.acpJob,
this.acpContractClient.walletAddress
);

this.onNewMsg(msg, this.acpJob);
}
});

const cleanup = async () => {
if (socket) {
socket.disconnect();
Expand Down Expand Up @@ -267,7 +304,8 @@ class AcpClient {
memo.nextPhase
);
}),
job.phase
job.phase,
job.negoStatus
);
});
} catch (error) {
Expand Down Expand Up @@ -307,7 +345,8 @@ class AcpClient {
memo.nextPhase
);
}),
job.phase
job.phase,
job.negoStatus
);
});
} catch (error) {
Expand Down Expand Up @@ -346,7 +385,8 @@ class AcpClient {
memo.nextPhase
);
}),
job.phase
job.phase,
job.negoStatus
);
});
} catch (error) {
Expand Down Expand Up @@ -390,7 +430,8 @@ class AcpClient {
memo.nextPhase
);
}),
job.phase
job.phase,
job.negoStatus
);
} catch (error) {
throw error;
Expand Down
7 changes: 7 additions & 0 deletions src/acpContractClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ export enum AcpJobPhases {
REJECTED = 5,
}

export enum AcpNegoStatus {
PENDING = "PENDING",
AGREED = "AGREED",
DISAGREED = "DISAGREED",
NOT_STARTED = "NOT_STARTED",
}

class AcpContractClient {
private _sessionKeyClient: ModularAccountV2Client | undefined;

Expand Down
5 changes: 3 additions & 2 deletions src/acpJob.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Address } from "viem";
import AcpClient from "./acpClient";
import { AcpJobPhases } from "./acpContractClient";
import { AcpJobPhases, AcpNegoStatus } from "./acpContractClient";
import AcpMemo from "./acpMemo";

class AcpJob {
Expand All @@ -11,7 +11,8 @@ class AcpJob {
public providerAddress: Address,
public evaluatorAddress: Address,
public memos: AcpMemo[],
public phase: AcpJobPhases
public phase: AcpJobPhases,
public negoStatus?: AcpNegoStatus
) {}

public get serviceRequirement() {
Expand Down
64 changes: 64 additions & 0 deletions src/acpMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Socket } from "socket.io-client";
import { SocketEvents } from "./acpClient";
import AcpJob from "./acpJob";
import { AcpJobPhases, AcpNegoStatus } from "./acpContractClient";
import { Address } from "viem";

interface Message {
id: number;
sender: Address;
recipient: Address;
content: string;
timestamp: number;
}

class AcpMessage {
constructor(
public id: number,
public messages: Message[],
public socket: Socket,
public acpJob: AcpJob | null,
public walletAddress: Address
) {}

initOrReply(message: string) {
if (!this.acpJob) {
throw new Error("Cannot initiate or reply conversation without job");
}

if (this.acpJob.negoStatus !== AcpNegoStatus.PENDING) {
throw new Error(
"Cannot initiate or reply conversation in non-negotiation phase"
);
}

if (
this.messages.length > 0 &&
this.messages[this.messages.length - 1].sender === this.walletAddress
) {
throw new Error("Cannot reply to own message");
}

this.socket.timeout(5000).emit(
SocketEvents.ON_CREATE_MSG,
{
jobId: this.acpJob.id,
content: message,
sender: this.walletAddress,
recipient:
this.messages.length > 0
? this.messages[this.messages.length - 1].sender
: this.acpJob.providerAddress,
},
(err: any, response: any) => {
if (err || !response) {
console.log(`Message not received`, err);
} else {
console.log(`Message received`);
}
}
);
}
}

export default AcpMessage;
9 changes: 8 additions & 1 deletion src/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { Address } from "viem";
import AcpContractClient, { AcpJobPhases, MemoType } from "./acpContractClient";
import AcpContractClient, {
AcpJobPhases,
AcpNegoStatus,
MemoType,
} from "./acpContractClient";
import AcpJob from "./acpJob";
import AcpMessage from "./acpMessage";

export interface IDeliverable {
type: string;
Expand Down Expand Up @@ -32,6 +37,7 @@ export interface IAcpJob {
deliverable: IDeliverable | null;
memos: IAcpMemoData[];
createdAt: string;
negoStatus: AcpNegoStatus;
};
error?: Error;
}
Expand All @@ -52,4 +58,5 @@ export interface IAcpClientOptions {
acpContractClient: AcpContractClient;
onNewTask?: (job: AcpJob) => void;
onEvaluate?: (job: AcpJob) => void;
onNewMsg?: (msg: AcpMessage, job: AcpJob) => void;
}