openclaw-overlay-plugin 0.7.22
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.
- package/README.md +406 -0
- package/SKILL.md +78 -0
- package/clawdbot.plugin.json +106 -0
- package/dist/cli-main.d.ts +7 -0
- package/dist/cli-main.js +192 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.js +14 -0
- package/dist/core/config.d.ts +11 -0
- package/dist/core/config.js +13 -0
- package/dist/core/index.d.ts +25 -0
- package/dist/core/index.js +26 -0
- package/dist/core/payment.d.ts +16 -0
- package/dist/core/payment.js +94 -0
- package/dist/core/types.d.ts +94 -0
- package/dist/core/types.js +4 -0
- package/dist/core/verify.d.ts +28 -0
- package/dist/core/verify.js +104 -0
- package/dist/core/wallet.d.ts +99 -0
- package/dist/core/wallet.js +219 -0
- package/dist/scripts/baemail/commands.d.ts +64 -0
- package/dist/scripts/baemail/commands.js +258 -0
- package/dist/scripts/baemail/handler.d.ts +36 -0
- package/dist/scripts/baemail/handler.js +284 -0
- package/dist/scripts/baemail/index.d.ts +5 -0
- package/dist/scripts/baemail/index.js +5 -0
- package/dist/scripts/config.d.ts +48 -0
- package/dist/scripts/config.js +68 -0
- package/dist/scripts/index.d.ts +7 -0
- package/dist/scripts/index.js +7 -0
- package/dist/scripts/messaging/connect.d.ts +8 -0
- package/dist/scripts/messaging/connect.js +114 -0
- package/dist/scripts/messaging/handlers.d.ts +21 -0
- package/dist/scripts/messaging/handlers.js +334 -0
- package/dist/scripts/messaging/inbox.d.ts +11 -0
- package/dist/scripts/messaging/inbox.js +51 -0
- package/dist/scripts/messaging/index.d.ts +8 -0
- package/dist/scripts/messaging/index.js +8 -0
- package/dist/scripts/messaging/poll.d.ts +7 -0
- package/dist/scripts/messaging/poll.js +52 -0
- package/dist/scripts/messaging/send.d.ts +7 -0
- package/dist/scripts/messaging/send.js +43 -0
- package/dist/scripts/output.d.ts +12 -0
- package/dist/scripts/output.js +19 -0
- package/dist/scripts/overlay/discover.d.ts +7 -0
- package/dist/scripts/overlay/discover.js +72 -0
- package/dist/scripts/overlay/index.d.ts +7 -0
- package/dist/scripts/overlay/index.js +7 -0
- package/dist/scripts/overlay/registration.d.ts +19 -0
- package/dist/scripts/overlay/registration.js +176 -0
- package/dist/scripts/overlay/services.d.ts +29 -0
- package/dist/scripts/overlay/services.js +167 -0
- package/dist/scripts/overlay/transaction.d.ts +42 -0
- package/dist/scripts/overlay/transaction.js +103 -0
- package/dist/scripts/payment/build.d.ts +24 -0
- package/dist/scripts/payment/build.js +54 -0
- package/dist/scripts/payment/commands.d.ts +15 -0
- package/dist/scripts/payment/commands.js +73 -0
- package/dist/scripts/payment/index.d.ts +6 -0
- package/dist/scripts/payment/index.js +6 -0
- package/dist/scripts/payment/types.d.ts +56 -0
- package/dist/scripts/payment/types.js +4 -0
- package/dist/scripts/services/index.d.ts +6 -0
- package/dist/scripts/services/index.js +6 -0
- package/dist/scripts/services/queue.d.ts +11 -0
- package/dist/scripts/services/queue.js +28 -0
- package/dist/scripts/services/request.d.ts +7 -0
- package/dist/scripts/services/request.js +82 -0
- package/dist/scripts/services/respond.d.ts +11 -0
- package/dist/scripts/services/respond.js +132 -0
- package/dist/scripts/types.d.ts +107 -0
- package/dist/scripts/types.js +4 -0
- package/dist/scripts/utils/index.d.ts +6 -0
- package/dist/scripts/utils/index.js +6 -0
- package/dist/scripts/utils/merkle.d.ts +12 -0
- package/dist/scripts/utils/merkle.js +47 -0
- package/dist/scripts/utils/storage.d.ts +66 -0
- package/dist/scripts/utils/storage.js +211 -0
- package/dist/scripts/utils/woc.d.ts +26 -0
- package/dist/scripts/utils/woc.js +91 -0
- package/dist/scripts/wallet/balance.d.ts +22 -0
- package/dist/scripts/wallet/balance.js +240 -0
- package/dist/scripts/wallet/identity.d.ts +70 -0
- package/dist/scripts/wallet/identity.js +151 -0
- package/dist/scripts/wallet/index.d.ts +6 -0
- package/dist/scripts/wallet/index.js +6 -0
- package/dist/scripts/wallet/setup.d.ts +15 -0
- package/dist/scripts/wallet/setup.js +105 -0
- package/dist/scripts/x-verification/commands.d.ts +27 -0
- package/dist/scripts/x-verification/commands.js +222 -0
- package/dist/scripts/x-verification/index.d.ts +4 -0
- package/dist/scripts/x-verification/index.js +4 -0
- package/dist/services/built-in/api-proxy/index.d.ts +6 -0
- package/dist/services/built-in/api-proxy/index.js +23 -0
- package/dist/services/built-in/code-develop/index.d.ts +6 -0
- package/dist/services/built-in/code-develop/index.js +23 -0
- package/dist/services/built-in/code-review/index.d.ts +10 -0
- package/dist/services/built-in/code-review/index.js +51 -0
- package/dist/services/built-in/image-analysis/index.d.ts +6 -0
- package/dist/services/built-in/image-analysis/index.js +33 -0
- package/dist/services/built-in/memory-store/index.d.ts +6 -0
- package/dist/services/built-in/memory-store/index.js +22 -0
- package/dist/services/built-in/roulette/index.d.ts +6 -0
- package/dist/services/built-in/roulette/index.js +27 -0
- package/dist/services/built-in/summarize/index.d.ts +6 -0
- package/dist/services/built-in/summarize/index.js +21 -0
- package/dist/services/built-in/tell-joke/handler.d.ts +7 -0
- package/dist/services/built-in/tell-joke/handler.js +122 -0
- package/dist/services/built-in/tell-joke/index.d.ts +9 -0
- package/dist/services/built-in/tell-joke/index.js +31 -0
- package/dist/services/built-in/translate/index.d.ts +6 -0
- package/dist/services/built-in/translate/index.js +21 -0
- package/dist/services/built-in/web-research/index.d.ts +9 -0
- package/dist/services/built-in/web-research/index.js +51 -0
- package/dist/services/index.d.ts +13 -0
- package/dist/services/index.js +14 -0
- package/dist/services/loader.d.ts +77 -0
- package/dist/services/loader.js +292 -0
- package/dist/services/manager.d.ts +86 -0
- package/dist/services/manager.js +255 -0
- package/dist/services/registry.d.ts +98 -0
- package/dist/services/registry.js +204 -0
- package/dist/services/types.d.ts +230 -0
- package/dist/services/types.js +30 -0
- package/dist/test/cli.test.d.ts +7 -0
- package/dist/test/cli.test.js +329 -0
- package/dist/test/comprehensive-overlay.test.d.ts +13 -0
- package/dist/test/comprehensive-overlay.test.js +593 -0
- package/dist/test/key-derivation.test.d.ts +12 -0
- package/dist/test/key-derivation.test.js +86 -0
- package/dist/test/overlay-submit.test.d.ts +10 -0
- package/dist/test/overlay-submit.test.js +460 -0
- package/dist/test/request-response-flow.test.d.ts +5 -0
- package/dist/test/request-response-flow.test.js +209 -0
- package/dist/test/service-system.test.d.ts +5 -0
- package/dist/test/service-system.test.js +190 -0
- package/dist/test/utils/server-logic.d.ts +98 -0
- package/dist/test/utils/server-logic.js +286 -0
- package/dist/test/wallet.test.d.ts +7 -0
- package/dist/test/wallet.test.js +146 -0
- package/index.ts +1965 -0
- package/openclaw.plugin.json +106 -0
- package/package.json +73 -0
- package/src/cli-main.ts +230 -0
- package/src/cli.ts +16 -0
- package/src/core/README.md +246 -0
- package/src/core/config.ts +21 -0
- package/src/core/index.ts +42 -0
- package/src/core/payment.ts +111 -0
- package/src/core/types.ts +102 -0
- package/src/core/verify.ts +119 -0
- package/src/core/wallet.ts +282 -0
- package/src/scripts/baemail/commands.ts +326 -0
- package/src/scripts/baemail/handler.ts +338 -0
- package/src/scripts/baemail/index.ts +6 -0
- package/src/scripts/config.ts +81 -0
- package/src/scripts/index.ts +8 -0
- package/src/scripts/messaging/connect.ts +121 -0
- package/src/scripts/messaging/handlers.ts +394 -0
- package/src/scripts/messaging/inbox.ts +64 -0
- package/src/scripts/messaging/index.ts +9 -0
- package/src/scripts/messaging/poll.ts +59 -0
- package/src/scripts/messaging/send.ts +54 -0
- package/src/scripts/output.ts +21 -0
- package/src/scripts/overlay/discover.ts +81 -0
- package/src/scripts/overlay/index.ts +8 -0
- package/src/scripts/overlay/registration.ts +199 -0
- package/src/scripts/overlay/services.ts +199 -0
- package/src/scripts/overlay/transaction.ts +124 -0
- package/src/scripts/payment/build.ts +65 -0
- package/src/scripts/payment/commands.ts +92 -0
- package/src/scripts/payment/index.ts +7 -0
- package/src/scripts/payment/types.ts +62 -0
- package/src/scripts/services/index.ts +7 -0
- package/src/scripts/services/queue.ts +35 -0
- package/src/scripts/services/request.ts +98 -0
- package/src/scripts/services/respond.ts +149 -0
- package/src/scripts/types.ts +121 -0
- package/src/scripts/utils/index.ts +7 -0
- package/src/scripts/utils/merkle.ts +57 -0
- package/src/scripts/utils/storage.ts +231 -0
- package/src/scripts/utils/woc.ts +106 -0
- package/src/scripts/wallet/balance.ts +277 -0
- package/src/scripts/wallet/identity.ts +203 -0
- package/src/scripts/wallet/index.ts +7 -0
- package/src/scripts/wallet/setup.ts +121 -0
- package/src/scripts/x-verification/commands.ts +256 -0
- package/src/scripts/x-verification/index.ts +5 -0
- package/src/services/built-in/api-proxy/index.ts +26 -0
- package/src/services/built-in/api-proxy/prompt.md +26 -0
- package/src/services/built-in/code-develop/index.ts +26 -0
- package/src/services/built-in/code-develop/prompt.md +35 -0
- package/src/services/built-in/code-review/index.ts +54 -0
- package/src/services/built-in/code-review/prompt.md +105 -0
- package/src/services/built-in/image-analysis/index.ts +36 -0
- package/src/services/built-in/image-analysis/prompt.md +42 -0
- package/src/services/built-in/memory-store/index.ts +25 -0
- package/src/services/built-in/memory-store/prompt.md +45 -0
- package/src/services/built-in/roulette/index.ts +30 -0
- package/src/services/built-in/roulette/prompt.md +35 -0
- package/src/services/built-in/summarize/index.ts +24 -0
- package/src/services/built-in/summarize/prompt.md +27 -0
- package/src/services/built-in/tell-joke/handler.ts +134 -0
- package/src/services/built-in/tell-joke/index.ts +34 -0
- package/src/services/built-in/tell-joke/prompt.md +59 -0
- package/src/services/built-in/translate/index.ts +24 -0
- package/src/services/built-in/translate/prompt.md +23 -0
- package/src/services/built-in/web-research/index.ts +54 -0
- package/src/services/built-in/web-research/prompt.md +110 -0
- package/src/services/index.ts +16 -0
- package/src/services/loader.ts +344 -0
- package/src/services/manager.ts +304 -0
- package/src/services/registry.ts +246 -0
- package/src/services/types.ts +259 -0
- package/src/test/cli.test.ts +352 -0
- package/src/test/comprehensive-overlay.test.ts +729 -0
- package/src/test/key-derivation.test.ts +102 -0
- package/src/test/overlay-submit.test.ts +570 -0
- package/src/test/request-response-flow.test.ts +252 -0
- package/src/test/service-system.test.ts +241 -0
- package/src/test/utils/server-logic.ts +368 -0
- package/src/test/wallet.test.ts +166 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wallet identity helpers.
|
|
3
|
+
*/
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import { PATHS } from '../config.js';
|
|
6
|
+
import { CachedKeyDeriver, Utils } from '@bsv/sdk';
|
|
7
|
+
import { brc29ProtocolID } from '@bsv/wallet-toolbox';
|
|
8
|
+
// Dynamic import for @bsv/sdk
|
|
9
|
+
let _sdk = null;
|
|
10
|
+
async function getSdk() {
|
|
11
|
+
if (_sdk)
|
|
12
|
+
return _sdk;
|
|
13
|
+
try {
|
|
14
|
+
_sdk = await import('@bsv/sdk');
|
|
15
|
+
return _sdk;
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
const { fileURLToPath } = await import('node:url');
|
|
19
|
+
const path = await import('node:path');
|
|
20
|
+
const os = await import('node:os');
|
|
21
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
22
|
+
const candidates = [
|
|
23
|
+
path.resolve(__dirname, '..', '..', '..', 'node_modules', '@bsv', 'sdk', 'dist', 'esm', 'mod.js'),
|
|
24
|
+
path.resolve(__dirname, '..', '..', '..', '..', '..', 'a2a-bsv', 'packages', 'core', 'node_modules', '@bsv', 'sdk', 'dist', 'esm', 'mod.js'),
|
|
25
|
+
path.resolve(os.homedir(), 'a2a-bsv', 'packages', 'core', 'node_modules', '@bsv', 'sdk', 'dist', 'esm', 'mod.js'),
|
|
26
|
+
];
|
|
27
|
+
for (const p of candidates) {
|
|
28
|
+
try {
|
|
29
|
+
_sdk = await import(p);
|
|
30
|
+
return _sdk;
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
// Try next
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
throw new Error('Cannot find @bsv/sdk. Run setup.sh first.');
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Load wallet identity from disk.
|
|
41
|
+
* @returns Identity object with rootKeyHex and identityKey
|
|
42
|
+
* @throws Error if wallet not initialized
|
|
43
|
+
*/
|
|
44
|
+
export function loadWalletIdentity() {
|
|
45
|
+
if (!fs.existsSync(PATHS.walletIdentity)) {
|
|
46
|
+
throw new Error('Wallet not initialized. Run: cli setup');
|
|
47
|
+
}
|
|
48
|
+
// Security warning for overly permissive file mode
|
|
49
|
+
try {
|
|
50
|
+
const fileMode = fs.statSync(PATHS.walletIdentity).mode & 0o777;
|
|
51
|
+
if (fileMode & 0o044) { // world or group readable
|
|
52
|
+
console.error(`[security] WARNING: ${PATHS.walletIdentity} has permissive mode 0${fileMode.toString(8)}. Run: chmod 600 ${PATHS.walletIdentity}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// Ignore stat errors
|
|
57
|
+
}
|
|
58
|
+
return JSON.parse(fs.readFileSync(PATHS.walletIdentity, 'utf-8'));
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Load identity and private key for relay message signing.
|
|
62
|
+
* @returns Object with identityKey and privKey
|
|
63
|
+
*/
|
|
64
|
+
export async function loadIdentity() {
|
|
65
|
+
const identity = loadWalletIdentity();
|
|
66
|
+
const sdk = await getSdk();
|
|
67
|
+
const privKey = sdk.PrivateKey.fromHex(identity.rootKeyHex);
|
|
68
|
+
return { identityKey: identity.identityKey, privKey };
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Sign a relay message using ECDSA.
|
|
72
|
+
* @param privKey - Private key for signing
|
|
73
|
+
* @param to - Recipient's identity key
|
|
74
|
+
* @param type - Message type
|
|
75
|
+
* @param payload - Message payload
|
|
76
|
+
* @returns Hex-encoded DER signature
|
|
77
|
+
*/
|
|
78
|
+
export async function signRelayMessage(privKey, to, type, payload) {
|
|
79
|
+
const sdk = await getSdk();
|
|
80
|
+
const preimage = to + type + JSON.stringify(payload);
|
|
81
|
+
const msgHash = sdk.Hash.sha256(Array.from(new TextEncoder().encode(preimage)));
|
|
82
|
+
const sig = privKey.sign(msgHash);
|
|
83
|
+
return Array.from(sig.toDER()).map((b) => b.toString(16).padStart(2, '0')).join('');
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Verify a relay message signature.
|
|
87
|
+
* @param fromKey - Sender's public key
|
|
88
|
+
* @param to - Recipient's identity key
|
|
89
|
+
* @param type - Message type
|
|
90
|
+
* @param payload - Message payload
|
|
91
|
+
* @param signatureHex - Hex-encoded DER signature
|
|
92
|
+
* @returns Verification result
|
|
93
|
+
*/
|
|
94
|
+
export async function verifyRelaySignature(fromKey, to, type, payload, signatureHex) {
|
|
95
|
+
if (!signatureHex)
|
|
96
|
+
return { valid: false, reason: 'no signature' };
|
|
97
|
+
try {
|
|
98
|
+
const sdk = await getSdk();
|
|
99
|
+
const preimage = to + type + JSON.stringify(payload);
|
|
100
|
+
const msgHash = sdk.Hash.sha256(Array.from(new TextEncoder().encode(preimage)));
|
|
101
|
+
const sigBytes = [];
|
|
102
|
+
for (let i = 0; i < signatureHex.length; i += 2) {
|
|
103
|
+
sigBytes.push(parseInt(signatureHex.substring(i, i + 2), 16));
|
|
104
|
+
}
|
|
105
|
+
const sig = sdk.Signature.fromDER(sigBytes);
|
|
106
|
+
const pubKey = sdk.PublicKey.fromString(fromKey);
|
|
107
|
+
return { valid: pubKey.verify(msgHash, sig) };
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
return { valid: false, reason: String(err) };
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Derive wallet address components from a private key.
|
|
115
|
+
*
|
|
116
|
+
* IMPORTANT: This uses BRC-29 key derivation to create a child key.
|
|
117
|
+
* Any transactions spending to this address MUST use the matching
|
|
118
|
+
* child private key for signing, NOT the root key.
|
|
119
|
+
*
|
|
120
|
+
* Use deriveWalletKeys() to get both the address and signing key.
|
|
121
|
+
*/
|
|
122
|
+
export async function deriveWalletAddress(privKey) {
|
|
123
|
+
const keyDeriver = new CachedKeyDeriver(privKey);
|
|
124
|
+
const pubKey = keyDeriver.derivePublicKey(brc29ProtocolID, Utils.toBase64(Utils.toArray('import')) + ' ' + Utils.toBase64(Utils.toArray('now')), 'self', true);
|
|
125
|
+
const address = pubKey.toAddress();
|
|
126
|
+
const hash160 = Buffer.from(pubKey.toHash());
|
|
127
|
+
return { address, hash160, pubKey };
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Derive wallet keys for both address AND transaction signing.
|
|
131
|
+
*
|
|
132
|
+
* CRITICAL: Use this function to get the child private key for signing
|
|
133
|
+
* transactions that spend from the derived address. Do NOT use the
|
|
134
|
+
* root private key - it will cause signature verification failures!
|
|
135
|
+
*
|
|
136
|
+
* @param rootPrivKey - Root private key from wallet identity
|
|
137
|
+
* @returns Object with address, hash160, and CHILD private key for signing
|
|
138
|
+
*/
|
|
139
|
+
export async function deriveWalletKeys(rootPrivKey) {
|
|
140
|
+
const keyDeriver = new CachedKeyDeriver(rootPrivKey);
|
|
141
|
+
const derivationPrefix = Utils.toBase64(Utils.toArray('import'));
|
|
142
|
+
const derivationSuffix = Utils.toBase64(Utils.toArray('now'));
|
|
143
|
+
const keyString = `${derivationPrefix} ${derivationSuffix}`;
|
|
144
|
+
// Derive child private key (for signing)
|
|
145
|
+
const childPrivKey = keyDeriver.derivePrivateKey(brc29ProtocolID, keyString, 'self');
|
|
146
|
+
// Derive child public key (for address)
|
|
147
|
+
const pubKey = keyDeriver.derivePublicKey(brc29ProtocolID, keyString, 'self', true);
|
|
148
|
+
const address = pubKey.toAddress();
|
|
149
|
+
const hash160 = Buffer.from(pubKey.toHash());
|
|
150
|
+
return { address, hash160, pubKey, childPrivKey };
|
|
151
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wallet setup commands: setup, identity, address.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Setup command: create wallet and show identity.
|
|
6
|
+
*/
|
|
7
|
+
export declare function cmdSetup(): Promise<never>;
|
|
8
|
+
/**
|
|
9
|
+
* Identity command: show identity public key.
|
|
10
|
+
*/
|
|
11
|
+
export declare function cmdIdentity(): Promise<never>;
|
|
12
|
+
/**
|
|
13
|
+
* Address command: show P2PKH receive address.
|
|
14
|
+
*/
|
|
15
|
+
export declare function cmdAddress(): Promise<never>;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wallet setup commands: setup, identity, address.
|
|
3
|
+
*/
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import { NETWORK, WALLET_DIR, OVERLAY_URL, PATHS } from '../config.js';
|
|
6
|
+
import { ok, fail } from '../output.js';
|
|
7
|
+
import { loadWalletIdentity, deriveWalletAddress } from './identity.js';
|
|
8
|
+
import { BSVAgentWallet } from '../../core/index.js';
|
|
9
|
+
async function getBSVAgentWallet() {
|
|
10
|
+
return BSVAgentWallet;
|
|
11
|
+
}
|
|
12
|
+
// Dynamic import for @bsv/sdk
|
|
13
|
+
let _sdk = null;
|
|
14
|
+
async function getSdk() {
|
|
15
|
+
if (_sdk)
|
|
16
|
+
return _sdk;
|
|
17
|
+
try {
|
|
18
|
+
_sdk = await import('@bsv/sdk');
|
|
19
|
+
return _sdk;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
const { fileURLToPath } = await import('node:url');
|
|
23
|
+
const path = await import('node:path');
|
|
24
|
+
const os = await import('node:os');
|
|
25
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
26
|
+
const candidates = [
|
|
27
|
+
path.resolve(__dirname, '..', '..', '..', 'node_modules', '@bsv', 'sdk', 'dist', 'esm', 'mod.js'),
|
|
28
|
+
path.resolve(__dirname, '..', '..', '..', '..', '..', 'a2a-bsv', 'packages', 'core', 'node_modules', '@bsv', 'sdk', 'dist', 'esm', 'mod.js'),
|
|
29
|
+
path.resolve(os.homedir(), 'a2a-bsv', 'packages', 'core', 'node_modules', '@bsv', 'sdk', 'dist', 'esm', 'mod.js'),
|
|
30
|
+
];
|
|
31
|
+
for (const p of candidates) {
|
|
32
|
+
try {
|
|
33
|
+
_sdk = await import(p);
|
|
34
|
+
return _sdk;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
// Try next
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
throw new Error('Cannot find @bsv/sdk. Run setup.sh first.');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Setup command: create wallet and show identity.
|
|
45
|
+
*/
|
|
46
|
+
export async function cmdSetup() {
|
|
47
|
+
const BSVAgentWallet = await getBSVAgentWallet();
|
|
48
|
+
if (fs.existsSync(PATHS.walletIdentity)) {
|
|
49
|
+
const wallet = await BSVAgentWallet.load({ network: NETWORK, storageDir: WALLET_DIR });
|
|
50
|
+
const identityKey = await wallet.getIdentityKey();
|
|
51
|
+
await wallet.destroy();
|
|
52
|
+
return ok({
|
|
53
|
+
identityKey,
|
|
54
|
+
walletDir: WALLET_DIR,
|
|
55
|
+
network: NETWORK,
|
|
56
|
+
overlayUrl: OVERLAY_URL,
|
|
57
|
+
alreadyExisted: true,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
fs.mkdirSync(WALLET_DIR, { recursive: true });
|
|
61
|
+
const wallet = await BSVAgentWallet.load({ network: NETWORK, storageDir: WALLET_DIR });
|
|
62
|
+
const identityKey = await wallet.getIdentityKey();
|
|
63
|
+
await wallet.destroy();
|
|
64
|
+
// Restrict permissions on wallet-identity.json (contains private key)
|
|
65
|
+
if (fs.existsSync(PATHS.walletIdentity)) {
|
|
66
|
+
fs.chmodSync(PATHS.walletIdentity, 0o600);
|
|
67
|
+
}
|
|
68
|
+
return ok({
|
|
69
|
+
identityKey,
|
|
70
|
+
walletDir: WALLET_DIR,
|
|
71
|
+
network: NETWORK,
|
|
72
|
+
overlayUrl: OVERLAY_URL,
|
|
73
|
+
alreadyExisted: false,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Identity command: show identity public key.
|
|
78
|
+
*/
|
|
79
|
+
export async function cmdIdentity() {
|
|
80
|
+
const BSVAgentWallet = await getBSVAgentWallet();
|
|
81
|
+
const wallet = await BSVAgentWallet.load({ network: NETWORK, storageDir: WALLET_DIR });
|
|
82
|
+
const identityKey = await wallet.getIdentityKey();
|
|
83
|
+
await wallet.destroy();
|
|
84
|
+
return ok({ identityKey });
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Address command: show P2PKH receive address.
|
|
88
|
+
*/
|
|
89
|
+
export async function cmdAddress() {
|
|
90
|
+
if (!fs.existsSync(PATHS.walletIdentity)) {
|
|
91
|
+
return fail('Wallet not initialized. Run: setup');
|
|
92
|
+
}
|
|
93
|
+
const sdk = await getSdk();
|
|
94
|
+
const identity = loadWalletIdentity();
|
|
95
|
+
const privKey = sdk.PrivateKey.fromHex(identity.rootKeyHex);
|
|
96
|
+
const { address } = await deriveWalletAddress(privKey);
|
|
97
|
+
return ok({
|
|
98
|
+
address,
|
|
99
|
+
network: NETWORK,
|
|
100
|
+
identityKey: identity.identityKey,
|
|
101
|
+
note: NETWORK === 'mainnet'
|
|
102
|
+
? `Fund this address at an exchange — Explorer: https://whatsonchain.com/address/${address}`
|
|
103
|
+
: `Fund via faucet: https://witnessonchain.com/faucet/tbsv — Explorer: https://test.whatsonchain.com/address/${address}`,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* X (Twitter) verification commands.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Start X verification: generate a tweet with identity key and signature.
|
|
6
|
+
*/
|
|
7
|
+
export declare function cmdXVerifyStart(handleArg: string | undefined): Promise<never>;
|
|
8
|
+
/**
|
|
9
|
+
* Complete X verification by checking the posted tweet.
|
|
10
|
+
*/
|
|
11
|
+
export declare function cmdXVerifyComplete(tweetUrl: string | undefined): Promise<never>;
|
|
12
|
+
/**
|
|
13
|
+
* List verified X accounts (local cache).
|
|
14
|
+
*/
|
|
15
|
+
export declare function cmdXVerifications(): Promise<never>;
|
|
16
|
+
/**
|
|
17
|
+
* Lookup X verifications from the overlay network.
|
|
18
|
+
*/
|
|
19
|
+
export declare function cmdXLookup(query: string | undefined): Promise<never>;
|
|
20
|
+
/**
|
|
21
|
+
* List pending X engagement requests.
|
|
22
|
+
*/
|
|
23
|
+
export declare function cmdXEngagementQueue(): Promise<never>;
|
|
24
|
+
/**
|
|
25
|
+
* Mark an X engagement request as fulfilled.
|
|
26
|
+
*/
|
|
27
|
+
export declare function cmdXEngagementFulfill(requestId: string | undefined, proofUrl?: string): Promise<never>;
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* X (Twitter) verification commands.
|
|
3
|
+
*/
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import { PROTOCOL_ID, TOPICS, LOOKUP_SERVICES, PATHS } from '../config.js';
|
|
6
|
+
import { ok, fail } from '../output.js';
|
|
7
|
+
import { loadIdentity } from '../wallet/identity.js';
|
|
8
|
+
import { loadXVerifications, saveXVerifications, readJsonl, ensureStateDir } from '../utils/storage.js';
|
|
9
|
+
import { buildRealOverlayTransaction, lookupOverlay } from '../overlay/transaction.js';
|
|
10
|
+
// Dynamic import for @bsv/sdk
|
|
11
|
+
let _sdk = null;
|
|
12
|
+
async function getSdk() {
|
|
13
|
+
if (_sdk)
|
|
14
|
+
return _sdk;
|
|
15
|
+
try {
|
|
16
|
+
_sdk = await import('@bsv/sdk');
|
|
17
|
+
return _sdk;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
const { fileURLToPath } = await import('node:url');
|
|
21
|
+
const path = await import('node:path');
|
|
22
|
+
const os = await import('node:os');
|
|
23
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
24
|
+
const candidates = [
|
|
25
|
+
path.resolve(__dirname, '..', '..', '..', 'node_modules', '@bsv', 'sdk', 'dist', 'esm', 'mod.js'),
|
|
26
|
+
path.resolve(__dirname, '..', '..', '..', '..', '..', 'a2a-bsv', 'packages', 'core', 'node_modules', '@bsv', 'sdk', 'dist', 'esm', 'mod.js'),
|
|
27
|
+
path.resolve(os.homedir(), 'a2a-bsv', 'packages', 'core', 'node_modules', '@bsv', 'sdk', 'dist', 'esm', 'mod.js'),
|
|
28
|
+
];
|
|
29
|
+
for (const p of candidates) {
|
|
30
|
+
try {
|
|
31
|
+
_sdk = await import(p);
|
|
32
|
+
return _sdk;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// Try next
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
throw new Error('Cannot find @bsv/sdk. Run setup.sh first.');
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Start X verification: generate a tweet with identity key and signature.
|
|
43
|
+
*/
|
|
44
|
+
export async function cmdXVerifyStart(handleArg) {
|
|
45
|
+
if (!handleArg) {
|
|
46
|
+
return fail('Usage: x-verify-start <@handle>');
|
|
47
|
+
}
|
|
48
|
+
const sdk = await getSdk();
|
|
49
|
+
const handle = handleArg.startsWith('@') ? handleArg : `@${handleArg}`;
|
|
50
|
+
const { identityKey, privKey } = await loadIdentity();
|
|
51
|
+
// Sign the verification message
|
|
52
|
+
const message = `Verify ${identityKey}`;
|
|
53
|
+
const msgHash = sdk.Hash.sha256(Array.from(new TextEncoder().encode(message)));
|
|
54
|
+
const sig = privKey.sign(msgHash);
|
|
55
|
+
const signatureHex = Array.from(sig.toDER()).map((b) => b.toString(16).padStart(2, '0')).join('');
|
|
56
|
+
// Save pending verification
|
|
57
|
+
const pending = {
|
|
58
|
+
identityKey,
|
|
59
|
+
handle,
|
|
60
|
+
signature: signatureHex,
|
|
61
|
+
message,
|
|
62
|
+
createdAt: new Date().toISOString(),
|
|
63
|
+
};
|
|
64
|
+
ensureStateDir();
|
|
65
|
+
fs.writeFileSync(PATHS.pendingXVerification, JSON.stringify(pending, null, 2));
|
|
66
|
+
// Build tweet text (under 280 chars)
|
|
67
|
+
// Use shortened signature (first 40 chars) to fit in tweet
|
|
68
|
+
const tweetText = `BSV Agent Verify: ${identityKey.slice(0, 10)}...${identityKey.slice(-10)} sig:${signatureHex.slice(0, 40)}`;
|
|
69
|
+
return ok({
|
|
70
|
+
tweetText,
|
|
71
|
+
handle,
|
|
72
|
+
identityKey,
|
|
73
|
+
signature: signatureHex,
|
|
74
|
+
note: `Post the tweet above from ${handle}, then run: x-verify-complete <tweet_url>`,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Complete X verification by checking the posted tweet.
|
|
79
|
+
*/
|
|
80
|
+
export async function cmdXVerifyComplete(tweetUrl) {
|
|
81
|
+
if (!tweetUrl)
|
|
82
|
+
return fail('Usage: x-verify-complete <tweet-url>');
|
|
83
|
+
// Load pending verification
|
|
84
|
+
if (!fs.existsSync(PATHS.pendingXVerification)) {
|
|
85
|
+
return fail('No pending X verification. Run x-verify-start first.');
|
|
86
|
+
}
|
|
87
|
+
const pending = JSON.parse(fs.readFileSync(PATHS.pendingXVerification, 'utf-8'));
|
|
88
|
+
// Extract tweet ID from URL
|
|
89
|
+
const tweetIdMatch = tweetUrl.match(/status\/(\d+)/);
|
|
90
|
+
if (!tweetIdMatch)
|
|
91
|
+
return fail('Invalid tweet URL. Expected format: https://x.com/user/status/123456789');
|
|
92
|
+
const tweetId = tweetIdMatch[1];
|
|
93
|
+
// Fetch the tweet using bird CLI
|
|
94
|
+
let tweetData;
|
|
95
|
+
try {
|
|
96
|
+
const { execSync } = await import('child_process');
|
|
97
|
+
const birdOutput = execSync(`bird read ${tweetUrl} --json 2>/dev/null`, {
|
|
98
|
+
encoding: 'utf-8',
|
|
99
|
+
timeout: 30000,
|
|
100
|
+
});
|
|
101
|
+
tweetData = JSON.parse(birdOutput);
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
return fail(`Failed to fetch tweet: ${err.message}. Make sure bird CLI is configured.`);
|
|
105
|
+
}
|
|
106
|
+
// Verify the tweet contains our identity key and partial signature
|
|
107
|
+
const tweetText = tweetData.text || tweetData.full_text || '';
|
|
108
|
+
if (!tweetText.includes(pending.identityKey.slice(0, 10))) {
|
|
109
|
+
return fail('Tweet does not contain the expected identity key.');
|
|
110
|
+
}
|
|
111
|
+
// Check for partial signature (first 40 chars)
|
|
112
|
+
if (!tweetText.includes(pending.signature.slice(0, 40))) {
|
|
113
|
+
return fail('Tweet does not contain the expected verification signature prefix.');
|
|
114
|
+
}
|
|
115
|
+
// Get the X user info from the tweet
|
|
116
|
+
const xUserId = tweetData.user?.id_str || tweetData.authorId || tweetData.author?.id || tweetData.user_id;
|
|
117
|
+
const xHandle = tweetData.user?.screen_name || tweetData.author?.username || tweetData.author?.name || pending.handle.replace('@', '');
|
|
118
|
+
if (!xUserId) {
|
|
119
|
+
return fail('Could not extract X user ID from tweet data.');
|
|
120
|
+
}
|
|
121
|
+
// Build on-chain verification record
|
|
122
|
+
const verificationPayload = {
|
|
123
|
+
protocol: PROTOCOL_ID,
|
|
124
|
+
type: 'x-verification',
|
|
125
|
+
identityKey: pending.identityKey,
|
|
126
|
+
xHandle: `@${xHandle}`,
|
|
127
|
+
xUserId,
|
|
128
|
+
tweetId,
|
|
129
|
+
tweetUrl,
|
|
130
|
+
signature: pending.signature,
|
|
131
|
+
verifiedAt: new Date().toISOString(),
|
|
132
|
+
};
|
|
133
|
+
// Submit to overlay (may fail if topic manager not deployed yet)
|
|
134
|
+
let result = { txid: null, funded: 'pending-server-support' };
|
|
135
|
+
let onChainStored = false;
|
|
136
|
+
try {
|
|
137
|
+
result = await buildRealOverlayTransaction(verificationPayload, TOPICS.X_VERIFICATION);
|
|
138
|
+
onChainStored = true;
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
console.error(`[x-verify] On-chain storage failed: ${err.message}`);
|
|
142
|
+
console.error('[x-verify] Storing verification locally.');
|
|
143
|
+
}
|
|
144
|
+
// Save verification locally
|
|
145
|
+
const verifications = loadXVerifications();
|
|
146
|
+
verifications.push({
|
|
147
|
+
...verificationPayload,
|
|
148
|
+
txid: result.txid,
|
|
149
|
+
});
|
|
150
|
+
saveXVerifications(verifications);
|
|
151
|
+
// Clean up pending
|
|
152
|
+
fs.unlinkSync(PATHS.pendingXVerification);
|
|
153
|
+
return ok({
|
|
154
|
+
verified: true,
|
|
155
|
+
identityKey: pending.identityKey,
|
|
156
|
+
xHandle: `@${xHandle}`,
|
|
157
|
+
xUserId,
|
|
158
|
+
tweetId,
|
|
159
|
+
txid: result.txid,
|
|
160
|
+
funded: result.funded,
|
|
161
|
+
onChainStored,
|
|
162
|
+
note: onChainStored ? undefined : 'Stored locally. On-chain anchoring pending server topic manager deployment.',
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* List verified X accounts (local cache).
|
|
167
|
+
*/
|
|
168
|
+
export async function cmdXVerifications() {
|
|
169
|
+
const verifications = loadXVerifications();
|
|
170
|
+
return ok({ verifications, count: verifications.length });
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Lookup X verifications from the overlay network.
|
|
174
|
+
*/
|
|
175
|
+
export async function cmdXLookup(query) {
|
|
176
|
+
try {
|
|
177
|
+
const lookupQuery = query
|
|
178
|
+
? (query.startsWith('@') ? { xHandle: query } : { identityKey: query })
|
|
179
|
+
: { type: 'list' };
|
|
180
|
+
const response = await lookupOverlay(LOOKUP_SERVICES.X_VERIFICATIONS, lookupQuery);
|
|
181
|
+
return ok({ verifications: response.outputs || response || [], query: lookupQuery });
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
return ok({ verifications: [], query, note: 'X verification lookup service may not be deployed yet.' });
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* List pending X engagement requests.
|
|
189
|
+
*/
|
|
190
|
+
export async function cmdXEngagementQueue() {
|
|
191
|
+
if (!fs.existsSync(PATHS.xEngagementQueue)) {
|
|
192
|
+
return ok({ queue: [], count: 0 });
|
|
193
|
+
}
|
|
194
|
+
const queue = readJsonl(PATHS.xEngagementQueue).filter(e => e.status === 'pending');
|
|
195
|
+
return ok({ queue, count: queue.length });
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Mark an X engagement request as fulfilled.
|
|
199
|
+
*/
|
|
200
|
+
export async function cmdXEngagementFulfill(requestId, proofUrl) {
|
|
201
|
+
if (!requestId)
|
|
202
|
+
return fail('Usage: x-engagement-fulfill <requestId> [proofUrl]');
|
|
203
|
+
if (!fs.existsSync(PATHS.xEngagementQueue)) {
|
|
204
|
+
return fail('No engagement queue found.');
|
|
205
|
+
}
|
|
206
|
+
const queue = readJsonl(PATHS.xEngagementQueue);
|
|
207
|
+
const entryIndex = queue.findIndex(e => e.requestId === requestId);
|
|
208
|
+
if (entryIndex === -1) {
|
|
209
|
+
return fail(`Request ${requestId} not found in queue.`);
|
|
210
|
+
}
|
|
211
|
+
// Mark as fulfilled
|
|
212
|
+
queue[entryIndex].status = 'fulfilled';
|
|
213
|
+
queue[entryIndex].fulfilledAt = new Date().toISOString();
|
|
214
|
+
queue[entryIndex].proofUrl = proofUrl || null;
|
|
215
|
+
// Rewrite queue file
|
|
216
|
+
fs.writeFileSync(PATHS.xEngagementQueue, queue.map(e => JSON.stringify(e)).join('\n') + '\n');
|
|
217
|
+
return ok({
|
|
218
|
+
fulfilled: true,
|
|
219
|
+
requestId,
|
|
220
|
+
entry: queue[entryIndex],
|
|
221
|
+
});
|
|
222
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Proxy service definition.
|
|
3
|
+
*/
|
|
4
|
+
import { ServiceCategory } from '../../types.js';
|
|
5
|
+
const apiProxyService = {
|
|
6
|
+
id: 'api-proxy',
|
|
7
|
+
name: 'API Proxy',
|
|
8
|
+
description: 'Proxy HTTP requests to external APIs. Input: {url, method, headers, body}.',
|
|
9
|
+
defaultPrice: 15,
|
|
10
|
+
category: ServiceCategory.UTILITY,
|
|
11
|
+
inputSchema: {
|
|
12
|
+
type: 'object',
|
|
13
|
+
properties: {
|
|
14
|
+
url: { type: 'string', description: 'Target API URL' },
|
|
15
|
+
method: { type: 'string', enum: ['GET', 'POST', 'PUT', 'DELETE'], description: 'HTTP method' },
|
|
16
|
+
headers: { type: 'object', description: 'Request headers' },
|
|
17
|
+
body: { description: 'Request body' },
|
|
18
|
+
timeout: { type: 'number', description: 'Request timeout in ms' }
|
|
19
|
+
},
|
|
20
|
+
required: ['url']
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
export default apiProxyService;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code Development service definition.
|
|
3
|
+
*/
|
|
4
|
+
import { ServiceCategory } from '../../types.js';
|
|
5
|
+
const codeDevelopService = {
|
|
6
|
+
id: 'code-develop',
|
|
7
|
+
name: 'Code Development',
|
|
8
|
+
description: 'Generate code from requirements. Specify language, task description, and constraints.',
|
|
9
|
+
defaultPrice: 100,
|
|
10
|
+
category: ServiceCategory.DEVELOPMENT,
|
|
11
|
+
inputSchema: {
|
|
12
|
+
type: 'object',
|
|
13
|
+
properties: {
|
|
14
|
+
requirements: { type: 'string', description: 'Detailed description of what code to generate' },
|
|
15
|
+
language: { type: 'string', description: 'Programming language (e.g., JavaScript, Python, Java)' },
|
|
16
|
+
constraints: { type: 'string', description: 'Any specific constraints or requirements' },
|
|
17
|
+
style: { type: 'string', description: 'Code style preferences' },
|
|
18
|
+
includeTests: { type: 'boolean', description: 'Whether to include unit tests' }
|
|
19
|
+
},
|
|
20
|
+
required: ['requirements', 'language']
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
export default codeDevelopService;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code Review service definition.
|
|
3
|
+
*
|
|
4
|
+
* Provides thorough code review covering bugs, security issues, style,
|
|
5
|
+
* performance, and improvement suggestions. This is an agent-mode service
|
|
6
|
+
* that leverages the LLM's capabilities.
|
|
7
|
+
*/
|
|
8
|
+
import { ServiceDefinition } from '../../types.js';
|
|
9
|
+
declare const codeReviewService: ServiceDefinition;
|
|
10
|
+
export default codeReviewService;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code Review service definition.
|
|
3
|
+
*
|
|
4
|
+
* Provides thorough code review covering bugs, security issues, style,
|
|
5
|
+
* performance, and improvement suggestions. This is an agent-mode service
|
|
6
|
+
* that leverages the LLM's capabilities.
|
|
7
|
+
*/
|
|
8
|
+
import { ServiceCategory } from '../../types.js';
|
|
9
|
+
const codeReviewService = {
|
|
10
|
+
id: 'code-review',
|
|
11
|
+
name: 'Code Review',
|
|
12
|
+
description: 'Thorough code review covering bugs, security issues, style, performance, and improvement suggestions.',
|
|
13
|
+
defaultPrice: 50,
|
|
14
|
+
category: ServiceCategory.DEVELOPMENT,
|
|
15
|
+
inputSchema: {
|
|
16
|
+
type: 'object',
|
|
17
|
+
properties: {
|
|
18
|
+
code: {
|
|
19
|
+
type: 'string',
|
|
20
|
+
description: 'Code to review'
|
|
21
|
+
},
|
|
22
|
+
language: {
|
|
23
|
+
type: 'string',
|
|
24
|
+
description: 'Programming language (auto-detected if not provided)'
|
|
25
|
+
},
|
|
26
|
+
prUrl: {
|
|
27
|
+
type: 'string',
|
|
28
|
+
description: 'GitHub/GitLab PR URL to review instead of direct code'
|
|
29
|
+
},
|
|
30
|
+
focusAreas: {
|
|
31
|
+
type: 'array',
|
|
32
|
+
items: {
|
|
33
|
+
type: 'string',
|
|
34
|
+
enum: ['security', 'performance', 'style', 'bugs', 'maintainability', 'testing']
|
|
35
|
+
},
|
|
36
|
+
description: 'Specific areas to focus the review on'
|
|
37
|
+
},
|
|
38
|
+
severity: {
|
|
39
|
+
type: 'string',
|
|
40
|
+
enum: ['basic', 'detailed', 'comprehensive'],
|
|
41
|
+
description: 'Depth of review (default: detailed)'
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
anyOf: [
|
|
45
|
+
{ required: ['code'] },
|
|
46
|
+
{ required: ['prUrl'] }
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
// No handler - this service uses agent mode for full LLM capabilities
|
|
50
|
+
};
|
|
51
|
+
export default codeReviewService;
|