@techwavedev/agi-agent-kit 1.1.3

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.
Files changed (196) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/README.md +147 -0
  3. package/bin/init.js +471 -0
  4. package/package.json +36 -0
  5. package/templates/.agent/agents/backend-specialist.md +263 -0
  6. package/templates/.agent/agents/code-archaeologist.md +106 -0
  7. package/templates/.agent/agents/database-architect.md +226 -0
  8. package/templates/.agent/agents/debugger.md +225 -0
  9. package/templates/.agent/agents/devops-engineer.md +242 -0
  10. package/templates/.agent/agents/documentation-writer.md +104 -0
  11. package/templates/.agent/agents/explorer-agent.md +73 -0
  12. package/templates/.agent/agents/frontend-specialist.md +556 -0
  13. package/templates/.agent/agents/game-developer.md +162 -0
  14. package/templates/.agent/agents/mobile-developer.md +377 -0
  15. package/templates/.agent/agents/orchestrator.md +416 -0
  16. package/templates/.agent/agents/penetration-tester.md +188 -0
  17. package/templates/.agent/agents/performance-optimizer.md +187 -0
  18. package/templates/.agent/agents/product-manager.md +112 -0
  19. package/templates/.agent/agents/project-planner.md +403 -0
  20. package/templates/.agent/agents/qa-automation-engineer.md +109 -0
  21. package/templates/.agent/agents/security-auditor.md +170 -0
  22. package/templates/.agent/agents/seo-specialist.md +111 -0
  23. package/templates/.agent/agents/test-engineer.md +158 -0
  24. package/templates/.agent/rules/GEMINI.md +253 -0
  25. package/templates/.agent/workflows/brainstorm.md +113 -0
  26. package/templates/.agent/workflows/create.md +59 -0
  27. package/templates/.agent/workflows/debug.md +103 -0
  28. package/templates/.agent/workflows/deploy.md +176 -0
  29. package/templates/.agent/workflows/enhance.md +63 -0
  30. package/templates/.agent/workflows/orchestrate.md +237 -0
  31. package/templates/.agent/workflows/plan.md +89 -0
  32. package/templates/.agent/workflows/preview.md +81 -0
  33. package/templates/.agent/workflows/status.md +86 -0
  34. package/templates/.agent/workflows/test.md +144 -0
  35. package/templates/.agent/workflows/ui-ux-pro-max.md +296 -0
  36. package/templates/base/.env.example +54 -0
  37. package/templates/base/AGENTS.md +463 -0
  38. package/templates/base/requirements.txt +6 -0
  39. package/templates/base/skill-creator/LICENSE.txt +202 -0
  40. package/templates/base/skill-creator/SKILL_skillcreator.md +389 -0
  41. package/templates/base/skill-creator/references/output-patterns.md +82 -0
  42. package/templates/base/skill-creator/references/workflows.md +28 -0
  43. package/templates/base/skill-creator/scripts/init_skill.py +304 -0
  44. package/templates/base/skill-creator/scripts/package_skill.py +110 -0
  45. package/templates/base/skill-creator/scripts/quick_validate.py +95 -0
  46. package/templates/base/skill-creator/scripts/update_catalog.py +371 -0
  47. package/templates/skills/core/README.md +21 -0
  48. package/templates/skills/core/documentation/SKILL.md +351 -0
  49. package/templates/skills/core/documentation/references/best_practices.md +201 -0
  50. package/templates/skills/core/documentation/scripts/analyze_code.py +307 -0
  51. package/templates/skills/core/documentation/scripts/detect_changes.py +460 -0
  52. package/templates/skills/core/documentation/scripts/generate_changelog.py +312 -0
  53. package/templates/skills/core/documentation/scripts/sync_docs.py +272 -0
  54. package/templates/skills/core/documentation/scripts/update_skill_docs.py +366 -0
  55. package/templates/skills/core/pdf-reader/SKILL.md +104 -0
  56. package/templates/skills/core/pdf-reader/references/pdf_libraries.md +83 -0
  57. package/templates/skills/core/pdf-reader/scripts/extract_text.py +295 -0
  58. package/templates/skills/core/qdrant-memory/SKILL.md +435 -0
  59. package/templates/skills/core/qdrant-memory/references/advanced_patterns.md +375 -0
  60. package/templates/skills/core/qdrant-memory/references/collection_schemas.md +229 -0
  61. package/templates/skills/core/qdrant-memory/references/complete_guide.md +724 -0
  62. package/templates/skills/core/qdrant-memory/references/embedding_models.md +325 -0
  63. package/templates/skills/core/qdrant-memory/scripts/benchmark_token_savings.py +640 -0
  64. package/templates/skills/core/qdrant-memory/scripts/embedding_utils.py +323 -0
  65. package/templates/skills/core/qdrant-memory/scripts/hybrid_search.py +214 -0
  66. package/templates/skills/core/qdrant-memory/scripts/init_collection.py +193 -0
  67. package/templates/skills/core/qdrant-memory/scripts/memory_retrieval.py +345 -0
  68. package/templates/skills/core/qdrant-memory/scripts/semantic_cache.py +282 -0
  69. package/templates/skills/core/qdrant-memory/scripts/test_skill.py +655 -0
  70. package/templates/skills/core/webcrawler/SKILL.md +292 -0
  71. package/templates/skills/core/webcrawler/references/advanced_crawling.md +181 -0
  72. package/templates/skills/core/webcrawler/scripts/crawl_docs.py +532 -0
  73. package/templates/skills/core/webcrawler/scripts/extract_page.py +189 -0
  74. package/templates/skills/core/webcrawler/scripts/filter_docs.py +200 -0
  75. package/templates/skills/knowledge/api-patterns/SKILL.md +81 -0
  76. package/templates/skills/knowledge/api-patterns/api-style.md +42 -0
  77. package/templates/skills/knowledge/api-patterns/auth.md +24 -0
  78. package/templates/skills/knowledge/api-patterns/documentation.md +26 -0
  79. package/templates/skills/knowledge/api-patterns/graphql.md +41 -0
  80. package/templates/skills/knowledge/api-patterns/rate-limiting.md +31 -0
  81. package/templates/skills/knowledge/api-patterns/response.md +37 -0
  82. package/templates/skills/knowledge/api-patterns/rest.md +40 -0
  83. package/templates/skills/knowledge/api-patterns/scripts/api_validator.py +211 -0
  84. package/templates/skills/knowledge/api-patterns/security-testing.md +122 -0
  85. package/templates/skills/knowledge/api-patterns/trpc.md +41 -0
  86. package/templates/skills/knowledge/api-patterns/versioning.md +22 -0
  87. package/templates/skills/knowledge/app-builder/SKILL.md +75 -0
  88. package/templates/skills/knowledge/app-builder/agent-coordination.md +71 -0
  89. package/templates/skills/knowledge/app-builder/feature-building.md +53 -0
  90. package/templates/skills/knowledge/app-builder/project-detection.md +34 -0
  91. package/templates/skills/knowledge/app-builder/scaffolding.md +118 -0
  92. package/templates/skills/knowledge/app-builder/tech-stack.md +40 -0
  93. package/templates/skills/knowledge/app-builder/templates/SKILL.md +39 -0
  94. package/templates/skills/knowledge/app-builder/templates/astro-static/TEMPLATE.md +76 -0
  95. package/templates/skills/knowledge/app-builder/templates/chrome-extension/TEMPLATE.md +92 -0
  96. package/templates/skills/knowledge/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
  97. package/templates/skills/knowledge/app-builder/templates/electron-desktop/TEMPLATE.md +88 -0
  98. package/templates/skills/knowledge/app-builder/templates/express-api/TEMPLATE.md +83 -0
  99. package/templates/skills/knowledge/app-builder/templates/flutter-app/TEMPLATE.md +90 -0
  100. package/templates/skills/knowledge/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -0
  101. package/templates/skills/knowledge/app-builder/templates/nextjs-fullstack/TEMPLATE.md +82 -0
  102. package/templates/skills/knowledge/app-builder/templates/nextjs-saas/TEMPLATE.md +100 -0
  103. package/templates/skills/knowledge/app-builder/templates/nextjs-static/TEMPLATE.md +106 -0
  104. package/templates/skills/knowledge/app-builder/templates/nuxt-app/TEMPLATE.md +101 -0
  105. package/templates/skills/knowledge/app-builder/templates/python-fastapi/TEMPLATE.md +83 -0
  106. package/templates/skills/knowledge/app-builder/templates/react-native-app/TEMPLATE.md +93 -0
  107. package/templates/skills/knowledge/architecture/SKILL.md +55 -0
  108. package/templates/skills/knowledge/architecture/context-discovery.md +43 -0
  109. package/templates/skills/knowledge/architecture/examples.md +94 -0
  110. package/templates/skills/knowledge/architecture/pattern-selection.md +68 -0
  111. package/templates/skills/knowledge/architecture/patterns-reference.md +50 -0
  112. package/templates/skills/knowledge/architecture/trade-off-analysis.md +77 -0
  113. package/templates/skills/knowledge/bash-linux/SKILL.md +199 -0
  114. package/templates/skills/knowledge/behavioral-modes/SKILL.md +242 -0
  115. package/templates/skills/knowledge/brainstorming/SKILL.md +163 -0
  116. package/templates/skills/knowledge/brainstorming/dynamic-questioning.md +350 -0
  117. package/templates/skills/knowledge/clean-code/SKILL.md +201 -0
  118. package/templates/skills/knowledge/code-review-checklist/SKILL.md +109 -0
  119. package/templates/skills/knowledge/database-design/SKILL.md +52 -0
  120. package/templates/skills/knowledge/database-design/database-selection.md +43 -0
  121. package/templates/skills/knowledge/database-design/indexing.md +39 -0
  122. package/templates/skills/knowledge/database-design/migrations.md +48 -0
  123. package/templates/skills/knowledge/database-design/optimization.md +36 -0
  124. package/templates/skills/knowledge/database-design/orm-selection.md +30 -0
  125. package/templates/skills/knowledge/database-design/schema-design.md +56 -0
  126. package/templates/skills/knowledge/database-design/scripts/schema_validator.py +172 -0
  127. package/templates/skills/knowledge/deployment-procedures/SKILL.md +241 -0
  128. package/templates/skills/knowledge/doc.md +177 -0
  129. package/templates/skills/knowledge/documentation-templates/SKILL.md +194 -0
  130. package/templates/skills/knowledge/frontend-design/SKILL.md +396 -0
  131. package/templates/skills/knowledge/frontend-design/animation-guide.md +331 -0
  132. package/templates/skills/knowledge/frontend-design/color-system.md +311 -0
  133. package/templates/skills/knowledge/frontend-design/decision-trees.md +418 -0
  134. package/templates/skills/knowledge/frontend-design/motion-graphics.md +306 -0
  135. package/templates/skills/knowledge/frontend-design/scripts/accessibility_checker.py +183 -0
  136. package/templates/skills/knowledge/frontend-design/scripts/ux_audit.py +722 -0
  137. package/templates/skills/knowledge/frontend-design/typography-system.md +345 -0
  138. package/templates/skills/knowledge/frontend-design/ux-psychology.md +541 -0
  139. package/templates/skills/knowledge/frontend-design/visual-effects.md +383 -0
  140. package/templates/skills/knowledge/game-development/2d-games/SKILL.md +119 -0
  141. package/templates/skills/knowledge/game-development/3d-games/SKILL.md +135 -0
  142. package/templates/skills/knowledge/game-development/SKILL.md +167 -0
  143. package/templates/skills/knowledge/game-development/game-art/SKILL.md +185 -0
  144. package/templates/skills/knowledge/game-development/game-audio/SKILL.md +190 -0
  145. package/templates/skills/knowledge/game-development/game-design/SKILL.md +129 -0
  146. package/templates/skills/knowledge/game-development/mobile-games/SKILL.md +108 -0
  147. package/templates/skills/knowledge/game-development/multiplayer/SKILL.md +132 -0
  148. package/templates/skills/knowledge/game-development/pc-games/SKILL.md +144 -0
  149. package/templates/skills/knowledge/game-development/vr-ar/SKILL.md +123 -0
  150. package/templates/skills/knowledge/game-development/web-games/SKILL.md +150 -0
  151. package/templates/skills/knowledge/geo-fundamentals/SKILL.md +156 -0
  152. package/templates/skills/knowledge/geo-fundamentals/scripts/geo_checker.py +289 -0
  153. package/templates/skills/knowledge/i18n-localization/SKILL.md +154 -0
  154. package/templates/skills/knowledge/i18n-localization/scripts/i18n_checker.py +241 -0
  155. package/templates/skills/knowledge/intelligent-routing/SKILL.md +334 -0
  156. package/templates/skills/knowledge/lint-and-validate/SKILL.md +45 -0
  157. package/templates/skills/knowledge/lint-and-validate/scripts/lint_runner.py +172 -0
  158. package/templates/skills/knowledge/lint-and-validate/scripts/type_coverage.py +173 -0
  159. package/templates/skills/knowledge/mcp-builder/SKILL.md +176 -0
  160. package/templates/skills/knowledge/mobile-design/SKILL.md +394 -0
  161. package/templates/skills/knowledge/mobile-design/decision-trees.md +516 -0
  162. package/templates/skills/knowledge/mobile-design/mobile-backend.md +491 -0
  163. package/templates/skills/knowledge/mobile-design/mobile-color-system.md +420 -0
  164. package/templates/skills/knowledge/mobile-design/mobile-debugging.md +122 -0
  165. package/templates/skills/knowledge/mobile-design/mobile-design-thinking.md +357 -0
  166. package/templates/skills/knowledge/mobile-design/mobile-navigation.md +458 -0
  167. package/templates/skills/knowledge/mobile-design/mobile-performance.md +767 -0
  168. package/templates/skills/knowledge/mobile-design/mobile-testing.md +356 -0
  169. package/templates/skills/knowledge/mobile-design/mobile-typography.md +433 -0
  170. package/templates/skills/knowledge/mobile-design/platform-android.md +666 -0
  171. package/templates/skills/knowledge/mobile-design/platform-ios.md +561 -0
  172. package/templates/skills/knowledge/mobile-design/scripts/mobile_audit.py +670 -0
  173. package/templates/skills/knowledge/mobile-design/touch-psychology.md +537 -0
  174. package/templates/skills/knowledge/nextjs-best-practices/SKILL.md +203 -0
  175. package/templates/skills/knowledge/nodejs-best-practices/SKILL.md +333 -0
  176. package/templates/skills/knowledge/parallel-agents/SKILL.md +175 -0
  177. package/templates/skills/knowledge/performance-profiling/SKILL.md +143 -0
  178. package/templates/skills/knowledge/performance-profiling/scripts/lighthouse_audit.py +76 -0
  179. package/templates/skills/knowledge/plan-writing/SKILL.md +152 -0
  180. package/templates/skills/knowledge/powershell-windows/SKILL.md +167 -0
  181. package/templates/skills/knowledge/python-patterns/SKILL.md +441 -0
  182. package/templates/skills/knowledge/react-patterns/SKILL.md +198 -0
  183. package/templates/skills/knowledge/red-team-tactics/SKILL.md +199 -0
  184. package/templates/skills/knowledge/seo-fundamentals/SKILL.md +129 -0
  185. package/templates/skills/knowledge/seo-fundamentals/scripts/seo_checker.py +219 -0
  186. package/templates/skills/knowledge/server-management/SKILL.md +161 -0
  187. package/templates/skills/knowledge/systematic-debugging/SKILL.md +109 -0
  188. package/templates/skills/knowledge/tailwind-patterns/SKILL.md +269 -0
  189. package/templates/skills/knowledge/tdd-workflow/SKILL.md +149 -0
  190. package/templates/skills/knowledge/testing-patterns/SKILL.md +178 -0
  191. package/templates/skills/knowledge/testing-patterns/scripts/test_runner.py +219 -0
  192. package/templates/skills/knowledge/vulnerability-scanner/SKILL.md +276 -0
  193. package/templates/skills/knowledge/vulnerability-scanner/checklists.md +121 -0
  194. package/templates/skills/knowledge/vulnerability-scanner/scripts/security_scan.py +458 -0
  195. package/templates/skills/knowledge/webapp-testing/SKILL.md +187 -0
  196. package/templates/skills/knowledge/webapp-testing/scripts/playwright_runner.py +173 -0
@@ -0,0 +1,193 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Script: init_collection.py
4
+ Purpose: Initialize Qdrant collections for semantic caching and memory storage.
5
+
6
+ Usage:
7
+ python init_collection.py --collection agent_memory --dimension 1536
8
+ python init_collection.py --collection semantic_cache --dimension 1536 --distance cosine
9
+
10
+ Arguments:
11
+ --collection Collection name (required)
12
+ --dimension Vector dimension (default: 1536 for OpenAI embeddings)
13
+ --distance Distance metric: cosine, euclid, dot (default: cosine)
14
+ --url Qdrant URL (default: http://localhost:6333)
15
+
16
+ Exit Codes:
17
+ 0 - Success
18
+ 1 - Invalid arguments
19
+ 2 - Connection error
20
+ 3 - Collection creation error
21
+ """
22
+
23
+ import argparse
24
+ import json
25
+ import os
26
+ import sys
27
+ from urllib.request import Request, urlopen
28
+ from urllib.error import URLError, HTTPError
29
+
30
+
31
+ def create_collection(url: str, name: str, dimension: int, distance: str) -> dict:
32
+ """Create a Qdrant collection with optimized settings."""
33
+
34
+ distance_map = {
35
+ "cosine": "Cosine",
36
+ "euclid": "Euclid",
37
+ "dot": "Dot"
38
+ }
39
+
40
+ payload = {
41
+ "vectors": {
42
+ "size": dimension,
43
+ "distance": distance_map.get(distance.lower(), "Cosine")
44
+ },
45
+ "optimizers_config": {
46
+ "indexing_threshold": 10000,
47
+ "memmap_threshold": 20000
48
+ },
49
+ "hnsw_config": {
50
+ "m": 16,
51
+ "ef_construct": 100,
52
+ "full_scan_threshold": 10000
53
+ }
54
+ }
55
+
56
+ req = Request(
57
+ f"{url}/collections/{name}",
58
+ data=json.dumps(payload).encode(),
59
+ headers={"Content-Type": "application/json"},
60
+ method="PUT"
61
+ )
62
+
63
+ try:
64
+ with urlopen(req, timeout=30) as response:
65
+ return json.loads(response.read().decode())
66
+ except HTTPError as e:
67
+ if e.code == 409:
68
+ return {"status": "exists", "message": f"Collection '{name}' already exists"}
69
+ raise
70
+
71
+
72
+ def create_payload_index(url: str, collection: str, field: str, field_type: str) -> dict:
73
+ """Create payload index for efficient filtering."""
74
+
75
+ schema_map = {
76
+ "keyword": "keyword",
77
+ "integer": "integer",
78
+ "float": "float",
79
+ "bool": "bool",
80
+ "datetime": "datetime",
81
+ "text": "text"
82
+ }
83
+
84
+ payload = {
85
+ "field_name": field,
86
+ "field_schema": schema_map.get(field_type, "keyword")
87
+ }
88
+
89
+ req = Request(
90
+ f"{url}/collections/{collection}/index",
91
+ data=json.dumps(payload).encode(),
92
+ headers={"Content-Type": "application/json"},
93
+ method="PUT"
94
+ )
95
+
96
+ try:
97
+ with urlopen(req, timeout=30) as response:
98
+ return json.loads(response.read().decode())
99
+ except HTTPError:
100
+ return {"status": "index_exists"}
101
+
102
+
103
+ def main():
104
+ parser = argparse.ArgumentParser(
105
+ description="Initialize Qdrant collection for agent memory"
106
+ )
107
+ parser.add_argument(
108
+ "--collection",
109
+ required=True,
110
+ help="Collection name"
111
+ )
112
+ parser.add_argument(
113
+ "--dimension",
114
+ type=int,
115
+ default=1536,
116
+ help="Vector dimension (default: 1536)"
117
+ )
118
+ parser.add_argument(
119
+ "--distance",
120
+ choices=["cosine", "euclid", "dot"],
121
+ default="cosine",
122
+ help="Distance metric (default: cosine)"
123
+ )
124
+ parser.add_argument(
125
+ "--url",
126
+ default=os.environ.get("QDRANT_URL", "http://localhost:6333"),
127
+ help="Qdrant URL"
128
+ )
129
+
130
+ args = parser.parse_args()
131
+
132
+ print(f"🔧 Initializing collection: {args.collection}")
133
+ print(f" URL: {args.url}")
134
+ print(f" Dimension: {args.dimension}")
135
+ print(f" Distance: {args.distance}")
136
+
137
+ try:
138
+ # Create collection
139
+ result = create_collection(
140
+ args.url,
141
+ args.collection,
142
+ args.dimension,
143
+ args.distance
144
+ )
145
+ print(f"✅ Collection created: {result}")
146
+
147
+ # Create standard payload indexes
148
+ indexes = [
149
+ ("type", "keyword"),
150
+ ("project", "keyword"),
151
+ ("timestamp", "datetime"),
152
+ ("tags", "keyword"),
153
+ ("model", "keyword"),
154
+ ("token_count", "integer"),
155
+ ("score_threshold", "float")
156
+ ]
157
+
158
+ print("📑 Creating payload indexes...")
159
+ for field, field_type in indexes:
160
+ idx_result = create_payload_index(
161
+ args.url,
162
+ args.collection,
163
+ field,
164
+ field_type
165
+ )
166
+ print(f" {field}: {idx_result.get('status', 'created')}")
167
+
168
+ print(json.dumps({
169
+ "status": "success",
170
+ "collection": args.collection,
171
+ "dimension": args.dimension,
172
+ "distance": args.distance
173
+ }))
174
+ sys.exit(0)
175
+
176
+ except URLError as e:
177
+ print(json.dumps({
178
+ "status": "error",
179
+ "type": "connection_error",
180
+ "message": f"Cannot connect to Qdrant at {args.url}: {e}"
181
+ }), file=sys.stderr)
182
+ sys.exit(2)
183
+ except Exception as e:
184
+ print(json.dumps({
185
+ "status": "error",
186
+ "type": type(e).__name__,
187
+ "message": str(e)
188
+ }), file=sys.stderr)
189
+ sys.exit(3)
190
+
191
+
192
+ if __name__ == "__main__":
193
+ main()
@@ -0,0 +1,345 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Script: memory_retrieval.py
4
+ Purpose: Long-term memory retrieval for context optimization.
5
+
6
+ Supports both Ollama (local/private) and OpenAI (cloud) embeddings.
7
+ Default: Ollama with nomic-embed-text model.
8
+
9
+ Usage:
10
+ # Retrieve relevant context (uses Ollama by default)
11
+ python3 memory_retrieval.py retrieve --query "database architecture decisions"
12
+
13
+ # Store memory
14
+ python3 memory_retrieval.py store --content "We chose PostgreSQL..." --type decision
15
+
16
+ # List memories
17
+ python3 memory_retrieval.py list --type decision --project api-catalogue
18
+
19
+ Environment Variables:
20
+ EMBEDDING_PROVIDER - "ollama" (default) or "openai"
21
+ OLLAMA_URL - Ollama server URL (default: http://localhost:11434)
22
+ OPENAI_API_KEY - Required for OpenAI provider
23
+ QDRANT_URL - Qdrant server URL (default: http://localhost:6333)
24
+ MEMORY_COLLECTION - Collection name (default: agent_memory)
25
+
26
+ Functions:
27
+ retrieve_context(query, filters, top_k) - Get relevant memory chunks
28
+ store_memory(content, memory_type, metadata) - Store new memory
29
+ list_memories(filters) - List memories with filtering
30
+
31
+ Exit Codes:
32
+ 0 - Success
33
+ 1 - No results found
34
+ 2 - Connection error
35
+ 3 - Operation error
36
+ """
37
+
38
+ import argparse
39
+ import json
40
+ import os
41
+ import sys
42
+ import uuid
43
+ from datetime import datetime
44
+ from typing import Optional, Dict, Any, List
45
+ from urllib.request import Request, urlopen
46
+ from urllib.error import URLError, HTTPError
47
+
48
+ # Import shared embedding utilities (supports Ollama and OpenAI)
49
+ try:
50
+ from embedding_utils import get_embedding
51
+ except ImportError:
52
+ # Fallback if run from different directory
53
+ sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
54
+ from embedding_utils import get_embedding
55
+
56
+ # Configuration
57
+ QDRANT_URL = os.environ.get("QDRANT_URL", "http://localhost:6333")
58
+ COLLECTION = os.environ.get("MEMORY_COLLECTION", "agent_memory")
59
+
60
+
61
+ def retrieve_context(
62
+ query: str,
63
+ filters: Optional[Dict[str, Any]] = None,
64
+ top_k: int = 5,
65
+ score_threshold: float = 0.7
66
+ ) -> List[Dict[str, Any]]:
67
+ """
68
+ Retrieve relevant context from long-term memory.
69
+
70
+ Instead of passing 20K tokens of conversation history,
71
+ this returns only the top-K most relevant chunks (500-1000 tokens).
72
+
73
+ Args:
74
+ query: Natural language query
75
+ filters: Qdrant filter conditions (type, project, tags, etc.)
76
+ top_k: Number of results to return
77
+ score_threshold: Minimum similarity score
78
+
79
+ Returns:
80
+ List of relevant memory chunks with metadata
81
+ """
82
+ embedding = get_embedding(query)
83
+
84
+ search_payload = {
85
+ "vector": embedding,
86
+ "limit": top_k,
87
+ "score_threshold": score_threshold,
88
+ "with_payload": True
89
+ }
90
+
91
+ if filters:
92
+ search_payload["filter"] = filters
93
+
94
+ req = Request(
95
+ f"{QDRANT_URL}/collections/{COLLECTION}/points/search",
96
+ data=json.dumps(search_payload).encode(),
97
+ headers={"Content-Type": "application/json"},
98
+ method="POST"
99
+ )
100
+
101
+ try:
102
+ with urlopen(req, timeout=30) as response:
103
+ result = json.loads(response.read().decode())
104
+
105
+ chunks = []
106
+ total_tokens = 0
107
+
108
+ for hit in result.get("result", []):
109
+ content = hit["payload"].get("content", "")
110
+ token_estimate = len(content.split())
111
+ total_tokens += token_estimate
112
+
113
+ chunks.append({
114
+ "content": content,
115
+ "score": hit["score"],
116
+ "type": hit["payload"].get("type"),
117
+ "project": hit["payload"].get("project"),
118
+ "timestamp": hit["payload"].get("timestamp"),
119
+ "tags": hit["payload"].get("tags", []),
120
+ "token_estimate": token_estimate
121
+ })
122
+
123
+ return {
124
+ "chunks": chunks,
125
+ "total_chunks": len(chunks),
126
+ "total_tokens_estimate": total_tokens,
127
+ "query": query
128
+ }
129
+
130
+ except HTTPError as e:
131
+ if e.code == 404:
132
+ return {"chunks": [], "total_chunks": 0, "total_tokens_estimate": 0}
133
+ raise
134
+
135
+
136
+ def store_memory(
137
+ content: str,
138
+ memory_type: str,
139
+ metadata: Optional[Dict[str, Any]] = None
140
+ ) -> Dict[str, Any]:
141
+ """
142
+ Store a new memory in long-term storage.
143
+
144
+ Args:
145
+ content: The memory content (text)
146
+ memory_type: Category (decision, code, error, conversation, technical)
147
+ metadata: Additional metadata (project, tags, etc.)
148
+
149
+ Returns:
150
+ Storage confirmation
151
+ """
152
+ embedding = get_embedding(content)
153
+
154
+ # Generate UUID for memory
155
+ point_id = str(uuid.uuid4())
156
+
157
+ payload = {
158
+ "content": content,
159
+ "type": memory_type,
160
+ "timestamp": datetime.utcnow().isoformat(),
161
+ "token_count": len(content.split()),
162
+ **(metadata or {})
163
+ }
164
+
165
+ upsert_payload = {
166
+ "points": [
167
+ {
168
+ "id": point_id,
169
+ "vector": embedding,
170
+ "payload": payload
171
+ }
172
+ ]
173
+ }
174
+
175
+ req = Request(
176
+ f"{QDRANT_URL}/collections/{COLLECTION}/points?wait=true",
177
+ data=json.dumps(upsert_payload).encode(),
178
+ headers={"Content-Type": "application/json"},
179
+ method="PUT"
180
+ )
181
+
182
+ with urlopen(req, timeout=30) as response:
183
+ result = json.loads(response.read().decode())
184
+
185
+ return {
186
+ "status": "stored",
187
+ "point_id": point_id,
188
+ "type": memory_type,
189
+ "token_count": payload["token_count"],
190
+ "result": result
191
+ }
192
+
193
+
194
+ def list_memories(
195
+ filters: Optional[Dict[str, Any]] = None,
196
+ limit: int = 20
197
+ ) -> Dict[str, Any]:
198
+ """
199
+ List memories with optional filtering.
200
+
201
+ Args:
202
+ filters: Qdrant filter conditions
203
+ limit: Maximum number of results
204
+
205
+ Returns:
206
+ List of memories matching filters
207
+ """
208
+ scroll_payload = {
209
+ "limit": limit,
210
+ "with_payload": True,
211
+ "with_vector": False
212
+ }
213
+
214
+ if filters:
215
+ scroll_payload["filter"] = filters
216
+
217
+ req = Request(
218
+ f"{QDRANT_URL}/collections/{COLLECTION}/points/scroll",
219
+ data=json.dumps(scroll_payload).encode(),
220
+ headers={"Content-Type": "application/json"},
221
+ method="POST"
222
+ )
223
+
224
+ with urlopen(req, timeout=30) as response:
225
+ result = json.loads(response.read().decode())
226
+
227
+ memories = []
228
+ for point in result.get("result", {}).get("points", []):
229
+ memories.append({
230
+ "id": point["id"],
231
+ "type": point["payload"].get("type"),
232
+ "content_preview": point["payload"].get("content", "")[:200] + "...",
233
+ "project": point["payload"].get("project"),
234
+ "timestamp": point["payload"].get("timestamp"),
235
+ "tags": point["payload"].get("tags", [])
236
+ })
237
+
238
+ return {
239
+ "memories": memories,
240
+ "count": len(memories),
241
+ "has_more": result.get("result", {}).get("next_page_offset") is not None
242
+ }
243
+
244
+
245
+ def build_filter(type_filter: str = None, project: str = None, tags: List[str] = None) -> Dict:
246
+ """Build Qdrant filter from arguments."""
247
+ must = []
248
+
249
+ if type_filter:
250
+ must.append({"key": "type", "match": {"value": type_filter}})
251
+ if project:
252
+ must.append({"key": "project", "match": {"value": project}})
253
+ if tags:
254
+ must.append({"key": "tags", "match": {"any": tags}})
255
+
256
+ return {"must": must} if must else None
257
+
258
+
259
+ def main():
260
+ parser = argparse.ArgumentParser(description="Long-term memory operations")
261
+ subparsers = parser.add_subparsers(dest="command", required=True)
262
+
263
+ # Retrieve command
264
+ retrieve_parser = subparsers.add_parser("retrieve", help="Retrieve relevant context")
265
+ retrieve_parser.add_argument("--query", required=True, help="Search query")
266
+ retrieve_parser.add_argument("--type", help="Filter by memory type")
267
+ retrieve_parser.add_argument("--project", help="Filter by project")
268
+ retrieve_parser.add_argument("--tags", nargs="+", help="Filter by tags")
269
+ retrieve_parser.add_argument("--top-k", type=int, default=5, help="Number of results")
270
+ retrieve_parser.add_argument("--threshold", type=float, default=0.7, help="Score threshold")
271
+
272
+ # Store command
273
+ store_parser = subparsers.add_parser("store", help="Store new memory")
274
+ store_parser.add_argument("--content", required=True, help="Memory content")
275
+ store_parser.add_argument("--type", required=True,
276
+ choices=["decision", "code", "error", "conversation", "technical"],
277
+ help="Memory type")
278
+ store_parser.add_argument("--project", help="Project name")
279
+ store_parser.add_argument("--tags", nargs="+", help="Tags for the memory")
280
+
281
+ # List command
282
+ list_parser = subparsers.add_parser("list", help="List memories")
283
+ list_parser.add_argument("--type", help="Filter by memory type")
284
+ list_parser.add_argument("--project", help="Filter by project")
285
+ list_parser.add_argument("--limit", type=int, default=20, help="Max results")
286
+
287
+ args = parser.parse_args()
288
+
289
+ try:
290
+ if args.command == "retrieve":
291
+ filters = build_filter(
292
+ type_filter=getattr(args, "type", None),
293
+ project=args.project,
294
+ tags=args.tags
295
+ )
296
+ result = retrieve_context(
297
+ args.query,
298
+ filters={"must": filters["must"]} if filters else None,
299
+ top_k=args.top_k,
300
+ score_threshold=args.threshold
301
+ )
302
+ print(json.dumps(result, indent=2))
303
+ sys.exit(0 if result["total_chunks"] > 0 else 1)
304
+
305
+ elif args.command == "store":
306
+ metadata = {}
307
+ if args.project:
308
+ metadata["project"] = args.project
309
+ if args.tags:
310
+ metadata["tags"] = args.tags
311
+
312
+ result = store_memory(args.content, args.type, metadata)
313
+ print(json.dumps(result, indent=2))
314
+ sys.exit(0)
315
+
316
+ elif args.command == "list":
317
+ filters = build_filter(
318
+ type_filter=getattr(args, "type", None),
319
+ project=args.project
320
+ )
321
+ result = list_memories(
322
+ filters={"must": filters["must"]} if filters else None,
323
+ limit=args.limit
324
+ )
325
+ print(json.dumps(result, indent=2))
326
+ sys.exit(0)
327
+
328
+ except URLError as e:
329
+ print(json.dumps({
330
+ "status": "error",
331
+ "type": "connection_error",
332
+ "message": str(e)
333
+ }), file=sys.stderr)
334
+ sys.exit(2)
335
+ except Exception as e:
336
+ print(json.dumps({
337
+ "status": "error",
338
+ "type": type(e).__name__,
339
+ "message": str(e)
340
+ }), file=sys.stderr)
341
+ sys.exit(3)
342
+
343
+
344
+ if __name__ == "__main__":
345
+ main()