Skill: 404-unknow/agent-comm-skill (version 0.1.0)

# Agent Communication Skill (PassDeck) This skill provides the security and networking foundation for AI Agent swarms. It handles DID (Decentralized Identity) registration, cryptographically secure signing using Ed25519, and E2EE (End-to-End Encryption) for sensitive data. ## 🚀 Key Actions ### `agent.register` - **Description**: Registers a new local agent identity or restores an existing one. Returns the agent's unique DID. - **Parameters**: `{ alias?: string }` - **Output**: `{ localId: string, did: string, publicKey: hex }` ### `message.sign` - **Description**: Signs a payload using the agent's private key. Ensures data integrity and non-repudiation. - **Parameters**: `{ localId: string, payload: any }` - **Output**: `{ signature: hex }` ### `message.verify` - **Description**: Verifies a signed message against a public key. Used to detect data tampering or unauthorized updates. - **Parameters**: `{ publicKeyHex: string, payload: any, signatureHex: string }` - **Output**: `{ verified: boolean }` ### `network.connect` - **Description**: Establishes an authorized connection to a Relay server. Implements a DID challenge-response handshake. - **Parameters**: `{ sessionId: string, localId: string, did: string, onUpdate: function }` - **Output**: `{ success: true }` ### `secret.encrypt / secret.decrypt` - **Description**: High-level E2EE functions for managing secure credentials within the collaborative pool. - **Parameters**: `{ payload/ciphertext: any, sessionKey: string }` - **Output**: `{ ciphertext/decrypted: any }`

path: index.js
content: import { v4 as uuidv4 } from 'uuid';
import { createRequire } from 'module';
import WebSocket from 'ws';
const require = createRequire(import.meta.url);
const vault = require('./scripts/vault.js');
const relayConnections = new Map();
const updateCallbacks = new Map();
export async function run(action, params, context) {
    try {
        switch (action) {
            case 'agent.register': return await registerIdentity(params);
            case 'message.sign': return await signMessage(params);
            case 'message.verify': return await verifyMessage(params);
            case 'network.connect': return await connectWithAuth(params);
            case 'network.broadcast': return await broadcastUpdate(params);
            case 'secret.genKey': return { success: true, data: { key: await vault.generateSessionKey() } };
            case 'secret.encrypt': return await encryptAction(params);
            case 'secret.decrypt': return await decryptAction(params);
            default: return { success: false, error: `Action ${action} unsupported` };
        }
    }
    catch (err) {
        return { success: false, error: err.message };
    }
}
async function registerIdentity(params) {
    const localAgentId = params.alias || `agent-${uuidv4()}`;
    const keys = await vault.getOrGenerateIdentity(localAgentId);
    const pubKeyHex = Buffer.from(keys.publicKey).toString('hex');
    return { success: true, data: { localId: localAgentId, did: `did:claw:ed25519:${pubKeyHex}`, publicKey: pubKeyHex } };
}
async function connectWithAuth(params) {
    const { sessionId, localId, did, relayUrl = 'ws://localhost:3001', onUpdate } = params;
    if (onUpdate)
        updateCallbacks.set(sessionId, onUpdate);
    return new Promise((resolve, reject) => {
        const ws = new WebSocket(relayUrl);
        ws.on('message', async (data) => {
            const msg = JSON.parse(data.toString());
            if (msg.action === 'challenge') {
                const signRes = await vault.signPayload(localId, msg.challenge);
                ws.send(JSON.stringify({ action: 'subscribe', sessionId, did, challenge: msg.challenge, signature: signRes }));
            }
            if (msg.action === 'authorized') {
                relayConnections.set(sessionId, ws);
                resolve({ success: true, data: { status: 'Authorized' } });
            }
            if (msg.action === 'update') {
                const cb = updateCallbacks.get(sessionId);
                if (cb)
                    cb(msg.payload);
            }
        });
        ws.on('open', () => ws.send(JSON.stringify({ action: 'auth_request' })));
        ws.on('error', (err) => reject({ success: false, error: err.message }));
    });
}
async function broadcastUpdate(params) {
    const { sessionId, payload } = params;
    const ws = relayConnections.get(sessionId);
    if (!ws || ws.readyState !== 1)
        return { success: false, error: "Not connected" };
    ws.send(JSON.stringify({ action: 'broadcast', sessionId, payload }));
    return { success: true };
}
async function signMessage(params) {
    const { localId, payload } = params;
    const contentStr = typeof payload === 'string' ? payload : JSON.stringify(payload);
    const signatureHex = await vault.signPayload(localId, contentStr);
    return { success: true, data: { signature: signatureHex } };
}
async function verifyMessage(params) {
    const { publicKeyHex, payload, signatureHex } = params;
    const contentStr = typeof payload === 'string' ? payload : JSON.stringify(payload);
    const isValid = await vault.verifySignature(publicKeyHex, contentStr, signatureHex);
    return { success: true, data: { verified: isValid } };
}
async function encryptAction(params) {
    const res = await vault.encryptSecret(typeof params.payload === 'string' ? params.payload : JSON.stringify(params.payload), params.sessionKey);
    return { success: true, data: res };
}
async function decryptAction(params) {
    const decrypted = await vault.decryptSecret(params.ciphertext, params.nonce, params.sessionKey);
    return decrypted ? { success: true, data: { decrypted } } : { success: false, error: "Decryption failed" };
}


path: index.ts
content: import { v4 as uuidv4 } from 'uuid';
import { createRequire } from 'module';
import WebSocket from 'ws';

const require = createRequire(import.meta.url);
const vault = require('./scripts/vault.js');

const relayConnections = new Map<string, WebSocket>();
const updateCallbacks = new Map<string, (payload: string) => void>();

export async function run(action: string, params: any, context?: any) {
  try {
    switch (action) {
      case 'agent.register': return await registerIdentity(params);
      case 'message.sign': return await signMessage(params);
      case 'message.verify': return await verifyMessage(params);
      case 'network.connect': return await connectWithAuth(params);
      case 'network.broadcast': return await broadcastUpdate(params);
      case 'secret.genKey': return { success: true, data: { key: await vault.generateSessionKey() } };
      case 'secret.encrypt': return await encryptAction(params);
      case 'secret.decrypt': return await decryptAction(params);
      default: return { success: false, error: `Action ${action} unsupported` };
    }
  } catch (err: any) {
    return { success: false, error: err.message };
  }
}

async function registerIdentity(params: any) {
  const localAgentId = params.alias || `agent-${uuidv4()}`;
  const keys = await vault.getOrGenerateIdentity(localAgentId);
  const pubKeyHex = Buffer.from(keys.publicKey).toString('hex');
  return { success: true, data: { localId: localAgentId, did: `did:claw:ed25519:${pubKeyHex}`, publicKey: pubKeyHex } };
}

async function connectWithAuth(params: any) {
  const { sessionId, localId, did, relayUrl = 'ws://localhost:3001', onUpdate } = params;
  if (onUpdate) updateCallbacks.set(sessionId, onUpdate);

  return new Promise((resolve, reject) => {
    const ws = new WebSocket(relayUrl);
    
    ws.on('message', async (data) => {
      const msg = JSON.parse(data.toString());
      if (msg.action === 'challenge') {
        const signRes = await vault.signPayload(localId, msg.challenge);
        ws.send(JSON.stringify({ action: 'subscribe', sessionId, did, challenge: msg.challenge, signature: signRes }));
      }
      if (msg.action === 'authorized') {
        relayConnections.set(sessionId, ws);
        resolve({ success: true, data: { status: 'Authorized' } });
      }
      if (msg.action === 'update') {
        const cb = updateCallbacks.get(sessionId);
        if (cb) cb(msg.payload);
      }
    });

    ws.on('open', () => ws.send(JSON.stringify({ action: 'auth_request' })));
    ws.on('error', (err) => reject({ success: false, error: err.message }));
  });
}

async function broadcastUpdate(params: any) {
  const { sessionId, payload } = params;
  const ws = relayConnections.get(sessionId);
  if (!ws || ws.readyState !== 1) return { success: false, error: "Not connected" };
  ws.send(JSON.stringify({ action: 'broadcast', sessionId, payload }));
  return { success: true };
}

async function signMessage(params: any) {
  const { localId, payload } = params;
  const contentStr = typeof payload === 'string' ? payload : JSON.stringify(payload);
  const signatureHex = await vault.signPayload(localId, contentStr);
  return { success: true, data: { signature: signatureHex } };
}

async function verifyMessage(params: any) {
  const { publicKeyHex, payload, signatureHex } = params;
  const contentStr = typeof payload === 'string' ? payload : JSON.stringify(payload);
  const isValid = await vault.verifySignature(publicKeyHex, contentStr, signatureHex);
  return { success: true, data: { verified: isValid } };
}

async function encryptAction(params: any) {
  const res = await vault.encryptSecret(typeof params.payload === 'string' ? params.payload : JSON.stringify(params.payload), params.sessionKey);
  return { success: true, data: res };
}

async function decryptAction(params: any) {
  const decrypted = await vault.decryptSecret(params.ciphertext, params.nonce, params.sessionKey);
  return decrypted ? { success: true, data: { decrypted } } : { success: false, error: "Decryption failed" };
}


path: package-lock.json
content: {
  "name": "agent-comm-skill",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "agent-comm-skill",
      "version": "1.0.0",
      "dependencies": {
        "libsodium-wrappers": "^0.7.16",
        "loro": "^1.0.0",
        "uuid": "^13.0.0",
        "ws": "^8.19.0"
      },
      "devDependencies": {
        "@types/node": "^20.0.0",
        "@types/uuid": "^10.0.0",
        "@types/ws": "^8.18.1",
        "typescript": "^5.0.0"
      }
    },
    "node_modules/@types/node": {
      "version": "20.19.37",
      "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.37.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "undici-types": "~6.21.0"
      }
    },
    "node_modules/@types/uuid": {
      "version": "10.0.0",
      "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/@types/ws": {
      "version": "8.18.1",
      "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@types/node": "*"
      }
    },
    "node_modules/accepts": {
      "version": "1.3.8",
      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "mime-types": "~2.1.34",
        "negotiator": "0.6.3"
      },
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/array-flatten": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/body-parser": {
      "version": "1.20.4",
      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "bytes": "~3.1.2",
        "content-type": "~1.0.5",
        "debug": "2.6.9",
        "depd": "2.0.0",
        "destroy": "~1.2.0",
        "http-errors": "~2.0.1",
        "iconv-lite": "~0.4.24",
        "on-finished": "~2.4.1",
        "qs": "~6.14.0",
        "raw-body": "~2.5.3",
        "type-is": "~1.6.18",
        "unpipe": "~1.0.0"
      },
      "engines": {
        "node": ">= 0.8",
        "npm": "1.2.8000 || >= 1.4.16"
      }
    },
    "node_modules/bytes": {
      "version": "3.1.2",
      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/call-bind-apply-helpers": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "es-errors": "^1.3.0",
        "function-bind": "^1.1.2"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/call-bound": {
      "version": "1.0.4",
      "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "call-bind-apply-helpers": "^1.0.2",
        "get-intrinsic": "^1.3.0"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/content-disposition": {
      "version": "0.5.4",
      "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "safe-buffer": "5.2.1"
      },
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/content-type": {
      "version": "1.0.5",
      "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/cookie": {
      "version": "0.7.2",
      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/cookie-signature": {
      "version": "1.0.7",
      "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/debug": {
      "version": "2.6.9",
      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "ms": "2.0.0"
      }
    },
    "node_modules/depd": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/destroy": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8",
        "npm": "1.2.8000 || >= 1.4.16"
      }
    },
    "node_modules/dunder-proto": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "call-bind-apply-helpers": "^1.0.1",
        "es-errors": "^1.3.0",
        "gopd": "^1.2.0"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/ee-first": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/encodeurl": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/es-define-property": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/es-errors": {
      "version": "1.3.0",
      "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/es-object-atoms": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "es-errors": "^1.3.0"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/escape-html": {
      "version": "1.0.3",
      "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/etag": {
      "version": "1.8.1",
      "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/express": {
      "version": "4.22.1",
      "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "accepts": "~1.3.8",
        "array-flatten": "1.1.1",
        "body-parser": "~1.20.3",
        "content-disposition": "~0.5.4",
        "content-type": "~1.0.4",
        "cookie": "~0.7.1",
        "cookie-signature": "~1.0.6",
        "debug": "2.6.9",
        "depd": "2.0.0",
        "encodeurl": "~2.0.0",
        "escape-html": "~1.0.3",
        "etag": "~1.8.1",
        "finalhandler": "~1.3.1",
        "fresh": "~0.5.2",
        "http-errors": "~2.0.0",
        "merge-descriptors": "1.0.3",
        "methods": "~1.1.2",
        "on-finished": "~2.4.1",
        "parseurl": "~1.3.3",
        "path-to-regexp": "~0.1.12",
        "proxy-addr": "~2.0.7",
        "qs": "~6.14.0",
        "range-parser": "~1.2.1",
        "safe-buffer": "5.2.1",
        "send": "~0.19.0",
        "serve-static": "~1.16.2",
        "setprototypeof": "1.2.0",
        "statuses": "~2.0.1",
        "type-is": "~1.6.18",
        "utils-merge": "1.0.1",
        "vary": "~1.1.2"
      },
      "engines": {
        "node": ">= 0.10.0"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/express"
      }
    },
    "node_modules/finalhandler": {
      "version": "1.3.2",
      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "debug": "2.6.9",
        "encodeurl": "~2.0.0",
        "escape-html": "~1.0.3",
        "on-finished": "~2.4.1",
        "parseurl": "~1.3.3",
        "statuses": "~2.0.2",
        "unpipe": "~1.0.0"
      },
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/forwarded": {
      "version": "0.2.0",
      "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/fresh": {
      "version": "0.5.2",
      "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/function-bind": {
      "version": "1.1.2",
      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/get-intrinsic": {
      "version": "1.3.0",
      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "call-bind-apply-helpers": "^1.0.2",
        "es-define-property": "^1.0.1",
        "es-errors": "^1.3.0",
        "es-object-atoms": "^1.1.1",
        "function-bind": "^1.1.2",
        "get-proto": "^1.0.1",
        "gopd": "^1.2.0",
        "has-symbols": "^1.1.0",
        "hasown": "^2.0.2",
        "math-intrinsics": "^1.1.0"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/get-proto": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "dunder-proto": "^1.0.1",
        "es-object-atoms": "^1.0.0"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/gopd": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/has-symbols": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/hasown": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "function-bind": "^1.1.2"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/http-errors": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "depd": "~2.0.0",
        "inherits": "~2.0.4",
        "setprototypeof": "~1.2.0",
        "statuses": "~2.0.2",
        "toidentifier": "~1.0.1"
      },
      "engines": {
        "node": ">= 0.8"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/express"
      }
    },
    "node_modules/iconv-lite": {
      "version": "0.4.24",
      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "safer-buffer": ">= 2.1.2 < 3"
      },
      "engines": {
        "node": ">=0.10.0"
      }
    },
    "node_modules/inherits": {
      "version": "2.0.4",
      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC"
    },
    "node_modules/ipaddr.js": {
      "version": "1.9.1",
      "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.10"
      }
    },
    "node_modules/libsodium": {
      "version": "0.7.16",
      "resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.16.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC"
    },
    "node_modules/libsodium-wrappers": {
      "version": "0.7.16",
      "resolved": "https://registry.npmjs.org/libsodium-wrappers/-/libsodium-wrappers-0.7.16.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC",
      "dependencies": {
        "libsodium": "^0.7.16"
      }
    },
    "node_modules/loro": {
      "version": "1.0.6",
      "resolved": "https://registry.npmjs.org/loro/-/loro-1.0.6.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "body-parser": "^1.13.1",
        "express": "^4.13.0"
      },
      "engines": {
        "node": ">= 0.10.x"
      }
    },
    "node_modules/math-intrinsics": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/media-typer": {
      "version": "0.3.0",
      "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/merge-descriptors": {
      "version": "1.0.3",
      "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/methods": {
      "version": "1.1.2",
      "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/mime": {
      "version": "1.6.0",
      "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "bin": {
        "mime": "cli.js"
      },
      "engines": {
        "node": ">=4"
      }
    },
    "node_modules/mime-db": {
      "version": "1.52.0",
      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/mime-types": {
      "version": "2.1.35",
      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "mime-db": "1.52.0"
      },
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/ms": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/negotiator": {
      "version": "0.6.3",
      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/object-inspect": {
      "version": "1.13.4",
      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/on-finished": {
      "version": "2.4.1",
      "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "ee-first": "1.1.1"
      },
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/parseurl": {
      "version": "1.3.3",
      "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/path-to-regexp": {
      "version": "0.1.12",
      "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/proxy-addr": {
      "version": "2.0.7",
      "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "forwarded": "0.2.0",
        "ipaddr.js": "1.9.1"
      },
      "engines": {
        "node": ">= 0.10"
      }
    },
    "node_modules/qs": {
      "version": "6.14.2",
      "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "BSD-3-Clause",
      "dependencies": {
        "side-channel": "^1.1.0"
      },
      "engines": {
        "node": ">=0.6"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/range-parser": {
      "version": "1.2.1",
      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/raw-body": {
      "version": "2.5.3",
      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "bytes": "~3.1.2",
        "http-errors": "~2.0.1",
        "iconv-lite": "~0.4.24",
        "unpipe": "~1.0.0"
      },
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/safe-buffer": {
      "version": "5.2.1",
      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/feross"
        },
        {
          "type": "patreon",
          "url": "https://www.patreon.com/feross"
        },
        {
          "type": "consulting",
          "url": "https://feross.org/support"
        }
      ],
      "license": "MIT"
    },
    "node_modules/safer-buffer": {
      "version": "2.1.2",
      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/send": {
      "version": "0.19.2",
      "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "debug": "2.6.9",
        "depd": "2.0.0",
        "destroy": "1.2.0",
        "encodeurl": "~2.0.0",
        "escape-html": "~1.0.3",
        "etag": "~1.8.1",
        "fresh": "~0.5.2",
        "http-errors": "~2.0.1",
        "mime": "1.6.0",
        "ms": "2.1.3",
        "on-finished": "~2.4.1",
        "range-parser": "~1.2.1",
        "statuses": "~2.0.2"
      },
      "engines": {
        "node": ">= 0.8.0"
      }
    },
    "node_modules/send/node_modules/ms": {
      "version": "2.1.3",
      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/serve-static": {
      "version": "1.16.3",
      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "encodeurl": "~2.0.0",
        "escape-html": "~1.0.3",
        "parseurl": "~1.3.3",
        "send": "~0.19.1"
      },
      "engines": {
        "node": ">= 0.8.0"
      }
    },
    "node_modules/setprototypeof": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC"
    },
    "node_modules/side-channel": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "es-errors": "^1.3.0",
        "object-inspect": "^1.13.3",
        "side-channel-list": "^1.0.0",
        "side-channel-map": "^1.0.1",
        "side-channel-weakmap": "^1.0.2"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/side-channel-list": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "es-errors": "^1.3.0",
        "object-inspect": "^1.13.3"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/side-channel-map": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "call-bound": "^1.0.2",
        "es-errors": "^1.3.0",
        "get-intrinsic": "^1.2.5",
        "object-inspect": "^1.13.3"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/side-channel-weakmap": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "call-bound": "^1.0.2",
        "es-errors": "^1.3.0",
        "get-intrinsic": "^1.2.5",
        "object-inspect": "^1.13.3",
        "side-channel-map": "^1.0.1"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/statuses": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/toidentifier": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=0.6"
      }
    },
    "node_modules/type-is": {
      "version": "1.6.18",
      "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "media-typer": "0.3.0",
        "mime-types": "~2.1.24"
      },
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/typescript": {
      "version": "5.9.3",
      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "Apache-2.0",
      "bin": {
        "tsc": "bin/tsc",
        "tsserver": "bin/tsserver"
      },
      "engines": {
        "node": ">=14.17"
      }
    },
    "node_modules/undici-types": {
      "version": "6.21.0",
      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/unpipe": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/utils-merge": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.4.0"
      }
    },
    "node_modules/uuid": {
      "version": "13.0.0",
      "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        "https://github.com/sponsors/broofa",
        "https://github.com/sponsors/ctavan"
      ],
      "license": "MIT",
      "bin": {
        "uuid": "dist-node/bin/uuid"
      }
    },
    "node_modules/vary": {
      "version": "1.1.2",
      "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/ws": {
      "version": "8.19.0",
      "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=10.0.0"
      },
      "peerDependencies": {
        "bufferutil": "^4.0.1",
        "utf-8-validate": ">=5.0.2"
      },
      "peerDependenciesMeta": {
        "bufferutil": {
          "optional": true
        },
        "utf-8-validate": {
          "optional": true
        }
      }
    }
  }
}


path: package.json
content: {
  "name": "agent-comm-skill",
  "version": "1.0.0",
  "description": "Agent Communication Skill for ClawHub",
  "type": "module",
  "main": "dist/index.js",
  "scripts": {
    "build": "tsc",
    "start": "node dist/index.js"
  },
  "dependencies": {
    "libsodium-wrappers": "^0.7.16",
    "loro": "^1.0.0",
    "uuid": "^13.0.0",
    "ws": "^8.19.0"
  },
  "devDependencies": {
    "@types/node": "^20.0.0",
    "@types/uuid": "^10.0.0",
    "@types/ws": "^8.18.1",
    "typescript": "^5.0.0"
  }
}


path: plugin.json
content: {
  "id": "agent-comm-skill",
  "name": "Agent Communication Skill",
  "version": "1.0.0",
  "description": "Enables agents to register and communicate securely using DID and Ed25519 signatures.",
  "permissions": ["local-storage", "cryptography"],
  "entry": "dist/index.js",
  "skills": [
    {
      "action": "agent.register",
      "description": "Register a new agent identity or restore an existing one",
      "parameters": [
        { "name": "alias", "type": "string", "required": false }
      ]
    },
    {
      "action": "message.sign",
      "description": "Securely sign CRDT payload using Vault ed25519 (Private)",
      "parameters": [
        { "name": "localId", "type": "string", "required": true },
        { "name": "payload", "type": "object", "required": true }
      ]
    },
    {
      "action": "message.verify",
      "description": "Verify external signatures to validate task assignments",
      "parameters": [
        { "name": "publicKeyHex", "type": "string", "required": true },
        { "name": "payload", "type": "object", "required": true },
        { "name": "signatureHex", "type": "string", "required": true }
      ]
    }
  ]
}


path: scripts/vault.js
content: #!/usr/bin/env node
const sodium = require('libsodium-wrappers');
const fs = require('fs');
const path = require('path');

const VAULT_PATH = path.join(process.cwd(), 'data/keystore');

module.exports = {
  // --- 身份与签名 (Phase 1) ---
  getOrGenerateIdentity: async (localAgentId) => {
    await sodium.ready;
    if (!fs.existsSync(VAULT_PATH)) fs.mkdirSync(VAULT_PATH, { recursive: true });
    const keyPath = path.join(VAULT_PATH, `${localAgentId}.keys.json`);
    if (fs.existsSync(keyPath)) {
      const keys = JSON.parse(fs.readFileSync(keyPath));
      return { publicKey: Buffer.from(keys.publicKey, 'hex'), privateKey: Buffer.from(keys.privateKey, 'hex') };
    }
    const keypair = sodium.crypto_sign_keypair();
    fs.writeFileSync(keyPath, JSON.stringify({
      publicKey: sodium.to_hex(keypair.publicKey),
      privateKey: sodium.to_hex(keypair.privateKey)
    }), { mode: 0o600 });
    return { publicKey: keypair.publicKey, privateKey: keypair.privateKey };
  },

  signPayload: async (localAgentId, payloadString) => {
    await sodium.ready;
    const keyPath = path.join(VAULT_PATH, `${localAgentId}.keys.json`);
    const keys = JSON.parse(fs.readFileSync(keyPath));
    const signature = sodium.crypto_sign_detached(payloadString, Buffer.from(keys.privateKey, 'hex'));
    return sodium.to_hex(signature);
  },

  verifySignature: async (publicKeyHex, payloadString, signatureHex) => {
    await sodium.ready;
    return sodium.crypto_sign_verify_detached(Buffer.from(signatureHex, 'hex'), payloadString, Buffer.from(publicKeyHex, 'hex'));
  },

  // --- 端到端对称加密 (Phase 3: E2EE) ---
  
  // 生成会话共享密钥 (32字节)
  generateSessionKey: async () => {
    await sodium.ready;
    return sodium.to_hex(sodium.randombytes_buf(sodium.crypto_secretbox_KEYBYTES));
  },

  encryptSecret: async (payloadString, sessionKeyHex) => {
    await sodium.ready;
    const key = Buffer.from(sessionKeyHex, 'hex');
    const nonce = sodium.randombytes_buf(sodium.crypto_secretbox_NONCEBYTES);
    const ciphertext = sodium.crypto_secretbox_easy(payloadString, nonce, key);
    return {
      ciphertext: sodium.to_hex(ciphertext),
      nonce: sodium.to_hex(nonce)
    };
  },

  decryptSecret: async (ciphertextHex, nonceHex, sessionKeyHex) => {
    await sodium.ready;
    try {
      const key = Buffer.from(sessionKeyHex, 'hex');
      const ciphertext = Buffer.from(ciphertextHex, 'hex');
      const nonce = Buffer.from(nonceHex, 'hex');
      const decrypted = sodium.crypto_secretbox_open_easy(ciphertext, nonce, key);
      return decrypted ? Buffer.from(decrypted).toString('utf-8') : null;
    } catch (e) {
      return null;
    }
  }
};


path: tsconfig.json
content: {
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "outDir": "./dist",
    "rootDir": "./",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "resolveJsonModule": true
  },
  "include": ["index.ts", "scripts/**/*"],
  "exclude": ["node_modules", "test"]
}


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (HIGH)