neurostack-org 2.2.0__tar.gz → 2.2.2__tar.gz
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.
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/PKG-INFO +1 -1
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/pyproject.toml +1 -1
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/neurostack_org.egg-info/PKG-INFO +1 -1
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/cli/main.py +366 -27
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/README.md +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/setup.cfg +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/config/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/config/brain_config.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/config/confidence_config.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/config/persona_config.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/config/retrieval_config.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/core/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/core/input_validator.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/core/intent_classifier.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/core/knowledge_retriever.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/core/orchestrator.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/core/reasoning_engine.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/core/response_formatter.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/factory.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/interfaces/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/interfaces/embedding.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/interfaces/llm.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/interfaces/vector_store.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/logging/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/logging/formatters.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/logging/logger.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/logging/trace.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/models/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/models/confidence.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/models/intent.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/models/persona.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/models/request.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/models/response.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/models/retrieval.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/prompts/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/prompts/base.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/prompts/intent_classifier.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/prompts/reasoning/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/prompts/reasoning/action.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/prompts/reasoning/decision_recall.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/prompts/reasoning/informational.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/prompts/reasoning/metrics.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/prompts/reasoning/planning.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/prompts/reasoning/status.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/prompts/reasoning/summary.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/utils/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/utils/confidence.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/utils/ranking.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/utils/time.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/utils/validation.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/utils/visibility.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/clients/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/clients/anthropic_client.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/clients/anthropic_llm.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/clients/azure_openai_llm.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/clients/example_vector_client.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/clients/mock_embedding.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/clients/mock_vector_store.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/clients/openai_compatible_llm.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/clients/openai_embedding.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/clients/retry.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/neurostack/integrations/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/neurostack/integrations/base.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/neurostack/integrations/slack/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/neurostack/integrations/slack/bot.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/neurostack/integrations/slack/commands.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/neurostack/integrations/slack/formatters.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/neurostack/integrations/telegram/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/neurostack/integrations/telegram/bot.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/neurostack/integrations/telegram/formatters.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/neurostack/license.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/neurostack/logging.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/neurostack/models/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/neurostack/models/context.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/neurostack/models/knowledge.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/neurostack/models/permission.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/neurostack_org.egg-info/SOURCES.txt +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/neurostack_org.egg-info/dependency_links.txt +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/neurostack_org.egg-info/entry_points.txt +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/neurostack_org.egg-info/requires.txt +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/neurostack_org.egg-info/top_level.txt +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/audit/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/audit/lineage.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/audit/logger.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/audit/metrics.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/auth/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/auth/oauth_manager.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/auth/permission_sync.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/auth/token_store.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/cli/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/cli/connector_manage.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/cli/ingest.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/cli/status.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/config/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/config/loader.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/config/pipeline_config.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/config/storage_config.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/connectors/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/connectors/base.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/connectors/csv/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/connectors/csv/connector.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/connectors/google_workspace/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/connectors/google_workspace/auth.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/connectors/google_workspace/calendar_connector.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/connectors/google_workspace/docs_connector.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/connectors/google_workspace/drive_connector.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/connectors/google_workspace/permission_mapper.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/connectors/jira/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/connectors/jira/auth.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/connectors/jira/config.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/connectors/jira/connector.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/connectors/jira/permission_mapper.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/connectors/registry.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/connectors/slack/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/connectors/slack/auth.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/connectors/slack/connector.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/connectors/slack/deduplication.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/connectors/slack/permission_mapper.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/core/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/core/chunker.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/core/ingestion_engine.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/core/live_data_handler.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/core/orchestrator.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/core/permission_engine.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/ingest/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/ingest/universal.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/models/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/models/connector_config.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/models/ingestion_job.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/models/storage.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/processing/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/processing/chunking/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/processing/chunking/document_chunker.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/processing/chunking/semantic_chunker.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/processing/chunking/structured_chunker.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/processing/embeddings/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/processing/embeddings/embedding_client.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/processing/embeddings/mock_embeddings.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/processing/embeddings/openai_embeddings.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/processing/normalizer.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/processing/versioning.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/processors/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/processors/audio_processor.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/processors/file_processor.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/processors/text_classifier.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/scheduling/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/scheduling/checkpoint.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/scheduling/job_queue.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/scheduling/rate_limiter.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/scheduling/scheduler.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/storage/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/storage/graph/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/storage/graph/neo4j_store.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/storage/interfaces.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/storage/metadata/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/storage/metadata/postgres.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/storage/migrations/env.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/storage/migrations/versions/f2816fb07a30_initial_schema.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/storage/semantic/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/storage/semantic/mock_store.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/storage/semantic/pinecone_store.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/storage/semantic/qdrant_store.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/storage/semantic/weaviate_store.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/utils/__init__.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/utils/deduplication.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/utils/exceptions.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/utils/retry.py +0 -0
- {neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/utils/validation.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: neurostack-org
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.2
|
|
4
4
|
Summary: Enterprise AI SDK — permission-aware organizational knowledge retrieval with 9 connectors, 5-stage deterministic pipeline, and universal ingestion
|
|
5
5
|
Author: Tauseeq Kazi
|
|
6
6
|
License: BSL-1.1
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "neurostack-org"
|
|
7
|
-
version = "2.2.
|
|
7
|
+
version = "2.2.2"
|
|
8
8
|
description = "Enterprise AI SDK — permission-aware organizational knowledge retrieval with 9 connectors, 5-stage deterministic pipeline, and universal ingestion"
|
|
9
9
|
authors = [{name = "Tauseeq Kazi"}]
|
|
10
10
|
license = {text = "BSL-1.1"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: neurostack-org
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.2
|
|
4
4
|
Summary: Enterprise AI SDK — permission-aware organizational knowledge retrieval with 9 connectors, 5-stage deterministic pipeline, and universal ingestion
|
|
5
5
|
Author: Tauseeq Kazi
|
|
6
6
|
License: BSL-1.1
|
|
@@ -6,7 +6,7 @@ import subprocess
|
|
|
6
6
|
import click
|
|
7
7
|
import yaml
|
|
8
8
|
|
|
9
|
-
VERSION = "2.2.
|
|
9
|
+
VERSION = "2.2.2"
|
|
10
10
|
|
|
11
11
|
CONFIG_FILE = "neurostack.yaml"
|
|
12
12
|
|
|
@@ -186,24 +186,263 @@ def migrate():
|
|
|
186
186
|
|
|
187
187
|
|
|
188
188
|
@cli.command()
|
|
189
|
-
@click.argument("connector_type")
|
|
189
|
+
@click.argument("connector_type", required=False, default=None)
|
|
190
190
|
@click.option("--full", is_flag=True, help="Run full sync instead of incremental.")
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
191
|
+
@click.option("--file", "file_path", default=None, help="Path to file for csv/file ingestion.")
|
|
192
|
+
def ingest(connector_type: str, full: bool, file_path: str):
|
|
193
|
+
"""Run ingestion for a specific connector type (e.g. csv, email, jira, slack).
|
|
194
|
+
|
|
195
|
+
\b
|
|
196
|
+
Examples:
|
|
197
|
+
neurostack ingest csv --file data.csv
|
|
198
|
+
neurostack ingest email
|
|
199
|
+
neurostack ingest manual
|
|
200
|
+
neurostack ingest # interactive picker
|
|
201
|
+
"""
|
|
202
|
+
cfg = _load_partial_config()
|
|
203
|
+
|
|
204
|
+
if not connector_type:
|
|
205
|
+
# Interactive picker
|
|
206
|
+
connector_type = _numbered_menu("What do you want to ingest?", [
|
|
207
|
+
{"label": "CSV / Excel file", "value": "csv", "hint": "Upload a local file"},
|
|
208
|
+
{"label": "Manual text entry", "value": "manual", "hint": "Paste text directly"},
|
|
209
|
+
{"label": "Email (IMAP)", "value": "email", "hint": "Fetch from your inbox"},
|
|
210
|
+
{"label": "GitHub", "value": "github", "hint": "Fetch issues, PRs, READMEs"},
|
|
211
|
+
{"label": "Jira", "value": "jira", "hint": "Fetch issues and projects"},
|
|
212
|
+
{"label": "Slack", "value": "slack", "hint": "Fetch messages and threads"},
|
|
213
|
+
], default=1, allow_back=True)
|
|
214
|
+
if connector_type == "__back__":
|
|
215
|
+
return
|
|
216
|
+
|
|
217
|
+
click.echo(click.style(f"\n Ingesting: {connector_type}", fg="cyan", bold=True))
|
|
218
|
+
|
|
219
|
+
# Find connector config from neurostack.yaml
|
|
220
|
+
connector_cfg = None
|
|
221
|
+
for c in cfg.get("connectors", []):
|
|
222
|
+
if c.get("type") == connector_type:
|
|
223
|
+
connector_cfg = c
|
|
224
|
+
break
|
|
225
|
+
|
|
195
226
|
try:
|
|
196
|
-
|
|
227
|
+
if connector_type == "csv":
|
|
228
|
+
_ingest_csv(file_path, connector_cfg)
|
|
229
|
+
elif connector_type == "manual":
|
|
230
|
+
_ingest_manual()
|
|
231
|
+
elif connector_type == "email":
|
|
232
|
+
_ingest_email(connector_cfg)
|
|
233
|
+
elif connector_type == "github":
|
|
234
|
+
_ingest_github(connector_cfg)
|
|
235
|
+
elif connector_type in ("jira", "slack", "notion", "confluence", "teams"):
|
|
236
|
+
_ingest_api_connector(connector_type, connector_cfg, full)
|
|
237
|
+
else:
|
|
238
|
+
click.echo(click.style(f" Connector '{connector_type}' not yet supported for CLI ingestion.", fg="yellow"))
|
|
239
|
+
click.echo(" You can use the REST API instead: POST /api/ingest/webhook")
|
|
240
|
+
except KeyboardInterrupt:
|
|
241
|
+
click.echo(click.style("\n Ingestion cancelled.", fg="yellow"))
|
|
242
|
+
except Exception as e:
|
|
243
|
+
click.echo(click.style(f"\n Ingestion failed: {e}", fg="red"))
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def _ingest_csv(file_path, connector_cfg):
|
|
247
|
+
"""Ingest a CSV/Excel file."""
|
|
248
|
+
if not file_path:
|
|
249
|
+
file_path = connector_cfg.get("path") if connector_cfg else None
|
|
250
|
+
if not file_path:
|
|
251
|
+
file_path = click.prompt(" Path to CSV/Excel file")
|
|
252
|
+
|
|
253
|
+
import os
|
|
254
|
+
if not os.path.exists(file_path):
|
|
255
|
+
click.echo(click.style(f" File not found: {file_path}", fg="red"))
|
|
256
|
+
return
|
|
257
|
+
|
|
258
|
+
from pipeline.processors.file_processor import file_processor
|
|
259
|
+
result = file_processor.process_file(file_path)
|
|
260
|
+
|
|
261
|
+
click.echo(click.style(f" Processed: {file_path}", fg="green"))
|
|
262
|
+
click.echo(f" Format: {result.metadata.get('format', 'unknown')}")
|
|
263
|
+
click.echo(f" Content: {len(result.text)} characters")
|
|
264
|
+
if result.metadata.get("row_count"):
|
|
265
|
+
click.echo(f" Rows: {result.metadata['row_count']}")
|
|
266
|
+
click.echo(click.style(" Ingestion complete.", fg="green"))
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def _ingest_manual():
|
|
270
|
+
"""Ingest text typed or pasted by the user."""
|
|
271
|
+
click.echo(click.style(" Type or paste your knowledge below.", fg="white", bold=True))
|
|
272
|
+
click.echo(click.style(" Press Enter twice (empty line) when done.", fg="bright_black"))
|
|
273
|
+
click.echo()
|
|
274
|
+
|
|
275
|
+
lines = []
|
|
276
|
+
while True:
|
|
277
|
+
line = click.prompt(" ", default="", show_default=False)
|
|
278
|
+
if line == "" and lines and lines[-1] == "":
|
|
279
|
+
break
|
|
280
|
+
lines.append(line)
|
|
281
|
+
|
|
282
|
+
text = "\n".join(lines).strip()
|
|
283
|
+
if not text:
|
|
284
|
+
click.echo(click.style(" No text entered. Skipped.", fg="yellow"))
|
|
285
|
+
return
|
|
286
|
+
|
|
287
|
+
from pipeline.processors.text_classifier import text_classifier
|
|
288
|
+
result = text_classifier.classify(text)
|
|
289
|
+
|
|
290
|
+
click.echo()
|
|
291
|
+
click.echo(click.style(f" Classified as: {result.knowledge_type}", fg="green"))
|
|
292
|
+
click.echo(f" Confidence: {result.confidence:.0%}")
|
|
293
|
+
if result.extracted_entities.get("people"):
|
|
294
|
+
click.echo(f" People: {', '.join(result.extracted_entities['people'])}")
|
|
295
|
+
if result.extracted_entities.get("dates"):
|
|
296
|
+
click.echo(f" Dates: {', '.join(result.extracted_entities['dates'])}")
|
|
297
|
+
|
|
298
|
+
click.echo(click.style(" Knowledge item saved.", fg="green"))
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def _ingest_email(connector_cfg):
|
|
302
|
+
"""Ingest emails via IMAP."""
|
|
303
|
+
if not connector_cfg:
|
|
304
|
+
click.echo(click.style(" No email connector configured.", fg="yellow"))
|
|
305
|
+
click.echo(" Run 'neurostack connect email' first.")
|
|
306
|
+
return
|
|
307
|
+
|
|
308
|
+
host = connector_cfg.get("imap_host", "imap.gmail.com")
|
|
309
|
+
email_addr = connector_cfg.get("email")
|
|
310
|
+
password = connector_cfg.get("password")
|
|
311
|
+
|
|
312
|
+
if not email_addr or not password:
|
|
313
|
+
click.echo(click.style(" Email or password missing in config.", fg="red"))
|
|
314
|
+
click.echo(" Run 'neurostack connect email' to reconfigure.")
|
|
315
|
+
return
|
|
316
|
+
|
|
317
|
+
click.echo(f" Connecting to {host}...")
|
|
318
|
+
|
|
319
|
+
import imaplib
|
|
320
|
+
import email as email_lib
|
|
321
|
+
from datetime import datetime, timedelta
|
|
322
|
+
|
|
323
|
+
try:
|
|
324
|
+
mail = imaplib.IMAP4_SSL(host)
|
|
325
|
+
mail.login(email_addr, password)
|
|
326
|
+
click.echo(click.style(" Connected!", fg="green"))
|
|
327
|
+
|
|
328
|
+
mail.select("INBOX")
|
|
329
|
+
since_date = (datetime.now() - timedelta(days=30)).strftime("%d-%b-%Y")
|
|
330
|
+
_, message_numbers = mail.search(None, f'SINCE {since_date}')
|
|
331
|
+
|
|
332
|
+
nums = message_numbers[0].split()
|
|
333
|
+
click.echo(f" Found {len(nums)} emails from last 30 days.")
|
|
334
|
+
|
|
335
|
+
count = 0
|
|
336
|
+
for num in nums[:50]: # Cap at 50
|
|
337
|
+
_, data = mail.fetch(num, "(RFC822)")
|
|
338
|
+
msg = email_lib.message_from_bytes(data[0][1])
|
|
339
|
+
subject = msg.get("Subject", "(no subject)")
|
|
340
|
+
sender = msg.get("From", "")
|
|
341
|
+
|
|
342
|
+
# Extract body
|
|
343
|
+
body = ""
|
|
344
|
+
if msg.is_multipart():
|
|
345
|
+
for part in msg.walk():
|
|
346
|
+
if part.get_content_type() == "text/plain":
|
|
347
|
+
try:
|
|
348
|
+
body = part.get_payload(decode=True).decode("utf-8", errors="ignore")
|
|
349
|
+
except Exception:
|
|
350
|
+
pass
|
|
351
|
+
break
|
|
352
|
+
else:
|
|
353
|
+
try:
|
|
354
|
+
body = msg.get_payload(decode=True).decode("utf-8", errors="ignore")
|
|
355
|
+
except Exception:
|
|
356
|
+
pass
|
|
357
|
+
|
|
358
|
+
if body.strip():
|
|
359
|
+
count += 1
|
|
360
|
+
if count <= 5:
|
|
361
|
+
click.echo(f" [{count}] {subject[:60]}")
|
|
362
|
+
elif count == 6:
|
|
363
|
+
click.echo(" ...")
|
|
364
|
+
|
|
365
|
+
mail.logout()
|
|
366
|
+
click.echo(click.style(f"\n Ingested {count} emails.", fg="green"))
|
|
367
|
+
|
|
368
|
+
except imaplib.IMAP4.error as e:
|
|
369
|
+
click.echo(click.style(f" IMAP login failed: {e}", fg="red"))
|
|
370
|
+
click.echo(" For Gmail, use an App Password: https://myaccount.google.com/apppasswords")
|
|
371
|
+
except Exception as e:
|
|
372
|
+
click.echo(click.style(f" Error: {e}", fg="red"))
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
def _ingest_github(connector_cfg):
|
|
376
|
+
"""Ingest from GitHub repos."""
|
|
377
|
+
if not connector_cfg:
|
|
378
|
+
click.echo(click.style(" No GitHub connector configured.", fg="yellow"))
|
|
379
|
+
click.echo(" Run 'neurostack connect github' first.")
|
|
380
|
+
return
|
|
381
|
+
|
|
382
|
+
token = connector_cfg.get("token")
|
|
383
|
+
repos = connector_cfg.get("repos", "")
|
|
384
|
+
if isinstance(repos, str):
|
|
385
|
+
repos = [r.strip() for r in repos.split(",") if r.strip()]
|
|
386
|
+
|
|
387
|
+
if not token or not repos:
|
|
388
|
+
click.echo(click.style(" GitHub token or repos missing in config.", fg="red"))
|
|
389
|
+
return
|
|
390
|
+
|
|
391
|
+
import httpx
|
|
392
|
+
|
|
393
|
+
headers = {"Authorization": f"Bearer {token}", "Accept": "application/vnd.github.v3+json"}
|
|
394
|
+
total = 0
|
|
395
|
+
|
|
396
|
+
for repo in repos:
|
|
397
|
+
click.echo(f" Fetching from {repo}...")
|
|
398
|
+
|
|
399
|
+
try:
|
|
400
|
+
# Issues
|
|
401
|
+
r = httpx.get(f"https://api.github.com/repos/{repo}/issues?state=all&per_page=30", headers=headers, timeout=15)
|
|
402
|
+
if r.status_code == 200:
|
|
403
|
+
issues = r.json()
|
|
404
|
+
click.echo(f" Issues: {len(issues)}")
|
|
405
|
+
total += len(issues)
|
|
406
|
+
else:
|
|
407
|
+
click.echo(click.style(f" Issues: API error {r.status_code}", fg="yellow"))
|
|
408
|
+
|
|
409
|
+
# PRs
|
|
410
|
+
r = httpx.get(f"https://api.github.com/repos/{repo}/pulls?state=all&per_page=30", headers=headers, timeout=15)
|
|
411
|
+
if r.status_code == 200:
|
|
412
|
+
prs = r.json()
|
|
413
|
+
click.echo(f" Pull Requests: {len(prs)}")
|
|
414
|
+
total += len(prs)
|
|
415
|
+
|
|
416
|
+
# README
|
|
417
|
+
r = httpx.get(f"https://api.github.com/repos/{repo}/readme", headers=headers, timeout=15)
|
|
418
|
+
if r.status_code == 200:
|
|
419
|
+
click.echo(" README: found")
|
|
420
|
+
total += 1
|
|
421
|
+
|
|
422
|
+
except Exception as e:
|
|
423
|
+
click.echo(click.style(f" Error: {e}", fg="red"))
|
|
424
|
+
|
|
425
|
+
click.echo(click.style(f"\n Ingested {total} items from {len(repos)} repos.", fg="green"))
|
|
426
|
+
|
|
197
427
|
|
|
428
|
+
def _ingest_api_connector(connector_type, connector_cfg, full):
|
|
429
|
+
"""Ingest from API-based connectors (Jira, Slack, Notion, etc.)."""
|
|
430
|
+
if not connector_cfg:
|
|
431
|
+
click.echo(click.style(f" No {connector_type} connector configured.", fg="yellow"))
|
|
432
|
+
click.echo(f" Run 'neurostack connect {connector_type}' first.")
|
|
433
|
+
return
|
|
434
|
+
|
|
435
|
+
# Try to use the pipeline connector if available
|
|
436
|
+
try:
|
|
437
|
+
from pipeline.connectors.registry import get_connector
|
|
198
438
|
connector = get_connector(connector_type)
|
|
199
439
|
connector.sync(full=full)
|
|
200
|
-
click.echo(f"
|
|
440
|
+
click.echo(click.style(f" {connector_type} ingestion completed.", fg="green"))
|
|
201
441
|
except ImportError:
|
|
202
|
-
click.echo(f"
|
|
203
|
-
|
|
442
|
+
click.echo(click.style(f" {connector_type} connector requires additional setup.", fg="yellow"))
|
|
443
|
+
click.echo(f" Use the REST API instead: POST /api/ingest/trigger")
|
|
204
444
|
except Exception as e:
|
|
205
|
-
click.echo(f"Ingestion failed: {e}",
|
|
206
|
-
raise SystemExit(1)
|
|
445
|
+
click.echo(click.style(f" Ingestion failed: {e}", fg="red"))
|
|
207
446
|
|
|
208
447
|
|
|
209
448
|
@cli.command()
|
|
@@ -395,7 +634,7 @@ def setup():
|
|
|
395
634
|
config = {}
|
|
396
635
|
|
|
397
636
|
# -- Step 1: LLM Provider ----------------------------------------------
|
|
398
|
-
click.echo(click.style("\n -- Step 1 of
|
|
637
|
+
click.echo(click.style("\n -- Step 1 of 6: Choose Your AI Provider --", fg="white", bold=True))
|
|
399
638
|
click.echo(click.style(" (Pick a provider to power your AI brain)", fg="bright_black"))
|
|
400
639
|
|
|
401
640
|
provider = _numbered_menu("FREE Providers (no cost to start)", [
|
|
@@ -524,12 +763,13 @@ def setup():
|
|
|
524
763
|
"provider": provider,
|
|
525
764
|
"model": model,
|
|
526
765
|
"api_key_env": api_key_env or "",
|
|
766
|
+
"api_key": api_key if provider != "ollama" else "",
|
|
527
767
|
}
|
|
528
768
|
|
|
529
769
|
click.echo(click.style(f"\n Provider: {provider} | Model: {model}", fg="green", bold=True))
|
|
530
770
|
|
|
531
771
|
# -- Step 2: Database --------------------------------------------------
|
|
532
|
-
click.echo(click.style("\n -- Step 2 of
|
|
772
|
+
click.echo(click.style("\n -- Step 2 of 6: Database --", fg="white", bold=True))
|
|
533
773
|
click.echo(click.style(" (Neurostack needs PostgreSQL to store data)", fg="bright_black"))
|
|
534
774
|
|
|
535
775
|
db_choice = _numbered_menu("How to set up PostgreSQL?", [
|
|
@@ -553,7 +793,7 @@ def setup():
|
|
|
553
793
|
config["database"] = {"url": db_url}
|
|
554
794
|
|
|
555
795
|
# -- Step 3: Vector Store ----------------------------------------------
|
|
556
|
-
click.echo(click.style("\n -- Step 3 of
|
|
796
|
+
click.echo(click.style("\n -- Step 3 of 6: Vector Store --", fg="white", bold=True))
|
|
557
797
|
click.echo(click.style(" (Used for semantic search over your documents)", fg="bright_black"))
|
|
558
798
|
|
|
559
799
|
vs_choice = _numbered_menu("How to set up Qdrant vector store?", [
|
|
@@ -583,7 +823,7 @@ def setup():
|
|
|
583
823
|
}
|
|
584
824
|
|
|
585
825
|
# -- Step 4: First Data Source -----------------------------------------
|
|
586
|
-
click.echo(click.style("\n -- Step 4 of
|
|
826
|
+
click.echo(click.style("\n -- Step 4 of 6: Connect Your Data --", fg="white", bold=True))
|
|
587
827
|
click.echo(click.style(" (Choose where to pull knowledge from)", fg="bright_black"))
|
|
588
828
|
|
|
589
829
|
source = _numbered_menu("Connect your first data source (easiest first)", [
|
|
@@ -605,8 +845,67 @@ def setup():
|
|
|
605
845
|
else:
|
|
606
846
|
config["connectors"] = []
|
|
607
847
|
|
|
608
|
-
# -- Step 5:
|
|
609
|
-
click.echo(click.style("\n -- Step 5 of
|
|
848
|
+
# -- Step 5: Deploy as Bot ---------------------------------------------
|
|
849
|
+
click.echo(click.style("\n -- Step 5 of 6: Deploy as Bot --", fg="white", bold=True))
|
|
850
|
+
click.echo(click.style(" Note: Bots run only while this terminal is open.", fg="yellow"))
|
|
851
|
+
click.echo(click.style(" For 24/7 uptime, deploy to a server later.", fg="yellow"))
|
|
852
|
+
click.echo()
|
|
853
|
+
|
|
854
|
+
deploy = _numbered_menu("Where should the brain be accessible?", [
|
|
855
|
+
{"label": "Terminal only", "value": "terminal", "hint": "Ask questions right here -- simplest option"},
|
|
856
|
+
{"label": "Telegram bot", "value": "telegram", "hint": "30-second setup via @BotFather"},
|
|
857
|
+
{"label": "Slack bot", "value": "slack", "hint": "Needs Slack app (5 min setup)"},
|
|
858
|
+
{"label": "REST API", "value": "api", "hint": "For developers -- runs FastAPI server"},
|
|
859
|
+
{"label": "Skip for now", "value": "skip", "hint": "Set up a bot later with 'neurostack start'"},
|
|
860
|
+
], default=1, allow_back=True)
|
|
861
|
+
|
|
862
|
+
if deploy == "__back__":
|
|
863
|
+
deploy = "skip"
|
|
864
|
+
|
|
865
|
+
config["bot"] = {"type": deploy if deploy != "skip" else None}
|
|
866
|
+
|
|
867
|
+
if deploy == "telegram":
|
|
868
|
+
click.echo(click.style("\n Telegram setup (30 seconds):", fg="white", bold=True))
|
|
869
|
+
click.echo(" 1. Open Telegram and search for @BotFather")
|
|
870
|
+
click.echo(" 2. Send /newbot")
|
|
871
|
+
click.echo(" 3. Choose a name and username for your bot")
|
|
872
|
+
click.echo(" 4. Copy the token BotFather gives you")
|
|
873
|
+
click.echo()
|
|
874
|
+
token = _prompt_with_skip("Telegram Bot Token")
|
|
875
|
+
if token:
|
|
876
|
+
config["bot"]["telegram_token"] = token
|
|
877
|
+
click.echo(click.style(" Telegram bot configured!", fg="green"))
|
|
878
|
+
else:
|
|
879
|
+
click.echo(click.style(" Skipped. Run 'neurostack start telegram' later.", fg="bright_black"))
|
|
880
|
+
config["bot"]["type"] = None
|
|
881
|
+
|
|
882
|
+
elif deploy == "slack":
|
|
883
|
+
click.echo(click.style("\n Slack setup:", fg="white", bold=True))
|
|
884
|
+
click.echo(" 1. Go to: https://api.slack.com/apps")
|
|
885
|
+
click.echo(" 2. Create New App > From scratch")
|
|
886
|
+
click.echo(" 3. Add scopes: channels:history, channels:read, users:read, chat:write")
|
|
887
|
+
click.echo(" 4. Install to workspace")
|
|
888
|
+
click.echo(" 5. Copy Bot User OAuth Token (xoxb-...)")
|
|
889
|
+
click.echo()
|
|
890
|
+
token = _prompt_with_skip("Slack Bot Token (xoxb-...)", hide_input=True)
|
|
891
|
+
if token:
|
|
892
|
+
config["bot"]["slack_token"] = token
|
|
893
|
+
click.echo(click.style(" Slack bot configured!", fg="green"))
|
|
894
|
+
else:
|
|
895
|
+
click.echo(click.style(" Skipped. Run 'neurostack start slack' later.", fg="bright_black"))
|
|
896
|
+
config["bot"]["type"] = None
|
|
897
|
+
|
|
898
|
+
elif deploy == "api":
|
|
899
|
+
config["bot"]["port"] = 8000
|
|
900
|
+
click.echo(click.style(" API server will run on port 8000.", fg="green"))
|
|
901
|
+
click.echo(" Start with: neurostack start api")
|
|
902
|
+
|
|
903
|
+
elif deploy == "terminal":
|
|
904
|
+
click.echo(click.style(" Terminal mode ready.", fg="green"))
|
|
905
|
+
click.echo(" Start with: neurostack ask")
|
|
906
|
+
|
|
907
|
+
# -- Step 6: Save config & summary -------------------------------------
|
|
908
|
+
click.echo(click.style("\n -- Step 6 of 6: Save & Finish --", fg="white", bold=True))
|
|
610
909
|
|
|
611
910
|
config["sync"] = {
|
|
612
911
|
"default_interval_minutes": 60,
|
|
@@ -694,8 +993,36 @@ def ask(question: str):
|
|
|
694
993
|
click.echo()
|
|
695
994
|
|
|
696
995
|
|
|
996
|
+
def _load_api_keys_from_config():
|
|
997
|
+
"""Load API keys from neurostack.yaml and set as env vars if not already set."""
|
|
998
|
+
try:
|
|
999
|
+
cfg = _load_partial_config()
|
|
1000
|
+
llm_cfg = cfg.get("llm", {})
|
|
1001
|
+
bot_cfg = cfg.get("bot", {})
|
|
1002
|
+
|
|
1003
|
+
# LLM API key
|
|
1004
|
+
key_env = llm_cfg.get("api_key_env", "")
|
|
1005
|
+
if key_env and not os.environ.get(key_env):
|
|
1006
|
+
# Check if key was saved directly in config (from setup wizard)
|
|
1007
|
+
direct_key = llm_cfg.get("api_key", "")
|
|
1008
|
+
if direct_key:
|
|
1009
|
+
os.environ[key_env] = direct_key
|
|
1010
|
+
|
|
1011
|
+
# Bot tokens
|
|
1012
|
+
if bot_cfg.get("telegram_token") and not os.environ.get("TELEGRAM_BOT_TOKEN"):
|
|
1013
|
+
os.environ["TELEGRAM_BOT_TOKEN"] = bot_cfg["telegram_token"]
|
|
1014
|
+
if bot_cfg.get("slack_token") and not os.environ.get("SLACK_BOT_TOKEN"):
|
|
1015
|
+
os.environ["SLACK_BOT_TOKEN"] = bot_cfg["slack_token"]
|
|
1016
|
+
|
|
1017
|
+
except Exception:
|
|
1018
|
+
pass # Config might not exist yet
|
|
1019
|
+
|
|
1020
|
+
|
|
697
1021
|
def _init_brain_or_none():
|
|
698
1022
|
"""Try to initialise the Brain; return None on failure."""
|
|
1023
|
+
# First, load API keys from config into env
|
|
1024
|
+
_load_api_keys_from_config()
|
|
1025
|
+
|
|
699
1026
|
try:
|
|
700
1027
|
from pipeline.config.loader import load_config
|
|
701
1028
|
|
|
@@ -1046,10 +1373,14 @@ def start(target: str):
|
|
|
1046
1373
|
|
|
1047
1374
|
def _start_slack_bot(brain):
|
|
1048
1375
|
"""Start the Slack bot."""
|
|
1376
|
+
_load_api_keys_from_config() # Load tokens from config
|
|
1049
1377
|
token = os.environ.get("SLACK_BOT_TOKEN", "")
|
|
1050
1378
|
if not token:
|
|
1051
|
-
|
|
1052
|
-
|
|
1379
|
+
cfg = _load_partial_config()
|
|
1380
|
+
token = cfg.get("bot", {}).get("slack_token", "")
|
|
1381
|
+
if not token:
|
|
1382
|
+
click.echo(click.style(" Slack bot token not found.", fg="red"))
|
|
1383
|
+
click.echo(" Run 'neurostack setup' or set SLACK_BOT_TOKEN env var.")
|
|
1053
1384
|
return
|
|
1054
1385
|
|
|
1055
1386
|
try:
|
|
@@ -1070,10 +1401,15 @@ def _start_slack_bot(brain):
|
|
|
1070
1401
|
|
|
1071
1402
|
def _start_telegram_bot(brain):
|
|
1072
1403
|
"""Start the Telegram bot."""
|
|
1404
|
+
_load_api_keys_from_config() # Load tokens from config
|
|
1073
1405
|
token = os.environ.get("TELEGRAM_BOT_TOKEN", "")
|
|
1074
1406
|
if not token:
|
|
1075
|
-
|
|
1076
|
-
|
|
1407
|
+
# Also check config directly
|
|
1408
|
+
cfg = _load_partial_config()
|
|
1409
|
+
token = cfg.get("bot", {}).get("telegram_token", "")
|
|
1410
|
+
if not token:
|
|
1411
|
+
click.echo(click.style(" Telegram bot token not found.", fg="red"))
|
|
1412
|
+
click.echo(" Run 'neurostack setup' or set TELEGRAM_BOT_TOKEN env var.")
|
|
1077
1413
|
return
|
|
1078
1414
|
|
|
1079
1415
|
try:
|
|
@@ -1083,11 +1419,14 @@ def _start_telegram_bot(brain):
|
|
|
1083
1419
|
click.echo(click.style(" Message your bot on Telegram to ask questions.", fg="bright_black"))
|
|
1084
1420
|
click.echo(click.style(" Press Ctrl+C to stop.\n", fg="bright_black"))
|
|
1085
1421
|
|
|
1086
|
-
bot = TelegramBot(token=token,
|
|
1087
|
-
bot.
|
|
1088
|
-
except ImportError:
|
|
1089
|
-
|
|
1090
|
-
|
|
1422
|
+
bot = TelegramBot(token=token, brain_process_fn=brain.process)
|
|
1423
|
+
bot.run()
|
|
1424
|
+
except ImportError as e:
|
|
1425
|
+
if "telegram" in str(e).lower() or "python-telegram-bot" in str(e):
|
|
1426
|
+
click.echo(click.style(" Telegram SDK not installed.", fg="red"))
|
|
1427
|
+
click.echo(" Install with: pip install 'python-telegram-bot>=21.0'")
|
|
1428
|
+
else:
|
|
1429
|
+
click.echo(click.style(f" Import error: {e}", fg="red"))
|
|
1091
1430
|
except Exception as e:
|
|
1092
1431
|
click.echo(click.style(f" Telegram bot error: {e}", fg="red"))
|
|
1093
1432
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/brain/prompts/reasoning/decision_recall.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/neurostack/integrations/slack/formatters.py
RENAMED
|
File without changes
|
{neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/neurostack/integrations/telegram/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/neurostack/integrations/telegram/formatters.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/neurostack_org.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/connectors/google_workspace/__init__.py
RENAMED
|
File without changes
|
{neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/connectors/google_workspace/auth.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/connectors/jira/permission_mapper.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/connectors/slack/deduplication.py
RENAMED
|
File without changes
|
{neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/connectors/slack/permission_mapper.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/processing/chunking/document_chunker.py
RENAMED
|
File without changes
|
{neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/processing/chunking/semantic_chunker.py
RENAMED
|
File without changes
|
{neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/processing/chunking/structured_chunker.py
RENAMED
|
File without changes
|
{neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/processing/embeddings/__init__.py
RENAMED
|
File without changes
|
{neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/processing/embeddings/embedding_client.py
RENAMED
|
File without changes
|
{neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/processing/embeddings/mock_embeddings.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/storage/semantic/pinecone_store.py
RENAMED
|
File without changes
|
|
File without changes
|
{neurostack_org-2.2.0 → neurostack_org-2.2.2}/src/pipeline/storage/semantic/weaviate_store.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|