quickagents 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,85 @@
1
+ """
2
+ QuickAgents - AI Agent Enhancement Toolkit
3
+
4
+ A Python package that provides local implementations of QuickAgents skills,
5
+ reducing token consumption by handling common operations locally.
6
+
7
+ Features:
8
+ - File operations with hash-based caching (SQLite backend)
9
+ - Memory management
10
+ - Loop detection
11
+ - Event reminders
12
+ - CLI tools
13
+
14
+ Installation:
15
+ pip install -e .
16
+ # or
17
+ pip install quickagents
18
+
19
+ Usage:
20
+ from quickagents import MemoryManager, LoopDetector, FileManager, CacheDB
21
+
22
+ # SQLite-based file operations with caching
23
+ fm = FileManager()
24
+ content = fm.read('path/to/file.md') # Cached read
25
+ fm.edit('path/to/file.md', old, new) # Auto-validates cache
26
+
27
+ # Memory management
28
+ memory = MemoryManager('.opencode/memory/MEMORY.md')
29
+ memory.set('project.name', 'MyProject')
30
+ name = memory.get('project.name')
31
+
32
+ # Loop detection
33
+ detector = LoopDetector()
34
+ result = detector.check('read', {'path': 'file.md'})
35
+ if result and result['detected']:
36
+ print(f"Loop detected: {result['count']} times")
37
+
38
+ # Direct SQLite cache access
39
+ db = CacheDB('.quickagents/cache.db')
40
+ stats = db.get_stats()
41
+
42
+ CLI Usage:
43
+ qa read <file> # 智能读取
44
+ qa write <file> <content> # 写入
45
+ qa edit <file> <old> <new> # 编辑
46
+ qa cache stats # 缓存统计
47
+ qa memory get <key> # 获取记忆
48
+ qa loop check # 循环检测
49
+ qa stats # 整体统计
50
+ """
51
+
52
+ __version__ = '1.0.0'
53
+ __author__ = 'QuickAgents Team'
54
+
55
+ from .core.file_manager import FileManager
56
+ from .core.memory import MemoryManager
57
+ from .core.loop_detector import LoopDetector
58
+ from .core.reminder import Reminder
59
+ from .core.cache_db import CacheDB
60
+ from .utils.hash_cache import HashCache
61
+ from .skills import (
62
+ FeedbackCollector, get_feedback_collector,
63
+ TDDWorkflow, TDDPhase, get_tdd_workflow,
64
+ GitCommit, get_git_commit
65
+ )
66
+
67
+ __all__ = [
68
+ # Core modules
69
+ 'FileManager',
70
+ 'MemoryManager',
71
+ 'LoopDetector',
72
+ 'Reminder',
73
+ 'CacheDB',
74
+ 'HashCache',
75
+ # Skills modules (100% localized)
76
+ 'FeedbackCollector',
77
+ 'get_feedback_collector',
78
+ 'TDDWorkflow',
79
+ 'TDDPhase',
80
+ 'get_tdd_workflow',
81
+ 'GitCommit',
82
+ 'get_git_commit',
83
+ # Version
84
+ '__version__',
85
+ ]
@@ -0,0 +1,437 @@
1
+ """
2
+ QuickAgents CLI - 命令行工具
3
+
4
+ 命令:
5
+ qa read <file> # 智能读取文件(哈希检测)
6
+ qa write <file> <content> # 写入文件
7
+ qa edit <file> <old> <new> # 编辑文件
8
+ qa hash <file> # 获取文件哈希
9
+ qa cache stats # 查看缓存统计
10
+ qa cache clear # 清空缓存
11
+ qa memory get <key> # 获取记忆
12
+ qa memory set <key> <val> # 设置记忆
13
+ qa memory search <keyword> # 搜索记忆
14
+ qa loop check # 检查循环模式
15
+ qa loop reset # 重置循环检测
16
+ qa stats # 查看整体统计
17
+
18
+ # 新增:Skills本地化命令
19
+ qa feedback bug <desc> # 记录Bug
20
+ qa feedback improve <desc> # 记录改进建议
21
+ qa feedback best <desc> # 记录最佳实践
22
+ qa feedback view [type] # 查看收集的经验
23
+
24
+ qa tdd red [test_file] # RED阶段:运行测试(应失败)
25
+ qa tdd green [test_file] # GREEN阶段:运行测试(应通过)
26
+ qa tdd refactor [test_file] # REFACTOR阶段
27
+ qa tdd stats # TDD统计
28
+ qa tdd coverage # 检查覆盖率
29
+
30
+ qa git status # Git状态
31
+ qa git check # Pre-commit检查
32
+ qa git commit <type> <scope> <subject> # 执行提交
33
+ qa git push # 推送到远程
34
+ """
35
+
36
+ import sys
37
+ import os
38
+ import argparse
39
+ from pathlib import Path
40
+
41
+ # 添加父目录到路径
42
+ sys.path.insert(0, str(Path(__file__).parent.parent))
43
+
44
+ from core.file_manager import FileManager
45
+ from core.memory import MemoryManager
46
+ from core.loop_detector import LoopDetector
47
+ from core.reminder import Reminder
48
+ from core.cache_db import CacheDB
49
+ from skills.feedback_collector import FeedbackCollector
50
+ from skills.tdd_workflow import TDDWorkflow, TDDPhase
51
+ from skills.git_commit import GitCommit
52
+
53
+
54
+ def cmd_read(args):
55
+ """读取文件命令"""
56
+ fm = FileManager()
57
+ content, changed = fm.read_if_changed(args.file)
58
+
59
+ print(f"文件: {args.file}")
60
+ print(f"状态: {'已变化/新读取' if changed else '使用缓存(节省Token)'}")
61
+ print("-" * 50)
62
+ print(content)
63
+
64
+
65
+ def cmd_write(args):
66
+ """写入文件命令"""
67
+ fm = FileManager()
68
+ fm.write(args.file, args.content)
69
+ print(f"✅ 已写入: {args.file}")
70
+
71
+
72
+ def cmd_edit(args):
73
+ """编辑文件命令"""
74
+ fm = FileManager()
75
+ result = fm.edit(args.file, args.old, args.new)
76
+
77
+ if result['success']:
78
+ print(f"✅ 编辑成功: {args.file}")
79
+ if result['token_saved'] > 0:
80
+ print(f"💰 节省Token: ~{result['token_saved']}")
81
+ else:
82
+ print(f"❌ 编辑失败: {result['message']}")
83
+
84
+
85
+ def cmd_hash(args):
86
+ """获取文件哈希"""
87
+ fm = FileManager()
88
+ hash_val = fm.get_file_hash(args.file)
89
+ print(f"文件: {args.file}")
90
+ print(f"哈希: {hash_val}")
91
+
92
+
93
+ def cmd_cache(args):
94
+ """缓存管理命令"""
95
+ db = CacheDB()
96
+
97
+ if args.action == 'stats':
98
+ stats = db.get_stats()['file_cache']
99
+ print("📊 缓存统计")
100
+ print(f" 缓存文件数: {stats['count']}")
101
+ print(f" 总大小: {stats['total_kb']} KB")
102
+
103
+ elif args.action == 'clear':
104
+ count = db.clear_file_cache()
105
+ print(f"✅ 已清空 {count} 个文件缓存")
106
+
107
+ elif args.action == 'list':
108
+ with db._get_connection() as conn:
109
+ cursor = conn.cursor()
110
+ cursor.execute('SELECT path, content_hash, size, access_count FROM file_cache')
111
+ rows = cursor.fetchall()
112
+
113
+ print("📁 缓存文件列表")
114
+ print("-" * 80)
115
+ for row in rows:
116
+ print(f" {row['path']}")
117
+ print(f" 哈希: {row['content_hash']}, 大小: {row['size']}B, 访问: {row['access_count']}次")
118
+
119
+
120
+ def cmd_memory(args):
121
+ """记忆管理命令"""
122
+ memory = MemoryManager()
123
+
124
+ if args.action == 'get':
125
+ value = memory.get(args.key)
126
+ if value is not None:
127
+ print(f"{args.key}: {value}")
128
+ else:
129
+ print(f"❌ 未找到: {args.key}")
130
+
131
+ elif args.action == 'set':
132
+ memory.set_factual(args.key, args.value)
133
+ memory.save()
134
+ print(f"✅ 已设置: {args.key} = {args.value}")
135
+
136
+ elif args.action == 'search':
137
+ results = memory.search(args.keyword)
138
+ print(f"🔍 搜索结果 ({len(results)} 条)")
139
+ print("-" * 50)
140
+ for r in results:
141
+ print(f" [{r['type']}] {r.get('key', r.get('category', ''))}: {r.get('value', r.get('content', ''))}")
142
+
143
+
144
+ def cmd_loop(args):
145
+ """循环检测命令"""
146
+ detector = LoopDetector()
147
+
148
+ if args.action == 'check':
149
+ patterns = detector.get_loop_patterns()
150
+ if patterns:
151
+ print("⚠️ 检测到循环模式")
152
+ print("-" * 50)
153
+ for p in patterns:
154
+ print(f" {p['tool_name']}: {p['count']}次")
155
+ print(f" 首次: {p['first_seen']}")
156
+ print(f" 最后: {p['last_seen']}")
157
+ else:
158
+ print("✅ 未检测到循环模式")
159
+
160
+ elif args.action == 'reset':
161
+ detector.reset()
162
+ print("✅ 已重置循环检测")
163
+
164
+ elif args.action == 'stats':
165
+ stats = detector.get_stats()
166
+ print("📊 循环检测统计")
167
+ print(f" 检测阈值: {stats['threshold']}")
168
+ print(f" 窗口大小: {stats['window_size']}")
169
+ print(f" 循环模式: {stats['total_patterns']}")
170
+
171
+
172
+ def cmd_stats(args):
173
+ """查看整体统计"""
174
+ db = CacheDB()
175
+ stats = db.get_stats()
176
+
177
+ print("📊 QuickAgents 统计")
178
+ print("=" * 50)
179
+
180
+ print("\n📁 文件缓存")
181
+ print(f" 缓存文件: {stats['file_cache']['count']}")
182
+ print(f" 总大小: {stats['file_cache']['total_kb']} KB")
183
+
184
+ print("\n🧠 记忆系统")
185
+ print(f" 记忆条目: {stats['memory']['count']}")
186
+
187
+ print("\n💰 Token节省")
188
+ print(f" 估算节省: {stats['tokens']['total_saved']} tokens")
189
+
190
+
191
+ def cmd_reminder(args):
192
+ """提醒系统命令"""
193
+ reminder = Reminder()
194
+
195
+ if args.action == 'check':
196
+ alerts = reminder.check_alerts()
197
+ if alerts:
198
+ print("⚠️ 活跃提醒")
199
+ print("-" * 50)
200
+ for a in alerts:
201
+ print(f" [{a['level']}] {a['message']}")
202
+ else:
203
+ print("✅ 无活跃提醒")
204
+
205
+ elif args.action == 'stats':
206
+ stats = reminder.get_stats()
207
+ print("📊 提醒系统统计")
208
+ print(f" 工具调用: {stats['tool_calls']}")
209
+ print(f" 错误次数: {stats['errors']}")
210
+ print(f" 运行时间: {int(stats['elapsed_minutes'])} 分钟")
211
+ print(f" 上下文使用: {stats['context_usage']}%")
212
+
213
+
214
+ # ==================== 新增:Skills本地化命令 ====================
215
+
216
+ def cmd_feedback(args):
217
+ """经验收集命令"""
218
+ collector = FeedbackCollector()
219
+
220
+ if args.action == 'bug':
221
+ success = collector.record('bug', args.description, scenario=args.scenario)
222
+ if success:
223
+ print(f"✅ 已记录Bug: {args.description}")
224
+ else:
225
+ print("ℹ️ 重复记录已忽略")
226
+
227
+ elif args.action == 'improve':
228
+ success = collector.record('improve', args.description, scenario=args.scenario)
229
+ if success:
230
+ print(f"✅ 已记录改进建议: {args.description}")
231
+ else:
232
+ print("ℹ️ 重复记录已忽略")
233
+
234
+ elif args.action == 'best':
235
+ success = collector.record('best', args.description, scenario=args.scenario)
236
+ if success:
237
+ print(f"✅ 已记录最佳实践: {args.description}")
238
+ else:
239
+ print("ℹ️ 重复记录已忽略")
240
+
241
+ elif args.action == 'view':
242
+ feedback_type = args.type if hasattr(args, 'type') and args.type else None
243
+ feedbacks = collector.get_feedback(feedback_type, limit=20)
244
+
245
+ print(f"📋 经验收集 ({len(feedbacks)} 条)")
246
+ print("-" * 50)
247
+ for fb in feedbacks:
248
+ print(f" [{fb['type']}] {fb['timestamp']}")
249
+ print(f" {fb['description'][:50]}...")
250
+
251
+ elif args.action == 'stats':
252
+ stats = collector.get_stats()
253
+ print("📊 经验收集统计")
254
+ print(f" 总计: {stats['total']} 条")
255
+ for ftype, count in stats['by_type'].items():
256
+ print(f" {ftype}: {count} 条")
257
+
258
+
259
+ def cmd_tdd(args):
260
+ """TDD工作流命令"""
261
+ tdd = TDDWorkflow()
262
+
263
+ if args.action == 'red':
264
+ result = tdd.run_red(args.test_file)
265
+ print(f"🔴 RED阶段: {'测试失败 ✓' if not result['passed'] else '测试通过 ⚠️'}")
266
+ print(f" 耗时: {result['duration_ms']}ms")
267
+ if result['passed']:
268
+ print(" ⚠️ 测试已通过,需要先写失败的测试!")
269
+
270
+ elif args.action == 'green':
271
+ result = tdd.run_green(args.test_file)
272
+ print(f"🟢 GREEN阶段: {'测试通过 ✓' if result['passed'] else '测试失败 ❌'}")
273
+ print(f" 耗时: {result['duration_ms']}ms")
274
+ if result['passed']:
275
+ print(" ✅ 可以进入Refactor阶段")
276
+
277
+ elif args.action == 'refactor':
278
+ result = tdd.run_refactor(args.test_file)
279
+ print(f"🔄 REFACTOR阶段: {'测试通过 ✓' if result['passed'] else '测试失败 ❌'}")
280
+ print(f" 耗时: {result['duration_ms']}ms")
281
+
282
+ elif args.action == 'stats':
283
+ stats = tdd.get_stats()
284
+ print("📊 TDD统计")
285
+ print(f" RED次数: {stats['red_count']}")
286
+ print(f" GREEN次数: {stats['green_count']}")
287
+ print(f" REFACTOR次数: {stats['refactor_count']}")
288
+ print(f" 测试命令: {stats['test_command']}")
289
+
290
+ elif args.action == 'coverage':
291
+ result = tdd.check_coverage(threshold=80)
292
+ print(f"📈 测试覆盖率: {result['coverage']}%")
293
+ print(f" 达标: {'✅' if result['meets_threshold'] else '❌'}")
294
+
295
+
296
+ def cmd_git(args):
297
+ """Git提交命令"""
298
+ git = GitCommit()
299
+
300
+ if args.action == 'status':
301
+ status = git.get_status()
302
+ print(f"🌿 分支: {status['branch']}")
303
+ print(f" 领先: {status['ahead']}, 落后: {status['behind']}")
304
+
305
+ if status['staged']:
306
+ print(f"\n✅ 已暂存 ({len(status['staged'])})")
307
+ for f in status['staged'][:5]:
308
+ print(f" {f}")
309
+
310
+ if status['unstaged']:
311
+ print(f"\n📝 未暂存 ({len(status['unstaged'])})")
312
+ for f in status['unstaged'][:5]:
313
+ print(f" {f}")
314
+
315
+ if status['untracked']:
316
+ print(f"\n❓ 未跟踪 ({len(status['untracked'])})")
317
+ for f in status['untracked'][:5]:
318
+ print(f" {f}")
319
+
320
+ elif args.action == 'check':
321
+ print("🔍 执行Pre-commit检查...")
322
+ checks = git.run_pre_commit_checks()
323
+
324
+ print(f"\n{'✅' if checks['all_passed'] else '❌'} 检查结果")
325
+ for check_name, result in checks['checks'].items():
326
+ status = '✅' if result['passed'] else ('⏭️' if result.get('skipped') else '❌')
327
+ print(f" {status} {check_name}")
328
+
329
+ elif args.action == 'commit':
330
+ print("🔍 执行Pre-commit检查...")
331
+ result = git.commit(
332
+ args.type, args.scope, args.subject,
333
+ run_checks=True
334
+ )
335
+
336
+ if result['success']:
337
+ print(f"✅ 提交成功: {result['commit_hash']}")
338
+ print(f" {result['message'].split(chr(10))[0]}")
339
+ else:
340
+ print(f"❌ 提交失败: {result['message']}")
341
+
342
+ elif args.action == 'push':
343
+ result = git.push()
344
+ if result['success']:
345
+ print("✅ 推送成功")
346
+ else:
347
+ print(f"❌ 推送失败: {result['message']}")
348
+
349
+
350
+ def main():
351
+ parser = argparse.ArgumentParser(description='QuickAgents CLI')
352
+ subparsers = parser.add_subparsers(dest='command', help='命令')
353
+
354
+ # read 命令
355
+ p_read = subparsers.add_parser('read', help='读取文件')
356
+ p_read.add_argument('file', help='文件路径')
357
+ p_read.set_defaults(func=cmd_read)
358
+
359
+ # write 命令
360
+ p_write = subparsers.add_parser('write', help='写入文件')
361
+ p_write.add_argument('file', help='文件路径')
362
+ p_write.add_argument('content', help='写入内容')
363
+ p_write.set_defaults(func=cmd_write)
364
+
365
+ # edit 命令
366
+ p_edit = subparsers.add_parser('edit', help='编辑文件')
367
+ p_edit.add_argument('file', help='文件路径')
368
+ p_edit.add_argument('old', help='要替换的内容')
369
+ p_edit.add_argument('new', help='替换后的内容')
370
+ p_edit.set_defaults(func=cmd_edit)
371
+
372
+ # hash 命令
373
+ p_hash = subparsers.add_parser('hash', help='获取文件哈希')
374
+ p_hash.add_argument('file', help='文件路径')
375
+ p_hash.set_defaults(func=cmd_hash)
376
+
377
+ # cache 命令
378
+ p_cache = subparsers.add_parser('cache', help='缓存管理')
379
+ p_cache.add_argument('action', choices=['stats', 'clear', 'list'], help='操作')
380
+ p_cache.set_defaults(func=cmd_cache)
381
+
382
+ # memory 命令
383
+ p_memory = subparsers.add_parser('memory', help='记忆管理')
384
+ p_memory.add_argument('action', choices=['get', 'set', 'search'], help='操作')
385
+ p_memory.add_argument('key', nargs='?', help='键名')
386
+ p_memory.add_argument('value', nargs='?', help='值')
387
+ p_memory.add_argument('--keyword', '-k', help='搜索关键词')
388
+ p_memory.set_defaults(func=cmd_memory)
389
+
390
+ # loop 命令
391
+ p_loop = subparsers.add_parser('loop', help='循环检测')
392
+ p_loop.add_argument('action', choices=['check', 'reset', 'stats'], help='操作')
393
+ p_loop.set_defaults(func=cmd_loop)
394
+
395
+ # stats 命令
396
+ p_stats = subparsers.add_parser('stats', help='查看统计')
397
+ p_stats.set_defaults(func=cmd_stats)
398
+
399
+ # reminder 命令
400
+ p_reminder = subparsers.add_parser('reminder', help='提醒系统')
401
+ p_reminder.add_argument('action', choices=['check', 'stats'], help='操作')
402
+ p_reminder.set_defaults(func=cmd_reminder)
403
+
404
+ # ==================== 新增命令 ====================
405
+
406
+ # feedback 命令
407
+ p_feedback = subparsers.add_parser('feedback', help='经验收集')
408
+ p_feedback.add_argument('action', choices=['bug', 'improve', 'best', 'view', 'stats'], help='操作')
409
+ p_feedback.add_argument('description', nargs='?', help='描述')
410
+ p_feedback.add_argument('--scenario', '-s', help='场景上下文')
411
+ p_feedback.add_argument('--type', '-t', help='反馈类型(view时使用)')
412
+ p_feedback.set_defaults(func=cmd_feedback)
413
+
414
+ # tdd 命令
415
+ p_tdd = subparsers.add_parser('tdd', help='TDD工作流')
416
+ p_tdd.add_argument('action', choices=['red', 'green', 'refactor', 'stats', 'coverage'], help='操作')
417
+ p_tdd.add_argument('test_file', nargs='?', help='测试文件')
418
+ p_tdd.set_defaults(func=cmd_tdd)
419
+
420
+ # git 命令
421
+ p_git = subparsers.add_parser('git', help='Git提交管理')
422
+ p_git.add_argument('action', choices=['status', 'check', 'commit', 'push'], help='操作')
423
+ p_git.add_argument('type', nargs='?', help='提交类型')
424
+ p_git.add_argument('scope', nargs='?', help='范围')
425
+ p_git.add_argument('subject', nargs='?', help='主题')
426
+ p_git.set_defaults(func=cmd_git)
427
+
428
+ args = parser.parse_args()
429
+
430
+ if hasattr(args, 'func'):
431
+ args.func(args)
432
+ else:
433
+ parser.print_help()
434
+
435
+
436
+ if __name__ == '__main__':
437
+ main()
quickagents/cli/qa.py ADDED
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ QuickAgents CLI Entry Point
4
+
5
+ Usage:
6
+ qa <command> [args]
7
+
8
+ Commands:
9
+ read <file> # 智能读取文件(哈希检测)
10
+ write <file> <content> # 写入文件
11
+ edit <file> <old> <new> # 编辑文件
12
+ hash <file> # 获取文件哈希
13
+ cache stats # 查看缓存统计
14
+ cache clear # 清空缓存
15
+ memory get <key> # 获取记忆
16
+ memory set <key> <val> # 设置记忆
17
+ loop check # 检查循环模式
18
+ stats # 查看整体统计
19
+ """
20
+
21
+ import sys
22
+ import os
23
+
24
+ # 添加包路径
25
+ script_dir = os.path.dirname(os.path.abspath(__file__))
26
+ package_dir = os.path.dirname(script_dir)
27
+ if package_dir not in sys.path:
28
+ sys.path.insert(0, package_dir)
29
+
30
+ from quickagents.cli.main import main
31
+
32
+ if __name__ == '__main__':
33
+ main()