@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,655 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Script: test_skill.py
4
+ Purpose: Comprehensive test suite for the qdrant-memory skill.
5
+
6
+ Usage:
7
+ # Quick connectivity test (no embeddings)
8
+ python test_skill.py --mode connectivity
9
+
10
+ # Full test with LOCAL embeddings (Ollama - recommended for M3 Mac)
11
+ python test_skill.py --mode full --embeddings ollama
12
+
13
+ # Full test with OpenAI embeddings
14
+ python test_skill.py --mode full --embeddings openai
15
+
16
+ # Cleanup after tests
17
+ python test_skill.py --cleanup
18
+
19
+ Prerequisites for Ollama (local):
20
+ 1. Install: brew install ollama
21
+ 2. Start: ollama serve
22
+ 3. Pull model: ollama pull nomic-embed-text
23
+
24
+ Exit Codes:
25
+ 0 - All tests passed
26
+ 1 - Some tests failed
27
+ 2 - Connection error
28
+ """
29
+
30
+ import argparse
31
+ import json
32
+ import os
33
+ import sys
34
+ import uuid
35
+ from datetime import datetime, timezone
36
+ from urllib.request import Request, urlopen
37
+ from urllib.error import URLError, HTTPError
38
+ from typing import Dict, Any, Optional, List
39
+
40
+ # Configuration
41
+ QDRANT_URL = os.environ.get("QDRANT_URL", "http://localhost:6333")
42
+ OLLAMA_URL = os.environ.get("OLLAMA_URL", "http://localhost:11434")
43
+ OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY", "")
44
+ TEST_COLLECTION = "test_qdrant_memory_skill"
45
+
46
+ # Embedding model configurations
47
+ EMBEDDING_CONFIGS = {
48
+ "ollama": {
49
+ "model": "nomic-embed-text",
50
+ "dimensions": 768,
51
+ "url": f"{OLLAMA_URL}/api/embeddings"
52
+ },
53
+ "openai": {
54
+ "model": "text-embedding-3-small",
55
+ "dimensions": 1536,
56
+ "url": "https://api.openai.com/v1/embeddings"
57
+ },
58
+ "bedrock": {
59
+ "model": "amazon.titan-embed-text-v2:0",
60
+ "dimensions": 1024,
61
+ "url": "via-boto3"
62
+ }
63
+ }
64
+
65
+ # Will be set based on --embeddings argument
66
+ EMBEDDING_PROVIDER = "ollama"
67
+ VECTOR_DIM = 768
68
+
69
+
70
+ class Colors:
71
+ GREEN = "\033[92m"
72
+ RED = "\033[91m"
73
+ YELLOW = "\033[93m"
74
+ BLUE = "\033[94m"
75
+ CYAN = "\033[96m"
76
+ RESET = "\033[0m"
77
+ BOLD = "\033[1m"
78
+
79
+
80
+ def print_header(text: str):
81
+ print(f"\n{Colors.BOLD}{Colors.BLUE}{'='*60}{Colors.RESET}")
82
+ print(f"{Colors.BOLD}{Colors.BLUE}{text}{Colors.RESET}")
83
+ print(f"{Colors.BOLD}{Colors.BLUE}{'='*60}{Colors.RESET}\n")
84
+
85
+
86
+ def print_test(name: str, passed: bool, details: str = ""):
87
+ icon = f"{Colors.GREEN}โœ“{Colors.RESET}" if passed else f"{Colors.RED}โœ—{Colors.RESET}"
88
+ status = f"{Colors.GREEN}PASS{Colors.RESET}" if passed else f"{Colors.RED}FAIL{Colors.RESET}"
89
+ print(f" {icon} {name}: {status}")
90
+ if details:
91
+ print(f" {Colors.YELLOW}{details}{Colors.RESET}")
92
+
93
+
94
+ def qdrant_request(method: str, endpoint: str, data: Optional[Dict] = None) -> Dict:
95
+ """Make a request to Qdrant API."""
96
+ url = f"{QDRANT_URL}{endpoint}"
97
+ req = Request(
98
+ url,
99
+ data=json.dumps(data).encode() if data else None,
100
+ headers={"Content-Type": "application/json"},
101
+ method=method
102
+ )
103
+
104
+ with urlopen(req, timeout=30) as response:
105
+ return json.loads(response.read().decode())
106
+
107
+
108
+ def get_embedding_ollama(text: str) -> List[float]:
109
+ """Generate embedding using Ollama (local)."""
110
+ config = EMBEDDING_CONFIGS["ollama"]
111
+
112
+ payload = {
113
+ "model": config["model"],
114
+ "prompt": text
115
+ }
116
+
117
+ req = Request(
118
+ config["url"],
119
+ data=json.dumps(payload).encode(),
120
+ headers={"Content-Type": "application/json"},
121
+ method="POST"
122
+ )
123
+
124
+ with urlopen(req, timeout=60) as response:
125
+ result = json.loads(response.read().decode())
126
+ return result["embedding"]
127
+
128
+
129
+ def get_embedding_openai(text: str) -> List[float]:
130
+ """Generate embedding using OpenAI API."""
131
+ if not OPENAI_API_KEY:
132
+ raise ValueError("OPENAI_API_KEY not set")
133
+
134
+ config = EMBEDDING_CONFIGS["openai"]
135
+
136
+ payload = {
137
+ "input": text,
138
+ "model": config["model"]
139
+ }
140
+
141
+ req = Request(
142
+ config["url"],
143
+ data=json.dumps(payload).encode(),
144
+ headers={
145
+ "Content-Type": "application/json",
146
+ "Authorization": f"Bearer {OPENAI_API_KEY}"
147
+ },
148
+ method="POST"
149
+ )
150
+
151
+ with urlopen(req, timeout=30) as response:
152
+ result = json.loads(response.read().decode())
153
+ return result["data"][0]["embedding"]
154
+
155
+
156
+ def get_embedding_bedrock(text: str) -> List[float]:
157
+ """Generate embedding using Amazon Bedrock."""
158
+ try:
159
+ import boto3
160
+ except ImportError:
161
+ raise ImportError("boto3 required for Bedrock: pip install boto3")
162
+
163
+ config = EMBEDDING_CONFIGS["bedrock"]
164
+ session = boto3.Session(region_name=os.environ.get("AWS_REGION", "eu-west-1"))
165
+ bedrock = session.client("bedrock-runtime")
166
+
167
+ body = json.dumps({"inputText": text})
168
+ response = bedrock.invoke_model(
169
+ modelId=config["model"],
170
+ body=body,
171
+ contentType="application/json",
172
+ accept="application/json"
173
+ )
174
+
175
+ result = json.loads(response["body"].read())
176
+ return result["embedding"]
177
+
178
+
179
+ def get_embedding(text: str) -> List[float]:
180
+ """Generate embedding using configured provider."""
181
+ if EMBEDDING_PROVIDER == "ollama":
182
+ return get_embedding_ollama(text)
183
+ elif EMBEDDING_PROVIDER == "bedrock":
184
+ return get_embedding_bedrock(text)
185
+ else:
186
+ return get_embedding_openai(text)
187
+
188
+
189
+ def test_connectivity() -> bool:
190
+ """Test 1: Basic Qdrant connectivity."""
191
+ try:
192
+ result = qdrant_request("GET", "/collections")
193
+ return result.get("status") == "ok"
194
+ except Exception as e:
195
+ print(f" Error: {e}")
196
+ return False
197
+
198
+
199
+ def test_ollama_connectivity() -> bool:
200
+ """Test Ollama connectivity."""
201
+ try:
202
+ req = Request(f"{OLLAMA_URL}/api/tags", method="GET")
203
+ with urlopen(req, timeout=10) as response:
204
+ result = json.loads(response.read().decode())
205
+ return "models" in result
206
+ except Exception as e:
207
+ print(f" Error: {e}")
208
+ return False
209
+
210
+
211
+ def test_create_collection() -> bool:
212
+ """Test 2: Create test collection."""
213
+ try:
214
+ payload = {
215
+ "vectors": {
216
+ "size": VECTOR_DIM,
217
+ "distance": "Cosine"
218
+ }
219
+ }
220
+ result = qdrant_request("PUT", f"/collections/{TEST_COLLECTION}", payload)
221
+ return result.get("result") == True or "already exists" in str(result)
222
+ except HTTPError as e:
223
+ if e.code == 409: # Collection exists
224
+ return True
225
+ print(f" Error: {e}")
226
+ return False
227
+ except Exception as e:
228
+ print(f" Error: {e}")
229
+ return False
230
+
231
+
232
+ def test_collection_info() -> bool:
233
+ """Test 3: Get collection info."""
234
+ try:
235
+ result = qdrant_request("GET", f"/collections/{TEST_COLLECTION}")
236
+ info = result.get("result", {})
237
+ # Accept both green (optimized) and yellow (indexing) status
238
+ valid_status = info.get("status") in ["green", "yellow"]
239
+ has_points = info.get("points_count") is not None
240
+ return valid_status and has_points
241
+ except Exception as e:
242
+ print(f" Error: {e}")
243
+ return False
244
+
245
+
246
+ def test_upsert_with_mock_vector() -> bool:
247
+ """Test 4: Upsert a point with mock vector (no API key needed)."""
248
+ try:
249
+ # Create a mock vector
250
+ mock_vector = [0.1 * (i % 10) for i in range(VECTOR_DIM)]
251
+
252
+ point_id = str(uuid.uuid4())
253
+ payload = {
254
+ "points": [{
255
+ "id": point_id,
256
+ "vector": mock_vector,
257
+ "payload": {
258
+ "content": "This is a test memory for validation purposes",
259
+ "type": "test",
260
+ "project": "qdrant-memory-test",
261
+ "timestamp": datetime.now(timezone.utc).isoformat(),
262
+ "tags": ["test", "validation"]
263
+ }
264
+ }]
265
+ }
266
+
267
+ result = qdrant_request("PUT", f"/collections/{TEST_COLLECTION}/points?wait=true", payload)
268
+ return result.get("status") == "ok"
269
+ except Exception as e:
270
+ print(f" Error: {e}")
271
+ return False
272
+
273
+
274
+ def test_search_with_mock_vector() -> bool:
275
+ """Test 5: Search using mock vector."""
276
+ try:
277
+ mock_vector = [0.1 * (i % 10) for i in range(VECTOR_DIM)]
278
+
279
+ payload = {
280
+ "vector": mock_vector,
281
+ "limit": 5,
282
+ "with_payload": True
283
+ }
284
+
285
+ result = qdrant_request("POST", f"/collections/{TEST_COLLECTION}/points/search", payload)
286
+ results = result.get("result", [])
287
+ return len(results) > 0 and results[0].get("score", 0) > 0.9
288
+ except Exception as e:
289
+ print(f" Error: {e}")
290
+ return False
291
+
292
+
293
+ def test_filter_search() -> bool:
294
+ """Test 6: Search with payload filter."""
295
+ try:
296
+ mock_vector = [0.1 * (i % 10) for i in range(VECTOR_DIM)]
297
+
298
+ payload = {
299
+ "vector": mock_vector,
300
+ "limit": 5,
301
+ "with_payload": True,
302
+ "filter": {
303
+ "must": [
304
+ {"key": "type", "match": {"value": "test"}}
305
+ ]
306
+ }
307
+ }
308
+
309
+ result = qdrant_request("POST", f"/collections/{TEST_COLLECTION}/points/search", payload)
310
+ results = result.get("result", [])
311
+ return len(results) > 0
312
+ except Exception as e:
313
+ print(f" Error: {e}")
314
+ return False
315
+
316
+
317
+ def test_embedding_generation() -> bool:
318
+ """Test 7: Embedding generation (local or OpenAI)."""
319
+ try:
320
+ embedding = get_embedding("This is a test query for embedding generation")
321
+ return len(embedding) == VECTOR_DIM
322
+ except Exception as e:
323
+ print(f" Error: {e}")
324
+ return False
325
+
326
+
327
+ def test_store_with_real_embedding() -> bool:
328
+ """Test 8: Store memory with real embedding."""
329
+ try:
330
+ text = "We decided to use PostgreSQL for user data due to ACID compliance requirements"
331
+ embedding = get_embedding(text)
332
+
333
+ point_id = str(uuid.uuid4())
334
+ payload = {
335
+ "points": [{
336
+ "id": point_id,
337
+ "vector": embedding,
338
+ "payload": {
339
+ "content": text,
340
+ "type": "decision",
341
+ "project": "test-project",
342
+ "timestamp": datetime.now(timezone.utc).isoformat(),
343
+ "tags": ["database", "architecture", "test"]
344
+ }
345
+ }]
346
+ }
347
+
348
+ result = qdrant_request("PUT", f"/collections/{TEST_COLLECTION}/points?wait=true", payload)
349
+ return result.get("status") == "ok"
350
+ except Exception as e:
351
+ print(f" Error: {e}")
352
+ return False
353
+
354
+
355
+ def test_semantic_search() -> bool:
356
+ """Test 9: Semantic search (similar but not identical query)."""
357
+ try:
358
+ # Search with semantically similar query
359
+ query = "What database did we choose for storing user information?"
360
+ embedding = get_embedding(query)
361
+
362
+ payload = {
363
+ "vector": embedding,
364
+ "limit": 5,
365
+ "with_payload": True,
366
+ "score_threshold": 0.5 # Lower threshold for local models
367
+ }
368
+
369
+ result = qdrant_request("POST", f"/collections/{TEST_COLLECTION}/points/search", payload)
370
+ results = result.get("result", [])
371
+
372
+ # Check if we found the PostgreSQL decision
373
+ for r in results:
374
+ content = r.get("payload", {}).get("content", "")
375
+ if "PostgreSQL" in content or "database" in content.lower():
376
+ return True
377
+ return len(results) > 0 # At least found something
378
+ except Exception as e:
379
+ print(f" Error: {e}")
380
+ return False
381
+
382
+
383
+ def test_hybrid_search() -> bool:
384
+ """Test 10: Hybrid search (vector + filter)."""
385
+ try:
386
+ query = "database architecture"
387
+ embedding = get_embedding(query)
388
+
389
+ payload = {
390
+ "vector": embedding,
391
+ "limit": 5,
392
+ "with_payload": True,
393
+ "filter": {
394
+ "must": [
395
+ {"key": "type", "match": {"value": "decision"}}
396
+ ]
397
+ }
398
+ }
399
+
400
+ result = qdrant_request("POST", f"/collections/{TEST_COLLECTION}/points/search", payload)
401
+ results = result.get("result", [])
402
+
403
+ # Verify all results have type=decision
404
+ for r in results:
405
+ if r.get("payload", {}).get("type") != "decision":
406
+ return False
407
+ return len(results) > 0
408
+ except Exception as e:
409
+ print(f" Error: {e}")
410
+ return False
411
+
412
+
413
+ def test_cache_simulation() -> bool:
414
+ """Test 11: Cache simulation (store and retrieve similar query)."""
415
+ try:
416
+ # Store a "cached" response
417
+ original_query = "How do I reset my password in the admin panel?"
418
+ response_text = "Navigate to Settings > Security > Reset Password and follow the prompts."
419
+
420
+ embedding = get_embedding(original_query)
421
+
422
+ cache_payload = {
423
+ "points": [{
424
+ "id": str(uuid.uuid4()),
425
+ "vector": embedding,
426
+ "payload": {
427
+ "query": original_query,
428
+ "response": response_text,
429
+ "type": "cache",
430
+ "timestamp": datetime.now(timezone.utc).isoformat(),
431
+ "model": "test"
432
+ }
433
+ }]
434
+ }
435
+
436
+ qdrant_request("PUT", f"/collections/{TEST_COLLECTION}/points?wait=true", cache_payload)
437
+
438
+ # Now search with a similar (not identical) query
439
+ similar_query = "How can I change my password?"
440
+ similar_embedding = get_embedding(similar_query)
441
+
442
+ search_payload = {
443
+ "vector": similar_embedding,
444
+ "limit": 1,
445
+ "with_payload": True,
446
+ "score_threshold": 0.6, # Adjusted for local models
447
+ "filter": {
448
+ "must": [{"key": "type", "match": {"value": "cache"}}]
449
+ }
450
+ }
451
+
452
+ result = qdrant_request("POST", f"/collections/{TEST_COLLECTION}/points/search", search_payload)
453
+ results = result.get("result", [])
454
+
455
+ if results and results[0].get("score", 0) > 0.6:
456
+ cached_response = results[0].get("payload", {}).get("response")
457
+ return cached_response == response_text
458
+ return False
459
+ except Exception as e:
460
+ print(f" Error: {e}")
461
+ return False
462
+
463
+
464
+ def cleanup_test_collection() -> bool:
465
+ """Cleanup: Delete test collection."""
466
+ try:
467
+ result = qdrant_request("DELETE", f"/collections/{TEST_COLLECTION}")
468
+ return result.get("result") == True
469
+ except HTTPError as e:
470
+ if e.code == 404: # Already deleted
471
+ return True
472
+ return False
473
+ except Exception as e:
474
+ print(f" Error: {e}")
475
+ return False
476
+
477
+
478
+ def run_connectivity_tests() -> int:
479
+ """Run basic connectivity tests (no embeddings required)."""
480
+ print_header("๐Ÿ”Œ CONNECTIVITY TESTS (No Embeddings Required)")
481
+
482
+ tests = [
483
+ ("Qdrant Connection", test_connectivity),
484
+ ("Create Test Collection", test_create_collection),
485
+ ("Get Collection Info", test_collection_info),
486
+ ("Upsert with Mock Vector", test_upsert_with_mock_vector),
487
+ ("Search with Mock Vector", test_search_with_mock_vector),
488
+ ("Filter Search", test_filter_search),
489
+ ]
490
+
491
+ passed = 0
492
+ failed = 0
493
+
494
+ for name, test_func in tests:
495
+ try:
496
+ result = test_func()
497
+ print_test(name, result)
498
+ if result:
499
+ passed += 1
500
+ else:
501
+ failed += 1
502
+ except Exception as e:
503
+ print_test(name, False, str(e))
504
+ failed += 1
505
+
506
+ return 0 if failed == 0 else 1
507
+
508
+
509
+ def run_full_tests() -> int:
510
+ """Run full integration tests."""
511
+ global VECTOR_DIM
512
+
513
+ print_header("๐Ÿงช FULL INTEGRATION TESTS")
514
+
515
+ config = EMBEDDING_CONFIGS[EMBEDDING_PROVIDER]
516
+ VECTOR_DIM = config["dimensions"]
517
+
518
+ print(f" {Colors.CYAN}Embedding Provider: {EMBEDDING_PROVIDER.upper()}{Colors.RESET}")
519
+ print(f" {Colors.CYAN}Model: {config['model']}{Colors.RESET}")
520
+ print(f" {Colors.CYAN}Dimensions: {VECTOR_DIM}{Colors.RESET}\n")
521
+
522
+ # Check embedding provider is available
523
+ if EMBEDDING_PROVIDER == "ollama":
524
+ if not test_ollama_connectivity():
525
+ print(f"\n{Colors.RED}โŒ Ollama is not running!{Colors.RESET}")
526
+ print(f"\n{Colors.YELLOW}To start Ollama:{Colors.RESET}")
527
+ print(f" 1. Start server: ollama serve")
528
+ print(f" 2. Pull model: ollama pull nomic-embed-text")
529
+ print(f"\nAlternatively, use OpenAI:")
530
+ print(f" python test_skill.py --mode full --embeddings openai\n")
531
+ return 1
532
+ print_test("Ollama Connection", True)
533
+ elif EMBEDDING_PROVIDER == "openai":
534
+ if not OPENAI_API_KEY:
535
+ print(f"\n{Colors.RED}โŒ OPENAI_API_KEY not set!{Colors.RESET}")
536
+ print(f"\n{Colors.YELLOW}To use OpenAI, set your API key:{Colors.RESET}")
537
+ print(f" export OPENAI_API_KEY='your-key-here'")
538
+ print(f"\nAlternatively, use Ollama (local, free):")
539
+ print(f" python test_skill.py --mode full --embeddings ollama\n")
540
+ return 1
541
+
542
+ # Run connectivity tests first (with correct vector dimensions)
543
+ conn_result = run_connectivity_tests()
544
+ if conn_result != 0:
545
+ print(f"\n{Colors.RED}Connectivity tests failed. Skipping integration tests.{Colors.RESET}")
546
+ return 1
547
+
548
+ print_header("๐Ÿค– EMBEDDING & SEMANTIC TESTS")
549
+
550
+ tests = [
551
+ (f"Embedding Generation ({EMBEDDING_PROVIDER})", test_embedding_generation),
552
+ ("Store with Real Embedding", test_store_with_real_embedding),
553
+ ("Semantic Search (Similar Query)", test_semantic_search),
554
+ ("Hybrid Search (Vector + Filter)", test_hybrid_search),
555
+ ("Cache Simulation (Store & Retrieve)", test_cache_simulation),
556
+ ]
557
+
558
+ passed = 0
559
+ failed = 0
560
+
561
+ for name, test_func in tests:
562
+ try:
563
+ result = test_func()
564
+ print_test(name, result)
565
+ if result:
566
+ passed += 1
567
+ else:
568
+ failed += 1
569
+ except Exception as e:
570
+ print_test(name, False, str(e))
571
+ failed += 1
572
+
573
+ return 0 if failed == 0 else 1
574
+
575
+
576
+ def main():
577
+ global EMBEDDING_PROVIDER, VECTOR_DIM
578
+
579
+ parser = argparse.ArgumentParser(description="Test the qdrant-memory skill")
580
+ parser.add_argument(
581
+ "--mode",
582
+ choices=["connectivity", "full"],
583
+ default="full",
584
+ help="Test mode: connectivity (no embeddings) or full (with embeddings)"
585
+ )
586
+ parser.add_argument(
587
+ "--embeddings",
588
+ choices=["ollama", "openai", "bedrock"],
589
+ default="ollama",
590
+ help="Embedding provider: ollama (local, free), bedrock (AWS), or openai (cloud)"
591
+ )
592
+ parser.add_argument(
593
+ "--cleanup",
594
+ action="store_true",
595
+ help="Delete test collection after tests"
596
+ )
597
+ parser.add_argument(
598
+ "--cleanup-only",
599
+ action="store_true",
600
+ help="Only cleanup (delete test collection)"
601
+ )
602
+
603
+ args = parser.parse_args()
604
+
605
+ EMBEDDING_PROVIDER = args.embeddings
606
+ VECTOR_DIM = EMBEDDING_CONFIGS[EMBEDDING_PROVIDER]["dimensions"]
607
+
608
+ print(f"\n{Colors.BOLD}๐Ÿง  Qdrant Memory Skill Test Suite{Colors.RESET}")
609
+ print(f" Qdrant URL: {QDRANT_URL}")
610
+ print(f" Test Collection: {TEST_COLLECTION}")
611
+ print(f" Embedding Provider: {EMBEDDING_PROVIDER.upper()}")
612
+
613
+ if args.cleanup_only:
614
+ print_header("๐Ÿงน CLEANUP")
615
+ result = cleanup_test_collection()
616
+ print_test("Delete Test Collection", result)
617
+ sys.exit(0 if result else 1)
618
+
619
+ try:
620
+ # Check Qdrant is reachable
621
+ try:
622
+ qdrant_request("GET", "/collections")
623
+ except URLError as e:
624
+ print(f"\n{Colors.RED}โŒ Cannot connect to Qdrant at {QDRANT_URL}{Colors.RESET}")
625
+ print(f" Error: {e}")
626
+ print(f"\n{Colors.YELLOW}Make sure Qdrant is running:{Colors.RESET}")
627
+ print(f" docker run -p 6333:6333 qdrant/qdrant")
628
+ sys.exit(2)
629
+
630
+ if args.mode == "connectivity":
631
+ result = run_connectivity_tests()
632
+ else:
633
+ result = run_full_tests()
634
+
635
+ if args.cleanup:
636
+ print_header("๐Ÿงน CLEANUP")
637
+ cleanup_result = cleanup_test_collection()
638
+ print_test("Delete Test Collection", cleanup_result)
639
+
640
+ # Final summary
641
+ print_header("๐Ÿ“Š TEST SUMMARY")
642
+ if result == 0:
643
+ print(f" {Colors.GREEN}All tests passed! โœ“{Colors.RESET}")
644
+ else:
645
+ print(f" {Colors.RED}Some tests failed. See details above.{Colors.RESET}")
646
+
647
+ sys.exit(result)
648
+
649
+ except KeyboardInterrupt:
650
+ print(f"\n{Colors.YELLOW}Tests interrupted.{Colors.RESET}")
651
+ sys.exit(1)
652
+
653
+
654
+ if __name__ == "__main__":
655
+ main()