@dpantani/tdmcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +413 -0
- package/dist/cli/agent.d.ts +466 -0
- package/dist/cli/agent.js +1902 -0
- package/dist/cli/agent.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +4375 -0
- package/dist/index.js.map +1 -0
- package/dist/knowledge/data/glsl.json +1 -0
- package/dist/knowledge/data/meta.json +1 -0
- package/dist/knowledge/data/operators/ableton_link_chop.json +1322 -0
- package/dist/knowledge/data/operators/accumulate_pop.json +912 -0
- package/dist/knowledge/data/operators/actor_comp.json +7477 -0
- package/dist/knowledge/data/operators/add_sop.json +946 -0
- package/dist/knowledge/data/operators/add_top.json +1653 -0
- package/dist/knowledge/data/operators/alembic_sop.json +521 -0
- package/dist/knowledge/data/operators/align_sop.json +949 -0
- package/dist/knowledge/data/operators/ambient_light_comp.json +1698 -0
- package/dist/knowledge/data/operators/analyze_chop.json +710 -0
- package/dist/knowledge/data/operators/analyze_pop.json +698 -0
- package/dist/knowledge/data/operators/analyze_top.json +1276 -0
- package/dist/knowledge/data/operators/angle_chop.json +711 -0
- package/dist/knowledge/data/operators/animation_comp.json +2448 -0
- package/dist/knowledge/data/operators/annotate_comp.json +2913 -0
- package/dist/knowledge/data/operators/anti_alias_top.json +1278 -0
- package/dist/knowledge/data/operators/arm_sop.json +1747 -0
- package/dist/knowledge/data/operators/art-net_dat.json +472 -0
- package/dist/knowledge/data/operators/attribute_chop.json +617 -0
- package/dist/knowledge/data/operators/attribute_combine_pop.json +596 -0
- package/dist/knowledge/data/operators/attribute_convert_pop.json +462 -0
- package/dist/knowledge/data/operators/attribute_create_sop.json +191 -0
- package/dist/knowledge/data/operators/attribute_pop.json +1078 -0
- package/dist/knowledge/data/operators/attribute_sop.json +429 -0
- package/dist/knowledge/data/operators/audio_band_eq_chop.json +1228 -0
- package/dist/knowledge/data/operators/audio_binaural_chop.json +711 -0
- package/dist/knowledge/data/operators/audio_device_in_chop.json +1793 -0
- package/dist/knowledge/data/operators/audio_device_out_chop.json +1840 -0
- package/dist/knowledge/data/operators/audio_devices_dat.json +616 -0
- package/dist/knowledge/data/operators/audio_dynamics_chop.json +1132 -0
- package/dist/knowledge/data/operators/audio_file_in_chop.json +1605 -0
- package/dist/knowledge/data/operators/audio_file_out_chop.json +945 -0
- package/dist/knowledge/data/operators/audio_filter_chop.json +850 -0
- package/dist/knowledge/data/operators/audio_movie_chop.json +851 -0
- package/dist/knowledge/data/operators/audio_ndi_chop.json +526 -0
- package/dist/knowledge/data/operators/audio_oscillator_chop.json +1087 -0
- package/dist/knowledge/data/operators/audio_para_eq_chop.json +1276 -0
- package/dist/knowledge/data/operators/audio_play_chop.json +1744 -0
- package/dist/knowledge/data/operators/audio_render_chop.json +754 -0
- package/dist/knowledge/data/operators/audio_spectrum_chop.json +850 -0
- package/dist/knowledge/data/operators/audio_stream_in_chop.json +1039 -0
- package/dist/knowledge/data/operators/audio_stream_out_chop.json +806 -0
- package/dist/knowledge/data/operators/audio_vst_chop.json +1419 -0
- package/dist/knowledge/data/operators/audio_web_render_chop.json +523 -0
- package/dist/knowledge/data/operators/base_comp.json +1180 -0
- package/dist/knowledge/data/operators/basis_sop.json +805 -0
- package/dist/knowledge/data/operators/beat_chop.json +1745 -0
- package/dist/knowledge/data/operators/bind_chop.json +613 -0
- package/dist/knowledge/data/operators/blacktrax_chop.json +1180 -0
- package/dist/knowledge/data/operators/blend_chop.json +616 -0
- package/dist/knowledge/data/operators/blend_comp.json +3626 -0
- package/dist/knowledge/data/operators/blend_pop.json +618 -0
- package/dist/knowledge/data/operators/blend_sop.json +477 -0
- package/dist/knowledge/data/operators/blob_track_chop.json +1275 -0
- package/dist/knowledge/data/operators/blob_track_top.json +1931 -0
- package/dist/knowledge/data/operators/bloom_top.json +1370 -0
- package/dist/knowledge/data/operators/blur_top.json +1428 -0
- package/dist/knowledge/data/operators/body_track_chop.json +1233 -0
- package/dist/knowledge/data/operators/bone_comp.json +3672 -0
- package/dist/knowledge/data/operators/bone_group_sop.json +148 -0
- package/dist/knowledge/data/operators/boolean_sop.json +336 -0
- package/dist/knowledge/data/operators/box_pop.json +827 -0
- package/dist/knowledge/data/operators/box_sop.json +994 -0
- package/dist/knowledge/data/operators/bridge_sop.json +806 -0
- package/dist/knowledge/data/operators/bullet_solver_chop.json +898 -0
- package/dist/knowledge/data/operators/bullet_solver_comp.json +3720 -0
- package/dist/knowledge/data/operators/button_comp.json +6636 -0
- package/dist/knowledge/data/operators/cache_blend_pop.json +292 -0
- package/dist/knowledge/data/operators/cache_pop.json +412 -0
- package/dist/knowledge/data/operators/cache_select_pop.json +280 -0
- package/dist/knowledge/data/operators/cache_select_top.json +946 -0
- package/dist/knowledge/data/operators/cache_sop.json +478 -0
- package/dist/knowledge/data/operators/cache_top.json +1559 -0
- package/dist/knowledge/data/operators/camera_blend_comp.json +4847 -0
- package/dist/knowledge/data/operators/camera_comp.json +215 -0
- package/dist/knowledge/data/operators/cap_sop.json +527 -0
- package/dist/knowledge/data/operators/capture_region_sop.json +568 -0
- package/dist/knowledge/data/operators/capture_sop.json +619 -0
- package/dist/knowledge/data/operators/carve_sop.json +902 -0
- package/dist/knowledge/data/operators/channel_mix_top.json +1088 -0
- package/dist/knowledge/data/operators/chop_execute_dat.json +1277 -0
- package/dist/knowledge/data/operators/chop_to_dat.json +571 -0
- package/dist/knowledge/data/operators/chop_to_pop.json +1236 -0
- package/dist/knowledge/data/operators/chop_to_sop.json +714 -0
- package/dist/knowledge/data/operators/chop_to_top.json +1231 -0
- package/dist/knowledge/data/operators/chroma_key_top.json +1653 -0
- package/dist/knowledge/data/operators/circle_pop.json +821 -0
- package/dist/knowledge/data/operators/circle_sop.json +991 -0
- package/dist/knowledge/data/operators/circle_top.json +2307 -0
- package/dist/knowledge/data/operators/clay_sop.json +1231 -0
- package/dist/knowledge/data/operators/clip_blender_chop.json +1931 -0
- package/dist/knowledge/data/operators/clip_chop.json +1366 -0
- package/dist/knowledge/data/operators/clip_dat.json +849 -0
- package/dist/knowledge/data/operators/clip_sop.json +475 -0
- package/dist/knowledge/data/operators/clock_chop.json +1792 -0
- package/dist/knowledge/data/operators/composite_chop.json +1414 -0
- package/dist/knowledge/data/operators/composite_top.json +2131 -0
- package/dist/knowledge/data/operators/connectivity_pop.json +11 -0
- package/dist/knowledge/data/operators/constant_chop.json +1238 -0
- package/dist/knowledge/data/operators/constant_mat.json +2727 -0
- package/dist/knowledge/data/operators/constant_top.json +1323 -0
- package/dist/knowledge/data/operators/constraint_comp.json +2076 -0
- package/dist/knowledge/data/operators/container_comp.json +6299 -0
- package/dist/knowledge/data/operators/convert_dat.json +569 -0
- package/dist/knowledge/data/operators/convert_pop.json +322 -0
- package/dist/knowledge/data/operators/convert_sop.json +807 -0
- package/dist/knowledge/data/operators/convolve_top.json +1041 -0
- package/dist/knowledge/data/operators/copy_chop.json +993 -0
- package/dist/knowledge/data/operators/copy_pop.json +1799 -0
- package/dist/knowledge/data/operators/copy_sop.json +1887 -0
- package/dist/knowledge/data/operators/corner_pin_top.json +1512 -0
- package/dist/knowledge/data/operators/count_chop.json +1369 -0
- package/dist/knowledge/data/operators/cplusplus_chop.json +569 -0
- package/dist/knowledge/data/operators/cplusplus_dat.json +477 -0
- package/dist/knowledge/data/operators/cplusplus_pop.json +308 -0
- package/dist/knowledge/data/operators/cplusplus_sop.json +195 -0
- package/dist/knowledge/data/operators/cplusplus_top.json +1276 -0
- package/dist/knowledge/data/operators/creep_sop.json +385 -0
- package/dist/knowledge/data/operators/crop_top.json +1323 -0
- package/dist/knowledge/data/operators/cross_chop.json +478 -0
- package/dist/knowledge/data/operators/cross_top.json +1559 -0
- package/dist/knowledge/data/operators/cube_map_top.json +946 -0
- package/dist/knowledge/data/operators/curve_pop.json +1525 -0
- package/dist/knowledge/data/operators/curveclay_sop.json +618 -0
- package/dist/knowledge/data/operators/curvesect_sop.json +665 -0
- package/dist/knowledge/data/operators/cycle_chop.json +1040 -0
- package/dist/knowledge/data/operators/dat_execute_dat.json +1230 -0
- package/dist/knowledge/data/operators/dat_to_chop.json +1510 -0
- package/dist/knowledge/data/operators/dat_to_pop.json +756 -0
- package/dist/knowledge/data/operators/dat_to_sop.json +902 -0
- package/dist/knowledge/data/operators/deform_sop.json +291 -0
- package/dist/knowledge/data/operators/delay_chop.json +615 -0
- package/dist/knowledge/data/operators/delete_chop.json +1556 -0
- package/dist/knowledge/data/operators/delete_pop.json +1422 -0
- package/dist/knowledge/data/operators/delete_sop.json +1230 -0
- package/dist/knowledge/data/operators/depth_mat.json +1933 -0
- package/dist/knowledge/data/operators/depth_top.json +1322 -0
- package/dist/knowledge/data/operators/difference_top.json +1647 -0
- package/dist/knowledge/data/operators/dimension_pop.json +280 -0
- package/dist/knowledge/data/operators/direct_display_out_top.json +997 -0
- package/dist/knowledge/data/operators/directx_in_top.json +901 -0
- package/dist/knowledge/data/operators/directx_out_top.json +948 -0
- package/dist/knowledge/data/operators/displace_top.json +1322 -0
- package/dist/knowledge/data/operators/divide_sop.json +713 -0
- package/dist/knowledge/data/operators/dmx_fixture_pop.json +772 -0
- package/dist/knowledge/data/operators/dmx_in_chop.json +1420 -0
- package/dist/knowledge/data/operators/dmx_map_dat.json +11 -0
- package/dist/knowledge/data/operators/dmx_out_chop.json +1843 -0
- package/dist/knowledge/data/operators/dmx_out_pop.json +668 -0
- package/dist/knowledge/data/operators/edge_top.json +1370 -0
- package/dist/knowledge/data/operators/emboss_top.json +1275 -0
- package/dist/knowledge/data/operators/engine_comp.json +2685 -0
- package/dist/knowledge/data/operators/envelope_chop.json +946 -0
- package/dist/knowledge/data/operators/environment_light_comp.json +2121 -0
- package/dist/knowledge/data/operators/error_dat.json +949 -0
- package/dist/knowledge/data/operators/etherdream_dat.json +472 -0
- package/dist/knowledge/data/operators/evaluate_dat.json +1650 -0
- package/dist/knowledge/data/operators/event_chop.json +1653 -0
- package/dist/knowledge/data/operators/examine_dat.json +1182 -0
- package/dist/knowledge/data/operators/execute_dat.json +1184 -0
- package/dist/knowledge/data/operators/experimental +0 -0
- package/dist/knowledge/data/operators/expression_chop.json +617 -0
- package/dist/knowledge/data/operators/extend_chop.json +617 -0
- package/dist/knowledge/data/operators/extrude_pop.json +316 -0
- package/dist/knowledge/data/operators/extrude_sop.json +1081 -0
- package/dist/knowledge/data/operators/face_track_chop.json +998 -0
- package/dist/knowledge/data/operators/face_track_sop.json +244 -0
- package/dist/knowledge/data/operators/facet_pop.json +480 -0
- package/dist/knowledge/data/operators/facet_sop.json +619 -0
- package/dist/knowledge/data/operators/fan_chop.json +804 -0
- package/dist/knowledge/data/operators/fbx_comp.json +4942 -0
- package/dist/knowledge/data/operators/feedback_chop.json +664 -0
- package/dist/knowledge/data/operators/feedback_pop.json +368 -0
- package/dist/knowledge/data/operators/feedback_top.json +191 -0
- package/dist/knowledge/data/operators/field_pop.json +2304 -0
- package/dist/knowledge/data/operators/fifo_dat.json +711 -0
- package/dist/knowledge/data/operators/file_in_chop.json +1181 -0
- package/dist/knowledge/data/operators/file_in_dat.json +527 -0
- package/dist/knowledge/data/operators/file_in_pop.json +298 -0
- package/dist/knowledge/data/operators/file_in_sop.json +289 -0
- package/dist/knowledge/data/operators/file_out_chop.json +618 -0
- package/dist/knowledge/data/operators/file_out_dat.json +524 -0
- package/dist/knowledge/data/operators/fillet_sop.json +949 -0
- package/dist/knowledge/data/operators/filter_chop.json +1134 -0
- package/dist/knowledge/data/operators/fit_sop.json +1087 -0
- package/dist/knowledge/data/operators/fit_top.json +1559 -0
- package/dist/knowledge/data/operators/flip_top.json +1040 -0
- package/dist/knowledge/data/operators/folder_dat.json +1888 -0
- package/dist/knowledge/data/operators/force_comp.json +1701 -0
- package/dist/knowledge/data/operators/force_pop.json +878 -0
- package/dist/knowledge/data/operators/force_sop.json +429 -0
- package/dist/knowledge/data/operators/fractal_sop.json +479 -0
- package/dist/knowledge/data/operators/freed_in_chop.json +808 -0
- package/dist/knowledge/data/operators/freed_out_chop.json +714 -0
- package/dist/knowledge/data/operators/function_chop.json +1086 -0
- package/dist/knowledge/data/operators/function_top.json +1558 -0
- package/dist/knowledge/data/operators/geo_text_comp.json +7338 -0
- package/dist/knowledge/data/operators/geometry_comp.json +199 -0
- package/dist/knowledge/data/operators/gesture_chop.json +1133 -0
- package/dist/knowledge/data/operators/glsl_advanced_pop.json +3539 -0
- package/dist/knowledge/data/operators/glsl_comp.json +6962 -0
- package/dist/knowledge/data/operators/glsl_copy_pop.json +2128 -0
- package/dist/knowledge/data/operators/glsl_mat.json +3720 -0
- package/dist/knowledge/data/operators/glsl_multi_top.json +2922 -0
- package/dist/knowledge/data/operators/glsl_pop.json +2317 -0
- package/dist/knowledge/data/operators/glsl_select_pop.json +280 -0
- package/dist/knowledge/data/operators/glsl_top.json +2922 -0
- package/dist/knowledge/data/operators/grid_pop.json +1029 -0
- package/dist/knowledge/data/operators/grid_sop.json +1041 -0
- package/dist/knowledge/data/operators/group_pop.json +1423 -0
- package/dist/knowledge/data/operators/group_sop.json +2075 -0
- package/dist/knowledge/data/operators/handle_chop.json +712 -0
- package/dist/knowledge/data/operators/handle_comp.json +2171 -0
- package/dist/knowledge/data/operators/histogram_pop.json +533 -0
- package/dist/knowledge/data/operators/hog_chop.json +620 -0
- package/dist/knowledge/data/operators/hokuyo_chop.json +941 -0
- package/dist/knowledge/data/operators/hold_chop.json +664 -0
- package/dist/knowledge/data/operators/hole_sop.json +291 -0
- package/dist/knowledge/data/operators/hsv_adjust_top.json +1370 -0
- package/dist/knowledge/data/operators/hsv_to_rgb_top.json +847 -0
- package/dist/knowledge/data/operators/import_select_chop.json +1838 -0
- package/dist/knowledge/data/operators/import_select_pop.json +808 -0
- package/dist/knowledge/data/operators/import_select_sop.json +1463 -0
- package/dist/knowledge/data/operators/import_select_top.json +993 -0
- package/dist/knowledge/data/operators/impulse_force_comp.json +1415 -0
- package/dist/knowledge/data/operators/in_chop.json +572 -0
- package/dist/knowledge/data/operators/in_dat.json +386 -0
- package/dist/knowledge/data/operators/in_mat.json +1559 -0
- package/dist/knowledge/data/operators/in_pop.json +280 -0
- package/dist/knowledge/data/operators/in_sop.json +102 -0
- package/dist/knowledge/data/operators/in_top.json +903 -0
- package/dist/knowledge/data/operators/index.json +1 -0
- package/dist/knowledge/data/operators/indices_dat.json +526 -0
- package/dist/knowledge/data/operators/info_chop.json +757 -0
- package/dist/knowledge/data/operators/info_dat.json +430 -0
- package/dist/knowledge/data/operators/insert_dat.json +896 -0
- package/dist/knowledge/data/operators/inside_top.json +1652 -0
- package/dist/knowledge/data/operators/interpolate_chop.json +711 -0
- package/dist/knowledge/data/operators/inverse_curve_chop.json +898 -0
- package/dist/knowledge/data/operators/inverse_curve_sop.json +97 -0
- package/dist/knowledge/data/operators/inverse_kin_chop.json +850 -0
- package/dist/knowledge/data/operators/iso_surface_sop.json +337 -0
- package/dist/knowledge/data/operators/join_chop.json +1368 -0
- package/dist/knowledge/data/operators/join_sop.json +667 -0
- package/dist/knowledge/data/operators/joint_sop.json +573 -0
- package/dist/knowledge/data/operators/joystick_chop.json +1558 -0
- package/dist/knowledge/data/operators/json_dat.json +619 -0
- package/dist/knowledge/data/operators/keyboard_in_chop.json +1041 -0
- package/dist/knowledge/data/operators/keyboard_in_dat.json +950 -0
- package/dist/knowledge/data/operators/keyframe_chop.json +711 -0
- package/dist/knowledge/data/operators/kinect_azure_chop.json +1092 -0
- package/dist/knowledge/data/operators/kinect_azure_select_top.json +1187 -0
- package/dist/knowledge/data/operators/kinect_azure_top.json +2737 -0
- package/dist/knowledge/data/operators/kinect_chop.json +1700 -0
- package/dist/knowledge/data/operators/kinect_sop.json +379 -0
- package/dist/knowledge/data/operators/kinect_top.json +1700 -0
- package/dist/knowledge/data/operators/lag_chop.json +1040 -0
- package/dist/knowledge/data/operators/laser_chop.json +1746 -0
- package/dist/knowledge/data/operators/laser_device_chop.json +1228 -0
- package/dist/knowledge/data/operators/lattice_sop.json +432 -0
- package/dist/knowledge/data/operators/layout_top.json +1936 -0
- package/dist/knowledge/data/operators/leap_motion_chop.json +1699 -0
- package/dist/knowledge/data/operators/leap_motion_top.json +1323 -0
- package/dist/knowledge/data/operators/lens_distort_top.json +2262 -0
- package/dist/knowledge/data/operators/leuze_rod4_chop.json +1371 -0
- package/dist/knowledge/data/operators/level_top.json +2273 -0
- package/dist/knowledge/data/operators/lfo_chop.json +1088 -0
- package/dist/knowledge/data/operators/light_comp.json +5410 -0
- package/dist/knowledge/data/operators/limit_chop.json +1133 -0
- package/dist/knowledge/data/operators/limit_pop.json +1243 -0
- package/dist/knowledge/data/operators/limit_sop.json +2075 -0
- package/dist/knowledge/data/operators/limit_top.json +1557 -0
- package/dist/knowledge/data/operators/line_break_pop.json +447 -0
- package/dist/knowledge/data/operators/line_divide_pop.json +688 -0
- package/dist/knowledge/data/operators/line_mat.json +5551 -0
- package/dist/knowledge/data/operators/line_metrics_pop.json +548 -0
- package/dist/knowledge/data/operators/line_pop.json +1343 -0
- package/dist/knowledge/data/operators/line_smooth_pop.json +1028 -0
- package/dist/knowledge/data/operators/line_sop.json +330 -0
- package/dist/knowledge/data/operators/line_thick_sop.json +478 -0
- package/dist/knowledge/data/operators/list_comp.json +6729 -0
- package/dist/knowledge/data/operators/lod_sop.json +431 -0
- package/dist/knowledge/data/operators/logic_chop.json +946 -0
- package/dist/knowledge/data/operators/lookup_attribute_pop.json +684 -0
- package/dist/knowledge/data/operators/lookup_channel_pop.json +1140 -0
- package/dist/knowledge/data/operators/lookup_chop.json +992 -0
- package/dist/knowledge/data/operators/lookup_dat.json +664 -0
- package/dist/knowledge/data/operators/lookup_texture_pop.json +1494 -0
- package/dist/knowledge/data/operators/lookup_top.json +1510 -0
- package/dist/knowledge/data/operators/lsystem_sop.json +1699 -0
- package/dist/knowledge/data/operators/ltc_in_chop.json +760 -0
- package/dist/knowledge/data/operators/ltc_out_chop.json +1512 -0
- package/dist/knowledge/data/operators/luma_blur_top.json +1316 -0
- package/dist/knowledge/data/operators/luma_level_top.json +1746 -0
- package/dist/knowledge/data/operators/magnet_sop.json +759 -0
- package/dist/knowledge/data/operators/material_sop.json +98 -0
- package/dist/knowledge/data/operators/math_chop.json +1193 -0
- package/dist/knowledge/data/operators/math_combine_pop.json +4283 -0
- package/dist/knowledge/data/operators/math_mix_pop.json +2641 -0
- package/dist/knowledge/data/operators/math_pop.json +2163 -0
- package/dist/knowledge/data/operators/math_top.json +1885 -0
- package/dist/knowledge/data/operators/matte_top.json +994 -0
- package/dist/knowledge/data/operators/media_file_info_dat.json +571 -0
- package/dist/knowledge/data/operators/merge_chop.json +627 -0
- package/dist/knowledge/data/operators/merge_dat.json +620 -0
- package/dist/knowledge/data/operators/merge_pop.json +764 -0
- package/dist/knowledge/data/operators/merge_sop.json +100 -0
- package/dist/knowledge/data/operators/metaball_sop.json +476 -0
- package/dist/knowledge/data/operators/midi_event_dat.json +1135 -0
- package/dist/knowledge/data/operators/midi_in_chop.json +3297 -0
- package/dist/knowledge/data/operators/midi_in_dat.json +1183 -0
- package/dist/knowledge/data/operators/midi_in_map_chop.json +946 -0
- package/dist/knowledge/data/operators/midi_out_chop.json +1793 -0
- package/dist/knowledge/data/operators/mirror_top.json +1271 -0
- package/dist/knowledge/data/operators/model_sop.json +52 -0
- package/dist/knowledge/data/operators/monitors_dat.json +617 -0
- package/dist/knowledge/data/operators/monochrome_top.json +1041 -0
- package/dist/knowledge/data/operators/mosys_chop.json +804 -0
- package/dist/knowledge/data/operators/mosys_top.json +896 -0
- package/dist/knowledge/data/operators/mouse_in_chop.json +1275 -0
- package/dist/knowledge/data/operators/mouse_out_chop.json +711 -0
- package/dist/knowledge/data/operators/movie_file_in_top.json +3546 -0
- package/dist/knowledge/data/operators/movie_file_out_top.json +3390 -0
- package/dist/knowledge/data/operators/mpcdi_dat.json +711 -0
- package/dist/knowledge/data/operators/mpcdi_top.json +1369 -0
- package/dist/knowledge/data/operators/mqtt_client_dat.json +1229 -0
- package/dist/knowledge/data/operators/multi_touch_in_dat.json +1185 -0
- package/dist/knowledge/data/operators/multiply_top.json +1647 -0
- package/dist/knowledge/data/operators/ncam_chop.json +1039 -0
- package/dist/knowledge/data/operators/ncam_top.json +1039 -0
- package/dist/knowledge/data/operators/ndi_dat.json +478 -0
- package/dist/knowledge/data/operators/ndi_in_top.json +1326 -0
- package/dist/knowledge/data/operators/ndi_out_top.json +1420 -0
- package/dist/knowledge/data/operators/neighbor_pop.json +534 -0
- package/dist/knowledge/data/operators/noise_chop.json +2230 -0
- package/dist/knowledge/data/operators/noise_pop.json +2107 -0
- package/dist/knowledge/data/operators/noise_sop.json +1136 -0
- package/dist/knowledge/data/operators/noise_top.json +2356 -0
- package/dist/knowledge/data/operators/normal_map_top.json +1182 -0
- package/dist/knowledge/data/operators/normal_pop.json +1488 -0
- package/dist/knowledge/data/operators/normalize_pop.json +1298 -0
- package/dist/knowledge/data/operators/notch_top.json +1511 -0
- package/dist/knowledge/data/operators/null_chop.json +673 -0
- package/dist/knowledge/data/operators/null_comp.json +2921 -0
- package/dist/knowledge/data/operators/null_dat.json +344 -0
- package/dist/knowledge/data/operators/null_mat.json +1511 -0
- package/dist/knowledge/data/operators/null_pop.json +18 -0
- package/dist/knowledge/data/operators/null_sop.json +100 -0
- package/dist/knowledge/data/operators/null_top.json +862 -0
- package/dist/knowledge/data/operators/nvidia_background_top.json +996 -0
- package/dist/knowledge/data/operators/nvidia_denoise_top.json +1089 -0
- package/dist/knowledge/data/operators/nvidia_flex_solver_comp.json +5367 -0
- package/dist/knowledge/data/operators/nvidia_flex_top.json +995 -0
- package/dist/knowledge/data/operators/nvidia_flow_emitter_comp.json +7812 -0
- package/dist/knowledge/data/operators/nvidia_flow_top.json +3675 -0
- package/dist/knowledge/data/operators/nvidia_upscaler_top.json +1089 -0
- package/dist/knowledge/data/operators/oak_device_chop.json +1372 -0
- package/dist/knowledge/data/operators/oak_select_chop.json +947 -0
- package/dist/knowledge/data/operators/oak_select_top.json +1323 -0
- package/dist/knowledge/data/operators/object_chop.json +2356 -0
- package/dist/knowledge/data/operators/object_merge_sop.json +194 -0
- package/dist/knowledge/data/operators/oculus_audio_chop.json +1371 -0
- package/dist/knowledge/data/operators/oculus_rift_chop.json +901 -0
- package/dist/knowledge/data/operators/oculus_rift_sop.json +147 -0
- package/dist/knowledge/data/operators/oculus_rift_top.json +995 -0
- package/dist/knowledge/data/operators/op_execute_dat.json +1463 -0
- package/dist/knowledge/data/operators/op_find_dat.json +2827 -0
- package/dist/knowledge/data/operators/op_viewer_comp.json +6586 -0
- package/dist/knowledge/data/operators/op_viewer_top.json +993 -0
- package/dist/knowledge/data/operators/opencolorio_top.json +1980 -0
- package/dist/knowledge/data/operators/openvr_chop.json +1135 -0
- package/dist/knowledge/data/operators/openvr_sop.json +99 -0
- package/dist/knowledge/data/operators/openvr_top.json +900 -0
- package/dist/knowledge/data/operators/optical_flow_top.json +1230 -0
- package/dist/knowledge/data/operators/optitrack_in_chop.json +854 -0
- package/dist/knowledge/data/operators/orbbec_select_top.json +1042 -0
- package/dist/knowledge/data/operators/orbbec_top.json +1558 -0
- package/dist/knowledge/data/operators/osc_in_chop.json +1371 -0
- package/dist/knowledge/data/operators/osc_in_dat.json +1280 -0
- package/dist/knowledge/data/operators/osc_out_chop.json +1138 -0
- package/dist/knowledge/data/operators/osc_out_dat.json +1280 -0
- package/dist/knowledge/data/operators/ouster_select_top.json +1228 -0
- package/dist/knowledge/data/operators/ouster_top.json +2404 -0
- package/dist/knowledge/data/operators/out_chop.json +476 -0
- package/dist/knowledge/data/operators/out_dat.json +386 -0
- package/dist/knowledge/data/operators/out_mat.json +1982 -0
- package/dist/knowledge/data/operators/out_pop.json +286 -0
- package/dist/knowledge/data/operators/out_sop.json +93 -0
- package/dist/knowledge/data/operators/out_top.json +903 -0
- package/dist/knowledge/data/operators/outside_top.json +1651 -0
- package/dist/knowledge/data/operators/over_top.json +1651 -0
- package/dist/knowledge/data/operators/override_chop.json +663 -0
- package/dist/knowledge/data/operators/pack_top.json +946 -0
- package/dist/knowledge/data/operators/pan_tilt_chop.json +11 -0
- package/dist/knowledge/data/operators/panel_chop.json +663 -0
- package/dist/knowledge/data/operators/panel_execute_dat.json +1182 -0
- package/dist/knowledge/data/operators/pangolin_chop.json +1135 -0
- package/dist/knowledge/data/operators/parameter_chop.json +803 -0
- package/dist/knowledge/data/operators/parameter_comp.json +6962 -0
- package/dist/knowledge/data/operators/parameter_dat.json +1698 -0
- package/dist/knowledge/data/operators/parameter_execute_dat.json +1371 -0
- package/dist/knowledge/data/operators/pargroup_execute_dat.json +1271 -0
- package/dist/knowledge/data/operators/particle_pop.json +1130 -0
- package/dist/knowledge/data/operators/particle_sop.json +2214 -0
- package/dist/knowledge/data/operators/pattern_chop.json +1697 -0
- package/dist/knowledge/data/operators/pattern_pop.json +1767 -0
- package/dist/knowledge/data/operators/pbr_mat.json +4990 -0
- package/dist/knowledge/data/operators/perform_chop.json +1651 -0
- package/dist/knowledge/data/operators/perform_dat.json +1184 -0
- package/dist/knowledge/data/operators/phaser_chop.json +618 -0
- package/dist/knowledge/data/operators/phaser_pop.json +1043 -0
- package/dist/knowledge/data/operators/phong_mat.json +5458 -0
- package/dist/knowledge/data/operators/photoshop_in_top.json +1418 -0
- package/dist/knowledge/data/operators/pipe_in_chop.json +1323 -0
- package/dist/knowledge/data/operators/pipe_out_chop.json +1182 -0
- package/dist/knowledge/data/operators/point_file_in_pop.json +1246 -0
- package/dist/knowledge/data/operators/point_file_in_top.json +3343 -0
- package/dist/knowledge/data/operators/point_file_select_top.json +1086 -0
- package/dist/knowledge/data/operators/point_generator_pop.json +1407 -0
- package/dist/knowledge/data/operators/point_pop.json +752 -0
- package/dist/knowledge/data/operators/point_sop.json +2171 -0
- package/dist/knowledge/data/operators/point_sprite_mat.json +2920 -0
- package/dist/knowledge/data/operators/point_transform_top.json +2779 -0
- package/dist/knowledge/data/operators/polygonize_pop.json +386 -0
- package/dist/knowledge/data/operators/polyloft_sop.json +759 -0
- package/dist/knowledge/data/operators/polypatch_sop.json +761 -0
- package/dist/knowledge/data/operators/polyreduce_sop.json +806 -0
- package/dist/knowledge/data/operators/polyspline_sop.json +667 -0
- package/dist/knowledge/data/operators/polystitch_sop.json +336 -0
- package/dist/knowledge/data/operators/pop_to_chop.json +11 -0
- package/dist/knowledge/data/operators/pop_to_dat.json +11 -0
- package/dist/knowledge/data/operators/pop_to_sop.json +11 -0
- package/dist/knowledge/data/operators/pop_to_top.json +11 -0
- package/dist/knowledge/data/operators/posistagenet_chop.json +900 -0
- package/dist/knowledge/data/operators/prefilter_map_top.json +947 -0
- package/dist/knowledge/data/operators/primitive_pop.json +1254 -0
- package/dist/knowledge/data/operators/primitive_sop.json +2075 -0
- package/dist/knowledge/data/operators/profile_sop.json +756 -0
- package/dist/knowledge/data/operators/project_sop.json +1276 -0
- package/dist/knowledge/data/operators/projection_pop.json +1060 -0
- package/dist/knowledge/data/operators/projection_top.json +1135 -0
- package/dist/knowledge/data/operators/proximity_pop.json +505 -0
- package/dist/knowledge/data/operators/pulse_chop.json +1744 -0
- package/dist/knowledge/data/operators/quantize_pop.json +1052 -0
- package/dist/knowledge/data/operators/rails_sop.json +853 -0
- package/dist/knowledge/data/operators/ramp_top.json +1899 -0
- package/dist/knowledge/data/operators/random_pop.json +1219 -0
- package/dist/knowledge/data/operators/raster_sop.json +291 -0
- package/dist/knowledge/data/operators/ray_pop.json +497 -0
- package/dist/knowledge/data/operators/ray_sop.json +856 -0
- package/dist/knowledge/data/operators/realsense_top.json +1608 -0
- package/dist/knowledge/data/operators/record_chop.json +1040 -0
- package/dist/knowledge/data/operators/rectangle_pop.json +800 -0
- package/dist/knowledge/data/operators/rectangle_sop.json +758 -0
- package/dist/knowledge/data/operators/rectangle_top.json +2259 -0
- package/dist/knowledge/data/operators/refine_sop.json +667 -0
- package/dist/knowledge/data/operators/remap_top.json +1182 -0
- package/dist/knowledge/data/operators/rename_chop.json +522 -0
- package/dist/knowledge/data/operators/render_pass_top.json +3108 -0
- package/dist/knowledge/data/operators/render_pick_chop.json +2119 -0
- package/dist/knowledge/data/operators/render_pick_dat.json +1840 -0
- package/dist/knowledge/data/operators/render_select_top.json +1086 -0
- package/dist/knowledge/data/operators/render_top.json +218 -0
- package/dist/knowledge/data/operators/renderstream_in_chop.json +617 -0
- package/dist/knowledge/data/operators/renderstream_in_top.json +950 -0
- package/dist/knowledge/data/operators/renderstream_out_top.json +997 -0
- package/dist/knowledge/data/operators/reorder_chop.json +946 -0
- package/dist/knowledge/data/operators/reorder_dat.json +711 -0
- package/dist/knowledge/data/operators/reorder_top.json +1229 -0
- package/dist/knowledge/data/operators/replace_chop.json +568 -0
- package/dist/knowledge/data/operators/replicator_comp.json +2208 -0
- package/dist/knowledge/data/operators/rerange_pop.json +892 -0
- package/dist/knowledge/data/operators/resample_chop.json +1134 -0
- package/dist/knowledge/data/operators/resample_sop.json +619 -0
- package/dist/knowledge/data/operators/resolution_top.json +892 -0
- package/dist/knowledge/data/operators/revolve_pop.json +607 -0
- package/dist/knowledge/data/operators/revolve_sop.json +714 -0
- package/dist/knowledge/data/operators/rgb_key_top.json +1654 -0
- package/dist/knowledge/data/operators/rgb_to_hsv_top.json +853 -0
- package/dist/knowledge/data/operators/s_curve_chop.json +1176 -0
- package/dist/knowledge/data/operators/scalable_display_top.json +1042 -0
- package/dist/knowledge/data/operators/screen_grab_top.json +1465 -0
- package/dist/knowledge/data/operators/screen_top.json +1652 -0
- package/dist/knowledge/data/operators/script_chop.json +520 -0
- package/dist/knowledge/data/operators/script_dat.json +429 -0
- package/dist/knowledge/data/operators/script_sop.json +146 -0
- package/dist/knowledge/data/operators/script_top.json +947 -0
- package/dist/knowledge/data/operators/select_chop.json +899 -0
- package/dist/knowledge/data/operators/select_comp.json +5645 -0
- package/dist/knowledge/data/operators/select_dat.json +1371 -0
- package/dist/knowledge/data/operators/select_mat.json +1977 -0
- package/dist/knowledge/data/operators/select_pop.json +347 -0
- package/dist/knowledge/data/operators/select_sop.json +100 -0
- package/dist/knowledge/data/operators/select_top.json +901 -0
- package/dist/knowledge/data/operators/sequence_blend_sop.json +336 -0
- package/dist/knowledge/data/operators/serial_chop.json +1182 -0
- package/dist/knowledge/data/operators/serial_dat.json +1418 -0
- package/dist/knowledge/data/operators/shared_mem_in_chop.json +620 -0
- package/dist/knowledge/data/operators/shared_mem_in_comp.json +1323 -0
- package/dist/knowledge/data/operators/shared_mem_in_top.json +994 -0
- package/dist/knowledge/data/operators/shared_mem_out_chop.json +620 -0
- package/dist/knowledge/data/operators/shared_mem_out_comp.json +1372 -0
- package/dist/knowledge/data/operators/shared_mem_out_top.json +1137 -0
- package/dist/knowledge/data/operators/shift_chop.json +899 -0
- package/dist/knowledge/data/operators/shuffle_chop.json +612 -0
- package/dist/knowledge/data/operators/sick_top.json +1322 -0
- package/dist/knowledge/data/operators/skin_deform_pop.json +972 -0
- package/dist/knowledge/data/operators/skin_pop.json +330 -0
- package/dist/knowledge/data/operators/skin_sop.json +711 -0
- package/dist/knowledge/data/operators/slider_comp.json +6918 -0
- package/dist/knowledge/data/operators/slope_chop.json +661 -0
- package/dist/knowledge/data/operators/slope_top.json +1370 -0
- package/dist/knowledge/data/operators/socketio_dat.json +945 -0
- package/dist/knowledge/data/operators/sop_to_chop.json +1137 -0
- package/dist/knowledge/data/operators/sop_to_dat.json +622 -0
- package/dist/knowledge/data/operators/sop_to_pop.json +409 -0
- package/dist/knowledge/data/operators/sort_chop.json +805 -0
- package/dist/knowledge/data/operators/sort_dat.json +894 -0
- package/dist/knowledge/data/operators/sort_pop.json +1023 -0
- package/dist/knowledge/data/operators/sort_sop.json +569 -0
- package/dist/knowledge/data/operators/spectrum_top.json +1182 -0
- package/dist/knowledge/data/operators/speed_chop.json +1180 -0
- package/dist/knowledge/data/operators/sphere_pop.json +1141 -0
- package/dist/knowledge/data/operators/sphere_sop.json +1370 -0
- package/dist/knowledge/data/operators/splice_chop.json +1226 -0
- package/dist/knowledge/data/operators/spring_chop.json +899 -0
- package/dist/knowledge/data/operators/spring_sop.json +1463 -0
- package/dist/knowledge/data/operators/sprinkle_pop.json +420 -0
- package/dist/knowledge/data/operators/sprinkle_sop.json +337 -0
- package/dist/knowledge/data/operators/sprite_sop.json +571 -0
- package/dist/knowledge/data/operators/ssao_top.json +1510 -0
- package/dist/knowledge/data/operators/st2110_device_chop.json +11 -0
- package/dist/knowledge/data/operators/stitch_sop.json +807 -0
- package/dist/knowledge/data/operators/stretch_chop.json +945 -0
- package/dist/knowledge/data/operators/stype_in_chop.json +756 -0
- package/dist/knowledge/data/operators/stype_out_chop.json +852 -0
- package/dist/knowledge/data/operators/stype_top.json +943 -0
- package/dist/knowledge/data/operators/subdivide_pop.json +292 -0
- package/dist/knowledge/data/operators/subdivide_sop.json +618 -0
- package/dist/knowledge/data/operators/substance_select_top.json +945 -0
- package/dist/knowledge/data/operators/substance_top.json +1182 -0
- package/dist/knowledge/data/operators/substitute_dat.json +1605 -0
- package/dist/knowledge/data/operators/subtract_top.json +1650 -0
- package/dist/knowledge/data/operators/superquad_sop.json +1135 -0
- package/dist/knowledge/data/operators/surfsect_sop.json +853 -0
- package/dist/knowledge/data/operators/sweep_sop.json +947 -0
- package/dist/knowledge/data/operators/switch_chop.json +523 -0
- package/dist/knowledge/data/operators/switch_dat.json +383 -0
- package/dist/knowledge/data/operators/switch_mat.json +1553 -0
- package/dist/knowledge/data/operators/switch_pop.json +496 -0
- package/dist/knowledge/data/operators/switch_sop.json +101 -0
- package/dist/knowledge/data/operators/switch_top.json +959 -0
- package/dist/knowledge/data/operators/sync_in_chop.json +617 -0
- package/dist/knowledge/data/operators/sync_out_chop.json +993 -0
- package/dist/knowledge/data/operators/syphon_spout_in_top.json +946 -0
- package/dist/knowledge/data/operators/syphon_spout_out_top.json +948 -0
- package/dist/knowledge/data/operators/table_comp.json +7009 -0
- package/dist/knowledge/data/operators/table_dat.json +1080 -0
- package/dist/knowledge/data/operators/tablet_chop.json +1367 -0
- package/dist/knowledge/data/operators/text_comp.json +8981 -0
- package/dist/knowledge/data/operators/text_dat.json +675 -0
- package/dist/knowledge/data/operators/text_sop.json +1512 -0
- package/dist/knowledge/data/operators/text_top.json +4236 -0
- package/dist/knowledge/data/operators/texture_3d_top.json +1417 -0
- package/dist/knowledge/data/operators/texture_map_pop.json +1744 -0
- package/dist/knowledge/data/operators/texture_sop.json +992 -0
- package/dist/knowledge/data/operators/threshold_top.json +1227 -0
- package/dist/knowledge/data/operators/tile_top.json +1840 -0
- package/dist/knowledge/data/operators/time_comp.json +1745 -0
- package/dist/knowledge/data/operators/time_machine_top.json +1041 -0
- package/dist/knowledge/data/operators/time_slice_chop.json +568 -0
- package/dist/knowledge/data/operators/timecode_chop.json +1981 -0
- package/dist/knowledge/data/operators/timeline_chop.json +1038 -0
- package/dist/knowledge/data/operators/timer_chop.json +4236 -0
- package/dist/knowledge/data/operators/top_to_chop.json +2077 -0
- package/dist/knowledge/data/operators/top_to_pop.json +2144 -0
- package/dist/knowledge/data/operators/topology_pop.json +1526 -0
- package/dist/knowledge/data/operators/torus_pop.json +901 -0
- package/dist/knowledge/data/operators/torus_sop.json +1368 -0
- package/dist/knowledge/data/operators/touch_in_chop.json +1182 -0
- package/dist/knowledge/data/operators/touch_in_dat.json +618 -0
- package/dist/knowledge/data/operators/touch_in_top.json +1182 -0
- package/dist/knowledge/data/operators/touch_out_chop.json +947 -0
- package/dist/knowledge/data/operators/touch_out_dat.json +712 -0
- package/dist/knowledge/data/operators/touch_out_top.json +1134 -0
- package/dist/knowledge/data/operators/trace_sop.json +759 -0
- package/dist/knowledge/data/operators/trail_chop.json +901 -0
- package/dist/knowledge/data/operators/trail_pop.json +827 -0
- package/dist/knowledge/data/operators/trail_sop.json +616 -0
- package/dist/knowledge/data/operators/transform_chop.json +2168 -0
- package/dist/knowledge/data/operators/transform_pop.json +2659 -0
- package/dist/knowledge/data/operators/transform_sop.json +1466 -0
- package/dist/knowledge/data/operators/transform_top.json +1803 -0
- package/dist/knowledge/data/operators/transform_xyz_chop.json +1369 -0
- package/dist/knowledge/data/operators/transpose_dat.json +334 -0
- package/dist/knowledge/data/operators/trig_pop.json +1135 -0
- package/dist/knowledge/data/operators/trigger_chop.json +2214 -0
- package/dist/knowledge/data/operators/trim_chop.json +805 -0
- package/dist/knowledge/data/operators/trim_sop.json +336 -0
- package/dist/knowledge/data/operators/tristrip_sop.json +194 -0
- package/dist/knowledge/data/operators/tube_pop.json +861 -0
- package/dist/knowledge/data/operators/tube_sop.json +1323 -0
- package/dist/knowledge/data/operators/tuio_in_dat.json +806 -0
- package/dist/knowledge/data/operators/twist_pop.json +1127 -0
- package/dist/knowledge/data/operators/twist_sop.json +533 -0
- package/dist/knowledge/data/operators/udp_in_dat.json +1090 -0
- package/dist/knowledge/data/operators/udp_out_dat.json +1280 -0
- package/dist/knowledge/data/operators/under_top.json +1652 -0
- package/dist/knowledge/data/operators/usd_comp.json +4800 -0
- package/dist/knowledge/data/operators/vertex_sop.json +667 -0
- package/dist/knowledge/data/operators/video_device_in_top.json +3062 -0
- package/dist/knowledge/data/operators/video_device_out_top.json +1936 -0
- package/dist/knowledge/data/operators/video_devices_dat.json +616 -0
- package/dist/knowledge/data/operators/video_stream_in_top.json +1842 -0
- package/dist/knowledge/data/operators/video_stream_out_top.json +2548 -0
- package/dist/knowledge/data/operators/vioso_top.json +943 -0
- package/dist/knowledge/data/operators/warp_chop.json +570 -0
- package/dist/knowledge/data/operators/wave_chop.json +1510 -0
- package/dist/knowledge/data/operators/web_client_dat.json +1514 -0
- package/dist/knowledge/data/operators/web_render_top.json +1749 -0
- package/dist/knowledge/data/operators/web_server_dat.json +714 -0
- package/dist/knowledge/data/operators/webrtc_dat.json +851 -0
- package/dist/knowledge/data/operators/websocket_dat.json +901 -0
- package/dist/knowledge/data/operators/widget_comp.json +6299 -0
- package/dist/knowledge/data/operators/window_comp.json +3061 -0
- package/dist/knowledge/data/operators/wireframe_mat.json +2165 -0
- package/dist/knowledge/data/operators/wireframe_sop.json +338 -0
- package/dist/knowledge/data/operators/wrnchai_chop.json +1084 -0
- package/dist/knowledge/data/operators/xml_dat.json +1230 -0
- package/dist/knowledge/data/operators/zed_chop.json +1840 -0
- package/dist/knowledge/data/operators/zed_sop.json +712 -0
- package/dist/knowledge/data/operators/zed_top.json +1981 -0
- package/dist/knowledge/data/patterns.json +1 -0
- package/dist/knowledge/data/python-api/App.json +78 -0
- package/dist/knowledge/data/python-api/Attribute.json +43 -0
- package/dist/knowledge/data/python-api/Attributes.json +41 -0
- package/dist/knowledge/data/python-api/Bounds.json +10 -0
- package/dist/knowledge/data/python-api/CHOP.json +683 -0
- package/dist/knowledge/data/python-api/COMP.json +1019 -0
- package/dist/knowledge/data/python-api/Cell.json +80 -0
- package/dist/knowledge/data/python-api/Channel.json +100 -0
- package/dist/knowledge/data/python-api/Connector.json +43 -0
- package/dist/knowledge/data/python-api/DAT.json +1289 -0
- package/dist/knowledge/data/python-api/Dependency.json +10 -0
- package/dist/knowledge/data/python-api/Error_DAT.json +9 -0
- package/dist/knowledge/data/python-api/Group.json +54 -0
- package/dist/knowledge/data/python-api/License.json +25 -0
- package/dist/knowledge/data/python-api/MAT.json +621 -0
- package/dist/knowledge/data/python-api/MOD.json +83 -0
- package/dist/knowledge/data/python-api/Matrix.json +556 -0
- package/dist/knowledge/data/python-api/Monitor.json +25 -0
- package/dist/knowledge/data/python-api/Network.json +10 -0
- package/dist/knowledge/data/python-api/NetworkEditor.json +154 -0
- package/dist/knowledge/data/python-api/Node.json +10 -0
- package/dist/knowledge/data/python-api/OP.json +621 -0
- package/dist/knowledge/data/python-api/OP_Viewer_COMP.json +9 -0
- package/dist/knowledge/data/python-api/ObjectCOMP.json +1150 -0
- package/dist/knowledge/data/python-api/Page.json +797 -0
- package/dist/knowledge/data/python-api/Pane.json +62 -0
- package/dist/knowledge/data/python-api/Panel.json +25 -0
- package/dist/knowledge/data/python-api/PanelCOMP.json +1167 -0
- package/dist/knowledge/data/python-api/PanelValue.json +25 -0
- package/dist/knowledge/data/python-api/Par.json +115 -0
- package/dist/knowledge/data/python-api/ParGroup.json +101 -0
- package/dist/knowledge/data/python-api/Parameter.json +10 -0
- package/dist/knowledge/data/python-api/Parent.json +10 -0
- package/dist/knowledge/data/python-api/Pattern_CHOP.json +9 -0
- package/dist/knowledge/data/python-api/Peer.json +85 -0
- package/dist/knowledge/data/python-api/Point.json +32 -0
- package/dist/knowledge/data/python-api/Position.json +92 -0
- package/dist/knowledge/data/python-api/Prim.json +63 -0
- package/dist/knowledge/data/python-api/Project.json +118 -0
- package/dist/knowledge/data/python-api/PythonOp.json +140 -0
- package/dist/knowledge/data/python-api/Quaternion.json +24 -0
- package/dist/knowledge/data/python-api/Replicator_COMP.json +9 -0
- package/dist/knowledge/data/python-api/Run.json +32 -0
- package/dist/knowledge/data/python-api/Runs.json +10 -0
- package/dist/knowledge/data/python-api/SOP.json +642 -0
- package/dist/knowledge/data/python-api/ScriptOp.json +119 -0
- package/dist/knowledge/data/python-api/Segment.json +25 -0
- package/dist/knowledge/data/python-api/Sequence.json +48 -0
- package/dist/knowledge/data/python-api/Stype.json +9 -0
- package/dist/knowledge/data/python-api/SysInfo.json +25 -0
- package/dist/knowledge/data/python-api/TOP.json +724 -0
- package/dist/knowledge/data/python-api/Timecode.json +200 -0
- package/dist/knowledge/data/python-api/UI.json +73 -0
- package/dist/knowledge/data/python-api/Vertex.json +25 -0
- package/dist/knowledge/data/python-api/baseCOMP.json +1019 -0
- package/dist/knowledge/data/python-api/evaluateDAT.json +1289 -0
- package/dist/knowledge/data/python-api/examineDAT.json +1289 -0
- package/dist/knowledge/data/python-api/glslTOP.json +724 -0
- package/dist/knowledge/data/python-api/index.json +1 -0
- package/dist/knowledge/data/python-api/listCOMP.json +1516 -0
- package/dist/knowledge/data/python-api/midiinDAT.json +1328 -0
- package/dist/knowledge/data/python-api/scriptCHOP.json +24 -0
- package/dist/knowledge/data/python-api/scriptDAT.json +1335 -0
- package/dist/knowledge/data/python-api/scriptSOP.json +24 -0
- package/dist/knowledge/data/python-api/scriptTOP.json +24 -0
- package/dist/knowledge/data/python-api/serialDAT.json +1323 -0
- package/dist/knowledge/data/python-api/tcpipDAT.json +1357 -0
- package/dist/knowledge/data/python-api/td.json +646 -0
- package/dist/knowledge/data/python-api/td_Module.json +24 -0
- package/dist/knowledge/data/tutorials/anatomy_of_a_chop.json +275 -0
- package/dist/knowledge/data/tutorials/build_a_list_comp.json +268 -0
- package/dist/knowledge/data/tutorials/index.json +1 -0
- package/dist/knowledge/data/tutorials/introduction_to_python_tutorial.json +1598 -0
- package/dist/knowledge/data/tutorials/tdbitwig_user_guide.json +1986 -0
- package/dist/knowledge/data/tutorials/touchdesigner_video_server_specification_guide.json +555 -0
- package/dist/knowledge/data/tutorials/video_streaming_user_guide.json +653 -0
- package/dist/knowledge/data/tutorials/write_a_cplusplus_chop.json +139 -0
- package/dist/knowledge/data/tutorials/write_a_cplusplus_plugin.json +796 -0
- package/dist/knowledge/data/tutorials/write_a_cplusplus_top.json +104 -0
- package/dist/knowledge/data/tutorials/write_a_cuda_dll.json +259 -0
- package/dist/knowledge/data/tutorials/write_a_glsl_material.json +2353 -0
- package/dist/knowledge/data/tutorials/write_a_glsl_top.json +818 -0
- package/dist/knowledge/data/tutorials/write_a_shared_memory_chop.json +261 -0
- package/dist/knowledge/data/tutorials/write_a_shared_memory_top.json +193 -0
- package/dist/recipes/audio_spectrum_bars.json +26 -0
- package/dist/recipes/data_sonification.json +37 -0
- package/dist/recipes/feedback_tunnel.json +73 -0
- package/dist/recipes/kinect_silhouette.json +45 -0
- package/dist/recipes/led_strip_mapper.json +32 -0
- package/dist/recipes/noise_landscape.json +76 -0
- package/dist/recipes/particle_galaxy.json +52 -0
- package/dist/recipes/projection_mapping.json +25 -0
- package/dist/recipes/reaction_diffusion.json +90 -0
- package/dist/recipes/webcam_glitch.json +40 -0
- package/package.json +74 -0
- package/recipes/audio_spectrum_bars.json +26 -0
- package/recipes/data_sonification.json +37 -0
- package/recipes/feedback_tunnel.json +73 -0
- package/recipes/kinect_silhouette.json +45 -0
- package/recipes/led_strip_mapper.json +32 -0
- package/recipes/noise_landscape.json +76 -0
- package/recipes/particle_galaxy.json +52 -0
- package/recipes/projection_mapping.json +25 -0
- package/recipes/reaction_diffusion.json +90 -0
- package/recipes/webcam_glitch.json +40 -0
- package/td/README.md +160 -0
- package/td/bootstrap.py +73 -0
- package/td/modules/mcp/__init__.py +1 -0
- package/td/modules/mcp/controllers/__init__.py +1 -0
- package/td/modules/mcp/controllers/api_controller.py +240 -0
- package/td/modules/mcp/dev.py +40 -0
- package/td/modules/mcp/events.py +25 -0
- package/td/modules/mcp/install.py +155 -0
- package/td/modules/mcp/services/__init__.py +1 -0
- package/td/modules/mcp/services/analysis_service.py +64 -0
- package/td/modules/mcp/services/api_service.py +195 -0
- package/td/modules/mcp/services/batch_service.py +49 -0
- package/td/modules/mcp/services/preview_service.py +40 -0
- package/td/modules/utils/__init__.py +1 -0
- package/td/modules/utils/version.py +3 -0
- package/td/startup.py +34 -0
- package/td/templates/webserver_callbacks.py +50 -0
- package/td/tests/test_api_controller.py +242 -0
|
@@ -0,0 +1,1902 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/cli/agent.ts
|
|
4
|
+
import { pathToFileURL } from "url";
|
|
5
|
+
import { parseArgs } from "util";
|
|
6
|
+
import { z as z21 } from "zod";
|
|
7
|
+
|
|
8
|
+
// src/knowledge/index.ts
|
|
9
|
+
import { existsSync as existsSync2, readdirSync, readFileSync } from "fs";
|
|
10
|
+
import { join } from "path";
|
|
11
|
+
|
|
12
|
+
// src/utils/logger.ts
|
|
13
|
+
var LEVELS = {
|
|
14
|
+
debug: 10,
|
|
15
|
+
info: 20,
|
|
16
|
+
warn: 30,
|
|
17
|
+
error: 40,
|
|
18
|
+
silent: 99
|
|
19
|
+
};
|
|
20
|
+
function createLogger(level = "info") {
|
|
21
|
+
const threshold = LEVELS[level];
|
|
22
|
+
const emit = (lvl, message, meta) => {
|
|
23
|
+
if (LEVELS[lvl] < threshold) return;
|
|
24
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
25
|
+
const suffix = meta && Object.keys(meta).length > 0 ? ` ${JSON.stringify(meta)}` : "";
|
|
26
|
+
process.stderr.write(`[tdmcp] ${stamp} ${lvl.toUpperCase()} ${message}${suffix}
|
|
27
|
+
`);
|
|
28
|
+
};
|
|
29
|
+
return {
|
|
30
|
+
debug: (message, meta) => emit("debug", message, meta),
|
|
31
|
+
info: (message, meta) => emit("info", message, meta),
|
|
32
|
+
warn: (message, meta) => emit("warn", message, meta),
|
|
33
|
+
error: (message, meta) => emit("error", message, meta)
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
var silentLogger = {
|
|
37
|
+
debug: () => {
|
|
38
|
+
},
|
|
39
|
+
info: () => {
|
|
40
|
+
},
|
|
41
|
+
warn: () => {
|
|
42
|
+
},
|
|
43
|
+
error: () => {
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// src/utils/paths.ts
|
|
48
|
+
import { existsSync } from "fs";
|
|
49
|
+
import { dirname, resolve } from "path";
|
|
50
|
+
import { fileURLToPath } from "url";
|
|
51
|
+
var moduleDir = dirname(fileURLToPath(import.meta.url));
|
|
52
|
+
function firstExisting(candidates, fallback) {
|
|
53
|
+
for (const candidate of candidates) {
|
|
54
|
+
if (existsSync(candidate)) return candidate;
|
|
55
|
+
}
|
|
56
|
+
return fallback;
|
|
57
|
+
}
|
|
58
|
+
function knowledgeDataDir() {
|
|
59
|
+
return firstExisting(
|
|
60
|
+
[resolve(moduleDir, "../knowledge/data"), resolve(moduleDir, "knowledge/data")],
|
|
61
|
+
resolve(moduleDir, "../knowledge/data")
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
function recipesDir() {
|
|
65
|
+
return firstExisting(
|
|
66
|
+
[resolve(moduleDir, "../../recipes"), resolve(moduleDir, "recipes")],
|
|
67
|
+
resolve(moduleDir, "../../recipes")
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
function bottobotPackageDir() {
|
|
71
|
+
const candidates = [
|
|
72
|
+
resolve(moduleDir, "../../node_modules/@bottobot/td-mcp"),
|
|
73
|
+
resolve(moduleDir, "../node_modules/@bottobot/td-mcp"),
|
|
74
|
+
resolve(process.cwd(), "node_modules/@bottobot/td-mcp")
|
|
75
|
+
];
|
|
76
|
+
for (const candidate of candidates) {
|
|
77
|
+
if (existsSync(resolve(candidate, "wiki/data/processed"))) return candidate;
|
|
78
|
+
}
|
|
79
|
+
return void 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// src/knowledge/normalize.ts
|
|
83
|
+
function slugify(value) {
|
|
84
|
+
return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
85
|
+
}
|
|
86
|
+
function compactKey(value) {
|
|
87
|
+
return value.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
88
|
+
}
|
|
89
|
+
function toOperatorSummary(slug, doc) {
|
|
90
|
+
return {
|
|
91
|
+
slug,
|
|
92
|
+
name: doc.name,
|
|
93
|
+
displayName: doc.displayName ?? doc.name,
|
|
94
|
+
category: doc.category ?? "Unknown",
|
|
95
|
+
subcategory: doc.subcategory ?? "",
|
|
96
|
+
summary: doc.summary ?? doc.description ?? "",
|
|
97
|
+
keywords: doc.keywords ?? []
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function toPythonSummary(cls) {
|
|
101
|
+
return {
|
|
102
|
+
className: cls.className,
|
|
103
|
+
displayName: cls.displayName ?? cls.className,
|
|
104
|
+
category: cls.category ?? "Unknown",
|
|
105
|
+
methodCount: cls.methods?.length ?? 0,
|
|
106
|
+
memberCount: cls.members?.length ?? 0
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function toTutorialSummary(tut) {
|
|
110
|
+
return {
|
|
111
|
+
id: tut.id,
|
|
112
|
+
name: tut.name,
|
|
113
|
+
category: tut.category ?? "Unknown",
|
|
114
|
+
summary: tut.summary ?? tut.description ?? ""
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
function normalizePatterns(raw) {
|
|
118
|
+
let list = [];
|
|
119
|
+
if (Array.isArray(raw)) {
|
|
120
|
+
list = raw;
|
|
121
|
+
} else if (raw && typeof raw === "object") {
|
|
122
|
+
const obj = raw;
|
|
123
|
+
if (Array.isArray(obj.patterns)) {
|
|
124
|
+
list = obj.patterns;
|
|
125
|
+
} else {
|
|
126
|
+
list = Object.values(obj).filter((v) => !!v && typeof v === "object");
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return list.filter((p) => typeof p.name === "string").map((p) => ({
|
|
130
|
+
id: slugify(p.name),
|
|
131
|
+
name: p.name,
|
|
132
|
+
description: p.description,
|
|
133
|
+
category: p.category,
|
|
134
|
+
workflow: Array.isArray(p.workflow) ? p.workflow : void 0,
|
|
135
|
+
use_case: p.use_case
|
|
136
|
+
}));
|
|
137
|
+
}
|
|
138
|
+
function normalizeGlsl(raw) {
|
|
139
|
+
const file = raw ?? {};
|
|
140
|
+
const techniques = Array.isArray(file.techniques) ? file.techniques : [];
|
|
141
|
+
return techniques.filter((t) => !!t && typeof t === "object").map((t) => {
|
|
142
|
+
const name = typeof t.name === "string" ? t.name : "Untitled";
|
|
143
|
+
const id = typeof t.id === "string" && t.id.length > 0 ? t.id : slugify(name);
|
|
144
|
+
return {
|
|
145
|
+
id,
|
|
146
|
+
name,
|
|
147
|
+
subcategory: typeof t.subcategory === "string" ? t.subcategory : void 0,
|
|
148
|
+
description: typeof t.description === "string" ? t.description : void 0,
|
|
149
|
+
difficulty: typeof t.difficulty === "string" ? t.difficulty : void 0,
|
|
150
|
+
operators: Array.isArray(t.operators) ? t.operators : void 0,
|
|
151
|
+
tags: Array.isArray(t.tags) ? t.tags : void 0,
|
|
152
|
+
notes: typeof t.notes === "string" ? t.notes : void 0,
|
|
153
|
+
code: t.code ?? void 0,
|
|
154
|
+
setup: typeof t.setup === "string" ? t.setup : void 0
|
|
155
|
+
};
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// src/knowledge/index.ts
|
|
160
|
+
var EMPTY_SOURCE = {
|
|
161
|
+
kind: "empty",
|
|
162
|
+
operatorsDir: "",
|
|
163
|
+
pythonDir: "",
|
|
164
|
+
tutorialsDir: "",
|
|
165
|
+
patternsFile: "",
|
|
166
|
+
glslFile: ""
|
|
167
|
+
};
|
|
168
|
+
var KnowledgeBase = class _KnowledgeBase {
|
|
169
|
+
logger;
|
|
170
|
+
source;
|
|
171
|
+
opIndexCache;
|
|
172
|
+
opLookupCache;
|
|
173
|
+
opDocCache = /* @__PURE__ */ new Map();
|
|
174
|
+
pyIndexCache;
|
|
175
|
+
pyLookupCache;
|
|
176
|
+
pyDocCache = /* @__PURE__ */ new Map();
|
|
177
|
+
tutIndexCache;
|
|
178
|
+
tutLookupCache;
|
|
179
|
+
tutDocCache = /* @__PURE__ */ new Map();
|
|
180
|
+
patternsCache;
|
|
181
|
+
glslCache;
|
|
182
|
+
constructor(options = {}) {
|
|
183
|
+
this.logger = options.logger ?? silentLogger;
|
|
184
|
+
this.source = _KnowledgeBase.resolveSource(options.dataDir ?? knowledgeDataDir());
|
|
185
|
+
this.logger.debug("knowledge source resolved", { kind: this.source.kind });
|
|
186
|
+
}
|
|
187
|
+
static resolveSource(localDir) {
|
|
188
|
+
if (existsSync2(join(localDir, "operators"))) {
|
|
189
|
+
return {
|
|
190
|
+
kind: "local",
|
|
191
|
+
operatorsDir: join(localDir, "operators"),
|
|
192
|
+
operatorsIndex: join(localDir, "operators", "index.json"),
|
|
193
|
+
pythonDir: join(localDir, "python-api"),
|
|
194
|
+
tutorialsDir: join(localDir, "tutorials"),
|
|
195
|
+
patternsFile: join(localDir, "patterns.json"),
|
|
196
|
+
glslFile: join(localDir, "glsl.json")
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
const bb = bottobotPackageDir();
|
|
200
|
+
if (bb) {
|
|
201
|
+
return {
|
|
202
|
+
kind: "bottobot",
|
|
203
|
+
operatorsDir: join(bb, "wiki/data/processed"),
|
|
204
|
+
pythonDir: join(bb, "wiki/data/python-api"),
|
|
205
|
+
tutorialsDir: join(bb, "wiki/data/tutorials"),
|
|
206
|
+
patternsFile: join(bb, "data/patterns.json"),
|
|
207
|
+
glslFile: join(bb, "wiki/data/experimental/glsl.json")
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
return EMPTY_SOURCE;
|
|
211
|
+
}
|
|
212
|
+
readJson(path) {
|
|
213
|
+
try {
|
|
214
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
215
|
+
} catch (err) {
|
|
216
|
+
this.logger.debug("knowledge readJson failed", { path, error: String(err) });
|
|
217
|
+
return void 0;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
listJsonFiles(dir) {
|
|
221
|
+
if (!dir || !existsSync2(dir)) return [];
|
|
222
|
+
try {
|
|
223
|
+
return readdirSync(dir).filter((f) => f.endsWith(".json") && f !== "index.json");
|
|
224
|
+
} catch {
|
|
225
|
+
return [];
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
// ---- Operators -----------------------------------------------------------
|
|
229
|
+
operatorIndex() {
|
|
230
|
+
if (this.opIndexCache) return this.opIndexCache;
|
|
231
|
+
if (this.source.kind === "empty") {
|
|
232
|
+
this.opIndexCache = [];
|
|
233
|
+
return this.opIndexCache;
|
|
234
|
+
}
|
|
235
|
+
if (this.source.operatorsIndex && existsSync2(this.source.operatorsIndex)) {
|
|
236
|
+
const data = this.readJson(this.source.operatorsIndex);
|
|
237
|
+
if (Array.isArray(data)) {
|
|
238
|
+
this.opIndexCache = data;
|
|
239
|
+
return this.opIndexCache;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
const summaries = [];
|
|
243
|
+
for (const file of this.listJsonFiles(this.source.operatorsDir)) {
|
|
244
|
+
const doc = this.readJson(join(this.source.operatorsDir, file));
|
|
245
|
+
if (doc?.name) summaries.push(toOperatorSummary(file.replace(/\.json$/, ""), doc));
|
|
246
|
+
}
|
|
247
|
+
this.opIndexCache = summaries;
|
|
248
|
+
return this.opIndexCache;
|
|
249
|
+
}
|
|
250
|
+
operatorLookup() {
|
|
251
|
+
if (this.opLookupCache) return this.opLookupCache;
|
|
252
|
+
const map = /* @__PURE__ */ new Map();
|
|
253
|
+
for (const summary of this.operatorIndex()) {
|
|
254
|
+
map.set(compactKey(summary.slug), summary.slug);
|
|
255
|
+
map.set(compactKey(summary.name), summary.slug);
|
|
256
|
+
map.set(compactKey(summary.displayName), summary.slug);
|
|
257
|
+
}
|
|
258
|
+
this.opLookupCache = map;
|
|
259
|
+
return map;
|
|
260
|
+
}
|
|
261
|
+
listOperatorCategories() {
|
|
262
|
+
const set = /* @__PURE__ */ new Set();
|
|
263
|
+
for (const summary of this.operatorIndex()) set.add(summary.category);
|
|
264
|
+
return [...set].sort();
|
|
265
|
+
}
|
|
266
|
+
listOperators(category) {
|
|
267
|
+
const all = this.operatorIndex();
|
|
268
|
+
if (!category) return all;
|
|
269
|
+
const wanted = compactKey(category);
|
|
270
|
+
return all.filter((s) => compactKey(s.category) === wanted);
|
|
271
|
+
}
|
|
272
|
+
getOperator(nameOrSlug) {
|
|
273
|
+
if (this.source.kind === "empty") return void 0;
|
|
274
|
+
const slug = this.operatorLookup().get(compactKey(nameOrSlug)) ?? slugify(nameOrSlug);
|
|
275
|
+
const cached = this.opDocCache.get(slug);
|
|
276
|
+
if (cached !== void 0) return cached ?? void 0;
|
|
277
|
+
const file = join(this.source.operatorsDir, `${slug}.json`);
|
|
278
|
+
const doc = existsSync2(file) ? this.readJson(file) : void 0;
|
|
279
|
+
this.opDocCache.set(slug, doc ?? null);
|
|
280
|
+
return doc;
|
|
281
|
+
}
|
|
282
|
+
/** Soft existence check (by operator type, display name, or slug). */
|
|
283
|
+
operatorExists(typeOrName) {
|
|
284
|
+
return this.operatorLookup().has(compactKey(typeOrName));
|
|
285
|
+
}
|
|
286
|
+
searchOperators(query, limit = 25) {
|
|
287
|
+
const q = query.trim().toLowerCase();
|
|
288
|
+
if (!q) return [];
|
|
289
|
+
const terms = q.split(/\s+/);
|
|
290
|
+
const scored = [];
|
|
291
|
+
for (const summary of this.operatorIndex()) {
|
|
292
|
+
const haystack = `${summary.name} ${summary.displayName} ${summary.summary} ${summary.keywords.join(" ")}`.toLowerCase();
|
|
293
|
+
let score = 0;
|
|
294
|
+
for (const term of terms) {
|
|
295
|
+
if (haystack.includes(term)) score += 1;
|
|
296
|
+
if (summary.name.toLowerCase().includes(term)) score += 1;
|
|
297
|
+
}
|
|
298
|
+
if (score > 0) scored.push({ summary, score });
|
|
299
|
+
}
|
|
300
|
+
scored.sort((a, b) => b.score - a.score);
|
|
301
|
+
return scored.slice(0, limit).map((s) => s.summary);
|
|
302
|
+
}
|
|
303
|
+
// ---- Python API ----------------------------------------------------------
|
|
304
|
+
pythonIndex() {
|
|
305
|
+
if (this.pyIndexCache) return this.pyIndexCache;
|
|
306
|
+
if (this.source.kind === "empty") {
|
|
307
|
+
this.pyIndexCache = [];
|
|
308
|
+
return this.pyIndexCache;
|
|
309
|
+
}
|
|
310
|
+
const indexPath = join(this.source.pythonDir, "index.json");
|
|
311
|
+
if (existsSync2(indexPath)) {
|
|
312
|
+
const data = this.readJson(indexPath);
|
|
313
|
+
if (Array.isArray(data)) {
|
|
314
|
+
this.pyIndexCache = data;
|
|
315
|
+
return this.pyIndexCache;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
const summaries = [];
|
|
319
|
+
for (const file of this.listJsonFiles(this.source.pythonDir)) {
|
|
320
|
+
const cls = this.readJson(join(this.source.pythonDir, file));
|
|
321
|
+
if (cls?.className) summaries.push(toPythonSummary(cls));
|
|
322
|
+
}
|
|
323
|
+
this.pyIndexCache = summaries;
|
|
324
|
+
return this.pyIndexCache;
|
|
325
|
+
}
|
|
326
|
+
pythonLookup() {
|
|
327
|
+
if (this.pyLookupCache) return this.pyLookupCache;
|
|
328
|
+
const map = /* @__PURE__ */ new Map();
|
|
329
|
+
for (const summary of this.pythonIndex()) {
|
|
330
|
+
map.set(compactKey(summary.className), summary.className);
|
|
331
|
+
map.set(compactKey(summary.displayName), summary.className);
|
|
332
|
+
}
|
|
333
|
+
this.pyLookupCache = map;
|
|
334
|
+
return map;
|
|
335
|
+
}
|
|
336
|
+
listPythonClasses() {
|
|
337
|
+
return this.pythonIndex();
|
|
338
|
+
}
|
|
339
|
+
getPythonClass(name) {
|
|
340
|
+
if (this.source.kind === "empty") return void 0;
|
|
341
|
+
const className = this.pythonLookup().get(compactKey(name)) ?? name;
|
|
342
|
+
const cached = this.pyDocCache.get(className);
|
|
343
|
+
if (cached !== void 0) return cached ?? void 0;
|
|
344
|
+
const file = join(this.source.pythonDir, `${className}.json`);
|
|
345
|
+
const cls = existsSync2(file) ? this.readJson(file) : void 0;
|
|
346
|
+
this.pyDocCache.set(className, cls ?? null);
|
|
347
|
+
return cls;
|
|
348
|
+
}
|
|
349
|
+
// ---- Patterns ------------------------------------------------------------
|
|
350
|
+
patterns() {
|
|
351
|
+
if (this.patternsCache) return this.patternsCache;
|
|
352
|
+
if (this.source.kind === "empty") {
|
|
353
|
+
this.patternsCache = [];
|
|
354
|
+
return this.patternsCache;
|
|
355
|
+
}
|
|
356
|
+
const data = this.readJson(this.source.patternsFile);
|
|
357
|
+
if (Array.isArray(data) && data.length > 0 && typeof data[0].id === "string") {
|
|
358
|
+
this.patternsCache = data;
|
|
359
|
+
} else {
|
|
360
|
+
this.patternsCache = normalizePatterns(data);
|
|
361
|
+
}
|
|
362
|
+
return this.patternsCache;
|
|
363
|
+
}
|
|
364
|
+
listPatterns() {
|
|
365
|
+
return this.patterns().map((p) => ({
|
|
366
|
+
id: p.id,
|
|
367
|
+
name: p.name,
|
|
368
|
+
category: p.category ?? "Unknown",
|
|
369
|
+
description: p.description ?? ""
|
|
370
|
+
}));
|
|
371
|
+
}
|
|
372
|
+
getPattern(name) {
|
|
373
|
+
const key = compactKey(name);
|
|
374
|
+
return this.patterns().find((p) => compactKey(p.id) === key || compactKey(p.name) === key);
|
|
375
|
+
}
|
|
376
|
+
// ---- GLSL ----------------------------------------------------------------
|
|
377
|
+
glsl() {
|
|
378
|
+
if (this.glslCache) return this.glslCache;
|
|
379
|
+
if (this.source.kind === "empty") {
|
|
380
|
+
this.glslCache = [];
|
|
381
|
+
return this.glslCache;
|
|
382
|
+
}
|
|
383
|
+
const data = this.readJson(this.source.glslFile);
|
|
384
|
+
this.glslCache = Array.isArray(data) ? data : normalizeGlsl(data);
|
|
385
|
+
return this.glslCache;
|
|
386
|
+
}
|
|
387
|
+
listGlslPatterns() {
|
|
388
|
+
return this.glsl().map((g) => ({
|
|
389
|
+
id: g.id,
|
|
390
|
+
name: g.name,
|
|
391
|
+
description: g.description ?? "",
|
|
392
|
+
difficulty: g.difficulty ?? "unknown"
|
|
393
|
+
}));
|
|
394
|
+
}
|
|
395
|
+
getGlslPattern(name) {
|
|
396
|
+
const key = compactKey(name);
|
|
397
|
+
return this.glsl().find((g) => compactKey(g.id) === key || compactKey(g.name) === key);
|
|
398
|
+
}
|
|
399
|
+
// ---- Tutorials -----------------------------------------------------------
|
|
400
|
+
tutorialIndex() {
|
|
401
|
+
if (this.tutIndexCache) return this.tutIndexCache;
|
|
402
|
+
if (this.source.kind === "empty") {
|
|
403
|
+
this.tutIndexCache = [];
|
|
404
|
+
return this.tutIndexCache;
|
|
405
|
+
}
|
|
406
|
+
const indexPath = join(this.source.tutorialsDir, "index.json");
|
|
407
|
+
if (existsSync2(indexPath)) {
|
|
408
|
+
const data = this.readJson(indexPath);
|
|
409
|
+
if (Array.isArray(data)) {
|
|
410
|
+
this.tutIndexCache = data;
|
|
411
|
+
return this.tutIndexCache;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
const summaries = [];
|
|
415
|
+
for (const file of this.listJsonFiles(this.source.tutorialsDir)) {
|
|
416
|
+
const tut = this.readJson(join(this.source.tutorialsDir, file));
|
|
417
|
+
if (tut?.id || tut?.name) {
|
|
418
|
+
const normalized = {
|
|
419
|
+
...tut,
|
|
420
|
+
id: tut.id ?? file.replace(/\.json$/, ""),
|
|
421
|
+
name: tut.name ?? file
|
|
422
|
+
};
|
|
423
|
+
summaries.push(toTutorialSummary(normalized));
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
this.tutIndexCache = summaries;
|
|
427
|
+
return this.tutIndexCache;
|
|
428
|
+
}
|
|
429
|
+
tutorialLookup() {
|
|
430
|
+
if (this.tutLookupCache) return this.tutLookupCache;
|
|
431
|
+
const map = /* @__PURE__ */ new Map();
|
|
432
|
+
for (const file of this.listJsonFiles(this.source.tutorialsDir)) {
|
|
433
|
+
const slug = file.replace(/\.json$/, "");
|
|
434
|
+
map.set(compactKey(slug), slug);
|
|
435
|
+
}
|
|
436
|
+
for (const summary of this.tutorialIndex()) {
|
|
437
|
+
map.set(compactKey(summary.id), summary.id);
|
|
438
|
+
map.set(compactKey(summary.name), summary.id);
|
|
439
|
+
}
|
|
440
|
+
this.tutLookupCache = map;
|
|
441
|
+
return map;
|
|
442
|
+
}
|
|
443
|
+
listTutorials() {
|
|
444
|
+
return this.tutorialIndex();
|
|
445
|
+
}
|
|
446
|
+
getTutorial(name) {
|
|
447
|
+
if (this.source.kind === "empty") return void 0;
|
|
448
|
+
const slug = this.tutorialLookup().get(compactKey(name)) ?? slugify(name);
|
|
449
|
+
const cached = this.tutDocCache.get(slug);
|
|
450
|
+
if (cached !== void 0) return cached ?? void 0;
|
|
451
|
+
const file = join(this.source.tutorialsDir, `${slug}.json`);
|
|
452
|
+
const tut = existsSync2(file) ? this.readJson(file) : void 0;
|
|
453
|
+
this.tutDocCache.set(slug, tut ?? null);
|
|
454
|
+
return tut;
|
|
455
|
+
}
|
|
456
|
+
// ---- Meta ----------------------------------------------------------------
|
|
457
|
+
get sourceKind() {
|
|
458
|
+
return this.source.kind;
|
|
459
|
+
}
|
|
460
|
+
stats() {
|
|
461
|
+
return {
|
|
462
|
+
source: this.source.kind,
|
|
463
|
+
operators: this.operatorIndex().length,
|
|
464
|
+
pythonClasses: this.pythonIndex().length,
|
|
465
|
+
patterns: this.patterns().length,
|
|
466
|
+
glsl: this.glsl().length,
|
|
467
|
+
tutorials: this.tutorialIndex().length
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
// src/recipes/loader.ts
|
|
473
|
+
import { existsSync as existsSync3, readdirSync as readdirSync2, readFileSync as readFileSync2 } from "fs";
|
|
474
|
+
import { join as join2 } from "path";
|
|
475
|
+
|
|
476
|
+
// src/recipes/schema.ts
|
|
477
|
+
import { z } from "zod";
|
|
478
|
+
var RecipeNodeSchema = z.object({
|
|
479
|
+
name: z.string().describe("Unique node name within the recipe (used for wiring)."),
|
|
480
|
+
type: z.string().describe("Operator type, e.g. 'noiseTOP'."),
|
|
481
|
+
parameters: z.record(z.string(), z.unknown()).default({}),
|
|
482
|
+
parent: z.string().optional().describe(
|
|
483
|
+
"Name of another recipe node (a COMP, e.g. a geometryCOMP) to nest this node inside of. The parent must appear earlier in `nodes`. Used to place SOPs inside a Geometry COMP."
|
|
484
|
+
),
|
|
485
|
+
render: z.boolean().optional().describe(
|
|
486
|
+
"For a SOP nested in a geometryCOMP: make this the rendered geometry. Sets the render/display flags on it and clears its siblings, so the COMP renders this instead of its default torus."
|
|
487
|
+
),
|
|
488
|
+
comment: z.string().optional()
|
|
489
|
+
});
|
|
490
|
+
var RecipeConnectionSchema = z.object({
|
|
491
|
+
from: z.string().describe("Source node name."),
|
|
492
|
+
to: z.string().describe("Target node name."),
|
|
493
|
+
from_output: z.number().int().nonnegative().default(0),
|
|
494
|
+
to_input: z.number().int().nonnegative().default(0)
|
|
495
|
+
});
|
|
496
|
+
var RecipeParameterSchema = z.object({
|
|
497
|
+
name: z.string().describe("Friendly name of the exposed control."),
|
|
498
|
+
node: z.string().describe("Recipe node name the parameter belongs to."),
|
|
499
|
+
param: z.string().describe("TD parameter name on that node."),
|
|
500
|
+
value: z.unknown().optional(),
|
|
501
|
+
label: z.string().optional(),
|
|
502
|
+
min: z.number().optional(),
|
|
503
|
+
max: z.number().optional(),
|
|
504
|
+
description: z.string().optional()
|
|
505
|
+
});
|
|
506
|
+
var RecipeGlslUniformSchema = z.object({
|
|
507
|
+
node: z.string().describe("Recipe node name of the GLSL TOP that declares the uniform."),
|
|
508
|
+
name: z.string().describe("Uniform name as referenced in the shader, e.g. 'uFeed'."),
|
|
509
|
+
kind: z.enum(["float", "vec", "color"]).default("float").describe(
|
|
510
|
+
"Uniform kind: float (uniform float), vec (uniform vec2/3/4), color (rgba). float/vec use the Vectors page; color uses the Colors page."
|
|
511
|
+
),
|
|
512
|
+
value: z.union([z.number(), z.array(z.number())]).optional().describe("Initial value: a number for float, or an array of components for vec/color."),
|
|
513
|
+
label: z.string().optional(),
|
|
514
|
+
min: z.number().optional(),
|
|
515
|
+
max: z.number().optional(),
|
|
516
|
+
description: z.string().optional()
|
|
517
|
+
});
|
|
518
|
+
var RecipeSchema = z.object({
|
|
519
|
+
id: z.string(),
|
|
520
|
+
name: z.string(),
|
|
521
|
+
description: z.string().default(""),
|
|
522
|
+
tags: z.array(z.string()).default([]),
|
|
523
|
+
difficulty: z.enum(["beginner", "intermediate", "advanced"]).default("intermediate"),
|
|
524
|
+
td_version_min: z.string().default("2023"),
|
|
525
|
+
nodes: z.array(RecipeNodeSchema).min(1),
|
|
526
|
+
connections: z.array(RecipeConnectionSchema).default([]),
|
|
527
|
+
parameters: z.array(RecipeParameterSchema).default([]),
|
|
528
|
+
glsl_uniforms: z.array(RecipeGlslUniformSchema).default([]),
|
|
529
|
+
glsl_code: z.record(z.string(), z.string()).optional(),
|
|
530
|
+
python_code: z.record(z.string(), z.string()).optional(),
|
|
531
|
+
preview_description: z.string().default("")
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
// src/recipes/loader.ts
|
|
535
|
+
var RecipeLibrary = class {
|
|
536
|
+
dir;
|
|
537
|
+
logger;
|
|
538
|
+
cache;
|
|
539
|
+
constructor(options = {}) {
|
|
540
|
+
this.dir = options.dir ?? recipesDir();
|
|
541
|
+
this.logger = options.logger ?? silentLogger;
|
|
542
|
+
}
|
|
543
|
+
load() {
|
|
544
|
+
if (this.cache) return this.cache;
|
|
545
|
+
const recipes = [];
|
|
546
|
+
if (existsSync3(this.dir)) {
|
|
547
|
+
for (const file of readdirSync2(this.dir)) {
|
|
548
|
+
if (!file.endsWith(".json")) continue;
|
|
549
|
+
try {
|
|
550
|
+
const raw = JSON.parse(readFileSync2(join2(this.dir, file), "utf8"));
|
|
551
|
+
const parsed = RecipeSchema.safeParse(raw);
|
|
552
|
+
if (parsed.success) {
|
|
553
|
+
recipes.push(parsed.data);
|
|
554
|
+
} else {
|
|
555
|
+
this.logger.warn(`Invalid recipe ${file}`, { issues: parsed.error.issues.length });
|
|
556
|
+
}
|
|
557
|
+
} catch (err) {
|
|
558
|
+
this.logger.warn(`Failed to read recipe ${file}`, { error: String(err) });
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
this.cache = recipes;
|
|
563
|
+
return recipes;
|
|
564
|
+
}
|
|
565
|
+
all() {
|
|
566
|
+
return this.load();
|
|
567
|
+
}
|
|
568
|
+
list() {
|
|
569
|
+
return this.load().map((r2) => ({
|
|
570
|
+
id: r2.id,
|
|
571
|
+
name: r2.name,
|
|
572
|
+
description: r2.description,
|
|
573
|
+
tags: r2.tags,
|
|
574
|
+
difficulty: r2.difficulty
|
|
575
|
+
}));
|
|
576
|
+
}
|
|
577
|
+
get(id) {
|
|
578
|
+
const key = compactKey(id);
|
|
579
|
+
return this.load().find((r2) => compactKey(r2.id) === key || compactKey(r2.name) === key);
|
|
580
|
+
}
|
|
581
|
+
/** Finds the best recipe whose tags/name/description match any of the given terms. */
|
|
582
|
+
findByTags(terms) {
|
|
583
|
+
const wanted = terms.map((t) => t.toLowerCase()).filter(Boolean);
|
|
584
|
+
if (wanted.length === 0) return void 0;
|
|
585
|
+
let best;
|
|
586
|
+
for (const recipe of this.load()) {
|
|
587
|
+
const haystack = `${recipe.name} ${recipe.description} ${recipe.tags.join(" ")}`.toLowerCase();
|
|
588
|
+
let score = 0;
|
|
589
|
+
for (const term of wanted) {
|
|
590
|
+
if (recipe.tags.some((tag) => tag.toLowerCase() === term)) score += 2;
|
|
591
|
+
else if (haystack.includes(term)) score += 1;
|
|
592
|
+
}
|
|
593
|
+
if (score > 0 && (!best || score > best.score)) best = { recipe, score };
|
|
594
|
+
}
|
|
595
|
+
return best?.recipe;
|
|
596
|
+
}
|
|
597
|
+
};
|
|
598
|
+
|
|
599
|
+
// src/td-client/types.ts
|
|
600
|
+
var TdError = class extends Error {
|
|
601
|
+
code;
|
|
602
|
+
constructor(message, code, options) {
|
|
603
|
+
super(message, options);
|
|
604
|
+
this.name = "TdError";
|
|
605
|
+
this.code = code;
|
|
606
|
+
}
|
|
607
|
+
};
|
|
608
|
+
var TdConnectionError = class extends TdError {
|
|
609
|
+
constructor(message, options) {
|
|
610
|
+
super(message, "TD_CONNECTION", options);
|
|
611
|
+
this.name = "TdConnectionError";
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
var TdTimeoutError = class extends TdError {
|
|
615
|
+
constructor(message, options) {
|
|
616
|
+
super(message, "TD_TIMEOUT", options);
|
|
617
|
+
this.name = "TdTimeoutError";
|
|
618
|
+
}
|
|
619
|
+
};
|
|
620
|
+
var TdApiError = class extends TdError {
|
|
621
|
+
status;
|
|
622
|
+
apiCode;
|
|
623
|
+
constructor(message, options) {
|
|
624
|
+
super(message, "TD_API", options);
|
|
625
|
+
this.name = "TdApiError";
|
|
626
|
+
this.status = options?.status;
|
|
627
|
+
this.apiCode = options?.apiCode;
|
|
628
|
+
}
|
|
629
|
+
};
|
|
630
|
+
function friendlyTdError(err) {
|
|
631
|
+
if (err instanceof TdError) return err.message;
|
|
632
|
+
if (err instanceof Error) return err.message;
|
|
633
|
+
return String(err);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
// src/td-client/validators.ts
|
|
637
|
+
import { z as z2 } from "zod";
|
|
638
|
+
var ApiEnvelopeSchema = z2.object({
|
|
639
|
+
ok: z2.boolean(),
|
|
640
|
+
data: z2.unknown().optional(),
|
|
641
|
+
error: z2.object({ code: z2.string().optional(), message: z2.string() }).optional()
|
|
642
|
+
});
|
|
643
|
+
var NodeRefSchema = z2.object({
|
|
644
|
+
path: z2.string(),
|
|
645
|
+
type: z2.string().default(""),
|
|
646
|
+
name: z2.string().default("")
|
|
647
|
+
});
|
|
648
|
+
var NodeDetailSchema = NodeRefSchema.extend({
|
|
649
|
+
parameters: z2.record(z2.string(), z2.unknown()).default({}),
|
|
650
|
+
inputs: z2.array(z2.string()).optional(),
|
|
651
|
+
outputs: z2.array(z2.string()).optional(),
|
|
652
|
+
family: z2.string().optional(),
|
|
653
|
+
errors: z2.array(z2.string()).optional()
|
|
654
|
+
});
|
|
655
|
+
var NodeListSchema = z2.object({ nodes: z2.array(NodeRefSchema).default([]) });
|
|
656
|
+
var InfoSchema = z2.object({
|
|
657
|
+
td_version: z2.string().optional(),
|
|
658
|
+
python_version: z2.string().optional(),
|
|
659
|
+
build: z2.string().optional(),
|
|
660
|
+
bridge_version: z2.string().optional(),
|
|
661
|
+
project: z2.string().optional()
|
|
662
|
+
});
|
|
663
|
+
var NodeErrorSchema = z2.object({
|
|
664
|
+
path: z2.string(),
|
|
665
|
+
message: z2.string(),
|
|
666
|
+
type: z2.string().optional()
|
|
667
|
+
});
|
|
668
|
+
var NodeErrorsSchema = z2.object({ errors: z2.array(NodeErrorSchema).default([]) });
|
|
669
|
+
var PreviewSchema = z2.object({
|
|
670
|
+
path: z2.string(),
|
|
671
|
+
width: z2.number().int().positive(),
|
|
672
|
+
height: z2.number().int().positive(),
|
|
673
|
+
format: z2.string().default("png"),
|
|
674
|
+
base64: z2.string()
|
|
675
|
+
});
|
|
676
|
+
var ExecResultSchema = z2.object({
|
|
677
|
+
result: z2.unknown().optional(),
|
|
678
|
+
stdout: z2.string().optional(),
|
|
679
|
+
printed: z2.array(z2.string()).optional()
|
|
680
|
+
});
|
|
681
|
+
var MethodResultSchema = z2.object({ result: z2.unknown() });
|
|
682
|
+
var DeleteResultSchema = z2.object({ deleted: z2.string() });
|
|
683
|
+
var ConnectionSchema = z2.object({
|
|
684
|
+
source_path: z2.string(),
|
|
685
|
+
source_output: z2.number().int().default(0),
|
|
686
|
+
target_path: z2.string(),
|
|
687
|
+
target_input: z2.number().int().default(0)
|
|
688
|
+
});
|
|
689
|
+
var TopologySchema = z2.object({
|
|
690
|
+
nodes: z2.array(NodeRefSchema).default([]),
|
|
691
|
+
connections: z2.array(ConnectionSchema).default([])
|
|
692
|
+
});
|
|
693
|
+
var PerformanceSchema = z2.object({
|
|
694
|
+
nodes: z2.array(
|
|
695
|
+
z2.object({
|
|
696
|
+
path: z2.string(),
|
|
697
|
+
cook_time_ms: z2.number().default(0),
|
|
698
|
+
cook_count: z2.number().optional()
|
|
699
|
+
})
|
|
700
|
+
).default([]),
|
|
701
|
+
total_cook_time_ms: z2.number().optional(),
|
|
702
|
+
gpu_memory_mb: z2.number().optional()
|
|
703
|
+
});
|
|
704
|
+
var BatchOpResultSchema = z2.object({
|
|
705
|
+
action: z2.string(),
|
|
706
|
+
ok: z2.boolean(),
|
|
707
|
+
path: z2.string().optional(),
|
|
708
|
+
data: z2.unknown().optional(),
|
|
709
|
+
error: z2.string().optional()
|
|
710
|
+
});
|
|
711
|
+
var BatchResultSchema = z2.object({ results: z2.array(BatchOpResultSchema).default([]) });
|
|
712
|
+
var CreateNodeInputSchema = z2.object({
|
|
713
|
+
parent_path: z2.string(),
|
|
714
|
+
type: z2.string(),
|
|
715
|
+
name: z2.string().optional(),
|
|
716
|
+
parameters: z2.record(z2.string(), z2.unknown()).optional()
|
|
717
|
+
});
|
|
718
|
+
var BatchOperationSchema = z2.discriminatedUnion("action", [
|
|
719
|
+
z2.object({
|
|
720
|
+
action: z2.literal("create"),
|
|
721
|
+
parent_path: z2.string(),
|
|
722
|
+
type: z2.string(),
|
|
723
|
+
name: z2.string().optional(),
|
|
724
|
+
parameters: z2.record(z2.string(), z2.unknown()).optional()
|
|
725
|
+
}),
|
|
726
|
+
z2.object({
|
|
727
|
+
action: z2.literal("update"),
|
|
728
|
+
path: z2.string(),
|
|
729
|
+
parameters: z2.record(z2.string(), z2.unknown())
|
|
730
|
+
}),
|
|
731
|
+
z2.object({ action: z2.literal("delete"), path: z2.string() }),
|
|
732
|
+
z2.object({
|
|
733
|
+
action: z2.literal("connect"),
|
|
734
|
+
source_path: z2.string(),
|
|
735
|
+
target_path: z2.string(),
|
|
736
|
+
source_output: z2.number().int().default(0),
|
|
737
|
+
target_input: z2.number().int().default(0)
|
|
738
|
+
})
|
|
739
|
+
]);
|
|
740
|
+
|
|
741
|
+
// src/td-client/touchDesignerClient.ts
|
|
742
|
+
function extractErrorMessage(json) {
|
|
743
|
+
if (json && typeof json === "object") {
|
|
744
|
+
const obj = json;
|
|
745
|
+
const error = obj.error;
|
|
746
|
+
if (error && typeof error === "object" && typeof error.message === "string") {
|
|
747
|
+
return error.message;
|
|
748
|
+
}
|
|
749
|
+
if (typeof obj.message === "string") return obj.message;
|
|
750
|
+
}
|
|
751
|
+
return void 0;
|
|
752
|
+
}
|
|
753
|
+
function segment(path) {
|
|
754
|
+
return encodeURIComponent(path);
|
|
755
|
+
}
|
|
756
|
+
var TouchDesignerClient = class {
|
|
757
|
+
baseUrl;
|
|
758
|
+
timeoutMs;
|
|
759
|
+
logger;
|
|
760
|
+
token;
|
|
761
|
+
fetchImpl;
|
|
762
|
+
constructor(options) {
|
|
763
|
+
this.baseUrl = options.baseUrl.replace(/\/+$/, "");
|
|
764
|
+
this.timeoutMs = options.timeoutMs ?? 1e4;
|
|
765
|
+
this.logger = options.logger ?? silentLogger;
|
|
766
|
+
this.token = options.token;
|
|
767
|
+
this.fetchImpl = options.fetchImpl ?? fetch;
|
|
768
|
+
}
|
|
769
|
+
get endpoint() {
|
|
770
|
+
return this.baseUrl;
|
|
771
|
+
}
|
|
772
|
+
async request(method, path, schema, body, query) {
|
|
773
|
+
const url = new URL(`${this.baseUrl}${path}`);
|
|
774
|
+
if (query) {
|
|
775
|
+
for (const [key, value] of Object.entries(query)) {
|
|
776
|
+
if (value !== void 0) url.searchParams.set(key, String(value));
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
const controller = new AbortController();
|
|
780
|
+
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
781
|
+
let response;
|
|
782
|
+
try {
|
|
783
|
+
this.logger.debug(`TD ${method} ${path}`);
|
|
784
|
+
const headers = {};
|
|
785
|
+
if (body !== void 0) headers["content-type"] = "application/json";
|
|
786
|
+
if (this.token) headers.authorization = `Bearer ${this.token}`;
|
|
787
|
+
response = await this.fetchImpl(url, {
|
|
788
|
+
method,
|
|
789
|
+
signal: controller.signal,
|
|
790
|
+
headers: Object.keys(headers).length > 0 ? headers : void 0,
|
|
791
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
792
|
+
});
|
|
793
|
+
} catch (err) {
|
|
794
|
+
if (err instanceof Error && err.name === "AbortError") {
|
|
795
|
+
throw new TdTimeoutError(
|
|
796
|
+
`TouchDesigner request timed out after ${this.timeoutMs}ms (${method} ${path}).`,
|
|
797
|
+
{ cause: err }
|
|
798
|
+
);
|
|
799
|
+
}
|
|
800
|
+
throw new TdConnectionError(
|
|
801
|
+
`Cannot reach TouchDesigner at ${this.baseUrl}. Make sure TD is running with the tdmcp bridge (WebServer DAT) installed and listening on that port.`,
|
|
802
|
+
{ cause: err }
|
|
803
|
+
);
|
|
804
|
+
} finally {
|
|
805
|
+
clearTimeout(timer);
|
|
806
|
+
}
|
|
807
|
+
const text = await response.text();
|
|
808
|
+
let json;
|
|
809
|
+
if (text) {
|
|
810
|
+
try {
|
|
811
|
+
json = JSON.parse(text);
|
|
812
|
+
} catch {
|
|
813
|
+
json = void 0;
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
if (!response.ok) {
|
|
817
|
+
const message = extractErrorMessage(json) ?? `TouchDesigner bridge returned HTTP ${response.status} for ${method} ${path}.`;
|
|
818
|
+
throw new TdApiError(message, { status: response.status });
|
|
819
|
+
}
|
|
820
|
+
const envelope = ApiEnvelopeSchema.safeParse(json);
|
|
821
|
+
if (!envelope.success) {
|
|
822
|
+
throw new TdApiError(`Malformed response from TouchDesigner bridge for ${method} ${path}.`, {
|
|
823
|
+
status: response.status
|
|
824
|
+
});
|
|
825
|
+
}
|
|
826
|
+
if (!envelope.data.ok) {
|
|
827
|
+
throw new TdApiError(
|
|
828
|
+
envelope.data.error?.message ?? `TouchDesigner reported an error for ${method} ${path}.`,
|
|
829
|
+
{ status: response.status, apiCode: envelope.data.error?.code }
|
|
830
|
+
);
|
|
831
|
+
}
|
|
832
|
+
const parsed = schema.safeParse(envelope.data.data);
|
|
833
|
+
if (!parsed.success) {
|
|
834
|
+
throw new TdApiError(
|
|
835
|
+
`Unexpected data shape from TouchDesigner bridge for ${method} ${path}: ${parsed.error.message}`,
|
|
836
|
+
{ status: response.status }
|
|
837
|
+
);
|
|
838
|
+
}
|
|
839
|
+
return parsed.data;
|
|
840
|
+
}
|
|
841
|
+
getInfo() {
|
|
842
|
+
return this.request("GET", "/api/info", InfoSchema);
|
|
843
|
+
}
|
|
844
|
+
createNode(input) {
|
|
845
|
+
return this.request("POST", "/api/nodes", NodeRefSchema, CreateNodeInputSchema.parse(input));
|
|
846
|
+
}
|
|
847
|
+
deleteNode(path) {
|
|
848
|
+
return this.request("DELETE", `/api/nodes/${segment(path)}`, DeleteResultSchema);
|
|
849
|
+
}
|
|
850
|
+
getNodes(parentPath) {
|
|
851
|
+
return this.request("GET", "/api/nodes", NodeListSchema, void 0, { parent: parentPath });
|
|
852
|
+
}
|
|
853
|
+
getNode(path) {
|
|
854
|
+
return this.request("GET", `/api/nodes/${segment(path)}`, NodeDetailSchema);
|
|
855
|
+
}
|
|
856
|
+
updateNodeParameters(path, parameters) {
|
|
857
|
+
return this.request("PATCH", `/api/nodes/${segment(path)}`, NodeDetailSchema, { parameters });
|
|
858
|
+
}
|
|
859
|
+
executePythonScript(script, returnOutput = true) {
|
|
860
|
+
return this.request("POST", "/api/exec", ExecResultSchema, {
|
|
861
|
+
script,
|
|
862
|
+
return_output: returnOutput
|
|
863
|
+
});
|
|
864
|
+
}
|
|
865
|
+
execNodeMethod(path, method, args = [], kwargs = {}) {
|
|
866
|
+
return this.request("POST", `/api/nodes/${segment(path)}/method`, MethodResultSchema, {
|
|
867
|
+
method,
|
|
868
|
+
args,
|
|
869
|
+
kwargs
|
|
870
|
+
});
|
|
871
|
+
}
|
|
872
|
+
getNodeErrors(path) {
|
|
873
|
+
return this.request("GET", `/api/nodes/${segment(path)}/errors`, NodeErrorsSchema);
|
|
874
|
+
}
|
|
875
|
+
getPreview(path, width = 640, height = 360) {
|
|
876
|
+
return this.request("GET", `/api/preview/${segment(path)}`, PreviewSchema, void 0, {
|
|
877
|
+
width,
|
|
878
|
+
height
|
|
879
|
+
});
|
|
880
|
+
}
|
|
881
|
+
batch(operations) {
|
|
882
|
+
return this.request("POST", "/api/batch", BatchResultSchema, { operations });
|
|
883
|
+
}
|
|
884
|
+
getNetworkErrors(path) {
|
|
885
|
+
return this.request("GET", `/api/network/${segment(path)}/errors`, NodeErrorsSchema);
|
|
886
|
+
}
|
|
887
|
+
getNetworkTopology(path, recursive = false) {
|
|
888
|
+
return this.request(
|
|
889
|
+
"GET",
|
|
890
|
+
`/api/network/${segment(path)}/topology`,
|
|
891
|
+
TopologySchema,
|
|
892
|
+
void 0,
|
|
893
|
+
recursive ? { recursive: true } : void 0
|
|
894
|
+
);
|
|
895
|
+
}
|
|
896
|
+
getNetworkPerformance(path) {
|
|
897
|
+
return this.request("GET", `/api/network/${segment(path)}/performance`, PerformanceSchema);
|
|
898
|
+
}
|
|
899
|
+
};
|
|
900
|
+
|
|
901
|
+
// src/utils/config.ts
|
|
902
|
+
import { z as z3 } from "zod";
|
|
903
|
+
var ConfigSchema = z3.object({
|
|
904
|
+
/** TouchDesigner bridge host. */
|
|
905
|
+
tdHost: z3.string().min(1).default("127.0.0.1"),
|
|
906
|
+
/** TouchDesigner bridge port (WebServer DAT). */
|
|
907
|
+
tdPort: z3.coerce.number().int().positive().max(65535).default(9980),
|
|
908
|
+
/** MCP transport: `stdio` (default, for local clients) or `http` (Streamable HTTP, loopback-only). */
|
|
909
|
+
transport: z3.enum(["stdio", "http"]).default("stdio"),
|
|
910
|
+
/** Log verbosity (written to stderr). */
|
|
911
|
+
logLevel: z3.enum(["debug", "info", "warn", "error", "silent"]).default("info"),
|
|
912
|
+
/** Per-request timeout against the TD bridge, in milliseconds. */
|
|
913
|
+
requestTimeoutMs: z3.coerce.number().int().positive().default(1e4),
|
|
914
|
+
/** HTTP transport port (only used when transport=http). */
|
|
915
|
+
httpPort: z3.coerce.number().int().positive().max(65535).default(3939),
|
|
916
|
+
/** Subscribe to TD WebSocket events and forward them as MCP logging notifications. */
|
|
917
|
+
events: z3.enum(["on", "off"]).default("on"),
|
|
918
|
+
/**
|
|
919
|
+
* Raw Python escape-hatch tools (`execute_python_script`, `exec_node_method`).
|
|
920
|
+
* Set to "off" to lock them out for restricted setups; on by default.
|
|
921
|
+
*/
|
|
922
|
+
rawPython: z3.enum(["on", "off"]).default("on"),
|
|
923
|
+
/**
|
|
924
|
+
* Optional shared bearer token for the TD bridge. When set, the server sends it
|
|
925
|
+
* as `Authorization: Bearer <token>` and the bridge requires a match. Leave unset
|
|
926
|
+
* (default) for the zero-config local flow. Set the SAME value in TouchDesigner's
|
|
927
|
+
* environment (`TDMCP_BRIDGE_TOKEN`) to turn enforcement on.
|
|
928
|
+
*/
|
|
929
|
+
bridgeToken: z3.string().min(1).optional()
|
|
930
|
+
});
|
|
931
|
+
function loadConfig(env = process.env) {
|
|
932
|
+
return ConfigSchema.parse({
|
|
933
|
+
tdHost: env.TDMCP_TD_HOST,
|
|
934
|
+
tdPort: env.TDMCP_TD_PORT,
|
|
935
|
+
transport: env.TDMCP_TRANSPORT,
|
|
936
|
+
logLevel: env.TDMCP_LOG_LEVEL,
|
|
937
|
+
requestTimeoutMs: env.TDMCP_REQUEST_TIMEOUT_MS,
|
|
938
|
+
httpPort: env.TDMCP_HTTP_PORT,
|
|
939
|
+
events: env.TDMCP_EVENTS,
|
|
940
|
+
rawPython: env.TDMCP_RAW_PYTHON,
|
|
941
|
+
bridgeToken: env.TDMCP_BRIDGE_TOKEN || void 0
|
|
942
|
+
});
|
|
943
|
+
}
|
|
944
|
+
function tdBaseUrl(config) {
|
|
945
|
+
return `http://${config.tdHost}:${config.tdPort}`;
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
// src/server/connectionManager.ts
|
|
949
|
+
var ConnectionManager = class {
|
|
950
|
+
client;
|
|
951
|
+
constructor(config, logger) {
|
|
952
|
+
this.client = new TouchDesignerClient({
|
|
953
|
+
baseUrl: tdBaseUrl(config),
|
|
954
|
+
timeoutMs: config.requestTimeoutMs,
|
|
955
|
+
token: config.bridgeToken,
|
|
956
|
+
logger
|
|
957
|
+
});
|
|
958
|
+
}
|
|
959
|
+
async isReachable() {
|
|
960
|
+
try {
|
|
961
|
+
await this.client.getInfo();
|
|
962
|
+
return true;
|
|
963
|
+
} catch {
|
|
964
|
+
return false;
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
};
|
|
968
|
+
|
|
969
|
+
// src/server/context.ts
|
|
970
|
+
function buildToolContext(config, overrides = {}) {
|
|
971
|
+
const logger = overrides.logger ?? createLogger(config.logLevel);
|
|
972
|
+
const connection = overrides.connection ?? new ConnectionManager(config, logger);
|
|
973
|
+
const knowledge = overrides.knowledge ?? new KnowledgeBase({ logger });
|
|
974
|
+
const recipes = overrides.recipes ?? new RecipeLibrary({ logger });
|
|
975
|
+
return {
|
|
976
|
+
client: connection.client,
|
|
977
|
+
knowledge,
|
|
978
|
+
recipes,
|
|
979
|
+
logger,
|
|
980
|
+
allowRawPython: config.rawPython !== "off"
|
|
981
|
+
};
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
// src/tools/layer3/compareTdNodes.ts
|
|
985
|
+
import { z as z4 } from "zod";
|
|
986
|
+
|
|
987
|
+
// src/tools/result.ts
|
|
988
|
+
function textResult(text) {
|
|
989
|
+
return { content: [{ type: "text", text }] };
|
|
990
|
+
}
|
|
991
|
+
function errorResult(message) {
|
|
992
|
+
return { isError: true, content: [{ type: "text", text: message }] };
|
|
993
|
+
}
|
|
994
|
+
function jsonResult(summary, data) {
|
|
995
|
+
const text = `${summary}
|
|
996
|
+
|
|
997
|
+
\`\`\`json
|
|
998
|
+
${JSON.stringify(data, null, 2)}
|
|
999
|
+
\`\`\``;
|
|
1000
|
+
return { content: [{ type: "text", text }] };
|
|
1001
|
+
}
|
|
1002
|
+
function structuredResult(summary, data) {
|
|
1003
|
+
return {
|
|
1004
|
+
content: [{ type: "text", text: summary }],
|
|
1005
|
+
structuredContent: data
|
|
1006
|
+
};
|
|
1007
|
+
}
|
|
1008
|
+
async function guardTd(fn, onOk) {
|
|
1009
|
+
try {
|
|
1010
|
+
return onOk(await fn());
|
|
1011
|
+
} catch (err) {
|
|
1012
|
+
return errorResult(friendlyTdError(err));
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
// src/tools/layer3/compareTdNodes.ts
|
|
1017
|
+
var compareTdNodesSchema = z4.object({
|
|
1018
|
+
path_a: z4.string().describe("First node path."),
|
|
1019
|
+
path_b: z4.string().describe("Second node path."),
|
|
1020
|
+
only_diff: z4.boolean().default(true).describe("Return only the parameters that differ (true) or also list the identical ones.")
|
|
1021
|
+
});
|
|
1022
|
+
var compareTdNodesOutputSchema = z4.object({
|
|
1023
|
+
a: z4.string(),
|
|
1024
|
+
b: z4.string(),
|
|
1025
|
+
type_a: z4.string(),
|
|
1026
|
+
type_b: z4.string(),
|
|
1027
|
+
type_match: z4.boolean(),
|
|
1028
|
+
differing_count: z4.number(),
|
|
1029
|
+
same_count: z4.number(),
|
|
1030
|
+
differing: z4.array(z4.object({ param: z4.string(), a: z4.unknown(), b: z4.unknown() })),
|
|
1031
|
+
identical: z4.array(z4.string()).optional()
|
|
1032
|
+
});
|
|
1033
|
+
async function compareTdNodesImpl(ctx, args) {
|
|
1034
|
+
return guardTd(
|
|
1035
|
+
async () => {
|
|
1036
|
+
const [a, b] = await Promise.all([
|
|
1037
|
+
ctx.client.getNode(args.path_a),
|
|
1038
|
+
ctx.client.getNode(args.path_b)
|
|
1039
|
+
]);
|
|
1040
|
+
return { a, b };
|
|
1041
|
+
},
|
|
1042
|
+
({ a, b }) => {
|
|
1043
|
+
const keys = /* @__PURE__ */ new Set([...Object.keys(a.parameters), ...Object.keys(b.parameters)]);
|
|
1044
|
+
const differing = [];
|
|
1045
|
+
const identical = [];
|
|
1046
|
+
for (const key of [...keys].sort()) {
|
|
1047
|
+
const va = a.parameters[key];
|
|
1048
|
+
const vb = b.parameters[key];
|
|
1049
|
+
if (JSON.stringify(va) === JSON.stringify(vb)) identical.push(key);
|
|
1050
|
+
else differing.push({ param: key, a: va, b: vb });
|
|
1051
|
+
}
|
|
1052
|
+
const data = {
|
|
1053
|
+
a: a.path,
|
|
1054
|
+
b: b.path,
|
|
1055
|
+
type_a: a.type,
|
|
1056
|
+
type_b: b.type,
|
|
1057
|
+
type_match: a.type === b.type,
|
|
1058
|
+
differing_count: differing.length,
|
|
1059
|
+
same_count: identical.length,
|
|
1060
|
+
differing
|
|
1061
|
+
};
|
|
1062
|
+
if (!args.only_diff) data.identical = identical;
|
|
1063
|
+
return structuredResult(
|
|
1064
|
+
`${differing.length} differing parameter(s) between ${a.path} and ${b.path}${a.type === b.type ? "" : ` (types differ: ${a.type} vs ${b.type})`}.`,
|
|
1065
|
+
data
|
|
1066
|
+
);
|
|
1067
|
+
}
|
|
1068
|
+
);
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
// src/tools/layer3/createTdNode.ts
|
|
1072
|
+
import { z as z5 } from "zod";
|
|
1073
|
+
var createTdNodeSchema = z5.object({
|
|
1074
|
+
parent_path: z5.string().default("/project1").describe("Parent COMP path to create the node inside."),
|
|
1075
|
+
type: z5.string().describe("Operator type string, e.g. 'noiseTOP', 'feedbackTOP', 'nullTOP', 'constantCHOP'."),
|
|
1076
|
+
name: z5.string().optional().describe("Optional node name (auto-generated if omitted)."),
|
|
1077
|
+
parameters: z5.record(z5.string(), z5.unknown()).optional().describe("Optional initial parameter overrides as key\u2192value pairs.")
|
|
1078
|
+
});
|
|
1079
|
+
async function createTdNodeImpl(ctx, args) {
|
|
1080
|
+
const warnings = [];
|
|
1081
|
+
if (!ctx.knowledge.operatorExists(args.type)) {
|
|
1082
|
+
const suggestions = ctx.knowledge.searchOperators(args.type, 3).map((s) => s.name);
|
|
1083
|
+
warnings.push(
|
|
1084
|
+
`Operator type "${args.type}" was not found in the knowledge base.${suggestions.length ? ` Did you mean: ${suggestions.join(", ")}?` : ""}`
|
|
1085
|
+
);
|
|
1086
|
+
}
|
|
1087
|
+
return guardTd(
|
|
1088
|
+
() => ctx.client.createNode({
|
|
1089
|
+
parent_path: args.parent_path,
|
|
1090
|
+
type: args.type,
|
|
1091
|
+
name: args.name,
|
|
1092
|
+
parameters: args.parameters
|
|
1093
|
+
}),
|
|
1094
|
+
(node) => jsonResult(`Created ${node.type || args.type} at ${node.path}.`, { node, warnings })
|
|
1095
|
+
);
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
// src/tools/layer3/deleteTdNode.ts
|
|
1099
|
+
import { z as z6 } from "zod";
|
|
1100
|
+
var deleteTdNodeSchema = z6.object({
|
|
1101
|
+
path: z6.string().describe("Full path of the node to delete, e.g. '/project1/noise1'.")
|
|
1102
|
+
});
|
|
1103
|
+
async function deleteTdNodeImpl(ctx, args) {
|
|
1104
|
+
return guardTd(
|
|
1105
|
+
() => ctx.client.deleteNode(args.path),
|
|
1106
|
+
(result) => jsonResult(`Deleted ${result.deleted}.`, result)
|
|
1107
|
+
);
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
// src/tools/layer3/execNodeMethod.ts
|
|
1111
|
+
import { z as z7 } from "zod";
|
|
1112
|
+
var execNodeMethodSchema = z7.object({
|
|
1113
|
+
path: z7.string().describe("Full path of the node to call the method on."),
|
|
1114
|
+
method: z7.string().describe("Method name to call, e.g. 'cook', 'par', 'destroy', 'copy'."),
|
|
1115
|
+
args: z7.array(z7.unknown()).default([]).describe("Positional arguments."),
|
|
1116
|
+
kwargs: z7.record(z7.string(), z7.unknown()).default({}).describe("Keyword arguments.")
|
|
1117
|
+
});
|
|
1118
|
+
async function execNodeMethodImpl(ctx, args) {
|
|
1119
|
+
return guardTd(
|
|
1120
|
+
() => ctx.client.execNodeMethod(args.path, args.method, args.args, args.kwargs),
|
|
1121
|
+
(result) => jsonResult(`Called ${args.path}.${args.method}().`, result)
|
|
1122
|
+
);
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
// src/tools/layer3/executePythonScript.ts
|
|
1126
|
+
import { z as z8 } from "zod";
|
|
1127
|
+
var executePythonScriptSchema = z8.object({
|
|
1128
|
+
script: z8.string().min(1).describe(
|
|
1129
|
+
"Python source to execute inside TouchDesigner (runs in the TD process, not locally)."
|
|
1130
|
+
),
|
|
1131
|
+
return_output: z8.boolean().default(true).describe("Capture stdout / the value of the last expression and return it.")
|
|
1132
|
+
});
|
|
1133
|
+
async function executePythonScriptImpl(ctx, args) {
|
|
1134
|
+
return guardTd(
|
|
1135
|
+
() => ctx.client.executePythonScript(args.script, args.return_output),
|
|
1136
|
+
(result) => jsonResult("Python executed in TouchDesigner.", result)
|
|
1137
|
+
);
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
// src/tools/layer3/findTdNodes.ts
|
|
1141
|
+
import { z as z9 } from "zod";
|
|
1142
|
+
|
|
1143
|
+
// src/tools/layer3/nodeMatch.ts
|
|
1144
|
+
function globToRegExp(pattern) {
|
|
1145
|
+
const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
1146
|
+
return new RegExp(escaped, "i");
|
|
1147
|
+
}
|
|
1148
|
+
function parentOf(path) {
|
|
1149
|
+
const idx = path.lastIndexOf("/");
|
|
1150
|
+
return idx <= 0 ? "/" : path.slice(0, idx);
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
// src/tools/layer3/findTdNodes.ts
|
|
1154
|
+
var findTdNodesSchema = z9.object({
|
|
1155
|
+
parent_path: z9.string().default("/project1").describe("Where to search from."),
|
|
1156
|
+
pattern: z9.string().optional().describe("Case-insensitive name/path filter with '*' wildcards (e.g. 'text*', '*noise*')."),
|
|
1157
|
+
type: z9.string().optional().describe("Case-insensitive operator-type substring (e.g. 'TOP', 'noise')."),
|
|
1158
|
+
recursive: z9.boolean().default(true).describe("Search the whole sub-network (true) or only direct children (false)."),
|
|
1159
|
+
path_only: z9.boolean().default(false).describe("Return only matching paths."),
|
|
1160
|
+
limit: z9.number().int().positive().default(50).describe("Max matches to return.")
|
|
1161
|
+
});
|
|
1162
|
+
var findTdNodesOutputSchema = z9.object({
|
|
1163
|
+
parent_path: z9.string(),
|
|
1164
|
+
recursive: z9.boolean(),
|
|
1165
|
+
count: z9.number(),
|
|
1166
|
+
truncated: z9.boolean(),
|
|
1167
|
+
paths: z9.array(z9.string()).optional(),
|
|
1168
|
+
matches: z9.array(NodeRefSchema).optional()
|
|
1169
|
+
});
|
|
1170
|
+
async function findTdNodesImpl(ctx, args) {
|
|
1171
|
+
const fetch2 = args.recursive ? async () => (await ctx.client.getNetworkTopology(args.parent_path, true)).nodes : async () => (await ctx.client.getNodes(args.parent_path)).nodes;
|
|
1172
|
+
return guardTd(fetch2, (allNodes) => {
|
|
1173
|
+
let nodes = allNodes;
|
|
1174
|
+
if (args.pattern) {
|
|
1175
|
+
const re = globToRegExp(args.pattern);
|
|
1176
|
+
nodes = nodes.filter((n) => re.test(n.name) || re.test(n.path));
|
|
1177
|
+
}
|
|
1178
|
+
if (args.type) {
|
|
1179
|
+
const t = args.type.toLowerCase();
|
|
1180
|
+
nodes = nodes.filter((n) => n.type.toLowerCase().includes(t));
|
|
1181
|
+
}
|
|
1182
|
+
const count = nodes.length;
|
|
1183
|
+
const truncated = count > args.limit;
|
|
1184
|
+
nodes = nodes.slice(0, args.limit);
|
|
1185
|
+
const summary = `${count} match(es) under ${args.parent_path}${truncated ? ` (showing ${args.limit})` : ""}.`;
|
|
1186
|
+
const base = { parent_path: args.parent_path, recursive: args.recursive, count, truncated };
|
|
1187
|
+
return args.path_only ? structuredResult(summary, { ...base, paths: nodes.map((n) => n.path) }) : structuredResult(summary, { ...base, matches: nodes });
|
|
1188
|
+
});
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
// src/tools/layer3/getModuleHelp.ts
|
|
1192
|
+
import { z as z10 } from "zod";
|
|
1193
|
+
var getModuleHelpSchema = z10.object({
|
|
1194
|
+
name: z10.string().describe("Class or module name to get help for, e.g. 'OP', 'App', 'Project'.")
|
|
1195
|
+
});
|
|
1196
|
+
function getModuleHelpImpl(ctx, args) {
|
|
1197
|
+
const cls = ctx.knowledge.getPythonClass(args.name);
|
|
1198
|
+
if (!cls) {
|
|
1199
|
+
const suggestions = ctx.knowledge.listPythonClasses().filter((c) => c.className.toLowerCase().includes(args.name.toLowerCase())).slice(0, 5).map((c) => c.className);
|
|
1200
|
+
return jsonResult(`No help found for "${args.name}".`, { found: false, suggestions });
|
|
1201
|
+
}
|
|
1202
|
+
const lines = [`# ${cls.displayName || cls.className}`, ""];
|
|
1203
|
+
if (cls.description) lines.push(cls.description, "");
|
|
1204
|
+
if (cls.members && cls.members.length > 0) {
|
|
1205
|
+
lines.push("## Members");
|
|
1206
|
+
for (const m of cls.members) {
|
|
1207
|
+
const ro = m.readOnly ? " (read-only)" : "";
|
|
1208
|
+
lines.push(`- ${m.name}${m.returnType ? `: ${m.returnType}` : ""}${ro}`);
|
|
1209
|
+
}
|
|
1210
|
+
lines.push("");
|
|
1211
|
+
}
|
|
1212
|
+
if (cls.methods && cls.methods.length > 0) {
|
|
1213
|
+
lines.push("## Methods");
|
|
1214
|
+
for (const method of cls.methods) {
|
|
1215
|
+
const sig = method.signature || method.name || "";
|
|
1216
|
+
lines.push(`- ${sig}${method.returns ? ` -> ${method.returns}` : ""}`);
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
return textResult(lines.join("\n"));
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
// src/tools/layer3/getTdClassDetails.ts
|
|
1223
|
+
import { z as z11 } from "zod";
|
|
1224
|
+
var getTdClassDetailsSchema = z11.object({
|
|
1225
|
+
class_name: z11.string().describe("Python class name, e.g. 'OP', 'TOP', 'App', 'CHOP'.")
|
|
1226
|
+
});
|
|
1227
|
+
function getTdClassDetailsImpl(ctx, args) {
|
|
1228
|
+
const cls = ctx.knowledge.getPythonClass(args.class_name);
|
|
1229
|
+
if (!cls) {
|
|
1230
|
+
const suggestions = ctx.knowledge.listPythonClasses().filter((c) => c.className.toLowerCase().includes(args.class_name.toLowerCase())).slice(0, 5).map((c) => c.className);
|
|
1231
|
+
return structuredResult(`Python class "${args.class_name}" not found.`, {
|
|
1232
|
+
found: false,
|
|
1233
|
+
suggestions
|
|
1234
|
+
});
|
|
1235
|
+
}
|
|
1236
|
+
return structuredResult(
|
|
1237
|
+
`${cls.className} \u2014 ${cls.methods?.length ?? 0} methods, ${cls.members?.length ?? 0} members.`,
|
|
1238
|
+
cls
|
|
1239
|
+
);
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
// src/tools/layer3/getTdClasses.ts
|
|
1243
|
+
import { z as z12 } from "zod";
|
|
1244
|
+
var getTdClassesSchema = z12.object({
|
|
1245
|
+
filter: z12.string().optional().describe("Optional case-insensitive substring to filter class names by.")
|
|
1246
|
+
});
|
|
1247
|
+
function getTdClassesImpl(ctx, args) {
|
|
1248
|
+
let classes = ctx.knowledge.listPythonClasses();
|
|
1249
|
+
if (args.filter) {
|
|
1250
|
+
const needle = args.filter.toLowerCase();
|
|
1251
|
+
classes = classes.filter(
|
|
1252
|
+
(c) => c.className.toLowerCase().includes(needle) || c.displayName.toLowerCase().includes(needle)
|
|
1253
|
+
);
|
|
1254
|
+
}
|
|
1255
|
+
return structuredResult(`Found ${classes.length} TouchDesigner Python API class(es).`, {
|
|
1256
|
+
classes
|
|
1257
|
+
});
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
// src/tools/layer3/getTdInfo.ts
|
|
1261
|
+
async function getTdInfoImpl(ctx) {
|
|
1262
|
+
const knowledge = ctx.knowledge.stats();
|
|
1263
|
+
try {
|
|
1264
|
+
const info = await ctx.client.getInfo();
|
|
1265
|
+
return jsonResult("TouchDesigner is connected.", {
|
|
1266
|
+
connected: true,
|
|
1267
|
+
endpoint: ctx.client.endpoint,
|
|
1268
|
+
touchdesigner: info,
|
|
1269
|
+
knowledge
|
|
1270
|
+
});
|
|
1271
|
+
} catch (err) {
|
|
1272
|
+
return jsonResult("TouchDesigner is not reachable (the server is still running).", {
|
|
1273
|
+
connected: false,
|
|
1274
|
+
endpoint: ctx.client.endpoint,
|
|
1275
|
+
reason: friendlyTdError(err),
|
|
1276
|
+
knowledge
|
|
1277
|
+
});
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
// src/tools/layer3/getTdNodeErrors.ts
|
|
1282
|
+
import { z as z13 } from "zod";
|
|
1283
|
+
var getTdNodeErrorsSchema = z13.object({
|
|
1284
|
+
path: z13.string().describe("Full path of the node (or network root) to check for errors."),
|
|
1285
|
+
recursive: z13.boolean().default(false).describe("If true, check the whole network under `path`; otherwise just that node."),
|
|
1286
|
+
summary: z13.boolean().default(false).describe("Return only counts grouped by error type instead of the full error list.")
|
|
1287
|
+
});
|
|
1288
|
+
var getTdNodeErrorsOutputSchema = z13.object({
|
|
1289
|
+
path: z13.string(),
|
|
1290
|
+
total: z13.number(),
|
|
1291
|
+
errors: z13.array(NodeErrorSchema).optional(),
|
|
1292
|
+
by_type: z13.record(z13.string(), z13.number()).optional()
|
|
1293
|
+
});
|
|
1294
|
+
async function getTdNodeErrorsImpl(ctx, args) {
|
|
1295
|
+
return guardTd(
|
|
1296
|
+
() => args.recursive ? ctx.client.getNetworkErrors(args.path) : ctx.client.getNodeErrors(args.path),
|
|
1297
|
+
(result) => {
|
|
1298
|
+
const errors = result.errors;
|
|
1299
|
+
const total = errors.length;
|
|
1300
|
+
const none = total === 0;
|
|
1301
|
+
if (args.summary) {
|
|
1302
|
+
const byType = {};
|
|
1303
|
+
for (const e of errors) {
|
|
1304
|
+
const key = e.type || "error";
|
|
1305
|
+
byType[key] = (byType[key] ?? 0) + 1;
|
|
1306
|
+
}
|
|
1307
|
+
return structuredResult(
|
|
1308
|
+
none ? `No errors found at ${args.path}.` : `${total} error(s) at ${args.path}.`,
|
|
1309
|
+
{ path: args.path, total, by_type: byType }
|
|
1310
|
+
);
|
|
1311
|
+
}
|
|
1312
|
+
return structuredResult(
|
|
1313
|
+
none ? `No errors found at ${args.path}.` : `Found ${total} error(s) at ${args.path}.`,
|
|
1314
|
+
{ path: args.path, total, errors }
|
|
1315
|
+
);
|
|
1316
|
+
}
|
|
1317
|
+
);
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
// src/tools/layer3/getTdNodeParameters.ts
|
|
1321
|
+
import { z as z14 } from "zod";
|
|
1322
|
+
var getTdNodeParametersSchema = z14.object({
|
|
1323
|
+
path: z14.string().describe("Full path of the node to inspect."),
|
|
1324
|
+
keys: z14.array(z14.string()).optional().describe("Only return these parameter names (case-sensitive). Omit to return all parameters."),
|
|
1325
|
+
omit_io: z14.boolean().default(false).describe("Drop the inputs/outputs lists from the result to save context.")
|
|
1326
|
+
});
|
|
1327
|
+
async function getTdNodeParametersImpl(ctx, args) {
|
|
1328
|
+
return guardTd(
|
|
1329
|
+
() => ctx.client.getNode(args.path),
|
|
1330
|
+
(node) => {
|
|
1331
|
+
let parameters = node.parameters;
|
|
1332
|
+
if (args.keys && args.keys.length > 0) {
|
|
1333
|
+
const wanted = new Set(args.keys);
|
|
1334
|
+
parameters = Object.fromEntries(
|
|
1335
|
+
Object.entries(node.parameters).filter(([k]) => wanted.has(k))
|
|
1336
|
+
);
|
|
1337
|
+
}
|
|
1338
|
+
const data = {
|
|
1339
|
+
path: node.path,
|
|
1340
|
+
type: node.type,
|
|
1341
|
+
name: node.name,
|
|
1342
|
+
parameters
|
|
1343
|
+
};
|
|
1344
|
+
if (!args.omit_io) {
|
|
1345
|
+
data.inputs = node.inputs;
|
|
1346
|
+
data.outputs = node.outputs;
|
|
1347
|
+
}
|
|
1348
|
+
const count = Object.keys(parameters).length;
|
|
1349
|
+
return structuredResult(`${count} parameter(s) for ${node.path} (${node.type}).`, data);
|
|
1350
|
+
}
|
|
1351
|
+
);
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
// src/tools/layer3/getTdNodes.ts
|
|
1355
|
+
import { z as z15 } from "zod";
|
|
1356
|
+
var getTdNodesSchema = z15.object({
|
|
1357
|
+
parent_path: z15.string().default("/project1").describe("Parent COMP whose direct children should be listed."),
|
|
1358
|
+
pattern: z15.string().optional().describe(
|
|
1359
|
+
"Case-insensitive filter on node name/path. Supports '*' wildcards (e.g. 'text*', '*noise*')."
|
|
1360
|
+
),
|
|
1361
|
+
path_only: z15.boolean().default(false).describe("Return only the list of node paths, dropping type/name."),
|
|
1362
|
+
limit: z15.number().int().positive().optional().describe("Cap the number of nodes returned."),
|
|
1363
|
+
detail_level: z15.enum(["summary", "full"]).default("summary").describe(
|
|
1364
|
+
"'summary' (default) returns a count, a type breakdown and the first few paths; 'full' returns every node. Use 'full' (or path_only) when you need the complete list."
|
|
1365
|
+
)
|
|
1366
|
+
});
|
|
1367
|
+
var SAMPLE_SIZE = 10;
|
|
1368
|
+
var getTdNodesOutputSchema = z15.object({
|
|
1369
|
+
parent_path: z15.string(),
|
|
1370
|
+
count: z15.number(),
|
|
1371
|
+
detail_level: z15.enum(["summary", "full"]),
|
|
1372
|
+
truncated: z15.boolean(),
|
|
1373
|
+
by_type: z15.record(z15.string(), z15.number()).optional(),
|
|
1374
|
+
sample: z15.array(z15.string()).optional(),
|
|
1375
|
+
paths: z15.array(z15.string()).optional(),
|
|
1376
|
+
nodes: z15.array(NodeRefSchema).optional(),
|
|
1377
|
+
hint: z15.string().optional()
|
|
1378
|
+
});
|
|
1379
|
+
async function getTdNodesImpl(ctx, args) {
|
|
1380
|
+
return guardTd(
|
|
1381
|
+
() => ctx.client.getNodes(args.parent_path),
|
|
1382
|
+
(list) => {
|
|
1383
|
+
let nodes = list.nodes;
|
|
1384
|
+
if (args.pattern) {
|
|
1385
|
+
const re = globToRegExp(args.pattern);
|
|
1386
|
+
nodes = nodes.filter((n) => re.test(n.name) || re.test(n.path));
|
|
1387
|
+
}
|
|
1388
|
+
const matched = nodes.length;
|
|
1389
|
+
const truncated = args.limit !== void 0 && matched > args.limit;
|
|
1390
|
+
if (args.limit !== void 0) nodes = nodes.slice(0, args.limit);
|
|
1391
|
+
const where = args.pattern ? ` matching "${args.pattern}"` : "";
|
|
1392
|
+
const base = {
|
|
1393
|
+
parent_path: args.parent_path,
|
|
1394
|
+
count: matched,
|
|
1395
|
+
detail_level: args.detail_level,
|
|
1396
|
+
truncated
|
|
1397
|
+
};
|
|
1398
|
+
if (args.path_only) {
|
|
1399
|
+
return structuredResult(`${matched} node(s) under ${args.parent_path}${where}.`, {
|
|
1400
|
+
...base,
|
|
1401
|
+
paths: nodes.map((n) => n.path)
|
|
1402
|
+
});
|
|
1403
|
+
}
|
|
1404
|
+
if (args.detail_level === "summary") {
|
|
1405
|
+
const byType = {};
|
|
1406
|
+
for (const n of nodes) {
|
|
1407
|
+
const key = n.type || "unknown";
|
|
1408
|
+
byType[key] = (byType[key] ?? 0) + 1;
|
|
1409
|
+
}
|
|
1410
|
+
const sample = nodes.slice(0, SAMPLE_SIZE).map((n) => n.path);
|
|
1411
|
+
return structuredResult(
|
|
1412
|
+
`${matched} node(s) under ${args.parent_path}${where}. Summary only \u2014 pass detail_level:"full" or path_only:true for the full list.`,
|
|
1413
|
+
{
|
|
1414
|
+
...base,
|
|
1415
|
+
by_type: byType,
|
|
1416
|
+
sample,
|
|
1417
|
+
...matched > sample.length ? {
|
|
1418
|
+
hint: `Showing first ${sample.length} of ${matched}. Use detail_level:"full" for all.`
|
|
1419
|
+
} : {}
|
|
1420
|
+
}
|
|
1421
|
+
);
|
|
1422
|
+
}
|
|
1423
|
+
return structuredResult(`${matched} node(s) under ${args.parent_path}${where}.`, {
|
|
1424
|
+
...base,
|
|
1425
|
+
nodes
|
|
1426
|
+
});
|
|
1427
|
+
}
|
|
1428
|
+
);
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
// src/tools/layer3/getTdPerformance.ts
|
|
1432
|
+
import { z as z16 } from "zod";
|
|
1433
|
+
|
|
1434
|
+
// src/feedback/performanceMonitor.ts
|
|
1435
|
+
async function checkPerformance(client, path, targetFps = 60) {
|
|
1436
|
+
const perf = await client.getNetworkPerformance(path);
|
|
1437
|
+
const frameBudgetMs = 1e3 / targetFps;
|
|
1438
|
+
const warnings = [];
|
|
1439
|
+
for (const node of perf.nodes) {
|
|
1440
|
+
if (node.cook_time_ms > frameBudgetMs) {
|
|
1441
|
+
warnings.push(
|
|
1442
|
+
`${node.path} cooks in ${node.cook_time_ms.toFixed(2)}ms, exceeding the ${frameBudgetMs.toFixed(2)}ms budget at ${targetFps}fps.`
|
|
1443
|
+
);
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
const totalCookMs = perf.total_cook_time_ms ?? perf.nodes.reduce((sum, node) => sum + node.cook_time_ms, 0);
|
|
1447
|
+
if (totalCookMs > frameBudgetMs) {
|
|
1448
|
+
warnings.push(
|
|
1449
|
+
`Total cook time ${totalCookMs.toFixed(2)}ms exceeds the ${frameBudgetMs.toFixed(2)}ms budget at ${targetFps}fps.`
|
|
1450
|
+
);
|
|
1451
|
+
}
|
|
1452
|
+
return { path, targetFps, frameBudgetMs, totalCookMs, nodes: perf.nodes, warnings };
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
// src/tools/layer3/getTdPerformance.ts
|
|
1456
|
+
var getTdPerformanceSchema = z16.object({
|
|
1457
|
+
root_path: z16.string().default("/project1").describe("Network root to measure cook times under."),
|
|
1458
|
+
target_fps: z16.number().positive().default(60).describe("Frame-rate target used to flag slow nodes.")
|
|
1459
|
+
});
|
|
1460
|
+
var getTdPerformanceOutputSchema = z16.object({
|
|
1461
|
+
path: z16.string(),
|
|
1462
|
+
targetFps: z16.number(),
|
|
1463
|
+
frameBudgetMs: z16.number(),
|
|
1464
|
+
totalCookMs: z16.number(),
|
|
1465
|
+
nodes: z16.array(
|
|
1466
|
+
z16.object({
|
|
1467
|
+
path: z16.string(),
|
|
1468
|
+
cook_time_ms: z16.number(),
|
|
1469
|
+
cook_count: z16.number().optional()
|
|
1470
|
+
})
|
|
1471
|
+
),
|
|
1472
|
+
warnings: z16.array(z16.string())
|
|
1473
|
+
});
|
|
1474
|
+
async function getTdPerformanceImpl(ctx, args) {
|
|
1475
|
+
return guardTd(
|
|
1476
|
+
() => checkPerformance(ctx.client, args.root_path, args.target_fps),
|
|
1477
|
+
(report) => structuredResult(
|
|
1478
|
+
report.warnings.length === 0 ? `Within budget: ${report.totalCookMs.toFixed(2)}ms total under ${args.root_path} (${args.target_fps}fps).` : `${report.warnings.length} performance warning(s) under ${args.root_path}.`,
|
|
1479
|
+
report
|
|
1480
|
+
)
|
|
1481
|
+
);
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
// src/tools/layer3/getTdTopology.ts
|
|
1485
|
+
import { z as z17 } from "zod";
|
|
1486
|
+
|
|
1487
|
+
// src/feedback/networkVerifier.ts
|
|
1488
|
+
async function verifyNetwork(client, path) {
|
|
1489
|
+
const topology = await client.getNetworkTopology(path);
|
|
1490
|
+
const issues = [];
|
|
1491
|
+
if (topology.nodes.length === 0) {
|
|
1492
|
+
issues.push(`No nodes were found under ${path}.`);
|
|
1493
|
+
} else if (topology.nodes.length > 1 && topology.connections.length === 0) {
|
|
1494
|
+
issues.push("Multiple nodes exist but none are connected.");
|
|
1495
|
+
}
|
|
1496
|
+
return {
|
|
1497
|
+
path,
|
|
1498
|
+
nodeCount: topology.nodes.length,
|
|
1499
|
+
connectionCount: topology.connections.length,
|
|
1500
|
+
issues,
|
|
1501
|
+
topology
|
|
1502
|
+
};
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
// src/tools/layer3/getTdTopology.ts
|
|
1506
|
+
var getTdTopologySchema = z17.object({
|
|
1507
|
+
root_path: z17.string().default("/project1").describe("Network root to map.")
|
|
1508
|
+
});
|
|
1509
|
+
var getTdTopologyOutputSchema = z17.object({
|
|
1510
|
+
path: z17.string(),
|
|
1511
|
+
nodeCount: z17.number(),
|
|
1512
|
+
connectionCount: z17.number(),
|
|
1513
|
+
issues: z17.array(z17.string()),
|
|
1514
|
+
topology: TopologySchema
|
|
1515
|
+
});
|
|
1516
|
+
async function getTdTopologyImpl(ctx, args) {
|
|
1517
|
+
return guardTd(
|
|
1518
|
+
() => verifyNetwork(ctx.client, args.root_path),
|
|
1519
|
+
(report) => structuredResult(
|
|
1520
|
+
`${report.nodeCount} node(s), ${report.connectionCount} connection(s) under ${args.root_path}.`,
|
|
1521
|
+
report
|
|
1522
|
+
)
|
|
1523
|
+
);
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
// src/tools/layer3/snapshotTdGraph.ts
|
|
1527
|
+
import { z as z18 } from "zod";
|
|
1528
|
+
var MAX_PARAM_NODES = 60;
|
|
1529
|
+
var snapshotTdGraphSchema = z18.object({
|
|
1530
|
+
path: z18.string().default("/project1").describe("Network root to snapshot."),
|
|
1531
|
+
include_params: z18.boolean().default(false).describe("Also fetch each node's parameters (one request per node; capped for large graphs).")
|
|
1532
|
+
});
|
|
1533
|
+
var snapshotTdGraphOutputSchema = z18.object({
|
|
1534
|
+
path: z18.string(),
|
|
1535
|
+
nodeCount: z18.number(),
|
|
1536
|
+
connectionCount: z18.number(),
|
|
1537
|
+
issues: z18.array(z18.string()),
|
|
1538
|
+
params_truncated: z18.boolean(),
|
|
1539
|
+
nodes: z18.array(
|
|
1540
|
+
z18.object({
|
|
1541
|
+
path: z18.string(),
|
|
1542
|
+
type: z18.string(),
|
|
1543
|
+
name: z18.string(),
|
|
1544
|
+
parameters: z18.record(z18.string(), z18.unknown()).optional()
|
|
1545
|
+
})
|
|
1546
|
+
),
|
|
1547
|
+
connections: z18.array(ConnectionSchema)
|
|
1548
|
+
});
|
|
1549
|
+
async function snapshotTdGraphImpl(ctx, args) {
|
|
1550
|
+
return guardTd(
|
|
1551
|
+
async () => {
|
|
1552
|
+
const report = await verifyNetwork(ctx.client, args.path);
|
|
1553
|
+
const refs = report.topology.nodes;
|
|
1554
|
+
let paramsTruncated = false;
|
|
1555
|
+
const params = /* @__PURE__ */ new Map();
|
|
1556
|
+
if (args.include_params) {
|
|
1557
|
+
const targets = refs.slice(0, MAX_PARAM_NODES);
|
|
1558
|
+
paramsTruncated = refs.length > MAX_PARAM_NODES;
|
|
1559
|
+
const details = await Promise.allSettled(targets.map((n) => ctx.client.getNode(n.path)));
|
|
1560
|
+
for (const detail of details) {
|
|
1561
|
+
if (detail.status === "fulfilled") params.set(detail.value.path, detail.value.parameters);
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1564
|
+
const nodes = refs.map((n) => ({
|
|
1565
|
+
path: n.path,
|
|
1566
|
+
type: n.type,
|
|
1567
|
+
name: n.name,
|
|
1568
|
+
...args.include_params ? { parameters: params.get(n.path) ?? {} } : {}
|
|
1569
|
+
}));
|
|
1570
|
+
return { report, nodes, paramsTruncated };
|
|
1571
|
+
},
|
|
1572
|
+
({ report, nodes, paramsTruncated }) => structuredResult(
|
|
1573
|
+
`Snapshot of ${args.path}: ${report.nodeCount} node(s), ${report.connectionCount} connection(s)${report.issues.length ? `, ${report.issues.length} issue(s)` : ""}.`,
|
|
1574
|
+
{
|
|
1575
|
+
path: report.path,
|
|
1576
|
+
nodeCount: report.nodeCount,
|
|
1577
|
+
connectionCount: report.connectionCount,
|
|
1578
|
+
issues: report.issues,
|
|
1579
|
+
params_truncated: paramsTruncated,
|
|
1580
|
+
nodes,
|
|
1581
|
+
connections: report.topology.connections
|
|
1582
|
+
}
|
|
1583
|
+
)
|
|
1584
|
+
);
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1587
|
+
// src/tools/layer3/summarizeTdErrors.ts
|
|
1588
|
+
import { z as z19 } from "zod";
|
|
1589
|
+
var summarizeTdErrorsSchema = z19.object({
|
|
1590
|
+
path: z19.string().default("/project1").describe("Network root to collect errors under."),
|
|
1591
|
+
group_by: z19.enum(["message", "type", "parent"]).default("message").describe(
|
|
1592
|
+
"How to cluster errors: by exact message, by error type, or by parent container (to find a common upstream cause)."
|
|
1593
|
+
)
|
|
1594
|
+
});
|
|
1595
|
+
var summarizeTdErrorsOutputSchema = z19.object({
|
|
1596
|
+
path: z19.string(),
|
|
1597
|
+
total: z19.number(),
|
|
1598
|
+
group_by: z19.enum(["message", "type", "parent"]),
|
|
1599
|
+
groups: z19.array(
|
|
1600
|
+
z19.object({
|
|
1601
|
+
key: z19.string(),
|
|
1602
|
+
count: z19.number(),
|
|
1603
|
+
sample: z19.object({ path: z19.string(), message: z19.string() })
|
|
1604
|
+
})
|
|
1605
|
+
),
|
|
1606
|
+
suggestions: z19.array(z19.string())
|
|
1607
|
+
});
|
|
1608
|
+
async function summarizeTdErrorsImpl(ctx, args) {
|
|
1609
|
+
return guardTd(
|
|
1610
|
+
() => ctx.client.getNetworkErrors(args.path),
|
|
1611
|
+
(result) => {
|
|
1612
|
+
const errors = result.errors;
|
|
1613
|
+
const total = errors.length;
|
|
1614
|
+
if (total === 0) {
|
|
1615
|
+
return structuredResult(`No errors found under ${args.path}.`, {
|
|
1616
|
+
path: args.path,
|
|
1617
|
+
total: 0,
|
|
1618
|
+
group_by: args.group_by,
|
|
1619
|
+
groups: [],
|
|
1620
|
+
suggestions: []
|
|
1621
|
+
});
|
|
1622
|
+
}
|
|
1623
|
+
const keyOf = (e) => args.group_by === "message" ? e.message : args.group_by === "type" ? e.type || "error" : parentOf(e.path);
|
|
1624
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
1625
|
+
const byPath = /* @__PURE__ */ new Map();
|
|
1626
|
+
for (const e of errors) {
|
|
1627
|
+
const key = keyOf(e);
|
|
1628
|
+
const g = grouped.get(key);
|
|
1629
|
+
if (g) g.count += 1;
|
|
1630
|
+
else grouped.set(key, { count: 1, sample: { path: e.path, message: e.message } });
|
|
1631
|
+
byPath.set(e.path, (byPath.get(e.path) ?? 0) + 1);
|
|
1632
|
+
}
|
|
1633
|
+
const groups = [...grouped.entries()].map(([key, g]) => ({ key, count: g.count, sample: g.sample })).sort((a, b) => b.count - a.count);
|
|
1634
|
+
const worstNodes = [...byPath.entries()].sort((a, b) => b[1] - a[1]).slice(0, 3).map(([p, c]) => `${p} (${c} error${c === 1 ? "" : "s"})`);
|
|
1635
|
+
const suggestions = [];
|
|
1636
|
+
if (groups[0] && groups[0].count > 1) {
|
|
1637
|
+
suggestions.push(
|
|
1638
|
+
`${groups[0].count} errors share ${args.group_by} "${groups[0].key}" \u2014 fixing the common cause clears them at once.`
|
|
1639
|
+
);
|
|
1640
|
+
}
|
|
1641
|
+
if (worstNodes.length > 0) {
|
|
1642
|
+
suggestions.push(`Check first: ${worstNodes.join(", ")}.`);
|
|
1643
|
+
}
|
|
1644
|
+
return structuredResult(
|
|
1645
|
+
`${total} error(s) under ${args.path} in ${groups.length} ${args.group_by} group(s).`,
|
|
1646
|
+
{ path: args.path, total, group_by: args.group_by, groups, suggestions }
|
|
1647
|
+
);
|
|
1648
|
+
}
|
|
1649
|
+
);
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1652
|
+
// src/tools/layer3/updateTdNodeParameters.ts
|
|
1653
|
+
import { z as z20 } from "zod";
|
|
1654
|
+
var updateTdNodeParametersSchema = z20.object({
|
|
1655
|
+
path: z20.string().describe("Full path of the node whose parameters to update."),
|
|
1656
|
+
parameters: z20.record(z20.string(), z20.unknown()).describe("Parameter overrides as key\u2192value pairs, e.g. { period: 4, amplitude: 0.5 }.")
|
|
1657
|
+
});
|
|
1658
|
+
async function updateTdNodeParametersImpl(ctx, args) {
|
|
1659
|
+
return guardTd(
|
|
1660
|
+
() => ctx.client.updateNodeParameters(args.path, args.parameters),
|
|
1661
|
+
(node) => jsonResult(`Updated ${Object.keys(args.parameters).length} parameter(s) on ${node.path}.`, {
|
|
1662
|
+
node
|
|
1663
|
+
})
|
|
1664
|
+
);
|
|
1665
|
+
}
|
|
1666
|
+
|
|
1667
|
+
// src/cli/agent.ts
|
|
1668
|
+
var r = (schema, run, summary, opts = {}) => ({ schema, run, summary, mutates: !!opts.mutates, unsafe: !!opts.unsafe });
|
|
1669
|
+
var COMMANDS = {
|
|
1670
|
+
info: r(z21.object({}), (ctx) => getTdInfoImpl(ctx), "Health check + TD/bridge info."),
|
|
1671
|
+
"nodes list": r(
|
|
1672
|
+
getTdNodesSchema,
|
|
1673
|
+
getTdNodesImpl,
|
|
1674
|
+
"List a COMP's child nodes (summary by default)."
|
|
1675
|
+
),
|
|
1676
|
+
"nodes find": r(findTdNodesSchema, findTdNodesImpl, "Search nodes by name pattern and/or type."),
|
|
1677
|
+
"nodes get": r(getTdNodeParametersSchema, getTdNodeParametersImpl, "Read a node's parameters."),
|
|
1678
|
+
"nodes errors": r(getTdNodeErrorsSchema, getTdNodeErrorsImpl, "Check a node/network for errors."),
|
|
1679
|
+
"nodes compare": r(compareTdNodesSchema, compareTdNodesImpl, "Diff two nodes' parameters."),
|
|
1680
|
+
"nodes snapshot": r(snapshotTdGraphSchema, snapshotTdGraphImpl, "Capture a network snapshot."),
|
|
1681
|
+
"nodes topology": r(getTdTopologySchema, getTdTopologyImpl, "Map nodes + connections."),
|
|
1682
|
+
"nodes performance": r(getTdPerformanceSchema, getTdPerformanceImpl, "Report cook times."),
|
|
1683
|
+
"nodes update": r(
|
|
1684
|
+
updateTdNodeParametersSchema,
|
|
1685
|
+
updateTdNodeParametersImpl,
|
|
1686
|
+
"Set node parameters.",
|
|
1687
|
+
{ mutates: true }
|
|
1688
|
+
),
|
|
1689
|
+
"nodes create": r(createTdNodeSchema, createTdNodeImpl, "Create an operator.", { mutates: true }),
|
|
1690
|
+
"nodes delete": r(deleteTdNodeSchema, deleteTdNodeImpl, "Delete a node.", { mutates: true }),
|
|
1691
|
+
"errors summarize": r(
|
|
1692
|
+
summarizeTdErrorsSchema,
|
|
1693
|
+
summarizeTdErrorsImpl,
|
|
1694
|
+
"Cluster network errors by cause."
|
|
1695
|
+
),
|
|
1696
|
+
"classes list": r(getTdClassesSchema, getTdClassesImpl, "List TD Python API classes (offline)."),
|
|
1697
|
+
"classes get": r(
|
|
1698
|
+
getTdClassDetailsSchema,
|
|
1699
|
+
getTdClassDetailsImpl,
|
|
1700
|
+
"Get one Python class (offline)."
|
|
1701
|
+
),
|
|
1702
|
+
"module help": r(
|
|
1703
|
+
getModuleHelpSchema,
|
|
1704
|
+
getModuleHelpImpl,
|
|
1705
|
+
"Human-readable help for a class (offline)."
|
|
1706
|
+
),
|
|
1707
|
+
"exec python": r(
|
|
1708
|
+
executePythonScriptSchema,
|
|
1709
|
+
executePythonScriptImpl,
|
|
1710
|
+
"Escape hatch: run arbitrary Python in TD.",
|
|
1711
|
+
{ mutates: true, unsafe: true }
|
|
1712
|
+
),
|
|
1713
|
+
"exec node-method": r(
|
|
1714
|
+
execNodeMethodSchema,
|
|
1715
|
+
execNodeMethodImpl,
|
|
1716
|
+
"Escape hatch: call a Python method on a node.",
|
|
1717
|
+
{ mutates: true, unsafe: true }
|
|
1718
|
+
)
|
|
1719
|
+
};
|
|
1720
|
+
function textOf(result) {
|
|
1721
|
+
return result.content.filter((c) => c.type === "text").map((c) => c.text).join("\n");
|
|
1722
|
+
}
|
|
1723
|
+
function extractData(result) {
|
|
1724
|
+
if (result.structuredContent !== void 0) return result.structuredContent;
|
|
1725
|
+
const text = textOf(result);
|
|
1726
|
+
const fence = text.match(/```json\n([\s\S]*?)\n```/);
|
|
1727
|
+
if (fence) {
|
|
1728
|
+
try {
|
|
1729
|
+
return JSON.parse(fence[1]);
|
|
1730
|
+
} catch {
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
return { message: text };
|
|
1734
|
+
}
|
|
1735
|
+
function firstArray(data) {
|
|
1736
|
+
if (Array.isArray(data)) return data;
|
|
1737
|
+
if (data && typeof data === "object") {
|
|
1738
|
+
for (const value of Object.values(data)) if (Array.isArray(value)) return value;
|
|
1739
|
+
}
|
|
1740
|
+
return null;
|
|
1741
|
+
}
|
|
1742
|
+
function resolveCommand(positionals) {
|
|
1743
|
+
const key2 = positionals.slice(0, 2).join(" ");
|
|
1744
|
+
if (COMMANDS[key2]) return { key: key2, cmd: COMMANDS[key2] };
|
|
1745
|
+
const key1 = positionals[0] ?? "";
|
|
1746
|
+
if (COMMANDS[key1]) return { key: key1, cmd: COMMANDS[key1] };
|
|
1747
|
+
return void 0;
|
|
1748
|
+
}
|
|
1749
|
+
function usage() {
|
|
1750
|
+
const lines = ["tdmcp-agent \u2014 drive TouchDesigner from a shell (machine-readable output).", ""];
|
|
1751
|
+
lines.push("Usage: tdmcp-agent <command> [--params '<json>'] [--json '<json>'] [flags]", "");
|
|
1752
|
+
lines.push("Flags:");
|
|
1753
|
+
lines.push(
|
|
1754
|
+
" --params <json> Arguments object (validated against the command's input schema)."
|
|
1755
|
+
);
|
|
1756
|
+
lines.push(" --json <json> Merged into --params (e.g. for request bodies).");
|
|
1757
|
+
lines.push(" --output <fmt> json (default) | ndjson | text.");
|
|
1758
|
+
lines.push(" --dry-run Validate and print the intended call without executing.");
|
|
1759
|
+
lines.push(" --allow-unsafe Required for `exec` escape-hatch commands.");
|
|
1760
|
+
lines.push(" -h, --help Show this help.", "");
|
|
1761
|
+
lines.push("Commands:");
|
|
1762
|
+
for (const [key, cmd] of Object.entries(COMMANDS)) {
|
|
1763
|
+
const tags = [cmd.mutates ? "mutates" : "", cmd.unsafe ? "unsafe" : ""].filter(Boolean).join(",");
|
|
1764
|
+
lines.push(` ${key.padEnd(20)} ${cmd.summary}${tags ? ` [${tags}]` : ""}`);
|
|
1765
|
+
}
|
|
1766
|
+
lines.push(" schema <command> Print a command's JSON Schema and metadata.");
|
|
1767
|
+
return lines.join("\n");
|
|
1768
|
+
}
|
|
1769
|
+
function parseCliArgs(argv) {
|
|
1770
|
+
return parseArgs({
|
|
1771
|
+
args: argv,
|
|
1772
|
+
allowPositionals: true,
|
|
1773
|
+
options: {
|
|
1774
|
+
params: { type: "string" },
|
|
1775
|
+
json: { type: "string" },
|
|
1776
|
+
output: { type: "string", default: "json" },
|
|
1777
|
+
"dry-run": { type: "boolean", default: false },
|
|
1778
|
+
"allow-unsafe": { type: "boolean", default: false },
|
|
1779
|
+
help: { type: "boolean", short: "h", default: false }
|
|
1780
|
+
}
|
|
1781
|
+
});
|
|
1782
|
+
}
|
|
1783
|
+
async function runCli(argv, opts = {}) {
|
|
1784
|
+
let parsed;
|
|
1785
|
+
try {
|
|
1786
|
+
parsed = parseCliArgs(argv);
|
|
1787
|
+
} catch (err) {
|
|
1788
|
+
return { stdout: "", stderr: `${err.message}
|
|
1789
|
+
`, code: 2 };
|
|
1790
|
+
}
|
|
1791
|
+
const { values, positionals } = parsed;
|
|
1792
|
+
if (values.help || positionals.length === 0) {
|
|
1793
|
+
return { stdout: `${usage()}
|
|
1794
|
+
`, stderr: "", code: 0 };
|
|
1795
|
+
}
|
|
1796
|
+
if (positionals[0] === "schema") {
|
|
1797
|
+
const target = positionals.slice(1).join(" ");
|
|
1798
|
+
const cmd2 = COMMANDS[target];
|
|
1799
|
+
if (!cmd2) return { stdout: "", stderr: `Unknown command for schema: "${target}".
|
|
1800
|
+
`, code: 2 };
|
|
1801
|
+
const doc = {
|
|
1802
|
+
command: target,
|
|
1803
|
+
summary: cmd2.summary,
|
|
1804
|
+
mutates: cmd2.mutates,
|
|
1805
|
+
unsafe: cmd2.unsafe,
|
|
1806
|
+
input: z21.toJSONSchema(cmd2.schema)
|
|
1807
|
+
};
|
|
1808
|
+
return { stdout: `${JSON.stringify(doc, null, 2)}
|
|
1809
|
+
`, stderr: "", code: 0 };
|
|
1810
|
+
}
|
|
1811
|
+
const resolved = resolveCommand(positionals);
|
|
1812
|
+
if (!resolved) {
|
|
1813
|
+
return {
|
|
1814
|
+
stdout: "",
|
|
1815
|
+
stderr: `Unknown command: "${positionals.join(" ")}". Run with --help.
|
|
1816
|
+
`,
|
|
1817
|
+
code: 2
|
|
1818
|
+
};
|
|
1819
|
+
}
|
|
1820
|
+
const { key, cmd } = resolved;
|
|
1821
|
+
const raw = {};
|
|
1822
|
+
try {
|
|
1823
|
+
if (typeof values.params === "string") Object.assign(raw, JSON.parse(values.params));
|
|
1824
|
+
if (typeof values.json === "string") Object.assign(raw, JSON.parse(values.json));
|
|
1825
|
+
} catch (err) {
|
|
1826
|
+
return {
|
|
1827
|
+
stdout: "",
|
|
1828
|
+
stderr: `Invalid JSON in --params/--json: ${err.message}
|
|
1829
|
+
`,
|
|
1830
|
+
code: 2
|
|
1831
|
+
};
|
|
1832
|
+
}
|
|
1833
|
+
const args = cmd.schema.safeParse(raw);
|
|
1834
|
+
if (!args.success) {
|
|
1835
|
+
return {
|
|
1836
|
+
stdout: "",
|
|
1837
|
+
stderr: `Invalid arguments for "${key}": ${args.error.message}
|
|
1838
|
+
`,
|
|
1839
|
+
code: 2
|
|
1840
|
+
};
|
|
1841
|
+
}
|
|
1842
|
+
if (values["dry-run"]) {
|
|
1843
|
+
const doc = {
|
|
1844
|
+
dryRun: true,
|
|
1845
|
+
command: key,
|
|
1846
|
+
mutates: cmd.mutates,
|
|
1847
|
+
unsafe: cmd.unsafe,
|
|
1848
|
+
args: args.data
|
|
1849
|
+
};
|
|
1850
|
+
return { stdout: `${JSON.stringify(doc, null, 2)}
|
|
1851
|
+
`, stderr: "", code: 0 };
|
|
1852
|
+
}
|
|
1853
|
+
const ctx = opts.makeCtx ? opts.makeCtx() : buildToolContext(loadConfig(), { logger: silentLogger });
|
|
1854
|
+
if (cmd.unsafe) {
|
|
1855
|
+
if (ctx.allowRawPython === false) {
|
|
1856
|
+
return { stdout: "", stderr: `"${key}" is disabled (TDMCP_RAW_PYTHON=off).
|
|
1857
|
+
`, code: 2 };
|
|
1858
|
+
}
|
|
1859
|
+
if (!values["allow-unsafe"]) {
|
|
1860
|
+
return {
|
|
1861
|
+
stdout: "",
|
|
1862
|
+
stderr: `"${key}" is an escape hatch. Re-run with --allow-unsafe to execute.
|
|
1863
|
+
`,
|
|
1864
|
+
code: 2
|
|
1865
|
+
};
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
const result = await cmd.run(ctx, args.data);
|
|
1869
|
+
const summary = textOf(result).split("\n")[0] ?? "";
|
|
1870
|
+
if (result.isError) return { stdout: "", stderr: `${textOf(result)}
|
|
1871
|
+
`, code: 1 };
|
|
1872
|
+
const output = String(values.output);
|
|
1873
|
+
const data = extractData(result);
|
|
1874
|
+
if (output === "text") return { stdout: `${textOf(result)}
|
|
1875
|
+
`, stderr: "", code: 0 };
|
|
1876
|
+
if (output === "ndjson") {
|
|
1877
|
+
const arr = firstArray(data);
|
|
1878
|
+
const body = arr ? arr.map((item) => JSON.stringify(item)).join("\n") : JSON.stringify(data);
|
|
1879
|
+
return { stdout: `${body}
|
|
1880
|
+
`, stderr: summary ? `${summary}
|
|
1881
|
+
` : "", code: 0 };
|
|
1882
|
+
}
|
|
1883
|
+
return {
|
|
1884
|
+
stdout: `${JSON.stringify(data, null, 2)}
|
|
1885
|
+
`,
|
|
1886
|
+
stderr: summary ? `${summary}
|
|
1887
|
+
` : "",
|
|
1888
|
+
code: 0
|
|
1889
|
+
};
|
|
1890
|
+
}
|
|
1891
|
+
async function main() {
|
|
1892
|
+
const result = await runCli(process.argv.slice(2));
|
|
1893
|
+
if (result.stdout) process.stdout.write(result.stdout);
|
|
1894
|
+
if (result.stderr) process.stderr.write(result.stderr);
|
|
1895
|
+
process.exitCode = result.code;
|
|
1896
|
+
}
|
|
1897
|
+
var invokedDirectly = process.argv[1] !== void 0 && import.meta.url === pathToFileURL(process.argv[1]).href;
|
|
1898
|
+
if (invokedDirectly) void main();
|
|
1899
|
+
export {
|
|
1900
|
+
runCli
|
|
1901
|
+
};
|
|
1902
|
+
//# sourceMappingURL=agent.js.map
|