dexbot 1.4.19 → 1.4.21
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/CHANGELOG.md +36 -0
- package/README.md +22 -12
- package/analysis/ama_fitting/analyze_lambda_vs_slow.ts +2 -2
- package/analysis/ama_fitting/calibrate_convergence_er.ts +1 -1
- package/analysis/ama_fitting/optimizer_high_resolution.ts +2 -1
- package/analysis/ama_fitting/package.json +1 -1
- package/analysis/analyze_derivatives.ts +4 -2
- package/analysis/analyze_dynamic_weight.ts +3 -1
- package/analysis/analyze_kalman.ts +3 -1
- package/analysis/analyze_regime.ts +3 -1
- package/analysis/analyze_regime_windows.ts +3 -1
- package/analysis/analyze_volatility.ts +2 -2
- package/analysis/bot_fitting/backtest_ama_sweep.ts +2 -1
- package/analysis/bot_fitting/backtest_bot_fitting.ts +17 -12
- package/analysis/bot_fitting/shared_utils.ts +1 -1
- package/analysis/bot_key_utils.ts +1 -5
- package/analysis/bot_usage/kibana_bot_queries.ts +1 -256
- package/analysis/chart_css.ts +1 -1
- package/analysis/chart_utils.ts +24 -0
- package/analysis/derivative_chart_generator.ts +3 -2
- package/analysis/math_utils.ts +1 -8
- package/analysis/trend_detection/DYNAMIC_WEIGHT_RESEARCH.md +1 -1
- package/analysis/trend_detection/dynamic_weight_chart_generator.ts +91 -55
- package/analysis/trend_detection/package.json +1 -1
- package/claw/ecosystem.config.cjs +2 -3
- package/claw/examples/claw_profiles_example.ts +4 -1
- package/claw/examples/memu_integration_example.ts +17 -17
- package/claw/modules/chain_actions.ts +51 -54
- package/claw/modules/chain_broadcast.ts +66 -104
- package/claw/modules/claw_bridge.ts +60 -80
- package/claw/modules/claw_catalog.ts +48 -17
- package/claw/modules/claw_infra.ts +1 -5
- package/claw/modules/claw_launcher.ts +47 -49
- package/claw/modules/claw_skill_md.ts +14 -16
- package/claw/modules/credit_runtime_adapter.ts +2 -18
- package/claw/modules/decision_loop.ts +4 -0
- package/claw/modules/dexbot_bridge.ts +1 -1
- package/claw/modules/dexbot_profiles.ts +8 -22
- package/claw/modules/honest_ecosystem.ts +24 -8
- package/claw/modules/launcher_paths.ts +4 -2
- package/claw/modules/liquidity_pools.ts +10 -3
- package/claw/modules/mcp_utils.ts +109 -0
- package/claw/modules/memu_bridge.ts +76 -54
- package/claw/modules/mpa_utils.ts +26 -3
- package/claw/modules/position_discovery.ts +16 -27
- package/claw/modules/position_manager.ts +32 -41
- package/claw/modules/position_manager_watch.ts +3 -2
- package/claw/modules/short_mpa_strategy.ts +1 -9
- package/claw/modules/skill_utils.ts +5 -3
- package/claw/modules/utils.ts +9 -1
- package/claw/package.json +1 -1
- package/claw/runtimes/openclaw-plugin/index.ts +27 -10
- package/claw/runtimes/openclaw-plugin/openclaw.plugin.json +1 -1
- package/claw/runtimes/openclaw-plugin/package.json +1 -1
- package/claw/scripts/claw_bridge.ts +1 -1
- package/claw/scripts/claw_mcp_server.ts +19 -78
- package/claw/scripts/honest_assets_report.ts +19 -84
- package/claw/scripts/memu_mcp_server.ts +57 -155
- package/claw/tests/test_claw_bridge.ts +6 -2
- package/claw/tests/test_claw_mcp_transport.ts +2 -2
- package/dist/analysis/ama_fitting/analyze_lambda_vs_slow.js +2 -2
- package/dist/analysis/ama_fitting/analyze_lambda_vs_slow.js.map +1 -1
- package/dist/analysis/ama_fitting/calibrate_convergence_er.js +1 -1
- package/dist/analysis/ama_fitting/calibrate_convergence_er.js.map +1 -1
- package/dist/analysis/ama_fitting/optimizer_high_resolution.d.ts.map +1 -1
- package/dist/analysis/ama_fitting/optimizer_high_resolution.js +2 -1
- package/dist/analysis/ama_fitting/optimizer_high_resolution.js.map +1 -1
- package/dist/analysis/analyze_derivatives.d.ts.map +1 -1
- package/dist/analysis/analyze_derivatives.js +4 -2
- package/dist/analysis/analyze_derivatives.js.map +1 -1
- package/dist/analysis/analyze_dynamic_weight.js +3 -1
- package/dist/analysis/analyze_dynamic_weight.js.map +1 -1
- package/dist/analysis/analyze_kalman.js +3 -1
- package/dist/analysis/analyze_kalman.js.map +1 -1
- package/dist/analysis/analyze_regime.js +3 -1
- package/dist/analysis/analyze_regime.js.map +1 -1
- package/dist/analysis/analyze_regime_windows.js +3 -1
- package/dist/analysis/analyze_regime_windows.js.map +1 -1
- package/dist/analysis/analyze_volatility.js +2 -2
- package/dist/analysis/analyze_volatility.js.map +1 -1
- package/dist/analysis/bot_fitting/backtest_ama_sweep.d.ts.map +1 -1
- package/dist/analysis/bot_fitting/backtest_ama_sweep.js +2 -1
- package/dist/analysis/bot_fitting/backtest_ama_sweep.js.map +1 -1
- package/dist/analysis/bot_fitting/backtest_bot_fitting.js +18 -13
- package/dist/analysis/bot_fitting/backtest_bot_fitting.js.map +1 -1
- package/dist/analysis/bot_fitting/shared_utils.d.ts +1 -12
- package/dist/analysis/bot_fitting/shared_utils.d.ts.map +1 -1
- package/dist/analysis/bot_fitting/shared_utils.js +1 -1
- package/dist/analysis/bot_fitting/shared_utils.js.map +1 -1
- package/dist/analysis/bot_key_utils.d.ts +1 -1
- package/dist/analysis/bot_key_utils.d.ts.map +1 -1
- package/dist/analysis/bot_key_utils.js +1 -5
- package/dist/analysis/bot_key_utils.js.map +1 -1
- package/dist/analysis/bot_usage/kibana_bot_queries.d.ts +1 -337
- package/dist/analysis/bot_usage/kibana_bot_queries.d.ts.map +1 -1
- package/dist/analysis/bot_usage/kibana_bot_queries.js +1 -241
- package/dist/analysis/bot_usage/kibana_bot_queries.js.map +1 -1
- package/dist/analysis/chart_css.d.ts +1 -15
- package/dist/analysis/chart_css.d.ts.map +1 -1
- package/dist/analysis/chart_css.js +1 -1
- package/dist/analysis/chart_css.js.map +1 -1
- package/dist/analysis/chart_utils.d.ts +0 -3
- package/dist/analysis/chart_utils.d.ts.map +1 -1
- package/dist/analysis/chart_utils.js +25 -0
- package/dist/analysis/chart_utils.js.map +1 -1
- package/dist/analysis/derivative_chart_generator.d.ts.map +1 -1
- package/dist/analysis/derivative_chart_generator.js +3 -2
- package/dist/analysis/derivative_chart_generator.js.map +1 -1
- package/dist/analysis/math_utils.d.ts +3 -5
- package/dist/analysis/math_utils.d.ts.map +1 -1
- package/dist/analysis/math_utils.js +3 -5
- package/dist/analysis/math_utils.js.map +1 -1
- package/dist/analysis/trend_detection/dynamic_weight_chart_generator.d.ts.map +1 -1
- package/dist/analysis/trend_detection/dynamic_weight_chart_generator.js +82 -50
- package/dist/analysis/trend_detection/dynamic_weight_chart_generator.js.map +1 -1
- package/dist/bot.js +2 -2
- package/dist/bot.js.map +1 -1
- package/dist/credential-daemon.js +1 -1
- package/dist/credential-daemon.js.map +1 -1
- package/dist/dexbot.d.ts.map +1 -1
- package/dist/dexbot.js +20 -17
- package/dist/dexbot.js.map +1 -1
- package/dist/market_adapter/ama_signal_runner.js +3 -3
- package/dist/market_adapter/core/kibana_client.d.ts +1 -3
- package/dist/market_adapter/core/kibana_client.d.ts.map +1 -1
- package/dist/market_adapter/core/kibana_client.js +1 -1
- package/dist/market_adapter/core/kibana_client.js.map +1 -1
- package/dist/market_adapter/core/market_adapter_service.d.ts +1 -2
- package/dist/market_adapter/core/market_adapter_service.d.ts.map +1 -1
- package/dist/market_adapter/core/market_adapter_service.js +9 -4
- package/dist/market_adapter/core/market_adapter_service.js.map +1 -1
- package/dist/market_adapter/core/strategies/regime_gate.d.ts +1 -2
- package/dist/market_adapter/core/strategies/regime_gate.d.ts.map +1 -1
- package/dist/market_adapter/core/strategies/regime_gate.js +1 -1
- package/dist/market_adapter/core/strategies/regime_gate.js.map +1 -1
- package/dist/market_adapter/inputs/fetch_cex_synthetic_data.js +2 -2
- package/dist/market_adapter/inputs/fetch_cex_synthetic_data.js.map +1 -1
- package/dist/market_adapter/inputs/fetch_lp_data.d.ts +5 -5
- package/dist/market_adapter/inputs/fetch_lp_data.js +5 -5
- package/dist/market_adapter/inputs/kibana_source.d.ts +1 -2
- package/dist/market_adapter/inputs/kibana_source.d.ts.map +1 -1
- package/dist/market_adapter/inputs/kibana_source.js +1 -1
- package/dist/market_adapter/inputs/kibana_source.js.map +1 -1
- package/dist/market_adapter/lp_chart_strategy_loader.d.ts +1 -2
- package/dist/market_adapter/lp_chart_strategy_loader.d.ts.map +1 -1
- package/dist/market_adapter/lp_chart_strategy_loader.js +4 -4
- package/dist/market_adapter/lp_chart_strategy_loader.js.map +1 -1
- package/dist/market_adapter/market_adapter.d.ts.map +1 -1
- package/dist/market_adapter/market_adapter.js +2 -1
- package/dist/market_adapter/market_adapter.js.map +1 -1
- package/dist/modules/account_bots.d.ts +3 -0
- package/dist/modules/account_bots.d.ts.map +1 -1
- package/dist/modules/account_bots.js +156 -46
- package/dist/modules/account_bots.js.map +1 -1
- package/dist/modules/account_orders.d.ts +1 -7
- package/dist/modules/account_orders.d.ts.map +1 -1
- package/dist/modules/account_orders.js +9 -17
- package/dist/modules/account_orders.js.map +1 -1
- package/dist/modules/bitshares_client.d.ts +2 -14
- package/dist/modules/bitshares_client.d.ts.map +1 -1
- package/dist/modules/bitshares_client.js +22 -31
- package/dist/modules/bitshares_client.js.map +1 -1
- package/dist/modules/bot_settings.js +1 -1
- package/dist/modules/bot_settings.js.map +1 -1
- package/dist/modules/chain_keys.js +2 -2
- package/dist/modules/chain_keys.js.map +1 -1
- package/dist/modules/chain_orders.d.ts +2 -3
- package/dist/modules/chain_orders.d.ts.map +1 -1
- package/dist/modules/chain_orders.js +8 -25
- package/dist/modules/chain_orders.js.map +1 -1
- package/dist/modules/config.d.ts +2 -0
- package/dist/modules/config.d.ts.map +1 -1
- package/dist/modules/config.js +6 -1
- package/dist/modules/config.js.map +1 -1
- package/dist/modules/constants.d.ts +0 -1
- package/dist/modules/constants.d.ts.map +1 -1
- package/dist/modules/constants.js +1 -5
- package/dist/modules/constants.js.map +1 -1
- package/dist/modules/credential_policy.js +1 -1
- package/dist/modules/credential_policy.js.map +1 -1
- package/dist/modules/dexbot_class.d.ts.map +1 -1
- package/dist/modules/dexbot_class.js +3 -2
- package/dist/modules/dexbot_class.js.map +1 -1
- package/dist/modules/dexbot_cow_runtime.d.ts +0 -7
- package/dist/modules/dexbot_cow_runtime.d.ts.map +1 -1
- package/dist/modules/dexbot_cow_runtime.js +95 -0
- package/dist/modules/dexbot_cow_runtime.js.map +1 -1
- package/dist/modules/dexbot_state_recovery.d.ts.map +1 -1
- package/dist/modules/dexbot_state_recovery.js +22 -2
- package/dist/modules/dexbot_state_recovery.js.map +1 -1
- package/dist/modules/fund_registry.d.ts.map +1 -1
- package/dist/modules/fund_registry.js +5 -2
- package/dist/modules/fund_registry.js.map +1 -1
- package/dist/modules/launcher/bot_supervisor.d.ts.map +1 -1
- package/dist/modules/launcher/bot_supervisor.js +6 -7
- package/dist/modules/launcher/bot_supervisor.js.map +1 -1
- package/dist/modules/launcher/foreign_cred_daemon.d.ts.map +1 -1
- package/dist/modules/launcher/foreign_cred_daemon.js +6 -0
- package/dist/modules/launcher/foreign_cred_daemon.js.map +1 -1
- package/dist/modules/launcher/market_adapter_runtime.d.ts +2 -3
- package/dist/modules/launcher/market_adapter_runtime.d.ts.map +1 -1
- package/dist/modules/launcher/market_adapter_runtime.js +7 -15
- package/dist/modules/launcher/market_adapter_runtime.js.map +1 -1
- package/dist/modules/launcher/monolithic_runtime.d.ts.map +1 -1
- package/dist/modules/launcher/monolithic_runtime.js +1 -0
- package/dist/modules/launcher/monolithic_runtime.js.map +1 -1
- package/dist/modules/launcher/status_reporting.d.ts +1 -2
- package/dist/modules/launcher/status_reporting.d.ts.map +1 -1
- package/dist/modules/launcher/status_reporting.js +1 -4
- package/dist/modules/launcher/status_reporting.js.map +1 -1
- package/dist/modules/order/accounting.js +2 -2
- package/dist/modules/order/accounting.js.map +1 -1
- package/dist/modules/order/format.d.ts +0 -8
- package/dist/modules/order/format.d.ts.map +1 -1
- package/dist/modules/order/format.js +0 -8
- package/dist/modules/order/format.js.map +1 -1
- package/dist/modules/order/grid.d.ts.map +1 -1
- package/dist/modules/order/grid.js +146 -32
- package/dist/modules/order/grid.js.map +1 -1
- package/dist/modules/order/logger.js +1 -1
- package/dist/modules/order/logger.js.map +1 -1
- package/dist/modules/order/logger_state.d.ts +1 -13
- package/dist/modules/order/logger_state.d.ts.map +1 -1
- package/dist/modules/order/logger_state.js +1 -11
- package/dist/modules/order/logger_state.js.map +1 -1
- package/dist/modules/order/manager.d.ts +13 -0
- package/dist/modules/order/manager.d.ts.map +1 -1
- package/dist/modules/order/manager.js +75 -2
- package/dist/modules/order/manager.js.map +1 -1
- package/dist/modules/order/processed_fill_store.d.ts +0 -5
- package/dist/modules/order/processed_fill_store.d.ts.map +1 -1
- package/dist/modules/order/processed_fill_store.js +1 -12
- package/dist/modules/order/processed_fill_store.js.map +1 -1
- package/dist/modules/order/sync_engine.d.ts.map +1 -1
- package/dist/modules/order/sync_engine.js +10 -3
- package/dist/modules/order/sync_engine.js.map +1 -1
- package/dist/modules/order/utils/math.d.ts +80 -1
- package/dist/modules/order/utils/math.d.ts.map +1 -1
- package/dist/modules/order/utils/math.js +138 -2
- package/dist/modules/order/utils/math.js.map +1 -1
- package/dist/modules/order/utils/order.d.ts.map +1 -1
- package/dist/modules/order/utils/order.js +10 -2
- package/dist/modules/order/utils/order.js.map +1 -1
- package/dist/modules/paths.d.ts +26 -1
- package/dist/modules/paths.d.ts.map +1 -1
- package/dist/modules/paths.js +39 -6
- package/dist/modules/paths.js.map +1 -1
- package/dist/modules/runtime_settings.js +3 -1
- package/dist/modules/runtime_settings.js.map +1 -1
- package/dist/modules/settings_merge.d.ts.map +1 -1
- package/dist/modules/settings_merge.js +3 -1
- package/dist/modules/settings_merge.js.map +1 -1
- package/dist/modules/storage/browser_adapter.d.ts +8 -3
- package/dist/modules/storage/browser_adapter.d.ts.map +1 -1
- package/dist/modules/storage/browser_adapter.js +53 -4
- package/dist/modules/storage/browser_adapter.js.map +1 -1
- package/dist/modules/utils/sanitize_key.d.ts +7 -0
- package/dist/modules/utils/sanitize_key.d.ts.map +1 -0
- package/dist/modules/utils/sanitize_key.js +15 -0
- package/dist/modules/utils/sanitize_key.js.map +1 -0
- package/dist/pm2.js +6 -6
- package/dist/pm2.js.map +1 -1
- package/dist/scripts/analyze-git.js +2 -1
- package/dist/scripts/analyze-git.js.map +1 -1
- package/dist/scripts/analyze-orders.d.ts +2 -2
- package/dist/scripts/analyze-orders.d.ts.map +1 -1
- package/dist/scripts/analyze-orders.js +6 -14
- package/dist/scripts/analyze-orders.js.map +1 -1
- package/dist/scripts/runner.js +1 -1
- package/dist/scripts/runner.js.map +1 -1
- package/dist/scripts/update.js +1 -1
- package/dist/scripts/update.js.map +1 -1
- package/docs/BITSHARES_ONBOARDING.md +63 -18
- package/docs/COPY_ON_WRITE_MASTER_PLAN.md +5 -14
- package/docs/COW_INVARIANTS.md +4 -4
- package/docs/CREDENTIAL_SECURITY.md +0 -11
- package/docs/DEXBOT_COMPARISON.md +11 -11
- package/docs/EVOLUTION.md +12 -10
- package/docs/FUND_MOVEMENT_AND_ACCOUNTING.md +27 -83
- package/docs/GRID_RECALCULATION.md +1 -13
- package/docs/GRID_RECONCILE.md +24 -24
- package/docs/LIFECYCLE.md +4 -4
- package/docs/LOGGING.md +1 -1
- package/docs/MPA_CREDIT_USAGE.md +3 -3
- package/docs/README.md +2 -2
- package/docs/WORKFLOW.md +2 -2
- package/docs/architecture.md +43 -38
- package/docs/developer_guide.md +16 -18
- package/market_adapter/README.md +0 -2
- package/modules/README.md +2 -1
- package/package.json +2 -3
- package/scripts/README.md +1 -1
- package/scripts/lib/dexbot-paths.sh +20 -11
- package/claw/openclaw.plugin.json +0 -13
- package/dist/market_adapter/merge_lp_data.d.ts +0 -3
- package/dist/market_adapter/merge_lp_data.d.ts.map +0 -1
- package/dist/market_adapter/merge_lp_data.js +0 -125
- package/dist/market_adapter/merge_lp_data.js.map +0 -1
- package/dist/market_adapter/utils/paths.d.ts +0 -3
- package/dist/market_adapter/utils/paths.d.ts.map +0 -1
- package/dist/market_adapter/utils/paths.js +0 -5
- package/dist/market_adapter/utils/paths.js.map +0 -1
|
@@ -41,17 +41,7 @@ const DEXBOT_VERSION = (() => {
|
|
|
41
41
|
})();
|
|
42
42
|
|
|
43
43
|
function resolveMemuScript() {
|
|
44
|
-
|
|
45
|
-
PATHS.CLAW.MEMU_RUNNER_SCRIPT,
|
|
46
|
-
];
|
|
47
|
-
|
|
48
|
-
for (const candidate of candidates) {
|
|
49
|
-
if (storage.exists(candidate)) {
|
|
50
|
-
return candidate;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return candidates[0];
|
|
44
|
+
return PATHS.CLAW.MEMU_RUNNER_SCRIPT;
|
|
55
45
|
}
|
|
56
46
|
|
|
57
47
|
function ensureMemuDir(dir: any) {
|
|
@@ -132,6 +122,11 @@ function runMemuPython(args: string[], options: Record<string, any> = {}) {
|
|
|
132
122
|
});
|
|
133
123
|
|
|
134
124
|
if (options.stdin) {
|
|
125
|
+
// The child may exit before it drains stdin (bad args, crash); without
|
|
126
|
+
// an 'error' listener the resulting EPIPE crashes the host process.
|
|
127
|
+
child.stdin.on('error', () => {
|
|
128
|
+
// Best-effort write; the close handler reports the real exit status.
|
|
129
|
+
});
|
|
135
130
|
child.stdin.write(JSON.stringify(options.stdin));
|
|
136
131
|
child.stdin.end();
|
|
137
132
|
}
|
|
@@ -431,26 +426,78 @@ function describeMemuBridge(options: Record<string, any> = {}) {
|
|
|
431
426
|
};
|
|
432
427
|
}
|
|
433
428
|
|
|
429
|
+
/**
|
|
430
|
+
* Required-argument spec shared by runMemuCommand, the memU MCP server, and
|
|
431
|
+
* the claw bridge's memu-* commands, so every surface rejects bad input with
|
|
432
|
+
* the same message instead of maintaining three copies of the checks.
|
|
433
|
+
*/
|
|
434
|
+
const MEMU_REQUIRED_ARGS: Record<string, { groups: string[][]; message: string }> = {
|
|
435
|
+
'memorize': {
|
|
436
|
+
groups: [['resourceUrl'], ['modality']],
|
|
437
|
+
message: 'memorize requires resourceUrl and modality'
|
|
438
|
+
},
|
|
439
|
+
'retrieve': {
|
|
440
|
+
groups: [['queries']],
|
|
441
|
+
message: 'retrieve requires queries'
|
|
442
|
+
},
|
|
443
|
+
'create-item': {
|
|
444
|
+
groups: [['categoryId', 'categoryName', 'category'], ['summary']],
|
|
445
|
+
message: 'create-item requires categoryId or categoryName, plus summary'
|
|
446
|
+
},
|
|
447
|
+
'update-item': {
|
|
448
|
+
groups: [['itemId'], ['updates']],
|
|
449
|
+
message: 'update-item requires itemId and updates'
|
|
450
|
+
},
|
|
451
|
+
'delete-item': {
|
|
452
|
+
groups: [['itemId']],
|
|
453
|
+
message: 'delete-item requires itemId'
|
|
454
|
+
},
|
|
455
|
+
'memorize-conversation': {
|
|
456
|
+
groups: [['messages']],
|
|
457
|
+
message: 'memorize-conversation requires messages array'
|
|
458
|
+
},
|
|
459
|
+
'memorize-trading-context': {
|
|
460
|
+
groups: [['context']],
|
|
461
|
+
message: 'memorize-trading-context requires context'
|
|
462
|
+
},
|
|
463
|
+
'retrieve-trading-context': {
|
|
464
|
+
groups: [['query']],
|
|
465
|
+
message: 'retrieve-trading-context requires query'
|
|
466
|
+
}
|
|
467
|
+
};
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* Throw when a memU command is missing required arguments.
|
|
471
|
+
* Each group lists acceptable alternative field names; every group must be
|
|
472
|
+
* satisfied by at least one present (truthy) field.
|
|
473
|
+
*/
|
|
474
|
+
function validateMemuCommandArgs(command: string, options: Record<string, any>) {
|
|
475
|
+
const spec = MEMU_REQUIRED_ARGS[command];
|
|
476
|
+
if (!spec) {
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
const satisfied = spec.groups.every(
|
|
481
|
+
(group) => group.some((field) => options[field])
|
|
482
|
+
);
|
|
483
|
+
if (!satisfied) {
|
|
484
|
+
throw new Error(spec.message);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
434
488
|
async function runMemuCommand(command: string, options: Record<string, any> = {}) {
|
|
489
|
+
validateMemuCommandArgs(command, options);
|
|
435
490
|
const bridge = createMemuBridge(options);
|
|
436
491
|
|
|
437
492
|
switch (command) {
|
|
438
493
|
case 'manifest':
|
|
439
494
|
return describeMemuBridge(options);
|
|
440
495
|
|
|
441
|
-
case 'memorize':
|
|
442
|
-
if (!options.resourceUrl || !options.modality) {
|
|
443
|
-
throw new Error('memorize requires resourceUrl and modality');
|
|
444
|
-
}
|
|
496
|
+
case 'memorize':
|
|
445
497
|
return bridge.memorize(options.resourceUrl, options.modality, options.user);
|
|
446
|
-
}
|
|
447
498
|
|
|
448
|
-
case 'retrieve':
|
|
449
|
-
if (!options.queries) {
|
|
450
|
-
throw new Error('retrieve requires queries');
|
|
451
|
-
}
|
|
499
|
+
case 'retrieve':
|
|
452
500
|
return bridge.retrieve(options.queries, options.where, options.method || 'rag');
|
|
453
|
-
}
|
|
454
501
|
|
|
455
502
|
case 'list-categories':
|
|
456
503
|
return bridge.listCategories(normalizeScopeWhere(options.where, options.user));
|
|
@@ -458,32 +505,19 @@ async function runMemuCommand(command: string, options: Record<string, any> = {}
|
|
|
458
505
|
case 'list-items':
|
|
459
506
|
return bridge.listItems(normalizeScopeWhere(options.where, options.user));
|
|
460
507
|
|
|
461
|
-
case 'create-item':
|
|
462
|
-
const categoryRef = options.categoryId || options.categoryName || options.category;
|
|
463
|
-
if (!categoryRef || !options.summary) {
|
|
464
|
-
throw new Error('create-item requires categoryId or categoryName, plus summary');
|
|
465
|
-
}
|
|
508
|
+
case 'create-item':
|
|
466
509
|
return bridge.createMemoryItem(
|
|
467
|
-
|
|
510
|
+
options.categoryId || options.categoryName || options.category,
|
|
468
511
|
options.summary,
|
|
469
512
|
options.memoryType || 'knowledge',
|
|
470
513
|
options.user
|
|
471
514
|
);
|
|
472
|
-
}
|
|
473
515
|
|
|
474
|
-
case 'update-item':
|
|
475
|
-
if (!options.itemId || !options.updates) {
|
|
476
|
-
throw new Error('update-item requires itemId and updates');
|
|
477
|
-
}
|
|
516
|
+
case 'update-item':
|
|
478
517
|
return bridge.updateMemoryItem(options.itemId, options.updates);
|
|
479
|
-
}
|
|
480
518
|
|
|
481
|
-
case 'delete-item':
|
|
482
|
-
if (!options.itemId) {
|
|
483
|
-
throw new Error('delete-item requires itemId');
|
|
484
|
-
}
|
|
519
|
+
case 'delete-item':
|
|
485
520
|
return bridge.deleteMemoryItem(options.itemId);
|
|
486
|
-
}
|
|
487
521
|
|
|
488
522
|
case 'clear':
|
|
489
523
|
return bridge.clearMemory(normalizeScopeWhere(options.where, options.user));
|
|
@@ -491,31 +525,19 @@ async function runMemuCommand(command: string, options: Record<string, any> = {}
|
|
|
491
525
|
case 'status':
|
|
492
526
|
return bridge.getStatus(normalizeScopeWhere(options.where, options.user));
|
|
493
527
|
|
|
494
|
-
case 'memorize-conversation':
|
|
495
|
-
if (!options.messages) {
|
|
496
|
-
throw new Error('memorize-conversation requires messages array');
|
|
497
|
-
}
|
|
528
|
+
case 'memorize-conversation':
|
|
498
529
|
return bridge.memorizeConversation(options.messages, options.user);
|
|
499
|
-
}
|
|
500
530
|
|
|
501
|
-
case 'memorize-trading-context':
|
|
502
|
-
if (!options.context) {
|
|
503
|
-
throw new Error('memorize-trading-context requires context');
|
|
504
|
-
}
|
|
531
|
+
case 'memorize-trading-context':
|
|
505
532
|
return bridge.memorizeTradingContext(options.context, options.user);
|
|
506
|
-
}
|
|
507
533
|
|
|
508
|
-
case 'retrieve-trading-context':
|
|
509
|
-
if (!options.query) {
|
|
510
|
-
throw new Error('retrieve-trading-context requires query');
|
|
511
|
-
}
|
|
534
|
+
case 'retrieve-trading-context':
|
|
512
535
|
return bridge.retrieveTradingContext(options.query, options.user);
|
|
513
|
-
}
|
|
514
536
|
|
|
515
537
|
default:
|
|
516
538
|
throw new Error(`Unsupported memU command: ${command}`);
|
|
517
539
|
}
|
|
518
540
|
}
|
|
519
541
|
|
|
520
|
-
export { createMemuBridge, describeMemuBridge, runMemuCommand,
|
|
542
|
+
export { createMemuBridge, describeMemuBridge, runMemuCommand, validateMemuCommandArgs }
|
|
521
543
|
|
|
@@ -5,7 +5,7 @@ import { loadDexbotOrderUtils } from './dexbot_bridge.js';
|
|
|
5
5
|
|
|
6
6
|
const CORE_SYMBOL = 'BTS';
|
|
7
7
|
|
|
8
|
-
async function requireBtsBackedMpa(mpaSymbolOrId: any) {
|
|
8
|
+
async function requireBtsBackedMpa(mpaSymbolOrId: any, hint?: string) {
|
|
9
9
|
const mpaAsset = await getAsset(mpaSymbolOrId);
|
|
10
10
|
if (!mpaAsset) {
|
|
11
11
|
throw new Error(`Asset not found: ${mpaSymbolOrId}`);
|
|
@@ -19,7 +19,8 @@ async function requireBtsBackedMpa(mpaSymbolOrId: any) {
|
|
|
19
19
|
throw new Error(`Could not resolve backing asset for ${mpaSymbolOrId}`);
|
|
20
20
|
}
|
|
21
21
|
if (backingAsset.symbol !== CORE_SYMBOL) {
|
|
22
|
-
|
|
22
|
+
const hintSuffix = hint ? `; ${hint}` : '';
|
|
23
|
+
throw new Error(`${mpaAsset.symbol || mpaSymbolOrId} is backed by ${backingAsset.symbol}, not ${CORE_SYMBOL}${hintSuffix}`);
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
return {
|
|
@@ -62,5 +63,27 @@ function computeBtsPerMpa(settlementPrice: any, mpaAsset: any, backingAsset: any
|
|
|
62
63
|
return null;
|
|
63
64
|
}
|
|
64
65
|
|
|
65
|
-
|
|
66
|
+
/**
|
|
67
|
+
* Compute the normalized debt/collateral figures for a raw call order.
|
|
68
|
+
* Canonical implementation shared by position discovery and the position
|
|
69
|
+
* manager so both surfaces report identical amounts and ratios.
|
|
70
|
+
*/
|
|
71
|
+
function computeCallOrderAmounts(callOrder: any, mpaAsset: any, backingAsset: any, bitassetData: any) {
|
|
72
|
+
const blockchainToFloat = getBlockchainToFloat();
|
|
73
|
+
const debtAmount = blockchainToFloat(callOrder.debt, mpaAsset.precision);
|
|
74
|
+
const collateralAmount = blockchainToFloat(callOrder.collateral, backingAsset.precision);
|
|
75
|
+
const btsPerMpa = computeBtsPerMpa(bitassetData?.current_feed?.settlement_price, mpaAsset, backingAsset);
|
|
76
|
+
const debtValueInBts = debtAmount && btsPerMpa ? debtAmount * btsPerMpa : 0;
|
|
77
|
+
const collateralRatio = debtValueInBts > 0 ? collateralAmount / debtValueInBts : null;
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
btsPerMpa,
|
|
81
|
+
collateralAmount: collateralAmount || 0,
|
|
82
|
+
collateralRatio,
|
|
83
|
+
debtAmount: debtAmount || 0,
|
|
84
|
+
debtValueInBts
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export { CORE_SYMBOL, computeBtsPerMpa, computeCallOrderAmounts, getBlockchainToFloat, requireBtsBackedMpa }
|
|
66
89
|
|
|
@@ -9,16 +9,11 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
import { loadDexbotOrderUtils } from './dexbot_bridge.js';
|
|
13
|
-
import { computeBtsPerMpa } from './mpa_utils.js';
|
|
14
12
|
import { roundTo } from '../../modules/order/utils/math.js';
|
|
15
13
|
'use strict';
|
|
16
14
|
|
|
17
15
|
import { getAsset, getBackingAsset, getBitassetData, getFullAccount } from './chain_queries.js';
|
|
18
|
-
|
|
19
|
-
function getBlockchainToFloat() {
|
|
20
|
-
return loadDexbotOrderUtils().blockchainToFloat;
|
|
21
|
-
}
|
|
16
|
+
import { computeCallOrderAmounts } from './mpa_utils.js';
|
|
22
17
|
|
|
23
18
|
/**
|
|
24
19
|
* Normalize a raw call order into a position object compatible with
|
|
@@ -31,13 +26,7 @@ function getBlockchainToFloat() {
|
|
|
31
26
|
* @returns {Object} Normalized position
|
|
32
27
|
*/
|
|
33
28
|
function normalizeCallOrder(callOrder: any, mpaAsset: any, backingAsset: any, bitassetData: any) {
|
|
34
|
-
const
|
|
35
|
-
const debtAmount = blockchainToFloat(callOrder.debt, mpaAsset.precision);
|
|
36
|
-
const collateralAmount = blockchainToFloat(callOrder.collateral, backingAsset.precision);
|
|
37
|
-
const settlement = bitassetData?.current_feed?.settlement_price;
|
|
38
|
-
const btsPerMpa = computeBtsPerMpa(settlement, mpaAsset, backingAsset);
|
|
39
|
-
const debtValueInBts = debtAmount && btsPerMpa ? debtAmount * btsPerMpa : 0;
|
|
40
|
-
const collateralRatio = debtValueInBts > 0 ? collateralAmount / debtValueInBts : null;
|
|
29
|
+
const amounts = computeCallOrderAmounts(callOrder, mpaAsset, backingAsset, bitassetData);
|
|
41
30
|
|
|
42
31
|
return {
|
|
43
32
|
id: callOrder.id,
|
|
@@ -48,11 +37,11 @@ function normalizeCallOrder(callOrder: any, mpaAsset: any, backingAsset: any, bi
|
|
|
48
37
|
backingSymbol: backingAsset.symbol,
|
|
49
38
|
onChain: {
|
|
50
39
|
callOrderId: callOrder.id,
|
|
51
|
-
collateralAmount: collateralAmount
|
|
52
|
-
collateralRatio,
|
|
53
|
-
debtAmount: debtAmount
|
|
54
|
-
debtValueInBts,
|
|
55
|
-
btsPerMpa,
|
|
40
|
+
collateralAmount: amounts.collateralAmount,
|
|
41
|
+
collateralRatio: amounts.collateralRatio,
|
|
42
|
+
debtAmount: amounts.debtAmount,
|
|
43
|
+
debtValueInBts: amounts.debtValueInBts,
|
|
44
|
+
btsPerMpa: amounts.btsPerMpa,
|
|
56
45
|
feedPublicationTime: bitassetData?.current_feed_publication_time || null,
|
|
57
46
|
},
|
|
58
47
|
};
|
|
@@ -76,21 +65,21 @@ async function discoverPositions(accountName: string) {
|
|
|
76
65
|
callOrders.map((co: any) => co?.call_price?.quote?.asset_id).filter(Boolean)
|
|
77
66
|
)];
|
|
78
67
|
|
|
79
|
-
// Resolve
|
|
68
|
+
// Resolve every debt asset's MPA/backing/bitasset triple in parallel.
|
|
80
69
|
const assetCache = new Map();
|
|
81
70
|
const bitassetCache = new Map();
|
|
82
71
|
|
|
83
|
-
|
|
84
|
-
const mpaAsset = await
|
|
85
|
-
|
|
86
|
-
|
|
72
|
+
await Promise.all(debtAssetIds.map(async (assetId) => {
|
|
73
|
+
const [mpaAsset, backingAsset, bitassetData] = await Promise.all([
|
|
74
|
+
getAsset(assetId).catch(() => null),
|
|
75
|
+
getBackingAsset(assetId).catch(() => null),
|
|
76
|
+
getBitassetData(assetId).catch(() => null)
|
|
77
|
+
]);
|
|
87
78
|
|
|
88
|
-
|
|
79
|
+
if (mpaAsset) assetCache.set(assetId, mpaAsset);
|
|
89
80
|
if (backingAsset) assetCache.set(`backing:${assetId}`, backingAsset);
|
|
90
|
-
|
|
91
|
-
const bitassetData = await getBitassetData(assetId);
|
|
92
81
|
if (bitassetData) bitassetCache.set(assetId, bitassetData);
|
|
93
|
-
}
|
|
82
|
+
}));
|
|
94
83
|
|
|
95
84
|
// Normalize each call order
|
|
96
85
|
const positions: any[] = [];
|
|
@@ -3,11 +3,10 @@ import { getStorage } from '../../modules/storage/index.js';
|
|
|
3
3
|
import { path } from '../../modules/path_api.js';
|
|
4
4
|
import { PATHS } from '../../modules/paths.js';
|
|
5
5
|
import { Config } from '../../modules/config.js';
|
|
6
|
-
import { requireBtsBackedMpa,
|
|
6
|
+
import { requireBtsBackedMpa, computeCallOrderAmounts, getBlockchainToFloat } from './mpa_utils.js';
|
|
7
7
|
import { listenForFills } from './chain_actions.js';
|
|
8
8
|
import { writeJsonFileAtomic } from './dexbot_profiles.js';
|
|
9
|
-
import {
|
|
10
|
-
import { clone } from './utils.js';
|
|
9
|
+
import { clone, requirePositiveNumber } from './utils.js';
|
|
11
10
|
const storage = getStorage();
|
|
12
11
|
import { closeShortOnBts, openShortOnBts, placeTakeProfitBuyOrderOnBts } from './short_mpa_strategy.js';
|
|
13
12
|
import { getAsset, getBackingAsset, getBalances, getBitassetData, getFullAccount } from './chain_queries.js';
|
|
@@ -15,10 +14,6 @@ import { getErrorMessage } from '../../modules/utils/errors.js';
|
|
|
15
14
|
|
|
16
15
|
import type { ShortPositionOptions, PositionManagerOptions } from './types.js';
|
|
17
16
|
|
|
18
|
-
function getBlockchainToFloat() {
|
|
19
|
-
return loadDexbotOrderUtils().blockchainToFloat;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
17
|
const DEFAULT_STATE_PATH = PATHS.CLAW.POSITIONS_FILE;
|
|
23
18
|
const STRATEGY_NAME = 'short-mpa-bts';
|
|
24
19
|
|
|
@@ -38,14 +33,6 @@ function requireString(value: any, fieldName: string) {
|
|
|
38
33
|
return value.trim();
|
|
39
34
|
}
|
|
40
35
|
|
|
41
|
-
function requirePositiveNumber(value: any, fieldName: string) {
|
|
42
|
-
const numericValue = Number(value);
|
|
43
|
-
if (!Number.isFinite(numericValue) || numericValue <= 0) {
|
|
44
|
-
throw new Error(`${fieldName} must be a positive number`);
|
|
45
|
-
}
|
|
46
|
-
return numericValue;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
36
|
function almostZero(value: any, epsilon: number = 1e-12) {
|
|
50
37
|
return Math.abs(Number(value) || 0) <= epsilon;
|
|
51
38
|
}
|
|
@@ -116,18 +103,6 @@ function toTrackedAsset(asset: any) {
|
|
|
116
103
|
return asset ? { id: asset.id, precision: asset.precision, symbol: asset.symbol } : null;
|
|
117
104
|
}
|
|
118
105
|
|
|
119
|
-
function resolvePositionAssets(position: any) {
|
|
120
|
-
const tracked = position?.assets || {};
|
|
121
|
-
return {
|
|
122
|
-
collateral: tracked.collateral || null,
|
|
123
|
-
mpa: tracked.mpa || null
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
function getOrderTracking(position: any, side: string) {
|
|
128
|
-
return side === 'entry' ? position.entry : position.exit;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
106
|
function getAssetPrecisionFromTracking(orderTracking: any, assetId: string) {
|
|
132
107
|
if (orderTracking?.sellAsset?.id === assetId) {
|
|
133
108
|
return orderTracking.sellAsset.precision;
|
|
@@ -265,7 +240,7 @@ function refreshPositionPnl(position: any) {
|
|
|
265
240
|
}
|
|
266
241
|
|
|
267
242
|
function normalizeCallPosition(callOrder: any, mpaAsset: any, backingAsset: any, bitassetData: any) {
|
|
268
|
-
if (!callOrder) {
|
|
243
|
+
if (!callOrder || !mpaAsset || !backingAsset) {
|
|
269
244
|
return {
|
|
270
245
|
collateralAmount: 0,
|
|
271
246
|
collateralRatio: null,
|
|
@@ -276,18 +251,13 @@ function normalizeCallPosition(callOrder: any, mpaAsset: any, backingAsset: any,
|
|
|
276
251
|
};
|
|
277
252
|
}
|
|
278
253
|
|
|
279
|
-
const
|
|
280
|
-
const debtAmount = blockchainToFloat(callOrder.debt, mpaAsset.precision);
|
|
281
|
-
const collateralAmount = blockchainToFloat(callOrder.collateral, backingAsset.precision);
|
|
282
|
-
const btsPerMpa = computeBtsPerMpa(bitassetData?.current_feed?.settlement_price, mpaAsset, backingAsset);
|
|
283
|
-
const debtValueInBts = debtAmount && btsPerMpa ? debtAmount * btsPerMpa : 0;
|
|
284
|
-
const collateralRatio = debtValueInBts > 0 ? collateralAmount / debtValueInBts : null;
|
|
254
|
+
const amounts = computeCallOrderAmounts(callOrder, mpaAsset, backingAsset, bitassetData);
|
|
285
255
|
|
|
286
256
|
return {
|
|
287
|
-
collateralAmount: collateralAmount
|
|
288
|
-
collateralRatio,
|
|
289
|
-
debtAmount: debtAmount
|
|
290
|
-
debtValueInBts,
|
|
257
|
+
collateralAmount: amounts.collateralAmount,
|
|
258
|
+
collateralRatio: amounts.collateralRatio,
|
|
259
|
+
debtAmount: amounts.debtAmount,
|
|
260
|
+
debtValueInBts: amounts.debtValueInBts,
|
|
291
261
|
exists: true,
|
|
292
262
|
feedPublicationTime: bitassetData?.current_feed_publication_time || null
|
|
293
263
|
};
|
|
@@ -560,7 +530,14 @@ class PositionManager {
|
|
|
560
530
|
});
|
|
561
531
|
position.lastCloseTx = result?.repayResult?.raw || null;
|
|
562
532
|
|
|
563
|
-
|
|
533
|
+
// Persist before syncing: syncPosition can throw (network failure, asset
|
|
534
|
+
// resolution), and losing the close event/tx record after a successful
|
|
535
|
+
// on-chain repay would corrupt the position history. Mirrors openShort.
|
|
536
|
+
await this.saveState();
|
|
537
|
+
|
|
538
|
+
await this.syncPosition(positionId).catch((syncErr: any) => {
|
|
539
|
+
console.warn(`[POSITION] Post-close sync failed for ${positionId}: ${getErrorMessage(syncErr)}`);
|
|
540
|
+
});
|
|
564
541
|
return this.getPosition(positionId);
|
|
565
542
|
}
|
|
566
543
|
|
|
@@ -577,7 +554,15 @@ class PositionManager {
|
|
|
577
554
|
const mpaAsset = await getAsset(position.debt.asset);
|
|
578
555
|
const backingAsset = await getBackingAsset(position.debt.asset);
|
|
579
556
|
const bitassetData = await getBitassetData(position.debt.asset);
|
|
580
|
-
|
|
557
|
+
// Only match a call order when the debt asset resolved; matching against
|
|
558
|
+
// an undefined id could pair the position with an unrelated call order,
|
|
559
|
+
// and normalizing without asset precision would crash.
|
|
560
|
+
if (!mpaAsset) {
|
|
561
|
+
console.warn(`[POSITION] Could not resolve debt asset ${position.debt.asset} for ${positionId}; skipping on-chain debt sync`);
|
|
562
|
+
}
|
|
563
|
+
const callOrder = mpaAsset
|
|
564
|
+
? callOrders.find((entry: any) => entry?.call_price?.quote?.asset_id === mpaAsset.id) || null
|
|
565
|
+
: null;
|
|
581
566
|
const debtState = normalizeCallPosition(callOrder, mpaAsset, backingAsset, bitassetData);
|
|
582
567
|
const openOrderIds = openOrders.map((entry: any) => entry?.id).filter(Boolean);
|
|
583
568
|
const entryOrderOpen = position.entry.orderId ? openOrderIds.includes(position.entry.orderId) : false;
|
|
@@ -692,8 +677,14 @@ class PositionManager {
|
|
|
692
677
|
});
|
|
693
678
|
changed = true;
|
|
694
679
|
|
|
680
|
+
// Isolate user callback failures: a rejected onFill must not abort
|
|
681
|
+
// this handler before saveState()/post-fill syncs persist the fill.
|
|
695
682
|
if (typeof onFill === 'function') {
|
|
696
|
-
|
|
683
|
+
try {
|
|
684
|
+
await onFill(clone(position), fill);
|
|
685
|
+
} catch (err: any) {
|
|
686
|
+
console.error(`[POSITION] onFill callback failed for ${position.id}: ${getErrorMessage(err)}`);
|
|
687
|
+
}
|
|
697
688
|
}
|
|
698
689
|
}
|
|
699
690
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
|
|
2
2
|
import { getStorage } from '../../modules/storage/index.js';
|
|
3
|
-
import { path } from '../../modules/path_api.js';
|
|
4
3
|
import { PATHS } from '../../modules/paths.js';
|
|
5
4
|
import { PositionManager, DEFAULT_STATE_PATH } from './position_manager.js';
|
|
6
5
|
import * as client from './bitshares_client.js';
|
|
@@ -178,12 +177,14 @@ function createPositionManagerWatcher(options: Record<string, any> = {}) {
|
|
|
178
177
|
throw new Error('accountName is required. Pass --account or set BITSHARES_ACCOUNT.');
|
|
179
178
|
}
|
|
180
179
|
|
|
181
|
-
running = true;
|
|
182
180
|
logger.info(`[position-manager-watch] starting for ${resolvedOptions.accountName}`);
|
|
183
181
|
|
|
182
|
+
// Only flag running once the connection succeeded: a failed start must
|
|
183
|
+
// leave the watcher non-running (and re-startable) with healthy=false.
|
|
184
184
|
await waitForConnected().catch((err: any) => {
|
|
185
185
|
throw new Error(`BitShares connection not ready: ${getErrorMessage(err)}`);
|
|
186
186
|
});
|
|
187
|
+
running = true;
|
|
187
188
|
|
|
188
189
|
await manager.syncAllPositions()
|
|
189
190
|
.then(() => recordSyncSuccess())
|
|
@@ -2,15 +2,7 @@
|
|
|
2
2
|
import { Config } from '../../modules/config.js';
|
|
3
3
|
import { borrowMpa, createLimitOrder, repayMpaDebt } from './chain_actions.js';
|
|
4
4
|
import { requireBtsBackedMpa } from './mpa_utils.js';
|
|
5
|
-
|
|
6
|
-
function requirePositiveNumber(value: any, fieldName: string) {
|
|
7
|
-
const numericValue = Number(value);
|
|
8
|
-
if (!Number.isFinite(numericValue) || numericValue <= 0) {
|
|
9
|
-
throw new Error(`${fieldName} must be a positive number`);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
return numericValue;
|
|
13
|
-
}
|
|
5
|
+
import { requirePositiveNumber } from './utils.js';
|
|
14
6
|
|
|
15
7
|
function requireNonNegativeNumber(value: any, fieldName: string) {
|
|
16
8
|
const numericValue = Number(value);
|
|
@@ -42,11 +42,13 @@ export function tomlString(value: any) {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
export function buildSkillTomlLines(skillName: string, description: string, tags: string[], tools: any[]) {
|
|
45
|
+
// name/description go through tomlString so embedded quotes/backslashes
|
|
46
|
+
// produce valid escaped TOML basic strings.
|
|
45
47
|
const lines = [
|
|
46
48
|
'[skill]',
|
|
47
|
-
`name =
|
|
48
|
-
`description =
|
|
49
|
-
`version =
|
|
49
|
+
`name = ${tomlString(skillName)}`,
|
|
50
|
+
`description = ${tomlString(description)}`,
|
|
51
|
+
`version = ${tomlString(DEXBOT_VERSION)}`,
|
|
50
52
|
`tags = [${tags.map(t => JSON.stringify(t)).join(', ')}]`
|
|
51
53
|
];
|
|
52
54
|
|
package/claw/modules/utils.ts
CHANGED
|
@@ -5,5 +5,13 @@ function clone(value: any) {
|
|
|
5
5
|
return JSON.parse(JSON.stringify(value));
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
function requirePositiveNumber(value: any, fieldName: string) {
|
|
9
|
+
const numericValue = Number(value);
|
|
10
|
+
if (!Number.isFinite(numericValue) || numericValue <= 0) {
|
|
11
|
+
throw new Error(`${fieldName} must be a positive number`);
|
|
12
|
+
}
|
|
13
|
+
return numericValue;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export { clone, requirePositiveNumber }
|
|
9
17
|
|
package/claw/package.json
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
import definePluginEntry from 'openclaw/plugin-sdk/plugin-entry';
|
|
4
4
|
import { getClawToolCatalog } from '../../modules/claw_catalog.js';
|
|
5
5
|
import { runClawCommand } from '../../modules/claw_bridge.js';
|
|
6
|
+
import { getErrorMessage } from '../../../modules/utils/errors.js';
|
|
7
|
+
|
|
6
8
|
function formatResult(result: any) {
|
|
7
9
|
return JSON.stringify(result, null, 2);
|
|
8
10
|
}
|
|
@@ -18,16 +20,31 @@ const plugin = definePluginEntry({
|
|
|
18
20
|
description: `[${tool.risk}] ${tool.description}`,
|
|
19
21
|
parameters: tool.inputSchema,
|
|
20
22
|
async execute(_id: any, params: any) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
// Match the MCP servers' convention: tool failures surface as an
|
|
24
|
+
// isError result instead of a raw rejected promise.
|
|
25
|
+
try {
|
|
26
|
+
const result = await runClawCommand(tool.command, { ...params, runtimeName: 'openclaw' });
|
|
27
|
+
return {
|
|
28
|
+
content: [
|
|
29
|
+
{
|
|
30
|
+
type: "text",
|
|
31
|
+
text: formatResult(result)
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
structuredContent: result
|
|
35
|
+
};
|
|
36
|
+
} catch (error: any) {
|
|
37
|
+
const text = error && error.stack ? error.stack : getErrorMessage(error);
|
|
38
|
+
return {
|
|
39
|
+
content: [
|
|
40
|
+
{
|
|
41
|
+
type: "text",
|
|
42
|
+
text
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
isError: true
|
|
46
|
+
};
|
|
47
|
+
}
|
|
31
48
|
}
|
|
32
49
|
});
|
|
33
50
|
}
|