fluffychat/lib/pangea/common/network/requests.dart
wcjord dec473d579
Writing assistance (#5598)
* feat: wa working full stack

* feat: writing assistance made anew

* docs: migrate copilot docs to .github/instructions/ format

- Create choreographer.instructions.md (applyTo: lib/pangea/choreographer/**)
- Create events-and-tokens.instructions.md (applyTo: lib/pangea/events/**,lib/pangea/extensions/**)
- Create modules.instructions.md (applyTo: lib/pangea/**) — full module map
- Track copilot-instructions.md (remove .gitignore rule)
- Add documentation reference table to copilot-instructions.md

Content sourced from docs/copilot/ on writing-assistance branch.

* docs: remove old docs/copilot/ (migrated to .github/instructions/)

* docs: update choreographer + modules docs for writing-assistance audit

- Mark IT (Interactive Translation) as deprecated throughout
- Document new ReplacementTypeEnum taxonomy (grammar, surface, word-choice categories)
- Add AssistanceStateEnum, AutocorrectPopup, feedback rerun flow
- Mark SpanDataRepo/span_details as dead code
- Mark SpanChoiceTypeEnum.bestCorrection/bestAnswer as deprecated
- Add new files to modules listing (autocorrect_popup, start_igc_button, etc.)
- Update API endpoints table with active/deprecated/dead status

* formatting, replace deprecated withOpacity calls

* fix linter issues from deprecated types

* use better error color

* move cloing of overlays into choreographer

* reduce duplicate code on igc_controller, update UI on feedback

* couple of adjustments

* display prompt in span card by type

* fix error in tests

* translations

* simplify span card feedback

---------

Co-authored-by: ggurdin <ggurdin@gmail.com>
2026-02-09 15:55:18 -05:00

97 lines
2.3 KiB
Dart

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:fluffychat/pangea/common/models/base_request_model.dart';
class Requests {
late String? accessToken;
late String? choreoApiKey;
Requests({
this.accessToken,
this.choreoApiKey,
});
Future<http.Response> post({
required String url,
required Map<dynamic, dynamic> body,
}) async {
final enrichedBody = BaseRequestModel.injectUserContext(body);
dynamic encoded;
encoded = jsonEncode(enrichedBody);
final http.Response response = await http.post(
Uri.parse(url),
body: encoded,
headers: _headers,
);
handleError(response, body: body);
return response;
}
Future<http.Response> get({required String url}) async {
final http.Response response =
await http.get(Uri.parse(url), headers: _headers);
handleError(response);
return response;
}
void addBreadcrumb(
http.Response response, {
Map<dynamic, dynamic>? body,
}) {
debugPrint("Error - code: ${response.statusCode}");
debugPrint("api: ${response.request?.url}");
debugPrint("request body: $body");
Sentry.addBreadcrumb(
Breadcrumb.http(
url: response.request?.url ?? Uri(path: "not available"),
method: response.request?.method ?? "not available",
statusCode: response.statusCode,
),
);
Sentry.addBreadcrumb(
Breadcrumb(data: {"body": body}),
);
}
void handleError(
http.Response response, {
Map<dynamic, dynamic>? body,
}) {
if (response.statusCode == 401) {
final responseBody = jsonDecode(utf8.decode(response.bodyBytes));
if (responseBody['detail'] == 'No active subscription found') {
throw UnsubscribedException();
}
}
if (response.statusCode >= 400) {
addBreadcrumb(response, body: body);
throw response;
}
}
get _headers {
final Map<String, String> headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
if (accessToken != null) {
headers["Authorization"] = 'Bearer ${accessToken!}';
}
if (choreoApiKey != null) {
headers['api_key'] = choreoApiKey!;
}
return headers;
}
}
class UnsubscribedException implements Exception {}