@techwavedev/agi-agent-kit 1.1.7 → 1.2.1

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.

Potentially problematic release.


This version of @techwavedev/agi-agent-kit might be problematic. Click here for more details.

Files changed (111) hide show
  1. package/CHANGELOG.md +82 -1
  2. package/README.md +190 -12
  3. package/bin/init.js +30 -2
  4. package/package.json +6 -3
  5. package/templates/base/AGENTS.md +54 -23
  6. package/templates/base/README.md +325 -0
  7. package/templates/base/directives/memory_integration.md +95 -0
  8. package/templates/base/execution/memory_manager.py +309 -0
  9. package/templates/base/execution/session_boot.py +218 -0
  10. package/templates/base/execution/session_init.py +320 -0
  11. package/templates/base/skill-creator/SKILL_skillcreator.md +23 -36
  12. package/templates/base/skill-creator/scripts/init_skill.py +18 -135
  13. package/templates/skills/ec/README.md +31 -0
  14. package/templates/skills/ec/aws/SKILL.md +1020 -0
  15. package/templates/skills/ec/aws/defaults.yaml +13 -0
  16. package/templates/skills/ec/aws/references/common_patterns.md +80 -0
  17. package/templates/skills/ec/aws/references/mcp_servers.md +98 -0
  18. package/templates/skills/ec/aws-terraform/SKILL.md +349 -0
  19. package/templates/skills/ec/aws-terraform/references/best_practices.md +394 -0
  20. package/templates/skills/ec/aws-terraform/references/checkov_reference.md +337 -0
  21. package/templates/skills/ec/aws-terraform/scripts/configure_mcp.py +150 -0
  22. package/templates/skills/ec/confluent-kafka/SKILL.md +655 -0
  23. package/templates/skills/ec/confluent-kafka/references/ansible_playbooks.md +792 -0
  24. package/templates/skills/ec/confluent-kafka/references/ec_deployment.md +579 -0
  25. package/templates/skills/ec/confluent-kafka/references/kraft_migration.md +490 -0
  26. package/templates/skills/ec/confluent-kafka/references/troubleshooting.md +778 -0
  27. package/templates/skills/ec/confluent-kafka/references/upgrade_7x_to_8x.md +488 -0
  28. package/templates/skills/ec/confluent-kafka/scripts/kafka_health_check.py +435 -0
  29. package/templates/skills/ec/confluent-kafka/scripts/upgrade_preflight.py +568 -0
  30. package/templates/skills/ec/confluent-kafka/scripts/validate_config.py +455 -0
  31. package/templates/skills/ec/consul/SKILL.md +427 -0
  32. package/templates/skills/ec/consul/references/acl_setup.md +168 -0
  33. package/templates/skills/ec/consul/references/ha_config.md +196 -0
  34. package/templates/skills/ec/consul/references/troubleshooting.md +267 -0
  35. package/templates/skills/ec/consul/references/upgrades.md +213 -0
  36. package/templates/skills/ec/consul/scripts/consul_health_report.py +530 -0
  37. package/templates/skills/ec/consul/scripts/consul_status.py +264 -0
  38. package/templates/skills/ec/consul/scripts/generate_values.py +170 -0
  39. package/templates/skills/ec/documentation/SKILL.md +351 -0
  40. package/templates/skills/ec/documentation/references/best_practices.md +201 -0
  41. package/templates/skills/ec/documentation/scripts/analyze_code.py +307 -0
  42. package/templates/skills/ec/documentation/scripts/detect_changes.py +460 -0
  43. package/templates/skills/ec/documentation/scripts/generate_changelog.py +312 -0
  44. package/templates/skills/ec/documentation/scripts/sync_docs.py +272 -0
  45. package/templates/skills/ec/documentation/scripts/update_skill_docs.py +366 -0
  46. package/templates/skills/ec/gitlab/SKILL.md +529 -0
  47. package/templates/skills/ec/gitlab/references/agent_installation.md +416 -0
  48. package/templates/skills/ec/gitlab/references/api_reference.md +508 -0
  49. package/templates/skills/ec/gitlab/references/gitops_flux.md +465 -0
  50. package/templates/skills/ec/gitlab/references/troubleshooting.md +518 -0
  51. package/templates/skills/ec/gitlab/scripts/generate_agent_values.py +329 -0
  52. package/templates/skills/ec/gitlab/scripts/gitlab_agent_status.py +414 -0
  53. package/templates/skills/ec/jira/SKILL.md +484 -0
  54. package/templates/skills/ec/jira/references/jql_reference.md +148 -0
  55. package/templates/skills/ec/jira/scripts/add_comment.py +91 -0
  56. package/templates/skills/ec/jira/scripts/bulk_log_work.py +124 -0
  57. package/templates/skills/ec/jira/scripts/create_ticket.py +162 -0
  58. package/templates/skills/ec/jira/scripts/get_ticket.py +191 -0
  59. package/templates/skills/ec/jira/scripts/jira_client.py +383 -0
  60. package/templates/skills/ec/jira/scripts/log_work.py +154 -0
  61. package/templates/skills/ec/jira/scripts/search_tickets.py +104 -0
  62. package/templates/skills/ec/jira/scripts/update_comment.py +67 -0
  63. package/templates/skills/ec/jira/scripts/update_ticket.py +161 -0
  64. package/templates/skills/ec/karpenter/SKILL.md +301 -0
  65. package/templates/skills/ec/karpenter/references/ec2nodeclasses.md +421 -0
  66. package/templates/skills/ec/karpenter/references/migration.md +396 -0
  67. package/templates/skills/ec/karpenter/references/nodepools.md +400 -0
  68. package/templates/skills/ec/karpenter/references/troubleshooting.md +359 -0
  69. package/templates/skills/ec/karpenter/scripts/generate_ec2nodeclass.py +187 -0
  70. package/templates/skills/ec/karpenter/scripts/generate_nodepool.py +245 -0
  71. package/templates/skills/ec/karpenter/scripts/karpenter_status.py +359 -0
  72. package/templates/skills/ec/opensearch/SKILL.md +720 -0
  73. package/templates/skills/ec/opensearch/references/ml_neural_search.md +576 -0
  74. package/templates/skills/ec/opensearch/references/operator.md +532 -0
  75. package/templates/skills/ec/opensearch/references/query_dsl.md +532 -0
  76. package/templates/skills/ec/opensearch/scripts/configure_mcp.py +148 -0
  77. package/templates/skills/ec/victoriametrics/SKILL.md +598 -0
  78. package/templates/skills/ec/victoriametrics/references/kubernetes.md +531 -0
  79. package/templates/skills/ec/victoriametrics/references/prometheus_migration.md +333 -0
  80. package/templates/skills/ec/victoriametrics/references/troubleshooting.md +442 -0
  81. package/templates/skills/knowledge/SKILLS_CATALOG.md +274 -4
  82. package/templates/skills/knowledge/intelligent-routing/SKILL.md +237 -164
  83. package/templates/skills/knowledge/parallel-agents/SKILL.md +345 -73
  84. package/templates/skills/knowledge/plugin-discovery/SKILL.md +582 -0
  85. package/templates/skills/knowledge/plugin-discovery/scripts/platform_setup.py +1083 -0
  86. package/templates/skills/knowledge/design-md/README.md +0 -34
  87. package/templates/skills/knowledge/design-md/SKILL.md +0 -193
  88. package/templates/skills/knowledge/design-md/examples/DESIGN.md +0 -154
  89. package/templates/skills/knowledge/notebooklm-mcp/SKILL.md +0 -71
  90. package/templates/skills/knowledge/notebooklm-mcp/assets/example_asset.txt +0 -24
  91. package/templates/skills/knowledge/notebooklm-mcp/references/api_reference.md +0 -34
  92. package/templates/skills/knowledge/notebooklm-mcp/scripts/example.py +0 -19
  93. package/templates/skills/knowledge/react-components/README.md +0 -36
  94. package/templates/skills/knowledge/react-components/SKILL.md +0 -53
  95. package/templates/skills/knowledge/react-components/examples/gold-standard-card.tsx +0 -80
  96. package/templates/skills/knowledge/react-components/package-lock.json +0 -231
  97. package/templates/skills/knowledge/react-components/package.json +0 -16
  98. package/templates/skills/knowledge/react-components/resources/architecture-checklist.md +0 -15
  99. package/templates/skills/knowledge/react-components/resources/component-template.tsx +0 -37
  100. package/templates/skills/knowledge/react-components/resources/stitch-api-reference.md +0 -14
  101. package/templates/skills/knowledge/react-components/resources/style-guide.json +0 -27
  102. package/templates/skills/knowledge/react-components/scripts/fetch-stitch.sh +0 -30
  103. package/templates/skills/knowledge/react-components/scripts/validate.js +0 -68
  104. package/templates/skills/knowledge/self-update/SKILL.md +0 -60
  105. package/templates/skills/knowledge/self-update/scripts/update_kit.py +0 -103
  106. package/templates/skills/knowledge/stitch-loop/README.md +0 -54
  107. package/templates/skills/knowledge/stitch-loop/SKILL.md +0 -235
  108. package/templates/skills/knowledge/stitch-loop/examples/SITE.md +0 -73
  109. package/templates/skills/knowledge/stitch-loop/examples/next-prompt.md +0 -25
  110. package/templates/skills/knowledge/stitch-loop/resources/baton-schema.md +0 -61
  111. package/templates/skills/knowledge/stitch-loop/resources/site-template.md +0 -104
@@ -0,0 +1,309 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Script: memory_manager.py
4
+ Purpose: Unified memory management wrapper for all qdrant-memory operations.
5
+ Provides a single entry point for agents across any AI environment.
6
+
7
+ Usage:
8
+ # Auto-decide: check cache first, then retrieve context
9
+ python3 execution/memory_manager.py auto --query "How to set up auth middleware?"
10
+
11
+ # Explicit store (decision, code, error, technical, conversation)
12
+ python3 execution/memory_manager.py store --content "Chose PostgreSQL for relational model" --type decision --project myapp
13
+
14
+ # Retrieve context only
15
+ python3 execution/memory_manager.py retrieve --query "database architecture" --top-k 5
16
+
17
+ # Cache a response
18
+ python3 execution/memory_manager.py cache-store --query "How to X?" --response "Do Y..."
19
+
20
+ # Health check (Qdrant + Ollama)
21
+ python3 execution/memory_manager.py health
22
+
23
+ Environment Variables:
24
+ EMBEDDING_PROVIDER - "ollama" (default), "openai", or "bedrock"
25
+ OLLAMA_URL - Ollama server URL (default: http://localhost:11434)
26
+ QDRANT_URL - Qdrant server URL (default: http://localhost:6333)
27
+ MEMORY_COLLECTION - Memory collection name (default: agent_memory)
28
+ CACHE_COLLECTION - Cache collection name (default: semantic_cache)
29
+
30
+ Exit Codes:
31
+ 0 - Success
32
+ 1 - No results / cache miss
33
+ 2 - Connection error (Qdrant or embedding service down)
34
+ 3 - Operation error
35
+ """
36
+
37
+ import argparse
38
+ import json
39
+ import os
40
+ import sys
41
+ from urllib.request import Request, urlopen
42
+ from urllib.error import URLError
43
+
44
+ # Resolve path to qdrant-memory scripts
45
+ SKILL_SCRIPTS_DIR = os.path.join(
46
+ os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
47
+ "skills",
48
+ "qdrant-memory",
49
+ "scripts",
50
+ )
51
+ sys.path.insert(0, SKILL_SCRIPTS_DIR)
52
+
53
+ from embedding_utils import check_embedding_service, get_embedding_dimension
54
+ from semantic_cache import check_cache, store_response, clear_cache
55
+ from memory_retrieval import retrieve_context, store_memory, list_memories, build_filter
56
+
57
+ # Configuration
58
+ QDRANT_URL = os.environ.get("QDRANT_URL", "http://localhost:6333")
59
+
60
+
61
+ def health_check() -> dict:
62
+ """Check Qdrant connectivity and embedding service status."""
63
+ result = {"qdrant": "unknown", "embeddings": "unknown", "collections": []}
64
+
65
+ # Check Qdrant
66
+ try:
67
+ req = Request(f"{QDRANT_URL}/collections", method="GET")
68
+ with urlopen(req, timeout=10) as response:
69
+ data = json.loads(response.read().decode())
70
+ collections = [
71
+ c["name"] for c in data.get("result", {}).get("collections", [])
72
+ ]
73
+ result["qdrant"] = "ok"
74
+ result["collections"] = collections
75
+ except Exception as e:
76
+ result["qdrant"] = f"error: {e}"
77
+
78
+ # Check embedding service
79
+ embed_status = check_embedding_service()
80
+ result["embeddings"] = embed_status
81
+
82
+ # Check expected collections
83
+ expected = ["agent_memory", "semantic_cache"]
84
+ result["missing_collections"] = [
85
+ c for c in expected if c not in result.get("collections", [])
86
+ ]
87
+
88
+ # Overall status
89
+ result["ready"] = (
90
+ result["qdrant"] == "ok"
91
+ and embed_status.get("status") == "ok"
92
+ and len(result["missing_collections"]) == 0
93
+ )
94
+
95
+ return result
96
+
97
+
98
+ def auto_query(query: str, project: str = None, threshold: float = 0.92) -> dict:
99
+ """
100
+ Smart query: check cache first, then retrieve context.
101
+ This is the primary entry point for agents.
102
+
103
+ Flow:
104
+ 1. Check semantic cache (exact match saves 100% tokens)
105
+ 2. If miss, retrieve relevant memories (saves 80-95% tokens)
106
+ 3. Return combined result with token savings estimate
107
+ """
108
+ result = {
109
+ "source": "none",
110
+ "cache_hit": False,
111
+ "context_chunks": [],
112
+ "tokens_saved_estimate": 0,
113
+ }
114
+
115
+ # Step 1: Semantic cache check
116
+ try:
117
+ cached = check_cache(query, threshold)
118
+ if cached and cached.get("cache_hit"):
119
+ result["source"] = "cache"
120
+ result["cache_hit"] = True
121
+ result["cached_response"] = cached.get("response", "")
122
+ result["cache_score"] = cached.get("score", 0)
123
+ result["tokens_saved_estimate"] = cached.get("tokens_saved", 0)
124
+ return result
125
+ except Exception:
126
+ pass # Cache miss or error, continue to retrieval
127
+
128
+ # Step 2: Context retrieval
129
+ try:
130
+ filters = None
131
+ if project:
132
+ filters = {"must": [{"key": "project", "match": {"value": project}}]}
133
+
134
+ context = retrieve_context(query, filters=filters, top_k=5, score_threshold=0.7)
135
+ if context.get("total_chunks", 0) > 0:
136
+ result["source"] = "memory"
137
+ result["context_chunks"] = context.get("chunks", [])
138
+ result["total_chunks"] = context.get("total_chunks", 0)
139
+ result["tokens_saved_estimate"] = context.get("total_tokens_estimate", 0)
140
+ except Exception:
141
+ pass # No context available
142
+
143
+ return result
144
+
145
+
146
+ def main():
147
+ parser = argparse.ArgumentParser(
148
+ description="Unified memory manager for AI agents",
149
+ formatter_class=argparse.RawDescriptionHelpFormatter,
150
+ epilog="""
151
+ Examples:
152
+ # Smart auto-query (cache + context retrieval)
153
+ python3 execution/memory_manager.py auto --query "How to handle JWT refresh?"
154
+
155
+ # Store a key decision
156
+ python3 execution/memory_manager.py store --content "Chose Supabase for auth" --type decision
157
+
158
+ # Health check
159
+ python3 execution/memory_manager.py health
160
+ """,
161
+ )
162
+ subparsers = parser.add_subparsers(dest="command", required=True)
163
+
164
+ # Auto command (primary entry point)
165
+ auto_parser = subparsers.add_parser(
166
+ "auto", help="Smart query: cache check + context retrieval"
167
+ )
168
+ auto_parser.add_argument("--query", required=True, help="Natural language query")
169
+ auto_parser.add_argument("--project", help="Filter by project name")
170
+ auto_parser.add_argument(
171
+ "--threshold", type=float, default=0.92, help="Cache similarity threshold"
172
+ )
173
+
174
+ # Store command
175
+ store_parser = subparsers.add_parser(
176
+ "store", help="Store memory (decision, code, error, technical, conversation)"
177
+ )
178
+ store_parser.add_argument("--content", required=True, help="Memory content")
179
+ store_parser.add_argument(
180
+ "--type",
181
+ required=True,
182
+ choices=["decision", "code", "error", "conversation", "technical"],
183
+ help="Memory type",
184
+ )
185
+ store_parser.add_argument("--project", help="Project name")
186
+ store_parser.add_argument("--tags", nargs="+", help="Tags for the memory")
187
+
188
+ # Retrieve command
189
+ retrieve_parser = subparsers.add_parser(
190
+ "retrieve", help="Retrieve relevant context"
191
+ )
192
+ retrieve_parser.add_argument("--query", required=True, help="Search query")
193
+ retrieve_parser.add_argument("--type", help="Filter by memory type")
194
+ retrieve_parser.add_argument("--project", help="Filter by project")
195
+ retrieve_parser.add_argument(
196
+ "--top-k", type=int, default=5, help="Number of results"
197
+ )
198
+ retrieve_parser.add_argument(
199
+ "--threshold", type=float, default=0.7, help="Score threshold"
200
+ )
201
+
202
+ # Cache store command
203
+ cache_parser = subparsers.add_parser(
204
+ "cache-store", help="Store query-response in semantic cache"
205
+ )
206
+ cache_parser.add_argument("--query", required=True, help="Original query")
207
+ cache_parser.add_argument("--response", required=True, help="LLM response to cache")
208
+ cache_parser.add_argument("--model", default="agent", help="Model identifier")
209
+ cache_parser.add_argument("--project", help="Project name")
210
+
211
+ # List command
212
+ list_parser = subparsers.add_parser("list", help="List stored memories")
213
+ list_parser.add_argument("--type", help="Filter by memory type")
214
+ list_parser.add_argument("--project", help="Filter by project")
215
+ list_parser.add_argument("--limit", type=int, default=20, help="Max results")
216
+
217
+ # Health command
218
+ subparsers.add_parser("health", help="Check Qdrant + embedding service health")
219
+
220
+ # Cache clear command
221
+ clear_parser = subparsers.add_parser("cache-clear", help="Clear old cache entries")
222
+ clear_parser.add_argument(
223
+ "--older-than", type=int, default=7, help="Delete entries older than N days"
224
+ )
225
+
226
+ args = parser.parse_args()
227
+
228
+ try:
229
+ if args.command == "auto":
230
+ result = auto_query(args.query, args.project, args.threshold)
231
+ print(json.dumps(result, indent=2))
232
+ sys.exit(0 if result["source"] != "none" else 1)
233
+
234
+ elif args.command == "store":
235
+ metadata = {}
236
+ if args.project:
237
+ metadata["project"] = args.project
238
+ if args.tags:
239
+ metadata["tags"] = args.tags
240
+ result = store_memory(args.content, args.type, metadata)
241
+ print(json.dumps(result, indent=2))
242
+ sys.exit(0)
243
+
244
+ elif args.command == "retrieve":
245
+ filters = build_filter(
246
+ type_filter=getattr(args, "type", None), project=args.project
247
+ )
248
+ result = retrieve_context(
249
+ args.query,
250
+ filters={"must": filters["must"]} if filters else None,
251
+ top_k=args.top_k,
252
+ score_threshold=args.threshold,
253
+ )
254
+ print(json.dumps(result, indent=2))
255
+ sys.exit(0 if result.get("total_chunks", 0) > 0 else 1)
256
+
257
+ elif args.command == "cache-store":
258
+ metadata = {"model": args.model}
259
+ if args.project:
260
+ metadata["project"] = args.project
261
+ result = store_response(args.query, args.response, metadata)
262
+ print(json.dumps(result, indent=2))
263
+ sys.exit(0)
264
+
265
+ elif args.command == "list":
266
+ filters = build_filter(
267
+ type_filter=getattr(args, "type", None), project=args.project
268
+ )
269
+ result = list_memories(
270
+ filters={"must": filters["must"]} if filters else None, limit=args.limit
271
+ )
272
+ print(json.dumps(result, indent=2))
273
+ sys.exit(0)
274
+
275
+ elif args.command == "health":
276
+ result = health_check()
277
+ print(json.dumps(result, indent=2))
278
+ sys.exit(0 if result["ready"] else 2)
279
+
280
+ elif args.command == "cache-clear":
281
+ result = clear_cache(args.older_than)
282
+ print(json.dumps(result, indent=2))
283
+ sys.exit(0)
284
+
285
+ except URLError as e:
286
+ print(
287
+ json.dumps(
288
+ {
289
+ "status": "error",
290
+ "type": "connection_error",
291
+ "message": str(e),
292
+ "hint": "Is Qdrant running? Try: docker run -p 6333:6333 qdrant/qdrant",
293
+ }
294
+ ),
295
+ file=sys.stderr,
296
+ )
297
+ sys.exit(2)
298
+ except Exception as e:
299
+ print(
300
+ json.dumps(
301
+ {"status": "error", "type": type(e).__name__, "message": str(e)}
302
+ ),
303
+ file=sys.stderr,
304
+ )
305
+ sys.exit(3)
306
+
307
+
308
+ if __name__ == "__main__":
309
+ main()
@@ -0,0 +1,218 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Script: session_boot.py
4
+ Purpose: Single entry point for session initialization. Checks memory system,
5
+ initializes if needed, and returns a combined status report.
6
+
7
+ This is the FIRST script an agent should run at session start.
8
+ Combines: health check + session_init + platform detection.
9
+
10
+ Usage:
11
+ python3 execution/session_boot.py
12
+ python3 execution/session_boot.py --json
13
+ python3 execution/session_boot.py --auto-fix
14
+
15
+ Arguments:
16
+ --json Output JSON only (for programmatic use)
17
+ --auto-fix Automatically fix issues (pull model, create collections)
18
+
19
+ Exit Codes:
20
+ 0 - Memory system ready
21
+ 1 - Memory available but degraded (missing model, empty collections)
22
+ 2 - Memory unavailable (Qdrant or Ollama not running)
23
+ """
24
+
25
+ import argparse
26
+ import json
27
+ import os
28
+ import subprocess
29
+ import sys
30
+ from pathlib import Path
31
+ from urllib.request import Request, urlopen
32
+ from urllib.error import URLError, HTTPError
33
+
34
+ # Configuration
35
+ QDRANT_URL = os.environ.get("QDRANT_URL", "http://localhost:6333")
36
+ OLLAMA_URL = os.environ.get("OLLAMA_URL", "http://localhost:11434")
37
+ EMBEDDING_MODEL = "nomic-embed-text"
38
+ PROJECT_DIR = Path(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
39
+
40
+
41
+ def check_qdrant() -> dict:
42
+ """Check Qdrant connectivity and collection status."""
43
+ result = {"status": "not_running", "collections": {}, "url": QDRANT_URL}
44
+ try:
45
+ req = Request(f"{QDRANT_URL}/collections", method="GET")
46
+ with urlopen(req, timeout=5) as response:
47
+ data = json.loads(response.read().decode())
48
+ names = [c["name"] for c in data.get("result", {}).get("collections", [])]
49
+ result["status"] = "ok"
50
+
51
+ for col_name in ["agent_memory", "semantic_cache"]:
52
+ if col_name in names:
53
+ try:
54
+ col_req = Request(f"{QDRANT_URL}/collections/{col_name}", method="GET")
55
+ with urlopen(col_req, timeout=5) as col_resp:
56
+ col_data = json.loads(col_resp.read().decode())
57
+ points = col_data.get("result", {}).get("points_count", 0)
58
+ result["collections"][col_name] = {"exists": True, "points": points}
59
+ except Exception:
60
+ result["collections"][col_name] = {"exists": True, "points": -1}
61
+ else:
62
+ result["collections"][col_name] = {"exists": False, "points": 0}
63
+ except (URLError, HTTPError, Exception):
64
+ pass
65
+ return result
66
+
67
+
68
+ def check_ollama() -> dict:
69
+ """Check Ollama connectivity and embedding model."""
70
+ result = {"status": "not_running", "has_model": False, "url": OLLAMA_URL}
71
+ try:
72
+ req = Request(f"{OLLAMA_URL}/api/tags", method="GET")
73
+ with urlopen(req, timeout=5) as response:
74
+ data = json.loads(response.read().decode())
75
+ models = [m["name"] for m in data.get("models", [])]
76
+ result["status"] = "ok"
77
+ result["models"] = models
78
+ result["has_model"] = any(EMBEDDING_MODEL in m for m in models)
79
+ except (URLError, HTTPError, Exception):
80
+ pass
81
+ return result
82
+
83
+
84
+ def run_session_init() -> bool:
85
+ """Run session_init.py to create collections."""
86
+ init_script = PROJECT_DIR / "execution" / "session_init.py"
87
+ if not init_script.exists():
88
+ return False
89
+ try:
90
+ proc = subprocess.run(
91
+ ["python3", str(init_script)],
92
+ capture_output=True, text=True, timeout=30,
93
+ cwd=str(PROJECT_DIR),
94
+ )
95
+ return proc.returncode == 0
96
+ except Exception:
97
+ return False
98
+
99
+
100
+ def pull_model() -> bool:
101
+ """Pull the embedding model via Ollama."""
102
+ try:
103
+ proc = subprocess.run(
104
+ ["ollama", "pull", EMBEDDING_MODEL],
105
+ capture_output=True, text=True, timeout=120,
106
+ )
107
+ return proc.returncode == 0
108
+ except Exception:
109
+ return False
110
+
111
+
112
+ def main():
113
+ parser = argparse.ArgumentParser(
114
+ description="Session boot: check + initialize memory system"
115
+ )
116
+ parser.add_argument("--json", action="store_true", dest="json_output",
117
+ help="JSON output only")
118
+ parser.add_argument("--auto-fix", action="store_true",
119
+ help="Auto-fix issues (pull model, create collections)")
120
+ args = parser.parse_args()
121
+
122
+ report = {
123
+ "qdrant": {},
124
+ "ollama": {},
125
+ "memory_ready": False,
126
+ "actions_taken": [],
127
+ "issues": [],
128
+ }
129
+
130
+ # Step 1: Check Qdrant
131
+ qdrant = check_qdrant()
132
+ report["qdrant"] = qdrant
133
+
134
+ if qdrant["status"] != "ok":
135
+ report["issues"].append("Qdrant not running. Start with: docker run -d -p 6333:6333 -v qdrant_storage:/qdrant/storage qdrant/qdrant")
136
+
137
+ # Step 2: Check Ollama
138
+ ollama = check_ollama()
139
+ report["ollama"] = ollama
140
+
141
+ if ollama["status"] != "ok":
142
+ report["issues"].append("Ollama not running. Start with: ollama serve")
143
+ elif not ollama["has_model"]:
144
+ if args.auto_fix:
145
+ if not args.json_output:
146
+ print(f"⏳ Pulling {EMBEDDING_MODEL}...")
147
+ if pull_model():
148
+ report["actions_taken"].append(f"Pulled {EMBEDDING_MODEL}")
149
+ ollama["has_model"] = True
150
+ else:
151
+ report["issues"].append(f"Failed to pull {EMBEDDING_MODEL}")
152
+ else:
153
+ report["issues"].append(f"Embedding model missing. Run: ollama pull {EMBEDDING_MODEL}")
154
+
155
+ # Step 3: Initialize collections if needed
156
+ if qdrant["status"] == "ok" and ollama["status"] == "ok" and ollama["has_model"]:
157
+ agent_mem = qdrant["collections"].get("agent_memory", {})
158
+ sem_cache = qdrant["collections"].get("semantic_cache", {})
159
+
160
+ if not agent_mem.get("exists") or not sem_cache.get("exists"):
161
+ if args.auto_fix:
162
+ if not args.json_output:
163
+ print("⏳ Initializing collections...")
164
+ if run_session_init():
165
+ report["actions_taken"].append("Created collections via session_init.py")
166
+ # Re-check
167
+ qdrant = check_qdrant()
168
+ report["qdrant"] = qdrant
169
+ else:
170
+ report["issues"].append("Failed to initialize collections")
171
+ else:
172
+ report["issues"].append("Collections missing. Run: python3 execution/session_init.py")
173
+
174
+ # Final readiness
175
+ qdrant = report["qdrant"]
176
+ ollama = report["ollama"]
177
+ agent_mem = qdrant.get("collections", {}).get("agent_memory", {})
178
+ sem_cache = qdrant.get("collections", {}).get("semantic_cache", {})
179
+
180
+ report["memory_ready"] = (
181
+ qdrant.get("status") == "ok"
182
+ and ollama.get("status") == "ok"
183
+ and ollama.get("has_model", False)
184
+ and agent_mem.get("exists", False)
185
+ and sem_cache.get("exists", False)
186
+ )
187
+
188
+ # Summary
189
+ total_points = (
190
+ agent_mem.get("points", 0) + sem_cache.get("points", 0)
191
+ )
192
+ report["summary"] = {
193
+ "ready": report["memory_ready"],
194
+ "total_memories": agent_mem.get("points", 0),
195
+ "total_cached": sem_cache.get("points", 0),
196
+ }
197
+
198
+ if args.json_output:
199
+ print(json.dumps(report, indent=2))
200
+ else:
201
+ if report["memory_ready"]:
202
+ mem_pts = agent_mem.get("points", 0)
203
+ cache_pts = sem_cache.get("points", 0)
204
+ print(f"✅ Memory system ready — {mem_pts} memories, {cache_pts} cached responses")
205
+ else:
206
+ print("❌ Memory system not ready:")
207
+ for issue in report["issues"]:
208
+ print(f" • {issue}")
209
+
210
+ if report["actions_taken"]:
211
+ for action in report["actions_taken"]:
212
+ print(f" ✅ {action}")
213
+
214
+ sys.exit(0 if report["memory_ready"] else (1 if qdrant.get("status") == "ok" else 2))
215
+
216
+
217
+ if __name__ == "__main__":
218
+ main()