fix: clarify project registration controls

This commit is contained in:
Hamza Ayed
2026-10-04 03:28:30 +03:00
parent a91b35de1f
commit 40731f01d9
3 changed files with 49 additions and 9 deletions
+1
View File
@@ -190,6 +190,7 @@
- [x] نواة وكيل الملفات: تقدم الخطوات عبر SSE، ومعاينة diff وموافقة صريحة قبل تطبيق الكتابة داخل الجذر المخصص للحساب. اختبار API مباشر في 2026-10-03 أكد اختيار أداة الحاسبة وإرجاع النتيجة الصحيحة. الخطوة التالية للوكيل هي أوامر تطوير محددة داخل عزل نظام تشغيل قابل للتحقق؛ لم يُفعّل تشغيل الأوامر العامة.
- [x] توضيح تجربة المشاريع وإصلاح سياق الملف المحدد (2026-10-03): نقطة `/v1/agent/workspace/files` على الخدمة الحية سردت 121 ملفًا من مجلد المشروع المسموح. كشف الاختبار الأول أن Gemma قد تتجاهل سؤال الملف إذا وصلها مقتطف طويل؛ أضيف اختيار مقاطع مرتبطة بكلمات السؤال ضمن سقف 4,000 حرف، ورسالة موجزة بلا مخطط أدوات في مهارة «شرح الكود» عند إرفاق ملفات محددة، ودرجة حرارة 0. اختبارات مهارات الوكيل 20/20 ومجموعة Python الكاملة 90/90. بعد إعادة تشغيل FastAPI الحالي عبر `start-api.ps1` (PID 51376، مع قاعدة SQLite الفعلية نفسها)، أجاب `/v1/agent/run` عن `README.md` بـ`gemma4:e2b` مع الاستشهاد بالمصدر. تسجيل المجلد محلي؛ والأمر/الاختبار الآلي داخل المشروع ما زالا غير متاحين حتى اكتمال عزل نظام التشغيل.
- [x] توضيح إضافة المشروع في واجهة Windows/الويب (2026-10-04): على المساحات الواسعة يظهر زر نصّي «إضافة مجلد مشروع»، وفي القائمة الجانبية صار الإجراء «إضافة مجلد مشروع موجود» لتوضيح أنه يسجل مجلدًا موجودًا ولا ينشئ مشروعًا من الصفر. بقي الزر ظاهرًا عند إخفاء القائمة الجانبية؛ اجتازت اختبارات Flutter السبعة وتحليل Flutter بلا ملاحظات، وبُني Windows Debug من نسخة `%LOCALAPPDATA%` بنجاح خلال 71.3 ثانية. هذا تحسين للواجهة فقط: الوكيل ما زال يقرأ ويبحث ويقترح تعديلًا بموافقة المستخدم، ولا يشغّل أوامر المشروع أو اختباراته حتى يكتمل العزل المطلوب.
## ترتيب التنفيذ القادم
1. [x] التحقق من إجراءات المحادثة الجديدة على Windows Debug (2026-10-01): تشغيل API وGemma وGroq، اختبار صوت من الميكروفون حتى التفريغ والرد والحفظ في SQLite، نجاح اختبار الواجهة على نافذة 800px ونجاح `flutter analyze`.
@@ -1097,7 +1097,7 @@ class _ChatPageState extends State<ChatPage> {
),
),
IconButton(
tooltip: 'تسجيل مشروع جديد',
tooltip: 'إضافة مشروع موجود إلى القائمة',
visualDensity: VisualDensity.compact,
onPressed: chat.isSending ? null : _addWorkspaceProject,
icon: const Icon(Icons.create_new_folder_outlined, size: 19),
@@ -1108,7 +1108,7 @@ class _ChatPageState extends State<ChatPage> {
TextButton.icon(
onPressed: chat.isSending ? null : _addWorkspaceProject,
icon: const Icon(Icons.add, size: 16),
label: const Text('تسجيل مشروع جديد'),
label: const Text('إضافة مجلد مشروع موجود'),
style: TextButton.styleFrom(
alignment: Alignment.centerRight,
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 6),
@@ -1407,11 +1407,18 @@ class _ChatPageState extends State<ChatPage> {
),
),
SizedBox(width: compact ? 2 : 12),
IconButton.filledTonal(
onPressed: chat.isSending ? null : _addWorkspaceProject,
tooltip: 'تسجيل مشروع من مجلد موجود',
icon: const Icon(Icons.create_new_folder_outlined),
),
if (constraints.maxWidth >= 900)
FilledButton.tonalIcon(
onPressed: chat.isSending ? null : _addWorkspaceProject,
icon: const Icon(Icons.create_new_folder_outlined),
label: const Text('إضافة مجلد مشروع'),
)
else
IconButton.filledTonal(
onPressed: chat.isSending ? null : _addWorkspaceProject,
tooltip: 'إضافة مجلد مشروع موجود',
icon: const Icon(Icons.create_new_folder_outlined),
),
IconButton(
onPressed: _chooseWorkspace,
tooltip:
@@ -169,7 +169,7 @@ void main() {
expect(find.text('مساعدك المحلي'), findsOneWidget);
expect(find.text('مشاريعي'), findsOneWidget);
expect(find.byTooltip('تسجيل مشروع جديد'), findsOneWidget);
expect(find.byTooltip('إضافة مشروع موجود إلى القائمة'), findsOneWidget);
expect(tester.takeException(), isNull);
await chatCubit.setDarkMode(true);
@@ -210,7 +210,39 @@ void main() {
await tester.pumpAndSettle();
expect(find.text('مشاريعي'), findsNothing);
expect(find.byTooltip('تسجيل مشروع من مجلد موجود'), findsOneWidget);
expect(find.byTooltip('إضافة مجلد مشروع موجود'), findsOneWidget);
expect(tester.takeException(), isNull);
await chatCubit.close();
});
testWidgets('wide desktop shows a labeled project registration action', (
tester,
) async {
tester.view.physicalSize = const Size(1500, 900);
tester.view.devicePixelRatio = 1;
addTearDown(tester.view.resetPhysicalSize);
addTearDown(tester.view.resetDevicePixelRatio);
final api = _TestApiRepository();
final chatCubit = ChatCubit(
api,
settingsStore: LocalSettingsStore.inMemory(),
);
await tester.pumpWidget(
MultiRepositoryProvider(
providers: [RepositoryProvider<ApiRepository>.value(value: api)],
child: MultiBlocProvider(
providers: [
BlocProvider.value(value: chatCubit),
BlocProvider(create: (_) => VoiceCubit(api, AudioRecorder())),
],
child: const SovereignApp(),
),
),
);
await tester.pumpAndSettle();
expect(find.text('إضافة مجلد مشروع'), findsOneWidget);
expect(tester.takeException(), isNull);
await chatCubit.close();
});