how to create an AJAX field widget
I've tried to do this a few times and never really got very far (for the reasons you've already mentioned).

The way I found to do it instead was to install the Field Collection module (and Field Collection Table for a better UX), and use that to group the fields I need into a single field, which is represented as a single widget.

Then I just hook into the particular form that's showing the field and add the AJAX that way. As coincidence would have it I've just done exactly this a few hours ago. I know this is out of context but here's a (slightly anonymised) dump of the code I used; hopefully it'll give you a place to start if you choose to go down this route:

function MYMODULE_form_directory_listing_node_form_alter(&amp;$form, &amp;$form_state, $form_id) {
  $selected_country_tid = $form['field_address'][LANGUAGE_NONE][0]['field_country'][LANGUAGE_NONE]['#default_value'][0];

  $form['field_address'][LANGUAGE_NONE][0]['field_country'][LANGUAGE_NONE]['#ajax'] = array(
    'wrapper' =&gt; 'directory-form-county-wrapper',
    'callback' =&gt; 'MYMODULE_form_directory_listing_country_ajax'
  );

  $form['field_address'][LANGUAGE_NONE][0]['field_county'][LANGUAGE_NONE]['#prefix'] = '&lt;div id="directory-form-county-wrapper"&gt;';
  $form['field_address'][LANGUAGE_NONE][0]['field_county'][LANGUAGE_NONE]['#suffix'] = '&lt;/div&gt;';

  $selected_country_term = taxonomy_term_load($selected_country_tid);

  $options = array();
  foreach (_MYMODULE_get_country_counties($selected_country_term) as $county) {
    $options[$county-&gt;tid] = $county-&gt;name;
  }

  $form['field_address'][LANGUAGE_NONE][0]['field_county'][LANGUAGE_NONE]['#options'] = $options;
}


function MYMODULE_form_directory_listing_country_ajax(&amp;$form, &amp;$form_state) {
  return $form['field_address'][LANGUAGE_NONE][0]['field_county'][LANGUAGE_NONE];
}


field_address in the above example is the Field Collection field.