neurostack-org 2.2.3__tar.gz → 2.3.0__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.
Files changed (170) hide show
  1. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/PKG-INFO +1 -1
  2. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/pyproject.toml +1 -1
  3. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/neurostack/integrations/telegram/bot.py +1 -1
  4. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/neurostack_org.egg-info/PKG-INFO +1 -1
  5. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/cli/main.py +68 -9
  6. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/README.md +0 -0
  7. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/setup.cfg +0 -0
  8. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/__init__.py +0 -0
  9. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/config/__init__.py +0 -0
  10. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/config/brain_config.py +0 -0
  11. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/config/confidence_config.py +0 -0
  12. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/config/persona_config.py +0 -0
  13. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/config/retrieval_config.py +0 -0
  14. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/core/__init__.py +0 -0
  15. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/core/input_validator.py +0 -0
  16. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/core/intent_classifier.py +0 -0
  17. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/core/knowledge_retriever.py +0 -0
  18. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/core/orchestrator.py +0 -0
  19. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/core/reasoning_engine.py +0 -0
  20. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/core/response_formatter.py +0 -0
  21. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/factory.py +0 -0
  22. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/interfaces/__init__.py +0 -0
  23. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/interfaces/embedding.py +0 -0
  24. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/interfaces/llm.py +0 -0
  25. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/interfaces/vector_store.py +0 -0
  26. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/logging/__init__.py +0 -0
  27. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/logging/formatters.py +0 -0
  28. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/logging/logger.py +0 -0
  29. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/logging/trace.py +0 -0
  30. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/models/__init__.py +0 -0
  31. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/models/confidence.py +0 -0
  32. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/models/intent.py +0 -0
  33. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/models/persona.py +0 -0
  34. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/models/request.py +0 -0
  35. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/models/response.py +0 -0
  36. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/models/retrieval.py +0 -0
  37. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/prompts/__init__.py +0 -0
  38. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/prompts/base.py +0 -0
  39. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/prompts/intent_classifier.py +0 -0
  40. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/prompts/reasoning/__init__.py +0 -0
  41. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/prompts/reasoning/action.py +0 -0
  42. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/prompts/reasoning/decision_recall.py +0 -0
  43. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/prompts/reasoning/informational.py +0 -0
  44. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/prompts/reasoning/metrics.py +0 -0
  45. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/prompts/reasoning/planning.py +0 -0
  46. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/prompts/reasoning/status.py +0 -0
  47. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/prompts/reasoning/summary.py +0 -0
  48. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/utils/__init__.py +0 -0
  49. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/utils/confidence.py +0 -0
  50. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/utils/ranking.py +0 -0
  51. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/utils/time.py +0 -0
  52. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/utils/validation.py +0 -0
  53. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/brain/utils/visibility.py +0 -0
  54. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/clients/__init__.py +0 -0
  55. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/clients/anthropic_client.py +0 -0
  56. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/clients/anthropic_llm.py +0 -0
  57. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/clients/azure_openai_llm.py +0 -0
  58. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/clients/example_vector_client.py +0 -0
  59. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/clients/mock_embedding.py +0 -0
  60. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/clients/mock_vector_store.py +0 -0
  61. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/clients/openai_compatible_llm.py +0 -0
  62. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/clients/openai_embedding.py +0 -0
  63. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/clients/retry.py +0 -0
  64. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/neurostack/integrations/__init__.py +0 -0
  65. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/neurostack/integrations/base.py +0 -0
  66. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/neurostack/integrations/slack/__init__.py +0 -0
  67. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/neurostack/integrations/slack/bot.py +0 -0
  68. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/neurostack/integrations/slack/commands.py +0 -0
  69. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/neurostack/integrations/slack/formatters.py +0 -0
  70. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/neurostack/integrations/telegram/__init__.py +0 -0
  71. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/neurostack/integrations/telegram/formatters.py +0 -0
  72. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/neurostack/license.py +0 -0
  73. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/neurostack/logging.py +0 -0
  74. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/neurostack/models/__init__.py +0 -0
  75. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/neurostack/models/context.py +0 -0
  76. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/neurostack/models/knowledge.py +0 -0
  77. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/neurostack/models/permission.py +0 -0
  78. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/neurostack_org.egg-info/SOURCES.txt +0 -0
  79. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/neurostack_org.egg-info/dependency_links.txt +0 -0
  80. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/neurostack_org.egg-info/entry_points.txt +0 -0
  81. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/neurostack_org.egg-info/requires.txt +0 -0
  82. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/neurostack_org.egg-info/top_level.txt +0 -0
  83. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/__init__.py +0 -0
  84. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/audit/__init__.py +0 -0
  85. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/audit/lineage.py +0 -0
  86. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/audit/logger.py +0 -0
  87. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/audit/metrics.py +0 -0
  88. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/auth/__init__.py +0 -0
  89. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/auth/oauth_manager.py +0 -0
  90. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/auth/permission_sync.py +0 -0
  91. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/auth/token_store.py +0 -0
  92. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/cli/__init__.py +0 -0
  93. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/cli/connector_manage.py +0 -0
  94. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/cli/ingest.py +0 -0
  95. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/cli/status.py +0 -0
  96. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/config/__init__.py +0 -0
  97. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/config/loader.py +0 -0
  98. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/config/pipeline_config.py +0 -0
  99. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/config/storage_config.py +0 -0
  100. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/connectors/__init__.py +0 -0
  101. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/connectors/base.py +0 -0
  102. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/connectors/csv/__init__.py +0 -0
  103. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/connectors/csv/connector.py +0 -0
  104. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/connectors/google_workspace/__init__.py +0 -0
  105. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/connectors/google_workspace/auth.py +0 -0
  106. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/connectors/google_workspace/calendar_connector.py +0 -0
  107. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/connectors/google_workspace/docs_connector.py +0 -0
  108. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/connectors/google_workspace/drive_connector.py +0 -0
  109. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/connectors/google_workspace/permission_mapper.py +0 -0
  110. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/connectors/jira/__init__.py +0 -0
  111. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/connectors/jira/auth.py +0 -0
  112. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/connectors/jira/config.py +0 -0
  113. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/connectors/jira/connector.py +0 -0
  114. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/connectors/jira/permission_mapper.py +0 -0
  115. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/connectors/registry.py +0 -0
  116. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/connectors/slack/__init__.py +0 -0
  117. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/connectors/slack/auth.py +0 -0
  118. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/connectors/slack/connector.py +0 -0
  119. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/connectors/slack/deduplication.py +0 -0
  120. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/connectors/slack/permission_mapper.py +0 -0
  121. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/core/__init__.py +0 -0
  122. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/core/chunker.py +0 -0
  123. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/core/ingestion_engine.py +0 -0
  124. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/core/live_data_handler.py +0 -0
  125. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/core/orchestrator.py +0 -0
  126. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/core/permission_engine.py +0 -0
  127. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/ingest/__init__.py +0 -0
  128. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/ingest/universal.py +0 -0
  129. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/models/__init__.py +0 -0
  130. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/models/connector_config.py +0 -0
  131. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/models/ingestion_job.py +0 -0
  132. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/models/storage.py +0 -0
  133. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/processing/__init__.py +0 -0
  134. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/processing/chunking/__init__.py +0 -0
  135. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/processing/chunking/document_chunker.py +0 -0
  136. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/processing/chunking/semantic_chunker.py +0 -0
  137. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/processing/chunking/structured_chunker.py +0 -0
  138. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/processing/embeddings/__init__.py +0 -0
  139. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/processing/embeddings/embedding_client.py +0 -0
  140. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/processing/embeddings/mock_embeddings.py +0 -0
  141. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/processing/embeddings/openai_embeddings.py +0 -0
  142. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/processing/normalizer.py +0 -0
  143. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/processing/versioning.py +0 -0
  144. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/processors/__init__.py +0 -0
  145. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/processors/audio_processor.py +0 -0
  146. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/processors/file_processor.py +0 -0
  147. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/processors/text_classifier.py +0 -0
  148. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/scheduling/__init__.py +0 -0
  149. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/scheduling/checkpoint.py +0 -0
  150. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/scheduling/job_queue.py +0 -0
  151. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/scheduling/rate_limiter.py +0 -0
  152. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/scheduling/scheduler.py +0 -0
  153. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/storage/__init__.py +0 -0
  154. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/storage/graph/__init__.py +0 -0
  155. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/storage/graph/neo4j_store.py +0 -0
  156. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/storage/interfaces.py +0 -0
  157. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/storage/metadata/__init__.py +0 -0
  158. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/storage/metadata/postgres.py +0 -0
  159. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/storage/migrations/env.py +0 -0
  160. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/storage/migrations/versions/f2816fb07a30_initial_schema.py +0 -0
  161. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/storage/semantic/__init__.py +0 -0
  162. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/storage/semantic/mock_store.py +0 -0
  163. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/storage/semantic/pinecone_store.py +0 -0
  164. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/storage/semantic/qdrant_store.py +0 -0
  165. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/storage/semantic/weaviate_store.py +0 -0
  166. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/utils/__init__.py +0 -0
  167. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/utils/deduplication.py +0 -0
  168. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/utils/exceptions.py +0 -0
  169. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/src/pipeline/utils/retry.py +0 -0
  170. {neurostack_org-2.2.3 → neurostack_org-2.3.0}/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
3
+ Version: 2.3.0
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.3"
7
+ version = "2.3.0"
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"}
@@ -102,7 +102,7 @@ class TelegramBot:
102
102
  "conversation_history": [],
103
103
  "live_context": {},
104
104
  "options": {
105
- "mode": "answer",
105
+ "mode": "sync",
106
106
  "max_retrieval_depth": None,
107
107
  "require_sources": True,
108
108
  },
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: neurostack-org
3
- Version: 2.2.3
3
+ Version: 2.3.0
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.3"
9
+ VERSION = "2.3.0"
10
10
 
11
11
  CONFIG_FILE = "neurostack.yaml"
12
12
 
@@ -1493,8 +1493,7 @@ def connect(source: str):
1493
1493
  neurostack connect github
1494
1494
  neurostack connect # interactive picker
1495
1495
  """
1496
- # Sorted by ease of setup — easiest first
1497
- sources = [
1496
+ all_sources = [
1498
1497
  {"label": "CSV / Excel", "value": "csv", "hint": "Just drop a file -- no setup needed"},
1499
1498
  {"label": "Manual text entry", "value": "manual", "hint": "Paste text directly -- no setup needed"},
1500
1499
  {"label": "Email (IMAP)", "value": "email", "hint": "Just email + app password"},
@@ -1510,18 +1509,76 @@ def connect(source: str):
1510
1509
  {"label": "Microsoft Teams", "value": "teams", "hint": "Needs Azure AD app registration"},
1511
1510
  ]
1512
1511
 
1513
- if not source:
1514
- source = _numbered_menu("Choose a data source (easiest first)", sources, default=1, allow_back=True)
1512
+ # If source was passed directly, just connect that one
1513
+ if source:
1514
+ _connect_single_source(source)
1515
+ return
1516
+
1517
+ # Interactive mode — show existing sources, allow adding multiple
1518
+ while True:
1519
+ cfg = _load_partial_config()
1520
+ existing = cfg.get("connectors", [])
1521
+
1522
+ # Show already connected sources
1523
+ if existing:
1524
+ click.echo(click.style("\n Already connected:", fg="green"))
1525
+ for c in existing:
1526
+ ctype = c.get("type", "?")
1527
+ click.echo(f' {click.style("[OK]", fg="green")} {ctype}')
1528
+ click.echo()
1529
+
1530
+ source = _numbered_menu("Add a data source (easiest first)", all_sources, default=1, allow_back=True)
1531
+
1515
1532
  if source == "__back__":
1516
- click.echo(click.style(" Cancelled.", fg="bright_black"))
1533
+ if existing:
1534
+ click.echo(click.style(f"\n Done! {len(existing)} source(s) connected.", fg="green"))
1535
+ # Offer to ingest
1536
+ if click.confirm("\n Want to ingest data now?", default=True):
1537
+ for c in existing:
1538
+ ctype = c.get("type", "")
1539
+ if ctype and ctype != "manual":
1540
+ click.echo(click.style(f"\n Ingesting {ctype}...", fg="cyan"))
1541
+ click.get_current_context().invoke(ingest, connector_type=ctype)
1542
+ else:
1543
+ click.echo(click.style(" No sources connected. Run 'neurostack connect' anytime.", fg="bright_black"))
1517
1544
  return
1518
1545
 
1546
+ _connect_single_source(source)
1547
+
1548
+ # Ask if they want to add another
1549
+ click.echo()
1550
+ if not click.confirm(" Connect another data source?", default=False):
1551
+ cfg = _load_partial_config()
1552
+ total = len(cfg.get("connectors", []))
1553
+ click.echo(click.style(f"\n Done! {total} source(s) connected.", fg="green"))
1554
+
1555
+ # Offer to ingest
1556
+ if total > 0 and click.confirm(" Want to ingest data now?", default=True):
1557
+ for c in cfg.get("connectors", []):
1558
+ ctype = c.get("type", "")
1559
+ if ctype and ctype != "manual":
1560
+ click.echo(click.style(f"\n Ingesting {ctype}...", fg="cyan"))
1561
+ try:
1562
+ click.get_current_context().invoke(ingest, connector_type=ctype)
1563
+ except Exception as e:
1564
+ click.echo(click.style(f" Ingest error: {e}", fg="yellow"))
1565
+
1566
+ # Show next steps
1567
+ click.echo(click.style("\n Next steps:", fg="cyan"))
1568
+ click.echo(" neurostack start Start the bot")
1569
+ click.echo(" neurostack ask Ask questions in terminal")
1570
+ click.echo(" neurostack connect Add more sources later")
1571
+ return
1572
+
1573
+
1574
+ def _connect_single_source(source):
1575
+ """Connect a single data source and save to config."""
1519
1576
  click.echo(click.style(f"\n Connecting: {source}", fg="cyan", bold=True))
1520
1577
 
1521
1578
  connector_config = _configure_connector(source)
1522
1579
 
1523
1580
  if connector_config is None:
1524
- click.echo(click.style(" Skipped. You can try again with 'neurostack connect'.", fg="bright_black"))
1581
+ click.echo(click.style(" Skipped.", fg="bright_black"))
1525
1582
  return
1526
1583
 
1527
1584
  # Save to config
@@ -1529,11 +1586,13 @@ def connect(source: str):
1529
1586
  cfg = _load_partial_config()
1530
1587
  if "connectors" not in cfg:
1531
1588
  cfg["connectors"] = []
1589
+
1590
+ # Don't add duplicate connector types (replace instead)
1591
+ cfg["connectors"] = [c for c in cfg["connectors"] if c.get("type") != source]
1532
1592
  cfg["connectors"].append(connector_config)
1533
1593
  _save_config(cfg)
1534
1594
 
1535
- click.echo(click.style(f"\n {source} connected and saved!", fg="green"))
1536
- click.echo(f" Run 'neurostack ingest {source}' to start syncing data.")
1595
+ click.echo(click.style(f" {source} connected and saved!", fg="green"))
1537
1596
  except Exception as e:
1538
1597
  click.echo(click.style(f" Error saving config: {e}", fg="red"))
1539
1598
 
File without changes
File without changes