src/vs/workbench/contrib/terminal/browser/terminalTypeAheadAddon.ts/TypeAheadAddon/activate
class TypeAheadAddon:	activate(terminal: Terminal): void {
		const style = this._typeaheadStyle = this._register(new TypeAheadStyle(this._config.config.localEchoStyle, terminal));
		const timeline = this._timeline = new PredictionTimeline(terminal, this._typeaheadStyle);
		const stats = this.stats = this._register(new PredictionStats(this._timeline));

		timeline.setShowPredictions(this._typeaheadThreshold === 0);
		this._register(terminal.onData(e => this._onUserData(e)));
		this._register(terminal.onTitleChange(title => {
			this._terminalTitle = title;
			this._reevaluatePredictorState(stats, timeline);
		}));
		this._register(terminal.onResize(() => {
			timeline.setShowPredictions(false);
			timeline.clearCursor();
			this._reevaluatePredictorState(stats, timeline);
		}));
		this._register(this._config.onConfigChanged(() => {
			style.onUpdate(this._config.config.localEchoStyle);
			this._typeaheadThreshold = this._config.config.localEchoLatencyThreshold;
			this._excludeProgramRe = compileExcludeRegexp(this._config.config.localEchoExcludePrograms);
			this._reevaluatePredictorState(stats, timeline);
		}));
		this._register(this._timeline.onPredictionSucceeded(p => {
			if (this._lastRow?.charState === CharPredictState.HasPendingChar && isTenativeCharacterPrediction(p) && p.inner.appliedAt) {
				if (p.inner.appliedAt.pos.y + p.inner.appliedAt.pos.baseY === this._lastRow.y) {
					this._lastRow.charState = CharPredictState.Validated;
				}
			}
		}));
		this._register(this._processManager.onBeforeProcessData(e => this._onBeforeProcessData(e)));

		let nextStatsSend: any;
		this._register(stats.onChange(() => {
			if (!nextStatsSend) {
				nextStatsSend = setTimeout(() => {
					this._sendLatencyStats(stats);
					nextStatsSend = undefined;
				}, statsSendTelemetryEvery);
			}

			if (timeline.length === 0) {
				style.debounceStopTracking();
			}

			this._reevaluatePredictorState(stats, timeline);
		}));
	}