Protect private API routes and scope agent data

This commit is contained in:
Hamza Ayed
2026-10-03 00:34:49 +03:00
parent 1c1f662850
commit b0cd825838
17 changed files with 313 additions and 95 deletions
@@ -262,7 +262,7 @@ class ApiRepository {
final response = await http
.post(
Uri.parse('$_baseUrl/v1/chat/completions'),
headers: const {'Content-Type': 'application/json'},
headers: await _userHeaders(),
body: jsonEncode({
'messages':
messages
@@ -288,7 +288,7 @@ class ApiRepository {
Future<List<String>> listWorkspaceFiles(String workspacePath) async {
final response = await http.post(
Uri.parse('$_baseUrl/v1/agent/workspace/files'),
headers: const {'Content-Type': 'application/json'},
headers: await _userHeaders(),
body: jsonEncode({'workspace_path': workspacePath}),
);
_checkStatus(response);
@@ -303,7 +303,7 @@ class ApiRepository {
final response = await http
.post(
Uri.parse('$_baseUrl/v1/agent/knowledge/index'),
headers: const {'Content-Type': 'application/json'},
headers: await _userHeaders(),
body: jsonEncode({'workspace_path': workspacePath, 'files': files}),
)
.timeout(const Duration(minutes: 2));
@@ -318,7 +318,7 @@ class ApiRepository {
final response = await http
.delete(
Uri.parse('$_baseUrl/v1/agent/knowledge/index'),
headers: const {'Content-Type': 'application/json'},
headers: await _userHeaders(),
body: jsonEncode({'workspace_path': workspacePath, 'files': files}),
)
.timeout(const Duration(minutes: 1));
@@ -327,7 +327,10 @@ class ApiRepository {
}
Future<List<AgentSkillDescriptor>> getAgentSkills() async {
final response = await http.get(Uri.parse('$_baseUrl/v1/agent/skills'));
final response = await http.get(
Uri.parse('$_baseUrl/v1/agent/skills'),
headers: await _userHeaders(),
);
_checkStatus(response);
final data = jsonDecode(response.body) as Map<String, dynamic>;
return (data['skills'] as List<dynamic>? ?? const [])
@@ -350,7 +353,7 @@ class ApiRepository {
try {
final request =
http.Request('POST', Uri.parse('$_baseUrl/v1/agent/run/stream'))
..headers['Content-Type'] = 'application/json'
..headers.addAll(await _userHeaders())
..headers['Accept'] = 'text/event-stream'
..body = jsonEncode({
'task': task,
@@ -436,7 +439,7 @@ class ApiRepository {
Future<String> applyFileChange(FileChangeProposal proposal) async {
final response = await http.post(
Uri.parse('$_baseUrl/v1/agent/files/apply'),
headers: const {'Content-Type': 'application/json'},
headers: await _userHeaders(),
body: jsonEncode({'token': proposal.token, 'confirm': true}),
);
_checkStatus(response);
@@ -453,7 +456,7 @@ class ApiRepository {
try {
final request =
http.Request('POST', Uri.parse('$_baseUrl/v1/web/search'))
..headers['Content-Type'] = 'application/json'
..headers.addAll(await _userHeaders())
..body = jsonEncode({
'query': query,
'max_results': 5,
@@ -500,6 +503,7 @@ class ApiRepository {
'POST',
Uri.parse('$_baseUrl/v1/agent/files/analyze'),
)..fields['question'] = question;
request.headers['Authorization'] = 'Bearer ${await _localSessionToken()}';
if (model != null) request.fields['model'] = model;
for (final file in files) {
request.files.add(
@@ -540,6 +544,7 @@ class ApiRepository {
'POST',
Uri.parse('$_baseUrl/v1/agent/images/analyze'),
)..fields['question'] = question;
request.headers['Authorization'] = 'Bearer ${await _localSessionToken()}';
if (model != null) request.fields['model'] = model;
for (final file in files) {
request.files.add(
@@ -593,10 +598,8 @@ class ApiRepository {
try {
final request =
http.Request('POST', Uri.parse('$_baseUrl/v1/chat/stream'))
..headers.addAll({
'Content-Type': 'application/json',
'Accept': 'application/x-ndjson',
})
..headers.addAll(await _userHeaders())
..headers.addAll({'Accept': 'application/x-ndjson'})
..body = jsonEncode({
if (model != null && model.isNotEmpty) 'model': model,
'messages':
@@ -657,6 +660,7 @@ class ApiRepository {
contentType: MediaType('audio', 'wav'),
),
);
request.headers['Authorization'] = 'Bearer ${await _localSessionToken()}';
final streamed = await request.send().timeout(const Duration(minutes: 3));
final response = await http.Response.fromStream(streamed);
if (response.statusCode < 200 || response.statusCode >= 300) {