opencode-skills-collection 3.1.10 → 3.1.11

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 (66) hide show
  1. package/bundled-skills/.antigravity-install-manifest.json +8 -1
  2. package/bundled-skills/browser-testing-with-devtools/SKILL.md +334 -0
  3. package/bundled-skills/docs/integrations/jetski-cortex.md +3 -3
  4. package/bundled-skills/docs/integrations/jetski-gemini-loader/README.md +1 -1
  5. package/bundled-skills/docs/maintainers/repo-growth-seo.md +3 -3
  6. package/bundled-skills/docs/maintainers/skills-update-guide.md +1 -1
  7. package/bundled-skills/docs/sources/sources.md +4 -0
  8. package/bundled-skills/docs/users/bundles.md +1 -1
  9. package/bundled-skills/docs/users/claude-code-skills.md +1 -1
  10. package/bundled-skills/docs/users/gemini-cli-skills.md +1 -1
  11. package/bundled-skills/docs/users/getting-started.md +1 -1
  12. package/bundled-skills/docs/users/kiro-integration.md +1 -1
  13. package/bundled-skills/docs/users/usage.md +4 -4
  14. package/bundled-skills/docs/users/visual-guide.md +4 -4
  15. package/bundled-skills/drizzle-migration-conflict/SKILL.md +179 -0
  16. package/bundled-skills/drizzle-migration-conflict/references/ci-policy.md +87 -0
  17. package/bundled-skills/drizzle-migration-conflict/references/conflict-resolution.md +163 -0
  18. package/bundled-skills/drizzle-migration-conflict/references/report-template.md +69 -0
  19. package/bundled-skills/drizzle-migration-conflict/references/sources.md +51 -0
  20. package/bundled-skills/drizzle-migration-conflict/scripts/check_drizzle_migrations.py +721 -0
  21. package/bundled-skills/frontend-lighthouse/SKILL.md +348 -0
  22. package/bundled-skills/pre-release-review/SKILL.md +198 -0
  23. package/bundled-skills/pre-release-review/references/checklist.md +104 -0
  24. package/bundled-skills/pre-release-review/references/report-template.md +91 -0
  25. package/bundled-skills/re-create/SKILL.md +251 -0
  26. package/bundled-skills/weaviate/SKILL.md +132 -0
  27. package/bundled-skills/weaviate/references/ask.md +36 -0
  28. package/bundled-skills/weaviate/references/create_collection.md +152 -0
  29. package/bundled-skills/weaviate/references/environment_requirements.md +34 -0
  30. package/bundled-skills/weaviate/references/example_data.md +24 -0
  31. package/bundled-skills/weaviate/references/explore_collection.md +50 -0
  32. package/bundled-skills/weaviate/references/fetch_filter.md +88 -0
  33. package/bundled-skills/weaviate/references/get_collection.md +32 -0
  34. package/bundled-skills/weaviate/references/hybrid_search.md +47 -0
  35. package/bundled-skills/weaviate/references/import_data.md +160 -0
  36. package/bundled-skills/weaviate/references/keyword_search.md +38 -0
  37. package/bundled-skills/weaviate/references/list_collections.md +31 -0
  38. package/bundled-skills/weaviate/references/query_search.md +38 -0
  39. package/bundled-skills/weaviate/references/semantic_search.md +46 -0
  40. package/bundled-skills/weaviate/scripts/ask.py +106 -0
  41. package/bundled-skills/weaviate/scripts/create_collection.py +359 -0
  42. package/bundled-skills/weaviate/scripts/example_data.py +945 -0
  43. package/bundled-skills/weaviate/scripts/explore_collection.py +295 -0
  44. package/bundled-skills/weaviate/scripts/fetch_filter.py +261 -0
  45. package/bundled-skills/weaviate/scripts/get_collection.py +122 -0
  46. package/bundled-skills/weaviate/scripts/hybrid_search.py +157 -0
  47. package/bundled-skills/weaviate/scripts/import.py +701 -0
  48. package/bundled-skills/weaviate/scripts/keyword_search.py +142 -0
  49. package/bundled-skills/weaviate/scripts/list_collections.py +77 -0
  50. package/bundled-skills/weaviate/scripts/query_search.py +135 -0
  51. package/bundled-skills/weaviate/scripts/semantic_search.py +139 -0
  52. package/bundled-skills/weaviate/scripts/weaviate_conn.py +231 -0
  53. package/bundled-skills/weaviate-cookbooks/SKILL.md +67 -0
  54. package/bundled-skills/weaviate-cookbooks/references/advanced_rag.md +274 -0
  55. package/bundled-skills/weaviate-cookbooks/references/agentic_rag.md +360 -0
  56. package/bundled-skills/weaviate-cookbooks/references/async_client.md +428 -0
  57. package/bundled-skills/weaviate-cookbooks/references/basic_agent.md +270 -0
  58. package/bundled-skills/weaviate-cookbooks/references/basic_rag.md +219 -0
  59. package/bundled-skills/weaviate-cookbooks/references/data_explorer.md +336 -0
  60. package/bundled-skills/weaviate-cookbooks/references/environment_requirements.md +78 -0
  61. package/bundled-skills/weaviate-cookbooks/references/frontend_interface.md +104 -0
  62. package/bundled-skills/weaviate-cookbooks/references/pdf_multimodal_rag.md +635 -0
  63. package/bundled-skills/weaviate-cookbooks/references/project_setup.md +75 -0
  64. package/bundled-skills/weaviate-cookbooks/references/query_agent_chatbot.md +163 -0
  65. package/package.json +1 -1
  66. package/skills_index.json +156 -0
@@ -0,0 +1,295 @@
1
+ #!/usr/bin/env python3
2
+ # /// script
3
+ # dependencies = [
4
+ # "weaviate-client==4.19.2",
5
+ # "typer==0.21.0",
6
+ # ]
7
+ # ///
8
+ """
9
+ Explore a Weaviate collection's data: metrics, unique values (top occurrences), and sample objects.
10
+
11
+ Usage:
12
+ uv run explore_collection.py "CollectionName" [--limit 5] [--no-metrics] [--json]
13
+
14
+ Environment Variables:
15
+ WEAVIATE_URL: Weaviate Cloud cluster URL
16
+ WEAVIATE_API_KEY: API key for authentication
17
+ """
18
+
19
+ import json
20
+ import sys
21
+
22
+ import typer
23
+ import weaviate
24
+ import weaviate.classes as wvc
25
+ from weaviate.classes.aggregate import Metrics
26
+ from weaviate.collections.classes.config import DataType
27
+
28
+ # Import shared connection utilities (local to this skill)
29
+ from weaviate_conn import get_client
30
+
31
+ app = typer.Typer()
32
+
33
+
34
+ def get_metrics_for_property(prop_name: str, data_type: DataType | str) -> Metrics:
35
+ """
36
+ Return the appropriate Metrics object based on the property's data type.
37
+ """
38
+ # Text
39
+ if data_type in [DataType.TEXT, DataType.TEXT_ARRAY]:
40
+ return Metrics(prop_name).text(
41
+ count=True,
42
+ top_occurrences_count=True,
43
+ top_occurrences_value=True,
44
+ limit=5,
45
+ )
46
+ # Integer
47
+ elif data_type in [DataType.INT, DataType.INT_ARRAY]:
48
+ return Metrics(prop_name).integer(
49
+ count=True,
50
+ minimum=True,
51
+ maximum=True,
52
+ mean=True,
53
+ median=True,
54
+ mode=True,
55
+ sum_=True,
56
+ )
57
+ # Number
58
+ elif data_type in [DataType.NUMBER, DataType.NUMBER_ARRAY]:
59
+ return Metrics(prop_name).number(
60
+ count=True,
61
+ minimum=True,
62
+ maximum=True,
63
+ mean=True,
64
+ median=True,
65
+ mode=True,
66
+ sum_=True,
67
+ )
68
+ # Boolean
69
+ elif data_type in [DataType.BOOL, DataType.BOOL_ARRAY]:
70
+ return Metrics(prop_name).boolean(
71
+ count=True,
72
+ percentage_true=True,
73
+ percentage_false=True,
74
+ total_true=True,
75
+ total_false=True,
76
+ )
77
+ # Date
78
+ elif data_type in [DataType.DATE, DataType.DATE_ARRAY]:
79
+ return Metrics(prop_name).date_(
80
+ count=True,
81
+ minimum=True,
82
+ maximum=True,
83
+ median=True,
84
+ mode=True,
85
+ )
86
+ return None
87
+
88
+
89
+ @app.command()
90
+ def main(
91
+ name: str = typer.Argument(..., help="Collection name"),
92
+ limit: int = typer.Option(
93
+ 5, "--limit", "-l", help="Number of sample objects to show"
94
+ ),
95
+ no_metrics: bool = typer.Option(
96
+ False, "--no-metrics", help="Skip calculating metrics (faster)"
97
+ ),
98
+ json_output: bool = typer.Option(False, "--json", help="Output in JSON format"),
99
+ ):
100
+ """Explore data within a Weaviate collection."""
101
+ try:
102
+ with get_client() as client:
103
+ if not client.collections.exists(name):
104
+ print(f"Error: Collection '{name}' not found.", file=sys.stderr)
105
+ raise typer.Exit(1)
106
+
107
+ collection = client.collections.use(name)
108
+ config = collection.config.get()
109
+
110
+ # 1. Fetch Aggregation Metrics
111
+ metrics_data = {}
112
+ total_count = 0
113
+
114
+ if not no_metrics:
115
+ if not json_output:
116
+ print("Calculating metrics...", file=sys.stderr)
117
+
118
+ return_metrics = []
119
+ # Add metrics for each property based on type
120
+ for prop in config.properties:
121
+ m = get_metrics_for_property(prop.name, prop.data_type)
122
+ if m:
123
+ return_metrics.append(m)
124
+
125
+ try:
126
+ # Always ask for total_count
127
+ if return_metrics:
128
+ agg_response = collection.aggregate.over_all(
129
+ total_count=True, return_metrics=return_metrics
130
+ )
131
+ else:
132
+ # Fallback if no properties to aggregate
133
+ agg_response = collection.aggregate.over_all(total_count=True)
134
+
135
+ total_count = agg_response.total_count
136
+
137
+ for prop_name, agg_res in agg_response.properties.items():
138
+ prop_metrics = {}
139
+
140
+ # Helpers to extract common fields safely
141
+ def extract_fields(obj, fields):
142
+ for f in fields:
143
+ val = getattr(obj, f, None)
144
+ if val is not None:
145
+ prop_metrics[f] = val
146
+
147
+ # Identify type of result by checking attributes
148
+ if hasattr(agg_res, "top_occurrences"):
149
+ # Text
150
+ extract_fields(agg_res, ["count"])
151
+ if agg_res.top_occurrences:
152
+ prop_metrics["top_occurrences"] = [
153
+ {"value": to.value, "count": to.count}
154
+ for to in agg_res.top_occurrences
155
+ ]
156
+ elif hasattr(agg_res, "mean"):
157
+ # Number/Int
158
+ extract_fields(
159
+ agg_res,
160
+ [
161
+ "count",
162
+ "minimum",
163
+ "maximum",
164
+ "mean",
165
+ "median",
166
+ "mode",
167
+ "sum_",
168
+ ],
169
+ )
170
+ elif hasattr(agg_res, "percentage_true"):
171
+ # Boolean
172
+ extract_fields(
173
+ agg_res,
174
+ [
175
+ "count",
176
+ "total_true",
177
+ "total_false",
178
+ "percentage_true",
179
+ "percentage_false",
180
+ ],
181
+ )
182
+ elif hasattr(agg_res, "minimum") and not hasattr(
183
+ agg_res, "mean"
184
+ ):
185
+ # Date (has min/max but no mean)
186
+ extract_fields(
187
+ agg_res,
188
+ ["count", "minimum", "maximum", "median", "mode"],
189
+ )
190
+
191
+ if prop_metrics:
192
+ metrics_data[prop_name] = prop_metrics
193
+
194
+ except Exception as e:
195
+ if not json_output:
196
+ print(f"Warning: Aggregation failed: {e}", file=sys.stderr)
197
+ metrics_data["error"] = str(e)
198
+ else:
199
+ # Just get total count if metrics skipped
200
+ try:
201
+ agg_response = collection.aggregate.over_all(total_count=True)
202
+ total_count = agg_response.total_count
203
+ except Exception:
204
+ pass
205
+
206
+ # 2. Fetch Sample Objects
207
+ if limit > 0:
208
+ if not json_output:
209
+ print(f"Fetching {limit} sample objects...", file=sys.stderr)
210
+ # Fetch objects with all properties
211
+ objects_resp = collection.query.fetch_objects(limit=limit)
212
+ sample_objects = []
213
+ for obj in objects_resp.objects:
214
+ sample_objects.append(
215
+ {"uuid": str(obj.uuid), "properties": obj.properties}
216
+ )
217
+ else:
218
+ sample_objects = []
219
+
220
+ # 3. Output
221
+ result = {
222
+ "collection": name,
223
+ "total_count": total_count,
224
+ "metrics": metrics_data,
225
+ "sample_objects": sample_objects,
226
+ }
227
+
228
+ if json_output:
229
+ print(json.dumps(result, indent=2, default=str))
230
+ else:
231
+ # Markdown Output
232
+ print(f"## Collection Explorer: {name}\n")
233
+ print(f"**Total Objects:** {total_count}")
234
+
235
+ if metrics_data:
236
+ print("\n### Property Metrics\n")
237
+
238
+ prop_types = {p.name: p.data_type.value for p in config.properties}
239
+
240
+ for prop_name, data in metrics_data.items():
241
+ p_type = prop_types.get(prop_name, "unknown")
242
+ print(f"**{prop_name}** ({p_type})")
243
+ for k, v in data.items():
244
+ if k == "top_occurrences":
245
+ print(f"- Top Values:")
246
+ for item in v:
247
+ # Escape pipes and newlines in values
248
+ val_str = (
249
+ str(item["value"])
250
+ .replace("\n", " ")
251
+ .replace("|", "\\|")
252
+ )
253
+ print(f" - {val_str} ({item['count']})")
254
+ else:
255
+ label = k.replace("_", " ").capitalize()
256
+ print(f"- {label}: {v}")
257
+ print("")
258
+
259
+ if sample_objects:
260
+ print(f"### Sample Objects (Limit: {limit})\n")
261
+
262
+ all_props = set()
263
+ for obj in sample_objects:
264
+ all_props.update(obj["properties"].keys())
265
+ sorted_props = sorted(list(all_props))
266
+
267
+ headers = ["#", "UUID"] + sorted_props
268
+ header_row = "| " + " | ".join(headers) + " |"
269
+ separator_row = "| " + " | ".join(["---"] * len(headers)) + " |"
270
+
271
+ print(header_row)
272
+ print(separator_row)
273
+
274
+ for idx, obj in enumerate(sample_objects, 1):
275
+ row_data = [str(idx), str(obj["uuid"])]
276
+ props = obj["properties"]
277
+ for prop in sorted_props:
278
+ val = props.get(prop, "-")
279
+ val_str = str(val).replace("\n", " ").replace("|", "\\|")
280
+ if len(val_str) > 100:
281
+ val_str = val_str[:97] + "..."
282
+ row_data.append(val_str)
283
+ print("| " + " | ".join(row_data) + " |")
284
+ print()
285
+
286
+ except weaviate.exceptions.WeaviateConnectionError as e:
287
+ print(f"Error: Connection failed - {e}", file=sys.stderr)
288
+ raise typer.Exit(1)
289
+ except Exception as e:
290
+ print(f"Error: {e}", file=sys.stderr)
291
+ raise typer.Exit(1)
292
+
293
+
294
+ if __name__ == "__main__":
295
+ app()
@@ -0,0 +1,261 @@
1
+ #!/usr/bin/env python3
2
+ # /// script
3
+ # dependencies = [
4
+ # "weaviate-client==4.19.2",
5
+ # "typer==0.21.0",
6
+ # ]
7
+ # ///
8
+ """
9
+ Fetch and filter objects from a Weaviate collection.
10
+
11
+ Usage:
12
+ # Fetch random 10 objects
13
+ uv run fetch_filter.py "JeopardyQuestion"
14
+
15
+ # Fetch by ID
16
+ uv run fetch_filter.py "JeopardyQuestion" --id "uuid-string"
17
+
18
+ # Filter with simple JSON
19
+ uv run fetch_filter.py "JeopardyQuestion" --filters '[{"property": "round", "operator": "equal", "value": "Double Jeopardy!"}]'
20
+
21
+ Environment Variables:
22
+ WEAVIATE_URL: Weaviate Cloud cluster URL
23
+ WEAVIATE_API_KEY: API key for authentication
24
+ """
25
+
26
+ import json
27
+ import sys
28
+ from typing import Any, List, Optional
29
+
30
+ import typer
31
+ import weaviate
32
+ from weaviate.classes.query import Filter
33
+
34
+ # Import shared connection utilities (local to this skill)
35
+ from weaviate_conn import get_client
36
+
37
+ app = typer.Typer()
38
+
39
+
40
+ def parse_filter_item(item: Any) -> Optional[Filter]:
41
+ """
42
+ Recursively parse a single filter item (dict or list).
43
+
44
+ Supported structures:
45
+ 1. List of filters (implicit AND): [filter1, filter2]
46
+ 2. Explicit Logical Operators:
47
+ {"operator": "and", "filters": [...]}
48
+ {"operator": "or", "filters": [...]}
49
+ 3. Property Filter:
50
+ {"property": "name", "operator": "equal", "value": "foo"}
51
+ """
52
+ if isinstance(item, list):
53
+ # Implicit AND for lists
54
+ sub_filters = [parse_filter_item(x) for x in item]
55
+ # Filter out Nones
56
+ sub_filters = [f for f in sub_filters if f is not None]
57
+ if not sub_filters:
58
+ return None
59
+ return Filter.all_of(sub_filters)
60
+
61
+ if not isinstance(item, dict):
62
+ return None
63
+
64
+ # Check for logical operators
65
+ op = item.get("operator")
66
+
67
+ if op == "and":
68
+ sub_items = item.get("filters", [])
69
+ sub_filters = [parse_filter_item(x) for x in sub_items]
70
+ sub_filters = [f for f in sub_filters if f is not None]
71
+ return Filter.all_of(sub_filters) if sub_filters else None
72
+
73
+ if op == "or":
74
+ sub_items = item.get("filters", [])
75
+ sub_filters = [parse_filter_item(x) for x in sub_items]
76
+ sub_filters = [f for f in sub_filters if f is not None]
77
+ return Filter.any_of(sub_filters) if sub_filters else None
78
+
79
+ # Property Filter
80
+ prop = item.get("property")
81
+ val = item.get("value")
82
+
83
+ if not prop or not op:
84
+ return None
85
+
86
+ current_filter = Filter.by_property(prop)
87
+
88
+ # Map operator string to method
89
+ if op == "equal":
90
+ return current_filter.equal(val)
91
+ elif op == "not_equal":
92
+ return current_filter.not_equal(val)
93
+ elif op == "less_than":
94
+ return current_filter.less_than(val)
95
+ elif op == "less_or_equal":
96
+ return current_filter.less_or_equal(val)
97
+ elif op == "greater_than":
98
+ return current_filter.greater_than(val)
99
+ elif op == "greater_or_equal":
100
+ return current_filter.greater_or_equal(val)
101
+ elif op == "like":
102
+ return current_filter.like(val)
103
+ elif op == "contains_any":
104
+ if not isinstance(val, list):
105
+ print(
106
+ f"Error: Value for 'contains_any' must be a list, got {type(val)}",
107
+ file=sys.stderr,
108
+ )
109
+ raise typer.Exit(1)
110
+ return current_filter.contains_any(val)
111
+ elif op == "contains_all":
112
+ if not isinstance(val, list):
113
+ print(
114
+ f"Error: Value for 'contains_all' must be a list, got {type(val)}",
115
+ file=sys.stderr,
116
+ )
117
+ raise typer.Exit(1)
118
+ return current_filter.contains_all(val)
119
+ elif op == "is_none":
120
+ return current_filter.is_none(bool(val))
121
+ else:
122
+ print(
123
+ f"Warning: Unknown operator '{op}' for property '{prop}'. Skipping.",
124
+ file=sys.stderr,
125
+ )
126
+ return None
127
+
128
+
129
+ def parse_filters(filter_json: str) -> Optional[Filter]:
130
+ """
131
+ Parse a JSON string of filters into a Weaviate Filter object.
132
+ Supports complex nesting with AND/OR.
133
+ """
134
+ if not filter_json:
135
+ return None
136
+
137
+ try:
138
+ data = json.loads(filter_json)
139
+ except json.JSONDecodeError as e:
140
+ print(f"Error parsing filters JSON: {e}", file=sys.stderr)
141
+ raise typer.Exit(1)
142
+
143
+ return parse_filter_item(data)
144
+
145
+
146
+ @app.command()
147
+ def main(
148
+ collection_name: str = typer.Argument(..., help="Collection name"),
149
+ obj_id: str = typer.Option(None, "--id", help="Fetch specific object by UUID"),
150
+ filters: str = typer.Option(None, "--filters", "-f", help="JSON string of filters"),
151
+ limit: int = typer.Option(10, "--limit", "-l", help="Number of objects to fetch"),
152
+ properties: str = typer.Option(
153
+ None,
154
+ "--properties",
155
+ "-p",
156
+ help="Comma-separated properties to include (default: all)",
157
+ ),
158
+ json_output: bool = typer.Option(False, "--json", help="Output in JSON format"),
159
+ ):
160
+ """Fetch objects with optional filtering."""
161
+ try:
162
+ with get_client() as client:
163
+ if not client.collections.exists(collection_name):
164
+ print(
165
+ f"Error: Collection '{collection_name}' not found.", file=sys.stderr
166
+ )
167
+ raise typer.Exit(1)
168
+
169
+ collection = client.collections.use(collection_name)
170
+
171
+ # Determine return properties
172
+ return_properties = None
173
+ if properties:
174
+ return_properties = [
175
+ p.strip() for p in properties.split(",") if p.strip()
176
+ ]
177
+
178
+ results = []
179
+
180
+ if obj_id:
181
+ # Fetch single object by ID
182
+ if not json_output:
183
+ print(f"Fetching object {obj_id}...", file=sys.stderr)
184
+
185
+ obj = collection.query.fetch_object_by_id(obj_id)
186
+
187
+ if obj:
188
+ results.append(obj)
189
+ else:
190
+ print(f"Error: Object {obj_id} not found.", file=sys.stderr)
191
+ raise typer.Exit(1)
192
+
193
+ else:
194
+ # Fetch multiple with filters
195
+ weaviate_filter = parse_filters(filters)
196
+
197
+ if not json_output:
198
+ print(
199
+ f"Fetching objects from '{collection_name}'...", file=sys.stderr
200
+ )
201
+
202
+ response = collection.query.fetch_objects(
203
+ filters=weaviate_filter,
204
+ limit=limit,
205
+ return_properties=return_properties,
206
+ )
207
+ results = list(response.objects)
208
+
209
+ # Output Formatting
210
+ output_data = []
211
+ for obj in results:
212
+ item = {
213
+ "uuid": str(obj.uuid),
214
+ "properties": obj.properties,
215
+ "metadata": {
216
+ "creation_time": str(obj.metadata.creation_time)
217
+ if obj.metadata.creation_time
218
+ else None,
219
+ },
220
+ }
221
+ output_data.append(item)
222
+
223
+ if json_output:
224
+ print(json.dumps(output_data, indent=2, default=str))
225
+ else:
226
+ if not results:
227
+ print("No objects found.")
228
+ else:
229
+ print(f"## Found {len(results)} Objects\n")
230
+
231
+ # Gather all property keys for the table headers
232
+ all_keys = set()
233
+ for item in output_data:
234
+ all_keys.update(item["properties"].keys())
235
+ sorted_keys = sorted(list(all_keys))
236
+
237
+ # Table Header
238
+ headers = ["UUID"] + sorted_keys
239
+ print("| " + " | ".join(headers) + " |")
240
+ print("| " + " | ".join(["---"] * len(headers)) + " |")
241
+
242
+ for item in output_data:
243
+ row = [str(item["uuid"])]
244
+ for k in sorted_keys:
245
+ val = item["properties"].get(k, "-")
246
+ val_str = str(val).replace("\n", " ").replace("|", "\\|")
247
+ if len(val_str) > 100:
248
+ val_str = val_str[:97] + "..."
249
+ row.append(val_str)
250
+ print("| " + " | ".join(row) + " |")
251
+
252
+ except weaviate.exceptions.WeaviateConnectionError as e:
253
+ print(f"Error: Connection failed - {e}", file=sys.stderr)
254
+ raise typer.Exit(1)
255
+ except Exception as e:
256
+ print(f"Error: {e}", file=sys.stderr)
257
+ raise typer.Exit(1)
258
+
259
+
260
+ if __name__ == "__main__":
261
+ app()
@@ -0,0 +1,122 @@
1
+ #!/usr/bin/env python3
2
+ # /// script
3
+ # dependencies = [
4
+ # "weaviate-client==4.19.2",
5
+ # "typer==0.21.0",
6
+ # ]
7
+ # ///
8
+ """
9
+ Get details of a specific Weaviate collection.
10
+
11
+ Usage:
12
+ uv run get_collection.py --name "CollectionName" [--json]
13
+
14
+ Environment Variables:
15
+ WEAVIATE_URL: Weaviate Cloud cluster URL
16
+ WEAVIATE_API_KEY: API key for authentication
17
+ """
18
+
19
+ import json
20
+ import sys
21
+
22
+ import typer
23
+ import weaviate
24
+
25
+ # Import shared connection utilities (local to this skill)
26
+ from weaviate_conn import get_client
27
+
28
+ app = typer.Typer()
29
+
30
+
31
+ @app.command()
32
+ def main(
33
+ name: str = typer.Option(..., "--name", "-n", help="Collection name"),
34
+ json_output: bool = typer.Option(False, "--json", help="Output in JSON format"),
35
+ ):
36
+ """Get detailed configuration of a Weaviate collection."""
37
+ try:
38
+ with get_client() as client:
39
+ if not client.collections.exists(name):
40
+ print(f"Error: Collection '{name}' not found.", file=sys.stderr)
41
+ raise typer.Exit(1)
42
+
43
+ print("Fetching collection details...", file=sys.stderr)
44
+ collection = client.collections.use(name)
45
+ config = collection.config.get()
46
+
47
+ # Extract vectorizer config
48
+ vectorizer_config = None
49
+ if hasattr(config, "vectorizer_config") and config.vectorizer_config:
50
+ vc = config.vectorizer_config
51
+ if hasattr(vc, "vectorizer"):
52
+ vectorizer_config = {
53
+ "vectorizer": str(vc.vectorizer.value)
54
+ if hasattr(vc.vectorizer, "value")
55
+ else str(vc.vectorizer),
56
+ "model": getattr(vc, "model", None),
57
+ }
58
+
59
+ # Extract properties
60
+ properties = []
61
+ if hasattr(config, "properties") and config.properties:
62
+ for p in config.properties:
63
+ prop_info = {
64
+ "name": p.name,
65
+ "data_type": str(p.data_type),
66
+ "description": getattr(p, "description", None),
67
+ }
68
+ properties.append(prop_info)
69
+
70
+ result = {
71
+ "name": name,
72
+ "description": config.description,
73
+ "vectorizer_config": vectorizer_config,
74
+ "properties": properties,
75
+ "replication_factor": getattr(config.replication_config, "factor", None)
76
+ if hasattr(config, "replication_config")
77
+ else None,
78
+ "multi_tenancy_enabled": getattr(
79
+ config.multi_tenancy_config, "enabled", False
80
+ )
81
+ if hasattr(config, "multi_tenancy_config")
82
+ else False,
83
+ }
84
+
85
+ if json_output:
86
+ print(json.dumps(result, indent=2, default=str))
87
+ else:
88
+ print(f"## Collection: {name}\n")
89
+ print(f"**Description:** {config.description or 'N/A'}")
90
+
91
+ if vectorizer_config:
92
+ print(
93
+ f"**Vectorizer:** {vectorizer_config.get('vectorizer', 'N/A')}"
94
+ )
95
+ if vectorizer_config.get("model"):
96
+ print(f"**Model:** {vectorizer_config['model']}")
97
+
98
+ print(
99
+ f"**Replication Factor:** {result['replication_factor'] or 'N/A'}"
100
+ )
101
+ print(
102
+ f"**Multi-Tenancy:** {'Enabled' if result['multi_tenancy_enabled'] else 'Disabled'}"
103
+ )
104
+
105
+ if properties:
106
+ print(f"\n### Properties ({len(properties)})\n")
107
+ print("| Name | Data Type | Description |")
108
+ print("|------|-----------|-------------|")
109
+ for prop in properties:
110
+ desc = prop.get("description") or "-"
111
+ print(f"| {prop['name']} | {prop['data_type']} | {desc} |")
112
+
113
+ except weaviate.exceptions.WeaviateConnectionError as e:
114
+ print(f"Error: Connection failed - {e}", file=sys.stderr)
115
+ raise typer.Exit(1)
116
+ except Exception as e:
117
+ print(f"Error: {e}", file=sys.stderr)
118
+ raise typer.Exit(1)
119
+
120
+
121
+ if __name__ == "__main__":
122
+ app()