signalpilot-ai-internal 0.3.3__py3-none-any.whl → 0.3.4__py3-none-any.whl
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.
- signalpilot_ai_internal/_version.py +1 -1
- signalpilot_ai_internal/cache_service.py +1 -4
- signalpilot_ai_internal/snowflake_schema_service.py +52 -20
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/package.json +2 -2
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/schemas/signalpilot-ai-internal/package.json.orig +1 -1
- signalpilot_ai_internal-0.3.4.data/data/share/jupyter/labextensions/signalpilot-ai-internal/static/447.d8bc4aeaf8ddeacb2486.js +1 -0
- signalpilot_ai_internal-0.3.4.data/data/share/jupyter/labextensions/signalpilot-ai-internal/static/839.694baa59818fdf19fba9.js +1 -0
- signalpilot_ai_internal-0.3.3.data/data/share/jupyter/labextensions/signalpilot-ai-internal/static/remoteEntry.2e2c6ae0baa591126b0a.js → signalpilot_ai_internal-0.3.4.data/data/share/jupyter/labextensions/signalpilot-ai-internal/static/remoteEntry.a9d6eb0edda396db6779.js +1 -1
- {signalpilot_ai_internal-0.3.3.dist-info → signalpilot_ai_internal-0.3.4.dist-info}/METADATA +1 -1
- {signalpilot_ai_internal-0.3.3.dist-info → signalpilot_ai_internal-0.3.4.dist-info}/RECORD +39 -39
- signalpilot_ai_internal-0.3.3.data/data/share/jupyter/labextensions/signalpilot-ai-internal/static/447.0fea0d444fc7ba458d5a.js +0 -1
- signalpilot_ai_internal-0.3.3.data/data/share/jupyter/labextensions/signalpilot-ai-internal/static/839.c61f5bc4d0da4a0781d6.js +0 -1
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/etc/jupyter/jupyter_server_config.d/signalpilot_ai.json +0 -0
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/install.json +0 -0
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/schemas/signalpilot-ai-internal/plugin.json +0 -0
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/104.04e170724f369fcbaf19.js +0 -0
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/104.04e170724f369fcbaf19.js.LICENSE.txt +0 -0
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/122.e2dadf63dc64d7b5f1ee.js +0 -0
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/220.328403b5545f268b95c6.js +0 -0
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/262.726e1da31a50868cb297.js +0 -0
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/280.35d8c8b68815702a5238.js +0 -0
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/280.35d8c8b68815702a5238.js.LICENSE.txt +0 -0
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/353.72484b768a04f89bd3dd.js +0 -0
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/364.dbec4c2dc12e7b050dcc.js +0 -0
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/384.fa432bdb7fb6b1c95ad6.js +0 -0
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/439.37e271d7a80336daabe2.js +0 -0
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/476.9b4f05a99f5003f82094.js +0 -0
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/481.73c7a9290b7d35a8b9c1.js +0 -0
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/512.b58fc0093d080b8ee61c.js +0 -0
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/553.b4042a795c91d9ff71ef.js +0 -0
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/553.b4042a795c91d9ff71ef.js.LICENSE.txt +0 -0
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/606.90aaaae46b73dc3c08fb.js +0 -0
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/635.9720593ee20b768da3ca.js +0 -0
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/713.8e6edc9a965bdd578ca7.js +0 -0
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/742.91e7b516c8699eea3373.js +0 -0
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/785.3aa564fc148b37d1d719.js +0 -0
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/888.34054db17bcf6e87ec95.js +0 -0
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/style.js +0 -0
- {signalpilot_ai_internal-0.3.3.data → signalpilot_ai_internal-0.3.4.data}/data/share/jupyter/labextensions/signalpilot-ai-internal/static/third-party-licenses.json +0 -0
- {signalpilot_ai_internal-0.3.3.dist-info → signalpilot_ai_internal-0.3.4.dist-info}/WHEEL +0 -0
- {signalpilot_ai_internal-0.3.3.dist-info → signalpilot_ai_internal-0.3.4.dist-info}/licenses/LICENSE +0 -0
|
@@ -110,7 +110,7 @@ class RobustFileOperations:
|
|
|
110
110
|
@staticmethod
|
|
111
111
|
def safe_write_json(file_path: Path, data: Any, max_retries: int = 3) -> bool:
|
|
112
112
|
"""Safely write JSON data with atomic operations and backups"""
|
|
113
|
-
print(f"Attempting to write JSON to: {file_path}")
|
|
113
|
+
# print(f"Attempting to write JSON to: {file_path}")
|
|
114
114
|
|
|
115
115
|
if not file_path.parent.exists():
|
|
116
116
|
try:
|
|
@@ -138,8 +138,6 @@ class RobustFileOperations:
|
|
|
138
138
|
|
|
139
139
|
# Keep only the most recent backup that's at least 1 hour old
|
|
140
140
|
RobustFileOperations._cleanup_backups(file_path)
|
|
141
|
-
else:
|
|
142
|
-
print(f"Skipping backup for {file_path} - recent backup exists")
|
|
143
141
|
|
|
144
142
|
except Exception as e:
|
|
145
143
|
print(f"Warning: Could not create backup for {file_path}: {e}")
|
|
@@ -165,7 +163,6 @@ class RobustFileOperations:
|
|
|
165
163
|
|
|
166
164
|
shutil.move(str(temp_path), str(file_path))
|
|
167
165
|
|
|
168
|
-
print(f"Successfully wrote {file_path}")
|
|
169
166
|
return True
|
|
170
167
|
|
|
171
168
|
except Exception as e:
|
|
@@ -4,9 +4,12 @@ Provides REST API handlers for Snowflake database schema retrieval and query exe
|
|
|
4
4
|
Supports multiple databases within a single Snowflake connection.
|
|
5
5
|
|
|
6
6
|
Behavior:
|
|
7
|
-
-
|
|
7
|
+
- If a warehouse is specified in the config, it will be used directly.
|
|
8
|
+
- Otherwise, picks the smallest RUNNING warehouse.
|
|
8
9
|
- If none running, resumes the smallest SUSPENDED warehouse.
|
|
9
10
|
- If none exist, attempts to CREATE a tiny warehouse (requires privilege).
|
|
11
|
+
- If a database is specified in the config, only that database will be processed.
|
|
12
|
+
- Otherwise, all accessible databases will be processed.
|
|
10
13
|
- Builds a catalog with parallel schema processing for performance.
|
|
11
14
|
- For each table, includes detailed column information: name, type, ordinal position,
|
|
12
15
|
nullable, description, default value, and type-specific attributes.
|
|
@@ -321,26 +324,45 @@ class SnowflakeSchemaHandler(APIHandler):
|
|
|
321
324
|
print(f"Warning: Error processing schema {db}.{schema}: {e}", file=sys.stderr)
|
|
322
325
|
return {"schema": schema, "tables": [], "error": str(e)}
|
|
323
326
|
|
|
324
|
-
def _build_catalog(self, connector, conn, max_workers: int = 5) -> Dict:
|
|
325
|
-
"""Build complete catalog with parallel schema processing
|
|
327
|
+
def _build_catalog(self, connector, conn, max_workers: int = 5, specified_database: Optional[str] = None, specified_warehouse: Optional[str] = None) -> Dict:
|
|
328
|
+
"""Build complete catalog with parallel schema processing
|
|
329
|
+
|
|
330
|
+
Args:
|
|
331
|
+
connector: Snowflake connector module
|
|
332
|
+
conn: Active Snowflake connection
|
|
333
|
+
max_workers: Number of parallel workers for schema processing
|
|
334
|
+
specified_database: If provided, only process this database
|
|
335
|
+
specified_warehouse: If provided, use this warehouse (don't auto-select)
|
|
336
|
+
"""
|
|
326
337
|
cur = conn.cursor(connector.DictCursor)
|
|
327
338
|
try:
|
|
328
|
-
# 1)
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
cur.execute(
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
339
|
+
# 1) Handle warehouse selection
|
|
340
|
+
if specified_warehouse:
|
|
341
|
+
# Use the explicitly specified warehouse
|
|
342
|
+
wh = specified_warehouse
|
|
343
|
+
cur.execute(f'USE WAREHOUSE "{wh}"')
|
|
344
|
+
else:
|
|
345
|
+
# Auto-select a warehouse using existing logic
|
|
346
|
+
preferred_wh = None
|
|
347
|
+
# Extract warehouse from conn if available
|
|
348
|
+
try:
|
|
349
|
+
cur.execute("SELECT CURRENT_WAREHOUSE()")
|
|
350
|
+
row = cur.fetchone()
|
|
351
|
+
if row:
|
|
352
|
+
preferred_wh = row[0] if isinstance(row, tuple) else row.get("CURRENT_WAREHOUSE()")
|
|
353
|
+
except:
|
|
354
|
+
pass
|
|
355
|
+
|
|
356
|
+
wh = self._ensure_warehouse(cur, preferred_wh)
|
|
357
|
+
cur.execute(f'USE WAREHOUSE "{wh}"')
|
|
341
358
|
|
|
342
|
-
# 2)
|
|
343
|
-
|
|
359
|
+
# 2) Handle database selection
|
|
360
|
+
if specified_database:
|
|
361
|
+
# Only process the specified database
|
|
362
|
+
dbs = [specified_database]
|
|
363
|
+
else:
|
|
364
|
+
# List all databases
|
|
365
|
+
dbs = self._list_databases(cur)
|
|
344
366
|
cur.close()
|
|
345
367
|
|
|
346
368
|
catalog = []
|
|
@@ -423,12 +445,22 @@ class SnowflakeSchemaHandler(APIHandler):
|
|
|
423
445
|
conn_params = self._get_connection_params(config)
|
|
424
446
|
max_workers = int(body.get('max_workers', 5))
|
|
425
447
|
|
|
426
|
-
|
|
448
|
+
# Extract database and warehouse from config for filtering
|
|
449
|
+
specified_database = config.get('database')
|
|
450
|
+
specified_warehouse = config.get('warehouse')
|
|
451
|
+
|
|
452
|
+
print(f"[SnowflakeSchemaHandler] Connecting with account={conn_params['account']}, user={conn_params['user']}, warehouse={conn_params.get('warehouse')}, database={conn_params.get('database')}, role={conn_params.get('role')}")
|
|
427
453
|
|
|
428
454
|
connection = connector.connect(**conn_params, client_session_keep_alive=False)
|
|
429
455
|
|
|
430
456
|
try:
|
|
431
|
-
catalog = self._build_catalog(
|
|
457
|
+
catalog = self._build_catalog(
|
|
458
|
+
connector,
|
|
459
|
+
connection,
|
|
460
|
+
max_workers=max_workers,
|
|
461
|
+
specified_database=specified_database,
|
|
462
|
+
specified_warehouse=specified_warehouse
|
|
463
|
+
)
|
|
432
464
|
result = self._format_catalog_as_json(catalog)
|
|
433
465
|
self.finish(json.dumps(result, indent=2))
|
|
434
466
|
finally:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "signalpilot-ai-internal",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
4
4
|
"description": "SignalPilot Agent - Your Jupyter Notebook Assistant",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jupyter",
|
|
@@ -133,7 +133,7 @@
|
|
|
133
133
|
"outputDir": "signalpilot_ai_internal/labextension",
|
|
134
134
|
"schemaDir": "schema",
|
|
135
135
|
"_build": {
|
|
136
|
-
"load": "static/remoteEntry.
|
|
136
|
+
"load": "static/remoteEntry.a9d6eb0edda396db6779.js",
|
|
137
137
|
"extension": "./extension",
|
|
138
138
|
"style": "./style"
|
|
139
139
|
}
|