@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.
- package/CHANGELOG.md +59 -0
- package/README.md +147 -0
- package/bin/init.js +471 -0
- package/package.json +36 -0
- package/templates/.agent/agents/backend-specialist.md +263 -0
- package/templates/.agent/agents/code-archaeologist.md +106 -0
- package/templates/.agent/agents/database-architect.md +226 -0
- package/templates/.agent/agents/debugger.md +225 -0
- package/templates/.agent/agents/devops-engineer.md +242 -0
- package/templates/.agent/agents/documentation-writer.md +104 -0
- package/templates/.agent/agents/explorer-agent.md +73 -0
- package/templates/.agent/agents/frontend-specialist.md +556 -0
- package/templates/.agent/agents/game-developer.md +162 -0
- package/templates/.agent/agents/mobile-developer.md +377 -0
- package/templates/.agent/agents/orchestrator.md +416 -0
- package/templates/.agent/agents/penetration-tester.md +188 -0
- package/templates/.agent/agents/performance-optimizer.md +187 -0
- package/templates/.agent/agents/product-manager.md +112 -0
- package/templates/.agent/agents/project-planner.md +403 -0
- package/templates/.agent/agents/qa-automation-engineer.md +109 -0
- package/templates/.agent/agents/security-auditor.md +170 -0
- package/templates/.agent/agents/seo-specialist.md +111 -0
- package/templates/.agent/agents/test-engineer.md +158 -0
- package/templates/.agent/rules/GEMINI.md +253 -0
- package/templates/.agent/workflows/brainstorm.md +113 -0
- package/templates/.agent/workflows/create.md +59 -0
- package/templates/.agent/workflows/debug.md +103 -0
- package/templates/.agent/workflows/deploy.md +176 -0
- package/templates/.agent/workflows/enhance.md +63 -0
- package/templates/.agent/workflows/orchestrate.md +237 -0
- package/templates/.agent/workflows/plan.md +89 -0
- package/templates/.agent/workflows/preview.md +81 -0
- package/templates/.agent/workflows/status.md +86 -0
- package/templates/.agent/workflows/test.md +144 -0
- package/templates/.agent/workflows/ui-ux-pro-max.md +296 -0
- package/templates/base/.env.example +54 -0
- package/templates/base/AGENTS.md +463 -0
- package/templates/base/requirements.txt +6 -0
- package/templates/base/skill-creator/LICENSE.txt +202 -0
- package/templates/base/skill-creator/SKILL_skillcreator.md +389 -0
- package/templates/base/skill-creator/references/output-patterns.md +82 -0
- package/templates/base/skill-creator/references/workflows.md +28 -0
- package/templates/base/skill-creator/scripts/init_skill.py +304 -0
- package/templates/base/skill-creator/scripts/package_skill.py +110 -0
- package/templates/base/skill-creator/scripts/quick_validate.py +95 -0
- package/templates/base/skill-creator/scripts/update_catalog.py +371 -0
- package/templates/skills/core/README.md +21 -0
- package/templates/skills/core/documentation/SKILL.md +351 -0
- package/templates/skills/core/documentation/references/best_practices.md +201 -0
- package/templates/skills/core/documentation/scripts/analyze_code.py +307 -0
- package/templates/skills/core/documentation/scripts/detect_changes.py +460 -0
- package/templates/skills/core/documentation/scripts/generate_changelog.py +312 -0
- package/templates/skills/core/documentation/scripts/sync_docs.py +272 -0
- package/templates/skills/core/documentation/scripts/update_skill_docs.py +366 -0
- package/templates/skills/core/pdf-reader/SKILL.md +104 -0
- package/templates/skills/core/pdf-reader/references/pdf_libraries.md +83 -0
- package/templates/skills/core/pdf-reader/scripts/extract_text.py +295 -0
- package/templates/skills/core/qdrant-memory/SKILL.md +435 -0
- package/templates/skills/core/qdrant-memory/references/advanced_patterns.md +375 -0
- package/templates/skills/core/qdrant-memory/references/collection_schemas.md +229 -0
- package/templates/skills/core/qdrant-memory/references/complete_guide.md +724 -0
- package/templates/skills/core/qdrant-memory/references/embedding_models.md +325 -0
- package/templates/skills/core/qdrant-memory/scripts/benchmark_token_savings.py +640 -0
- package/templates/skills/core/qdrant-memory/scripts/embedding_utils.py +323 -0
- package/templates/skills/core/qdrant-memory/scripts/hybrid_search.py +214 -0
- package/templates/skills/core/qdrant-memory/scripts/init_collection.py +193 -0
- package/templates/skills/core/qdrant-memory/scripts/memory_retrieval.py +345 -0
- package/templates/skills/core/qdrant-memory/scripts/semantic_cache.py +282 -0
- package/templates/skills/core/qdrant-memory/scripts/test_skill.py +655 -0
- package/templates/skills/core/webcrawler/SKILL.md +292 -0
- package/templates/skills/core/webcrawler/references/advanced_crawling.md +181 -0
- package/templates/skills/core/webcrawler/scripts/crawl_docs.py +532 -0
- package/templates/skills/core/webcrawler/scripts/extract_page.py +189 -0
- package/templates/skills/core/webcrawler/scripts/filter_docs.py +200 -0
- package/templates/skills/knowledge/api-patterns/SKILL.md +81 -0
- package/templates/skills/knowledge/api-patterns/api-style.md +42 -0
- package/templates/skills/knowledge/api-patterns/auth.md +24 -0
- package/templates/skills/knowledge/api-patterns/documentation.md +26 -0
- package/templates/skills/knowledge/api-patterns/graphql.md +41 -0
- package/templates/skills/knowledge/api-patterns/rate-limiting.md +31 -0
- package/templates/skills/knowledge/api-patterns/response.md +37 -0
- package/templates/skills/knowledge/api-patterns/rest.md +40 -0
- package/templates/skills/knowledge/api-patterns/scripts/api_validator.py +211 -0
- package/templates/skills/knowledge/api-patterns/security-testing.md +122 -0
- package/templates/skills/knowledge/api-patterns/trpc.md +41 -0
- package/templates/skills/knowledge/api-patterns/versioning.md +22 -0
- package/templates/skills/knowledge/app-builder/SKILL.md +75 -0
- package/templates/skills/knowledge/app-builder/agent-coordination.md +71 -0
- package/templates/skills/knowledge/app-builder/feature-building.md +53 -0
- package/templates/skills/knowledge/app-builder/project-detection.md +34 -0
- package/templates/skills/knowledge/app-builder/scaffolding.md +118 -0
- package/templates/skills/knowledge/app-builder/tech-stack.md +40 -0
- package/templates/skills/knowledge/app-builder/templates/SKILL.md +39 -0
- package/templates/skills/knowledge/app-builder/templates/astro-static/TEMPLATE.md +76 -0
- package/templates/skills/knowledge/app-builder/templates/chrome-extension/TEMPLATE.md +92 -0
- package/templates/skills/knowledge/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
- package/templates/skills/knowledge/app-builder/templates/electron-desktop/TEMPLATE.md +88 -0
- package/templates/skills/knowledge/app-builder/templates/express-api/TEMPLATE.md +83 -0
- package/templates/skills/knowledge/app-builder/templates/flutter-app/TEMPLATE.md +90 -0
- package/templates/skills/knowledge/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -0
- package/templates/skills/knowledge/app-builder/templates/nextjs-fullstack/TEMPLATE.md +82 -0
- package/templates/skills/knowledge/app-builder/templates/nextjs-saas/TEMPLATE.md +100 -0
- package/templates/skills/knowledge/app-builder/templates/nextjs-static/TEMPLATE.md +106 -0
- package/templates/skills/knowledge/app-builder/templates/nuxt-app/TEMPLATE.md +101 -0
- package/templates/skills/knowledge/app-builder/templates/python-fastapi/TEMPLATE.md +83 -0
- package/templates/skills/knowledge/app-builder/templates/react-native-app/TEMPLATE.md +93 -0
- package/templates/skills/knowledge/architecture/SKILL.md +55 -0
- package/templates/skills/knowledge/architecture/context-discovery.md +43 -0
- package/templates/skills/knowledge/architecture/examples.md +94 -0
- package/templates/skills/knowledge/architecture/pattern-selection.md +68 -0
- package/templates/skills/knowledge/architecture/patterns-reference.md +50 -0
- package/templates/skills/knowledge/architecture/trade-off-analysis.md +77 -0
- package/templates/skills/knowledge/bash-linux/SKILL.md +199 -0
- package/templates/skills/knowledge/behavioral-modes/SKILL.md +242 -0
- package/templates/skills/knowledge/brainstorming/SKILL.md +163 -0
- package/templates/skills/knowledge/brainstorming/dynamic-questioning.md +350 -0
- package/templates/skills/knowledge/clean-code/SKILL.md +201 -0
- package/templates/skills/knowledge/code-review-checklist/SKILL.md +109 -0
- package/templates/skills/knowledge/database-design/SKILL.md +52 -0
- package/templates/skills/knowledge/database-design/database-selection.md +43 -0
- package/templates/skills/knowledge/database-design/indexing.md +39 -0
- package/templates/skills/knowledge/database-design/migrations.md +48 -0
- package/templates/skills/knowledge/database-design/optimization.md +36 -0
- package/templates/skills/knowledge/database-design/orm-selection.md +30 -0
- package/templates/skills/knowledge/database-design/schema-design.md +56 -0
- package/templates/skills/knowledge/database-design/scripts/schema_validator.py +172 -0
- package/templates/skills/knowledge/deployment-procedures/SKILL.md +241 -0
- package/templates/skills/knowledge/doc.md +177 -0
- package/templates/skills/knowledge/documentation-templates/SKILL.md +194 -0
- package/templates/skills/knowledge/frontend-design/SKILL.md +396 -0
- package/templates/skills/knowledge/frontend-design/animation-guide.md +331 -0
- package/templates/skills/knowledge/frontend-design/color-system.md +311 -0
- package/templates/skills/knowledge/frontend-design/decision-trees.md +418 -0
- package/templates/skills/knowledge/frontend-design/motion-graphics.md +306 -0
- package/templates/skills/knowledge/frontend-design/scripts/accessibility_checker.py +183 -0
- package/templates/skills/knowledge/frontend-design/scripts/ux_audit.py +722 -0
- package/templates/skills/knowledge/frontend-design/typography-system.md +345 -0
- package/templates/skills/knowledge/frontend-design/ux-psychology.md +541 -0
- package/templates/skills/knowledge/frontend-design/visual-effects.md +383 -0
- package/templates/skills/knowledge/game-development/2d-games/SKILL.md +119 -0
- package/templates/skills/knowledge/game-development/3d-games/SKILL.md +135 -0
- package/templates/skills/knowledge/game-development/SKILL.md +167 -0
- package/templates/skills/knowledge/game-development/game-art/SKILL.md +185 -0
- package/templates/skills/knowledge/game-development/game-audio/SKILL.md +190 -0
- package/templates/skills/knowledge/game-development/game-design/SKILL.md +129 -0
- package/templates/skills/knowledge/game-development/mobile-games/SKILL.md +108 -0
- package/templates/skills/knowledge/game-development/multiplayer/SKILL.md +132 -0
- package/templates/skills/knowledge/game-development/pc-games/SKILL.md +144 -0
- package/templates/skills/knowledge/game-development/vr-ar/SKILL.md +123 -0
- package/templates/skills/knowledge/game-development/web-games/SKILL.md +150 -0
- package/templates/skills/knowledge/geo-fundamentals/SKILL.md +156 -0
- package/templates/skills/knowledge/geo-fundamentals/scripts/geo_checker.py +289 -0
- package/templates/skills/knowledge/i18n-localization/SKILL.md +154 -0
- package/templates/skills/knowledge/i18n-localization/scripts/i18n_checker.py +241 -0
- package/templates/skills/knowledge/intelligent-routing/SKILL.md +334 -0
- package/templates/skills/knowledge/lint-and-validate/SKILL.md +45 -0
- package/templates/skills/knowledge/lint-and-validate/scripts/lint_runner.py +172 -0
- package/templates/skills/knowledge/lint-and-validate/scripts/type_coverage.py +173 -0
- package/templates/skills/knowledge/mcp-builder/SKILL.md +176 -0
- package/templates/skills/knowledge/mobile-design/SKILL.md +394 -0
- package/templates/skills/knowledge/mobile-design/decision-trees.md +516 -0
- package/templates/skills/knowledge/mobile-design/mobile-backend.md +491 -0
- package/templates/skills/knowledge/mobile-design/mobile-color-system.md +420 -0
- package/templates/skills/knowledge/mobile-design/mobile-debugging.md +122 -0
- package/templates/skills/knowledge/mobile-design/mobile-design-thinking.md +357 -0
- package/templates/skills/knowledge/mobile-design/mobile-navigation.md +458 -0
- package/templates/skills/knowledge/mobile-design/mobile-performance.md +767 -0
- package/templates/skills/knowledge/mobile-design/mobile-testing.md +356 -0
- package/templates/skills/knowledge/mobile-design/mobile-typography.md +433 -0
- package/templates/skills/knowledge/mobile-design/platform-android.md +666 -0
- package/templates/skills/knowledge/mobile-design/platform-ios.md +561 -0
- package/templates/skills/knowledge/mobile-design/scripts/mobile_audit.py +670 -0
- package/templates/skills/knowledge/mobile-design/touch-psychology.md +537 -0
- package/templates/skills/knowledge/nextjs-best-practices/SKILL.md +203 -0
- package/templates/skills/knowledge/nodejs-best-practices/SKILL.md +333 -0
- package/templates/skills/knowledge/parallel-agents/SKILL.md +175 -0
- package/templates/skills/knowledge/performance-profiling/SKILL.md +143 -0
- package/templates/skills/knowledge/performance-profiling/scripts/lighthouse_audit.py +76 -0
- package/templates/skills/knowledge/plan-writing/SKILL.md +152 -0
- package/templates/skills/knowledge/powershell-windows/SKILL.md +167 -0
- package/templates/skills/knowledge/python-patterns/SKILL.md +441 -0
- package/templates/skills/knowledge/react-patterns/SKILL.md +198 -0
- package/templates/skills/knowledge/red-team-tactics/SKILL.md +199 -0
- package/templates/skills/knowledge/seo-fundamentals/SKILL.md +129 -0
- package/templates/skills/knowledge/seo-fundamentals/scripts/seo_checker.py +219 -0
- package/templates/skills/knowledge/server-management/SKILL.md +161 -0
- package/templates/skills/knowledge/systematic-debugging/SKILL.md +109 -0
- package/templates/skills/knowledge/tailwind-patterns/SKILL.md +269 -0
- package/templates/skills/knowledge/tdd-workflow/SKILL.md +149 -0
- package/templates/skills/knowledge/testing-patterns/SKILL.md +178 -0
- package/templates/skills/knowledge/testing-patterns/scripts/test_runner.py +219 -0
- package/templates/skills/knowledge/vulnerability-scanner/SKILL.md +276 -0
- package/templates/skills/knowledge/vulnerability-scanner/checklists.md +121 -0
- package/templates/skills/knowledge/vulnerability-scanner/scripts/security_scan.py +458 -0
- package/templates/skills/knowledge/webapp-testing/SKILL.md +187 -0
- 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()
|