docs: def detect_change_mode(text,change):
    "returns 'add' 'delete' or 'internal'. see comments to update_changes for more details."
    # warning: some wacky diff logic (in python, probably in JS too) is making some adds / deletes look like replacements (see notes at bottom of diff.py)
    if len(change.deltas)>1: return 'internal'
    # todo below: why are blank deltas getting sent? is it a new seg thing? I'm picking 'add' because it has to be in some category and add is most likely next if this is a new seg.
    elif not change.deltas: return 'add'
    delta,=change.deltas # intentional crash if len(deltas)!=1
    if delta.a==delta.b and delta.a==len(text): return 'add'
    elif delta.b==len(text) and len(delta.text)==0: return 'delete'
    else: return 'internal'