openbroker 1.0.40 → 1.0.42
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/SKILL.md +33 -8
- package/openclaw.plugin.json +86 -0
- package/package.json +5 -1
- package/scripts/core/config.ts +3 -3
- package/scripts/plugin/cli.ts +127 -0
- package/scripts/plugin/config-bridge.ts +30 -0
- package/scripts/plugin/index.ts +57 -0
- package/scripts/plugin/tools.ts +715 -0
- package/scripts/plugin/types.ts +158 -0
- package/scripts/plugin/watcher.ts +312 -0
- package/scripts/setup/onboard.ts +0 -12
package/SKILL.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: openbroker
|
|
3
|
-
description: Hyperliquid trading
|
|
3
|
+
description: Hyperliquid trading plugin with background position monitoring. Execute market orders, limit orders, manage positions, view funding rates, and run trading strategies with automatic alerts for PnL changes and liquidation risk.
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: Requires Node.js 22+, network access to api.hyperliquid.xyz
|
|
6
6
|
homepage: https://www.npmjs.com/package/openbroker
|
|
7
|
-
metadata: {"author": "monemetrics", "version": "1.0.
|
|
8
|
-
allowed-tools: Bash(openbroker:*)
|
|
7
|
+
metadata: {"author": "monemetrics", "version": "1.0.42", "openclaw": {"requires": {"bins": ["openbroker"], "env": ["HYPERLIQUID_PRIVATE_KEY"]}, "primaryEnv": "HYPERLIQUID_PRIVATE_KEY", "install": [{"id": "node", "kind": "node", "package": "openbroker", "bins": ["openbroker"], "label": "Install openbroker (npm)"}]}}
|
|
8
|
+
allowed-tools: ob_account ob_positions ob_funding ob_markets ob_search ob_spot ob_buy ob_sell ob_limit ob_trigger ob_tpsl ob_cancel ob_twap ob_bracket ob_chase ob_watcher_status Bash(openbroker:*)
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
# Open Broker - Hyperliquid Trading CLI
|
|
@@ -39,10 +39,33 @@ openbroker setup # One-command setup (wallet + config + builder app
|
|
|
39
39
|
openbroker approve-builder --check # Check builder fee status (for troubleshooting)
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
The `setup` command
|
|
43
|
-
1.
|
|
44
|
-
2.
|
|
45
|
-
3.
|
|
42
|
+
The `setup` command offers three modes:
|
|
43
|
+
1. **Import existing key** — use a private key you already have (master wallet)
|
|
44
|
+
2. **Generate new wallet** — create a fresh master wallet
|
|
45
|
+
3. **Generate API wallet** (recommended for agents) — creates a restricted wallet that can trade but cannot withdraw
|
|
46
|
+
|
|
47
|
+
For options 1 and 2, setup saves config and approves the builder fee automatically.
|
|
48
|
+
For option 3 (API wallet), see the API Wallet Setup section below.
|
|
49
|
+
|
|
50
|
+
### API Wallet Setup (Recommended for Agents)
|
|
51
|
+
|
|
52
|
+
API wallets can place trades on behalf of a master account but **cannot withdraw funds**. This is the safest option for automated agents.
|
|
53
|
+
|
|
54
|
+
**Flow:**
|
|
55
|
+
1. Run `openbroker setup` and choose option 3 ("Generate API wallet")
|
|
56
|
+
2. The CLI generates a keypair and prints an approval URL (e.g. `https://openbroker.dev/approve?agent=0xABC...`)
|
|
57
|
+
3. The agent owner opens the URL in a browser and connects their master wallet (MetaMask etc.)
|
|
58
|
+
4. The master wallet signs two transactions: `ApproveAgent` (authorizes the API wallet) and `ApproveBuilderFee` (approves the 1 bps fee)
|
|
59
|
+
5. The CLI detects the approval automatically and saves the config
|
|
60
|
+
|
|
61
|
+
**After setup, the config will contain:**
|
|
62
|
+
```
|
|
63
|
+
HYPERLIQUID_PRIVATE_KEY=0x... # API wallet private key
|
|
64
|
+
HYPERLIQUID_ACCOUNT_ADDRESS=0x... # Master account address
|
|
65
|
+
HYPERLIQUID_NETWORK=mainnet
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Important for agents:** When using an API wallet, pass the approval URL to the agent owner (the human who controls the master wallet). The owner must approve in a browser before the agent can trade. The CLI waits up to 10 minutes for the approval. If it times out, re-run `openbroker setup`.
|
|
46
69
|
|
|
47
70
|
### Account Info
|
|
48
71
|
```bash
|
|
@@ -294,7 +317,9 @@ Run `openbroker setup` to create the global config interactively.
|
|
|
294
317
|
|----------|----------|-------------|
|
|
295
318
|
| `HYPERLIQUID_PRIVATE_KEY` | Yes | Wallet private key (0x...) |
|
|
296
319
|
| `HYPERLIQUID_NETWORK` | No | `mainnet` (default) or `testnet` |
|
|
297
|
-
| `HYPERLIQUID_ACCOUNT_ADDRESS` | No |
|
|
320
|
+
| `HYPERLIQUID_ACCOUNT_ADDRESS` | No | Master account address (required for API wallets) |
|
|
321
|
+
|
|
322
|
+
The builder fee (1 bps / 0.01%) is hardcoded and not configurable.
|
|
298
323
|
|
|
299
324
|
## Risk Warning
|
|
300
325
|
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "openbroker",
|
|
3
|
+
"name": "OpenBroker — Hyperliquid Trading",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"description": "Trade on Hyperliquid DEX with background position monitoring",
|
|
6
|
+
"configSchema": {
|
|
7
|
+
"type": "object",
|
|
8
|
+
"properties": {
|
|
9
|
+
"privateKey": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"description": "Hyperliquid wallet private key (0x-prefixed). Falls back to HYPERLIQUID_PRIVATE_KEY env var or ~/.openbroker/.env"
|
|
12
|
+
},
|
|
13
|
+
"accountAddress": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"description": "Master account address (for API wallets). Falls back to HYPERLIQUID_ACCOUNT_ADDRESS"
|
|
16
|
+
},
|
|
17
|
+
"network": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"enum": ["mainnet", "testnet"],
|
|
20
|
+
"default": "mainnet",
|
|
21
|
+
"description": "Network to use: mainnet or testnet"
|
|
22
|
+
},
|
|
23
|
+
"hooksToken": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"description": "Bearer token for gateway hooks endpoint (must match hooks.token in gateway config). Falls back to OPENCLAW_HOOKS_TOKEN env var."
|
|
26
|
+
},
|
|
27
|
+
"watcher": {
|
|
28
|
+
"type": "object",
|
|
29
|
+
"properties": {
|
|
30
|
+
"enabled": {
|
|
31
|
+
"type": "boolean",
|
|
32
|
+
"default": true,
|
|
33
|
+
"description": "Enable background position watcher"
|
|
34
|
+
},
|
|
35
|
+
"pollIntervalMs": {
|
|
36
|
+
"type": "number",
|
|
37
|
+
"default": 30000,
|
|
38
|
+
"description": "Poll interval in milliseconds"
|
|
39
|
+
},
|
|
40
|
+
"pnlChangeThresholdPct": {
|
|
41
|
+
"type": "number",
|
|
42
|
+
"default": 5,
|
|
43
|
+
"description": "Notify when unrealized PnL changes by this percentage"
|
|
44
|
+
},
|
|
45
|
+
"marginUsageWarningPct": {
|
|
46
|
+
"type": "number",
|
|
47
|
+
"default": 80,
|
|
48
|
+
"description": "Warn when margin usage exceeds this percentage"
|
|
49
|
+
},
|
|
50
|
+
"notifyOnPositionChange": {
|
|
51
|
+
"type": "boolean",
|
|
52
|
+
"default": true,
|
|
53
|
+
"description": "Send hook when positions open/close/change size"
|
|
54
|
+
},
|
|
55
|
+
"notifyOnFunding": {
|
|
56
|
+
"type": "boolean",
|
|
57
|
+
"default": true,
|
|
58
|
+
"description": "Send hook for funding rate alerts"
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"additionalProperties": false
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"additionalProperties": false
|
|
65
|
+
},
|
|
66
|
+
"uiHints": {
|
|
67
|
+
"privateKey": {
|
|
68
|
+
"label": "Private Key",
|
|
69
|
+
"sensitive": true,
|
|
70
|
+
"placeholder": "0x..."
|
|
71
|
+
},
|
|
72
|
+
"accountAddress": {
|
|
73
|
+
"label": "Account Address",
|
|
74
|
+
"placeholder": "0x..."
|
|
75
|
+
},
|
|
76
|
+
"network": {
|
|
77
|
+
"label": "Network",
|
|
78
|
+
"placeholder": "mainnet"
|
|
79
|
+
},
|
|
80
|
+
"hooksToken": {
|
|
81
|
+
"label": "Hooks Token",
|
|
82
|
+
"sensitive": true,
|
|
83
|
+
"placeholder": "your-hooks-secret"
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
package/package.json
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openbroker",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.42",
|
|
4
4
|
"description": "Hyperliquid trading CLI - execute orders, manage positions, and run trading strategies",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"openbroker": "./bin/openbroker.js"
|
|
8
8
|
},
|
|
9
|
+
"openclaw": {
|
|
10
|
+
"extensions": ["./scripts/plugin/index.ts"]
|
|
11
|
+
},
|
|
9
12
|
"files": [
|
|
10
13
|
"bin/",
|
|
11
14
|
"scripts/",
|
|
12
15
|
"config/example.env",
|
|
16
|
+
"openclaw.plugin.json",
|
|
13
17
|
"README.md",
|
|
14
18
|
"CHANGELOG.md",
|
|
15
19
|
"SKILL.md"
|
package/scripts/core/config.ts
CHANGED
|
@@ -109,9 +109,9 @@ export function loadConfig(): OpenBrokerConfig {
|
|
|
109
109
|
const network = process.env.HYPERLIQUID_NETWORK || 'mainnet';
|
|
110
110
|
const baseUrl = network === 'testnet' ? TESTNET_URL : MAINNET_URL;
|
|
111
111
|
|
|
112
|
-
//
|
|
113
|
-
const builderAddress =
|
|
114
|
-
const builderFee =
|
|
112
|
+
// Builder fee is hardcoded — set by OpenBroker, not configurable by users
|
|
113
|
+
const builderAddress = OPEN_BROKER_BUILDER_ADDRESS.toLowerCase();
|
|
114
|
+
const builderFee = 10; // 10 tenths-of-bps = 1 bps = 0.01%
|
|
115
115
|
const slippageBps = parseInt(process.env.SLIPPAGE_BPS || '50', 10); // default 0.5%
|
|
116
116
|
|
|
117
117
|
// Derive the wallet address from private key
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// CLI commands for the OpenClaw plugin
|
|
2
|
+
// Registered via api.registerCli with Commander.js-style program
|
|
3
|
+
|
|
4
|
+
import type { PluginLogger, OpenClawPluginApi } from './types.js';
|
|
5
|
+
import type { PositionWatcher } from './watcher.js';
|
|
6
|
+
|
|
7
|
+
export function registerCliCommands(
|
|
8
|
+
api: OpenClawPluginApi,
|
|
9
|
+
watcher: PositionWatcher | null,
|
|
10
|
+
logger: PluginLogger,
|
|
11
|
+
): void {
|
|
12
|
+
api.registerCli(({ program }) => {
|
|
13
|
+
const ob = program.command('ob').description('OpenBroker Hyperliquid trading tools');
|
|
14
|
+
|
|
15
|
+
ob
|
|
16
|
+
.command('watch')
|
|
17
|
+
.description('Start the position watcher in foreground (for debugging)')
|
|
18
|
+
.option('--interval <ms>', 'Poll interval in milliseconds', '30000')
|
|
19
|
+
.action(async (opts: unknown) => {
|
|
20
|
+
// If watcher is already running (gateway context), show its status
|
|
21
|
+
if (watcher && watcher.getStatus().running) {
|
|
22
|
+
const status = watcher.getStatus();
|
|
23
|
+
console.log('Position watcher is running as a background service.');
|
|
24
|
+
console.log(`Account: ${status.accountAddress}`);
|
|
25
|
+
console.log(`Tracking ${status.positions.length} position(s)`);
|
|
26
|
+
console.log(`Events detected: ${status.eventsDetected}`);
|
|
27
|
+
console.log(`Last poll: ${status.lastPollAt ?? 'Never'}`);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// CLI context: start watcher in foreground for debugging
|
|
32
|
+
const { PositionWatcher: WatcherClass } = await import('./watcher.js');
|
|
33
|
+
const { interval: intervalStr } = opts as { interval: string };
|
|
34
|
+
const interval = parseInt(intervalStr, 10);
|
|
35
|
+
|
|
36
|
+
const fgWatcher = new WatcherClass({
|
|
37
|
+
logger,
|
|
38
|
+
gatewayPort: api.gatewayPort || 0,
|
|
39
|
+
pollIntervalMs: interval,
|
|
40
|
+
notifyOnPositionChange: api.gatewayPort > 0,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
console.log('Starting position watcher in foreground...');
|
|
44
|
+
console.log(`Poll interval: ${interval / 1000}s`);
|
|
45
|
+
console.log('Press Ctrl+C to stop.\n');
|
|
46
|
+
|
|
47
|
+
process.on('SIGINT', async () => {
|
|
48
|
+
await fgWatcher.stop();
|
|
49
|
+
process.exit(0);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
await fgWatcher.start();
|
|
53
|
+
|
|
54
|
+
// Keep alive
|
|
55
|
+
await new Promise(() => {});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
ob
|
|
59
|
+
.command('status')
|
|
60
|
+
.description('Show position watcher status and current positions')
|
|
61
|
+
.action(async () => {
|
|
62
|
+
// If watcher is running in gateway context, show its live state
|
|
63
|
+
if (watcher && watcher.getStatus().running) {
|
|
64
|
+
const status = watcher.getStatus();
|
|
65
|
+
|
|
66
|
+
console.log('OpenBroker Position Watcher Status');
|
|
67
|
+
console.log('==================================\n');
|
|
68
|
+
console.log(`Running: Yes (background service)`);
|
|
69
|
+
console.log(`Account: ${status.accountAddress}`);
|
|
70
|
+
console.log(`Poll interval: ${status.pollIntervalMs / 1000}s`);
|
|
71
|
+
console.log(`Events detected: ${status.eventsDetected}`);
|
|
72
|
+
console.log(`Last poll: ${status.lastPollAt ?? 'Never'}`);
|
|
73
|
+
console.log(`Equity: $${status.equity ?? '?'}`);
|
|
74
|
+
console.log(`Margin used: ${status.marginUsedPct?.toFixed(1) ?? '?'}%`);
|
|
75
|
+
|
|
76
|
+
if (status.positions.length === 0) {
|
|
77
|
+
console.log('\nNo open positions.');
|
|
78
|
+
} else {
|
|
79
|
+
console.log(`\nOpen Positions (${status.positions.length}):`);
|
|
80
|
+
for (const p of status.positions) {
|
|
81
|
+
const side = parseFloat(p.size) > 0 ? 'LONG' : 'SHORT';
|
|
82
|
+
console.log(` ${p.coin} ${side}`);
|
|
83
|
+
console.log(` Size: ${p.size}`);
|
|
84
|
+
console.log(` Entry: $${p.entryPrice}`);
|
|
85
|
+
console.log(` Unreal PnL: $${p.unrealizedPnl}`);
|
|
86
|
+
console.log(` Liq Price: ${p.liquidationPrice ? `$${p.liquidationPrice}` : 'N/A'}`);
|
|
87
|
+
console.log('');
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// CLI context: one-shot account query
|
|
94
|
+
console.log('OpenBroker Status (live query)\n');
|
|
95
|
+
try {
|
|
96
|
+
const { getClient } = await import('../core/client.js');
|
|
97
|
+
const { formatUsd } = await import('../core/utils.js');
|
|
98
|
+
const client = getClient();
|
|
99
|
+
const state = await client.getUserState();
|
|
100
|
+
|
|
101
|
+
console.log(`Account: ${client.address}`);
|
|
102
|
+
console.log(`Equity: ${formatUsd(parseFloat(state.marginSummary.accountValue))}`);
|
|
103
|
+
console.log(`Margin: ${formatUsd(parseFloat(state.marginSummary.totalMarginUsed))}`);
|
|
104
|
+
|
|
105
|
+
const positions = state.assetPositions.filter(ap => parseFloat(ap.position.szi) !== 0);
|
|
106
|
+
if (positions.length === 0) {
|
|
107
|
+
console.log('\nNo open positions.');
|
|
108
|
+
} else {
|
|
109
|
+
console.log(`\nOpen Positions (${positions.length}):`);
|
|
110
|
+
for (const ap of positions) {
|
|
111
|
+
const p = ap.position;
|
|
112
|
+
const side = parseFloat(p.szi) > 0 ? 'LONG' : 'SHORT';
|
|
113
|
+
console.log(` ${p.coin} ${side} ${p.szi} @ $${p.entryPx} | PnL: $${p.unrealizedPnl} | Liq: ${p.liquidationPx ?? 'N/A'}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
} catch (err) {
|
|
117
|
+
console.error(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
118
|
+
console.log('\nRun "openbroker setup" to configure your wallet.');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (watcher && !watcher.getStatus().running) {
|
|
122
|
+
console.log('\nNote: The background watcher is registered but not running.');
|
|
123
|
+
console.log('It starts automatically with the gateway. Use "openclaw ob watch" for foreground mode.');
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}, { commands: ['ob'] });
|
|
127
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Maps OpenClaw plugin config → process.env vars
|
|
2
|
+
// Only sets vars that are not already defined (env vars take priority)
|
|
3
|
+
|
|
4
|
+
import type { OpenBrokerPluginConfig } from './types.js';
|
|
5
|
+
|
|
6
|
+
const CONFIG_MAP: Record<string, string> = {
|
|
7
|
+
privateKey: 'HYPERLIQUID_PRIVATE_KEY',
|
|
8
|
+
accountAddress: 'HYPERLIQUID_ACCOUNT_ADDRESS',
|
|
9
|
+
network: 'HYPERLIQUID_NETWORK',
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Inject plugin config values into process.env if not already set.
|
|
14
|
+
*
|
|
15
|
+
* Priority chain:
|
|
16
|
+
* 1. Real env vars (highest — already in process.env)
|
|
17
|
+
* 2. Plugin config (injected here)
|
|
18
|
+
* 3. ~/.openbroker/.env (loaded by core/config.ts)
|
|
19
|
+
* 4. Hardcoded defaults in core/config.ts
|
|
20
|
+
*/
|
|
21
|
+
export function applyConfigBridge(pluginConfig: Record<string, unknown>): void {
|
|
22
|
+
const config = pluginConfig as OpenBrokerPluginConfig;
|
|
23
|
+
|
|
24
|
+
for (const [key, envVar] of Object.entries(CONFIG_MAP)) {
|
|
25
|
+
const value = config[key as keyof OpenBrokerPluginConfig];
|
|
26
|
+
if (value !== undefined && value !== null && typeof value !== 'object' && !process.env[envVar]) {
|
|
27
|
+
process.env[envVar] = String(value);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// OpenClaw Plugin Entry Point for OpenBroker
|
|
2
|
+
|
|
3
|
+
import type { OpenClawPluginApi, OpenBrokerPluginConfig } from './types.js';
|
|
4
|
+
import { applyConfigBridge } from './config-bridge.js';
|
|
5
|
+
import { PositionWatcher } from './watcher.js';
|
|
6
|
+
import { createTools } from './tools.js';
|
|
7
|
+
import { registerCliCommands } from './cli.js';
|
|
8
|
+
|
|
9
|
+
export default {
|
|
10
|
+
id: 'openbroker',
|
|
11
|
+
name: 'OpenBroker — Hyperliquid Trading',
|
|
12
|
+
|
|
13
|
+
register(api: OpenClawPluginApi): void {
|
|
14
|
+
const { logger, gatewayPort } = api;
|
|
15
|
+
const pluginConfig = (api.pluginConfig ?? {}) as OpenBrokerPluginConfig;
|
|
16
|
+
|
|
17
|
+
// 1. Apply config bridge: inject plugin config → process.env
|
|
18
|
+
applyConfigBridge(pluginConfig as Record<string, unknown>);
|
|
19
|
+
logger.debug('OpenBroker config bridge applied');
|
|
20
|
+
|
|
21
|
+
// 2. Register background position watcher (unless disabled)
|
|
22
|
+
let watcher: PositionWatcher | null = null;
|
|
23
|
+
const watcherEnabled = pluginConfig.watcher?.enabled !== false;
|
|
24
|
+
|
|
25
|
+
if (watcherEnabled) {
|
|
26
|
+
watcher = new PositionWatcher({
|
|
27
|
+
logger,
|
|
28
|
+
gatewayPort,
|
|
29
|
+
hooksToken: pluginConfig.hooksToken,
|
|
30
|
+
accountAddress: pluginConfig.accountAddress
|
|
31
|
+
|| process.env.HYPERLIQUID_ACCOUNT_ADDRESS
|
|
32
|
+
|| undefined,
|
|
33
|
+
network: pluginConfig.network || process.env.HYPERLIQUID_NETWORK,
|
|
34
|
+
pollIntervalMs: pluginConfig.watcher?.pollIntervalMs,
|
|
35
|
+
pnlChangeThresholdPct: pluginConfig.watcher?.pnlChangeThresholdPct,
|
|
36
|
+
marginUsageWarningPct: pluginConfig.watcher?.marginUsageWarningPct,
|
|
37
|
+
notifyOnPositionChange: pluginConfig.watcher?.notifyOnPositionChange,
|
|
38
|
+
notifyOnFunding: pluginConfig.watcher?.notifyOnFunding,
|
|
39
|
+
});
|
|
40
|
+
api.registerService(watcher);
|
|
41
|
+
logger.debug('OpenBroker position watcher registered');
|
|
42
|
+
} else {
|
|
43
|
+
logger.debug('OpenBroker position watcher disabled by config');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// 3. Register agent tools
|
|
47
|
+
const tools = createTools(watcher);
|
|
48
|
+
for (const tool of tools) {
|
|
49
|
+
api.registerTool(tool);
|
|
50
|
+
}
|
|
51
|
+
logger.debug(`Registered ${tools.length} OpenBroker agent tools`);
|
|
52
|
+
|
|
53
|
+
// 4. Register CLI commands
|
|
54
|
+
registerCliCommands(api, watcher, logger);
|
|
55
|
+
logger.debug('OpenBroker CLI commands registered');
|
|
56
|
+
},
|
|
57
|
+
};
|