@tjamescouch/agentchat 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/lib/server.js +66 -7
  2. package/package.json +1 -1
package/lib/server.js CHANGED
@@ -23,6 +23,7 @@ import {
23
23
  isProposalMessage
24
24
  } from './protocol.js';
25
25
  import { ProposalStore, formatProposal, formatProposalResponse } from './proposals.js';
26
+ import { ReputationStore } from './reputation.js';
26
27
 
27
28
  export class AgentChatServer {
28
29
  constructor(options = {}) {
@@ -75,6 +76,9 @@ export class AgentChatServer {
75
76
  // Skills registry: agentId -> { skills: [], registered_at, sig }
76
77
  this.skillsRegistry = new Map();
77
78
 
79
+ // Reputation store for ELO ratings
80
+ this.reputationStore = new ReputationStore();
81
+
78
82
  this.wss = null;
79
83
  this.httpServer = null; // For TLS mode
80
84
  }
@@ -780,7 +784,7 @@ export class AgentChatServer {
780
784
  this._send(ws, outMsg);
781
785
  }
782
786
 
783
- _handleComplete(ws, msg) {
787
+ async _handleComplete(ws, msg) {
784
788
  const agent = this.agents.get(ws);
785
789
  if (!agent) {
786
790
  this._send(ws, createError(ErrorCode.AUTH_REQUIRED, 'Must IDENTIFY first'));
@@ -807,9 +811,27 @@ export class AgentChatServer {
807
811
  const proposal = result.proposal;
808
812
  this._log('complete', { id: proposal.id, by: agent.id });
809
813
 
814
+ // Update reputation ratings
815
+ let ratingChanges = null;
816
+ try {
817
+ ratingChanges = await this.reputationStore.processCompletion({
818
+ type: 'COMPLETE',
819
+ from: proposal.from,
820
+ to: proposal.to,
821
+ amount: proposal.amount
822
+ });
823
+ this._log('reputation_updated', {
824
+ proposal_id: proposal.id,
825
+ changes: ratingChanges
826
+ });
827
+ } catch (err) {
828
+ this._log('reputation_error', { error: err.message });
829
+ }
830
+
810
831
  // Notify both parties
811
832
  const outMsg = createMessage(ServerMessageType.COMPLETE, {
812
- ...formatProposalResponse(proposal, 'complete')
833
+ ...formatProposalResponse(proposal, 'complete'),
834
+ rating_changes: ratingChanges
813
835
  });
814
836
 
815
837
  // Notify the other party
@@ -823,7 +845,7 @@ export class AgentChatServer {
823
845
  this._send(ws, outMsg);
824
846
  }
825
847
 
826
- _handleDispute(ws, msg) {
848
+ async _handleDispute(ws, msg) {
827
849
  const agent = this.agents.get(ws);
828
850
  if (!agent) {
829
851
  this._send(ws, createError(ErrorCode.AUTH_REQUIRED, 'Must IDENTIFY first'));
@@ -850,9 +872,28 @@ export class AgentChatServer {
850
872
  const proposal = result.proposal;
851
873
  this._log('dispute', { id: proposal.id, by: agent.id, reason: msg.reason });
852
874
 
875
+ // Update reputation ratings
876
+ let ratingChanges = null;
877
+ try {
878
+ ratingChanges = await this.reputationStore.processDispute({
879
+ type: 'DISPUTE',
880
+ from: proposal.from,
881
+ to: proposal.to,
882
+ amount: proposal.amount,
883
+ disputed_by: `@${agent.id}`
884
+ });
885
+ this._log('reputation_updated', {
886
+ proposal_id: proposal.id,
887
+ changes: ratingChanges
888
+ });
889
+ } catch (err) {
890
+ this._log('reputation_error', { error: err.message });
891
+ }
892
+
853
893
  // Notify both parties
854
894
  const outMsg = createMessage(ServerMessageType.DISPUTE, {
855
- ...formatProposalResponse(proposal, 'dispute')
895
+ ...formatProposalResponse(proposal, 'dispute'),
896
+ rating_changes: ratingChanges
856
897
  });
857
898
 
858
899
  // Notify the other party
@@ -907,7 +948,7 @@ export class AgentChatServer {
907
948
  }
908
949
  }
909
950
 
910
- _handleSearchSkills(ws, msg) {
951
+ async _handleSearchSkills(ws, msg) {
911
952
  const agent = this.agents.get(ws);
912
953
  if (!agent) {
913
954
  this._send(ws, createError(ErrorCode.AUTH_REQUIRED, 'Must IDENTIFY first'));
@@ -955,8 +996,26 @@ export class AgentChatServer {
955
996
  }
956
997
  }
957
998
 
958
- // Sort by registration time (newest first)
959
- results.sort((a, b) => b.registered_at - a.registered_at);
999
+ // Enrich results with reputation data
1000
+ const uniqueAgentIds = [...new Set(results.map(r => r.agent_id))];
1001
+ const ratingCache = new Map();
1002
+ for (const agentId of uniqueAgentIds) {
1003
+ const ratingInfo = await this.reputationStore.getRating(agentId);
1004
+ ratingCache.set(agentId, ratingInfo);
1005
+ }
1006
+
1007
+ // Add rating info to each result
1008
+ for (const result of results) {
1009
+ const ratingInfo = ratingCache.get(result.agent_id);
1010
+ result.rating = ratingInfo.rating;
1011
+ result.transactions = ratingInfo.transactions;
1012
+ }
1013
+
1014
+ // Sort by rating (highest first), then by registration time
1015
+ results.sort((a, b) => {
1016
+ if (b.rating !== a.rating) return b.rating - a.rating;
1017
+ return b.registered_at - a.registered_at;
1018
+ });
960
1019
 
961
1020
  // Limit results
962
1021
  const limit = query.limit || 50;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tjamescouch/agentchat",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "Real-time IRC-like communication protocol for AI agents",
5
5
  "main": "lib/client.js",
6
6
  "files": [