Showing preview only (8,518K chars total). Download the full file or copy to clipboard to get everything.
Repository: Canner/WrenAI
Branch: main
Commit: eea642fde8e2
Files: 778
Total size: 8.0 MB
Directory structure:
gitextract_1iqodypf/
├── .claude/
│ ├── CLAUDE.md
│ └── settings.json
├── .editorconfig
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ └── feature_request.md
│ ├── dependabot.yaml
│ └── workflows/
│ ├── ai-service-release-image.yaml
│ ├── ai-service-release-nightly-image.yaml
│ ├── ai-service-release-stable-image.yaml
│ ├── ai-service-test.yaml
│ ├── create-rc-release-pr.yaml
│ ├── create-rc-release.yaml
│ ├── pr-tagger.yaml
│ ├── pull-request-title-validator.yaml
│ ├── ui-lint.yaml
│ ├── ui-release-image-stable.yaml
│ ├── ui-release-image.yaml
│ ├── ui-test.yaml
│ └── wren-launcher-ci.yaml
├── .gitignore
├── .gitmodules
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── SECURITY.md
├── deployment/
│ ├── README.md
│ └── kustomizations/
│ ├── .gitignore
│ ├── README.md
│ ├── base/
│ │ ├── cm.yaml
│ │ ├── deploy-wren-ai-service.yaml
│ │ ├── deploy-wren-engine.yaml
│ │ ├── deploy-wren-ibis-server.yaml
│ │ ├── deploy-wren-ui.yaml
│ │ ├── pvc.yaml
│ │ └── svc.yaml
│ ├── examples/
│ │ ├── .gitignore
│ │ ├── certificate-qdrant_example.yaml
│ │ ├── certificate-wren_example.yaml
│ │ ├── ingress-wren_example.yaml
│ │ └── secret-wren_example.yaml
│ ├── helm-values-qdrant_1.11.0.yaml
│ ├── helm-values_postgresql_15.yaml
│ ├── kustomization.yaml
│ └── patches/
│ ├── README.md
│ ├── cm.yaml
│ ├── rm-certificate.yaml
│ ├── rm-ingress.yaml
│ └── service.yaml
├── docker/
│ ├── README.md
│ ├── bootstrap/
│ │ ├── Dockerfile
│ │ └── init.sh
│ ├── config.example.yaml
│ ├── docker-compose-dev.yaml
│ └── docker-compose.yaml
├── wren-ai-service/
│ ├── .dockerignore
│ ├── .pre-commit-config.yaml
│ ├── CONTRIBUTING.md
│ ├── Justfile
│ ├── README.md
│ ├── docker/
│ │ └── Dockerfile
│ ├── docs/
│ │ ├── code_design.md
│ │ ├── config_examples/
│ │ │ ├── README.md
│ │ │ ├── config.anthropic.yaml
│ │ │ ├── config.azure.yaml
│ │ │ ├── config.bedrock.yaml
│ │ │ ├── config.deepseek.yaml
│ │ │ ├── config.google_ai_studio.yaml
│ │ │ ├── config.google_vertexai.yaml
│ │ │ ├── config.grok.yaml
│ │ │ ├── config.groq.yaml
│ │ │ ├── config.lm_studio.yaml
│ │ │ ├── config.ollama.yaml
│ │ │ ├── config.open_router.yaml
│ │ │ ├── config.qwen3.yaml
│ │ │ └── config.zhipu.yaml
│ │ └── configuration.md
│ ├── entrypoint.sh
│ ├── eval/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── __init__.py
│ │ ├── add_samples_to_toml.py
│ │ ├── data_curation/
│ │ │ ├── __init__.py
│ │ │ ├── app.py
│ │ │ └── utils.py
│ │ ├── dataset/
│ │ │ └── .gitignore
│ │ ├── dspy_modules/
│ │ │ ├── __init__.py
│ │ │ ├── ask_generation.py
│ │ │ └── prompt_optimizer.py
│ │ ├── evaluation.py
│ │ ├── mdl_to_csv.py
│ │ ├── metrics/
│ │ │ ├── __init__.py
│ │ │ ├── accuracy.py
│ │ │ ├── answer_relevancy.py
│ │ │ ├── context_precision.py
│ │ │ ├── context_recall.py
│ │ │ ├── context_relevancy.py
│ │ │ ├── faithfulness.py
│ │ │ ├── llm/
│ │ │ │ └── __init__.py
│ │ │ └── spider/
│ │ │ ├── __init__.py
│ │ │ ├── exact_match.py
│ │ │ ├── exec_match.py
│ │ │ └── process_sql.py
│ │ ├── optimized/
│ │ │ └── .gitignore
│ │ ├── pipelines.py
│ │ ├── prediction.py
│ │ ├── preparation.py
│ │ └── utils.py
│ ├── pyproject.toml
│ ├── ruff.toml
│ ├── src/
│ │ ├── __init__.py
│ │ ├── __main__.py
│ │ ├── config.py
│ │ ├── core/
│ │ │ ├── __init__.py
│ │ │ ├── engine.py
│ │ │ ├── pipeline.py
│ │ │ └── provider.py
│ │ ├── force_deploy.py
│ │ ├── force_update_config.py
│ │ ├── globals.py
│ │ ├── pipelines/
│ │ │ ├── __init__.py
│ │ │ ├── common.py
│ │ │ ├── generation/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── chart_adjustment.py
│ │ │ │ ├── chart_generation.py
│ │ │ │ ├── data_assistance.py
│ │ │ │ ├── followup_sql_generation.py
│ │ │ │ ├── followup_sql_generation_reasoning.py
│ │ │ │ ├── intent_classification.py
│ │ │ │ ├── misleading_assistance.py
│ │ │ │ ├── question_recommendation.py
│ │ │ │ ├── relationship_recommendation.py
│ │ │ │ ├── semantics_description.py
│ │ │ │ ├── sql_answer.py
│ │ │ │ ├── sql_correction.py
│ │ │ │ ├── sql_diagnosis.py
│ │ │ │ ├── sql_generation.py
│ │ │ │ ├── sql_generation_reasoning.py
│ │ │ │ ├── sql_question.py
│ │ │ │ ├── sql_regeneration.py
│ │ │ │ ├── sql_tables_extraction.py
│ │ │ │ ├── user_guide_assistance.py
│ │ │ │ └── utils/
│ │ │ │ ├── chart.py
│ │ │ │ ├── sql.py
│ │ │ │ └── vega-lite-schema-v5.json
│ │ │ ├── indexing/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── db_schema.py
│ │ │ │ ├── historical_question.py
│ │ │ │ ├── instructions.py
│ │ │ │ ├── project_meta.py
│ │ │ │ ├── sql_pairs.py
│ │ │ │ ├── table_description.py
│ │ │ │ └── utils/
│ │ │ │ └── helper.py
│ │ │ └── retrieval/
│ │ │ ├── __init__.py
│ │ │ ├── db_schema_retrieval.py
│ │ │ ├── historical_question_retrieval.py
│ │ │ ├── instructions.py
│ │ │ ├── preprocess_sql_data.py
│ │ │ ├── sql_executor.py
│ │ │ ├── sql_functions.py
│ │ │ ├── sql_knowledge.py
│ │ │ └── sql_pairs_retrieval.py
│ │ ├── providers/
│ │ │ ├── __init__.py
│ │ │ ├── document_store/
│ │ │ │ ├── __init__.py
│ │ │ │ └── qdrant.py
│ │ │ ├── embedder/
│ │ │ │ ├── __init__.py
│ │ │ │ └── litellm.py
│ │ │ ├── engine/
│ │ │ │ ├── __init__.py
│ │ │ │ └── wren.py
│ │ │ ├── llm/
│ │ │ │ ├── __init__.py
│ │ │ │ └── litellm.py
│ │ │ └── loader.py
│ │ ├── utils.py
│ │ └── web/
│ │ ├── __init__.py
│ │ ├── development.py
│ │ └── v1/
│ │ ├── __init__.py
│ │ ├── routers/
│ │ │ ├── __init__.py
│ │ │ ├── ask.py
│ │ │ ├── ask_feedbacks.py
│ │ │ ├── chart.py
│ │ │ ├── chart_adjustment.py
│ │ │ ├── instructions.py
│ │ │ ├── question_recommendation.py
│ │ │ ├── relationship_recommendation.py
│ │ │ ├── semantics_description.py
│ │ │ ├── semantics_preparation.py
│ │ │ ├── sql_answers.py
│ │ │ ├── sql_corrections.py
│ │ │ ├── sql_pairs.py
│ │ │ └── sql_question.py
│ │ └── services/
│ │ ├── __init__.py
│ │ ├── ask.py
│ │ ├── ask_feedback.py
│ │ ├── chart.py
│ │ ├── chart_adjustment.py
│ │ ├── instructions.py
│ │ ├── question_recommendation.py
│ │ ├── relationship_recommendation.py
│ │ ├── semantics_description.py
│ │ ├── semantics_preparation.py
│ │ ├── sql_answer.py
│ │ ├── sql_corrections.py
│ │ ├── sql_pairs.py
│ │ └── sql_question.py
│ ├── tests/
│ │ ├── __init__.py
│ │ ├── data/
│ │ │ ├── book_2_mdl.json
│ │ │ ├── config.test.yaml
│ │ │ ├── mock_pyproject.toml
│ │ │ └── pairs.json
│ │ ├── locust/
│ │ │ ├── __init__.py
│ │ │ ├── config_users.json
│ │ │ ├── locust.conf
│ │ │ ├── locust_script.py
│ │ │ └── locustfile.py
│ │ └── pytest/
│ │ ├── __init__.py
│ │ ├── eval/
│ │ │ ├── __init__.py
│ │ │ └── test_metrics.py
│ │ ├── pipelines/
│ │ │ ├── __init__.py
│ │ │ ├── generation/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── test_ask.py
│ │ │ │ └── test_semantics_enrichment.py
│ │ │ ├── indexing/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── test_db_schema.py
│ │ │ │ ├── test_helper.py
│ │ │ │ ├── test_historical_questions.py
│ │ │ │ ├── test_indexing.py
│ │ │ │ ├── test_instructions.py
│ │ │ │ ├── test_sql_pairs.py
│ │ │ │ └── test_table_description.py
│ │ │ └── retrieval/
│ │ │ ├── __init__.py
│ │ │ └── sql_function.py
│ │ ├── providers/
│ │ │ ├── __init__.py
│ │ │ ├── test_loader.py
│ │ │ └── test_providers.py
│ │ ├── services/
│ │ │ ├── __init__.py
│ │ │ ├── mocks.py
│ │ │ ├── test_ask.py
│ │ │ ├── test_instructions.py
│ │ │ ├── test_relationship_recommendation.py
│ │ │ ├── test_semantics_description.py
│ │ │ └── test_sql_pairs.py
│ │ ├── test_config.py
│ │ ├── test_main.py
│ │ ├── test_usecases.py
│ │ └── test_utils.py
│ └── tools/
│ ├── .env.example
│ ├── config/
│ │ ├── config.example.yaml
│ │ └── config.full.yaml
│ ├── dev/
│ │ ├── config.properties.example
│ │ └── docker-compose-dev.yaml
│ ├── mdl_to_str.py
│ └── run_sql.py
├── wren-launcher/
│ ├── .golangci.yml
│ ├── Makefile
│ ├── README.md
│ ├── commands/
│ │ ├── dbt/
│ │ │ ├── README.md
│ │ │ ├── converter.go
│ │ │ ├── data_source.go
│ │ │ ├── data_source_test.go
│ │ │ ├── profiles.go
│ │ │ ├── profiles_analyzer.go
│ │ │ ├── utils.go
│ │ │ └── wren_mdl.go
│ │ ├── dbt.go
│ │ └── launch.go
│ ├── config/
│ │ └── config.go
│ ├── go.mod
│ ├── go.sum
│ ├── main.go
│ └── utils/
│ ├── docker.go
│ ├── docker_test.go
│ ├── network.go
│ ├── os.go
│ ├── rc.go
│ └── rc_test.go
├── wren-mdl/
│ └── mdl.schema.json
└── wren-ui/
├── .dockerignore
├── .eslintignore
├── .eslintrc.json
├── .prettierrc
├── .yarn/
│ └── releases/
│ └── yarn-4.5.3.cjs
├── .yarnrc.yml
├── Dockerfile
├── README.md
├── codegen.yaml
├── e2e/
│ ├── README.md
│ ├── commonTests/
│ │ ├── home.ts
│ │ ├── modeling.ts
│ │ └── onboarding.ts
│ ├── config.ts
│ ├── global.setup.ts
│ ├── global.teardown.ts
│ ├── helper.ts
│ └── specs/
│ ├── connectBigQuery.spec.ts
│ ├── connectClickHouse.spec.ts
│ ├── connectDuckDB.spec.ts
│ ├── connectMySQL.spec.ts
│ ├── connectPostgreSQL.spec.ts
│ ├── connectSQLServer.spec.ts
│ ├── connectSampleECommerce.spec.ts
│ ├── connectSampleHR.spec.ts
│ ├── connectSnowflake.spec.ts
│ └── connectTrino.spec.ts
├── jest.config.js
├── knexfile.js
├── migrations/
│ ├── 20240125070643_create_project_table.js
│ ├── 20240125071855_create_model_table.js
│ ├── 20240125081244_create_model_column_table.js
│ ├── 20240125083821_create_relation_table.js
│ ├── 20240125085655_create_metrics_table.js
│ ├── 20240126100753_create_metrics_measure_table.js
│ ├── 20240129021453_create_view_table.js
│ ├── 20240319083758_create_deploy_table.js
│ ├── 20240327030000_create_ask_table.js
│ ├── 20240418000000_update_project_table_pg.js
│ ├── 20240419090558_add_foreign_key_to_model_column_and_metric_measure.js
│ ├── 20240425000000_add_thread_response_summary.js
│ ├── 20240430033014_update_model_column_table.js
│ ├── 20240446090560_update_relationship_table.js
│ ├── 20240502000000_add_properties_to_relationship.js
│ ├── 20240524044348_update_project_table.js
│ ├── 20240524071859_update_thread_table.js
│ ├── 20240530062133_update_project_table.js
│ ├── 20240530062809_transfer_project_table_data.js
│ ├── 20240530105955_drop_project_table_columns.js
│ ├── 20240531085916_transfer_model_properties.js
│ ├── 20240610070534_create_schema_change_table.js
│ ├── 20240928165009_create_model_nested_column.js
│ ├── 20241021073019_update_project_language.js
│ ├── 20241029092204_create_learning_table.js
│ ├── 20241106232204_update_project_table.js
│ ├── 20241107171828_update_thread_table.js
│ ├── 20241115031024_drop_thread_response_table_column.js
│ ├── 20241207000000_update_thread_response_for_answer.js
│ ├── 20241210072534_update_thread_response_table.js
│ ├── 20241226135712_remove_thread_sql.js
│ ├── 20250102074255_create_dashboard_table.js
│ ├── 20250102074256_create_dashboard_item_table.js
│ ├── 20250102074256_create_sql_pair_table.js
│ ├── 20250311046282_create_instruction_table.js
│ ├── 20250320074256_alter_sql_pair_table.js
│ ├── 20250422000000_alter_dashboard_table.js
│ ├── 20250423000000_create_dashboard_cache_refresh_table.js
│ ├── 20250509000000_create_asking_task.js
│ ├── 20250509000001_add_task_id_to_thread.js
│ ├── 20250510000000_add_adjustment_to_thread_response.js
│ ├── 20250510000001_alter_dashboard_item_table.js
│ ├── 20250510000002_add_version_to_project.js
│ └── 20250511000000-create-api-history.js
├── next.config.js
├── openapi.yaml
├── package.json
├── playwright.config.ts
├── src/
│ ├── apollo/
│ │ ├── client/
│ │ │ ├── graphql/
│ │ │ │ ├── __types__.ts
│ │ │ │ ├── apiManagement.generated.ts
│ │ │ │ ├── apiManagement.ts
│ │ │ │ ├── calculatedField.generated.ts
│ │ │ │ ├── calculatedField.ts
│ │ │ │ ├── dashboard.generated.ts
│ │ │ │ ├── dashboard.ts
│ │ │ │ ├── dataSource.generated.ts
│ │ │ │ ├── dataSource.ts
│ │ │ │ ├── deploy.generated.ts
│ │ │ │ ├── deploy.ts
│ │ │ │ ├── diagram.generated.ts
│ │ │ │ ├── diagram.ts
│ │ │ │ ├── home.generated.ts
│ │ │ │ ├── home.ts
│ │ │ │ ├── instructions.generated.ts
│ │ │ │ ├── instructions.ts
│ │ │ │ ├── learning.generated.ts
│ │ │ │ ├── learning.ts
│ │ │ │ ├── metadata.generated.ts
│ │ │ │ ├── metadata.ts
│ │ │ │ ├── model.generated.ts
│ │ │ │ ├── model.ts
│ │ │ │ ├── onboarding.generated.ts
│ │ │ │ ├── onboarding.ts
│ │ │ │ ├── relationship.generated.ts
│ │ │ │ ├── relationship.ts
│ │ │ │ ├── settings.generated.ts
│ │ │ │ ├── settings.ts
│ │ │ │ ├── sql.generated.ts
│ │ │ │ ├── sql.ts
│ │ │ │ ├── sqlPairs.generated.ts
│ │ │ │ ├── sqlPairs.ts
│ │ │ │ ├── view.generated.ts
│ │ │ │ └── view.ts
│ │ │ └── index.ts
│ │ └── server/
│ │ ├── adaptors/
│ │ │ ├── ibisAdaptor.ts
│ │ │ ├── index.ts
│ │ │ ├── tests/
│ │ │ │ ├── ibisAdaptor.test.ts
│ │ │ │ └── wrenAIAdaptor.test.ts
│ │ │ ├── wrenAIAdaptor.ts
│ │ │ └── wrenEngineAdaptor.ts
│ │ ├── backgrounds/
│ │ │ ├── adjustmentBackgroundTracker.ts
│ │ │ ├── chart.ts
│ │ │ ├── dashboardCacheBackgroundTracker.ts
│ │ │ ├── index.ts
│ │ │ ├── recommend-question.ts
│ │ │ └── textBasedAnswerBackgroundTracker.ts
│ │ ├── config.ts
│ │ ├── data/
│ │ │ ├── index.ts
│ │ │ ├── sample.ts
│ │ │ └── type.ts
│ │ ├── dataSource.ts
│ │ ├── index.ts
│ │ ├── managers/
│ │ │ └── dataSourceSchemaDetector.ts
│ │ ├── mdl/
│ │ │ ├── mdlBuilder.ts
│ │ │ ├── test/
│ │ │ │ └── mdlBuilder.test.ts
│ │ │ └── type.ts
│ │ ├── models/
│ │ │ ├── adaptor.ts
│ │ │ ├── dashboard.ts
│ │ │ ├── index.ts
│ │ │ ├── instruction.ts
│ │ │ └── model.ts
│ │ ├── repositories/
│ │ │ ├── apiHistoryRepository.ts
│ │ │ ├── askingTaskRepository.ts
│ │ │ ├── baseRepository.ts
│ │ │ ├── dashboardItemRefreshJobRepository.ts
│ │ │ ├── dashboardItemRepository.ts
│ │ │ ├── dashboardRepository.ts
│ │ │ ├── deployLogRepository.ts
│ │ │ ├── index.ts
│ │ │ ├── instructionRepository.ts
│ │ │ ├── learningRepository.ts
│ │ │ ├── metricsMeasureRepository.ts
│ │ │ ├── metricsRepository.ts
│ │ │ ├── modelColumnRepository.ts
│ │ │ ├── modelNestedColumnRepository.ts
│ │ │ ├── modelRepository.ts
│ │ │ ├── projectRepository.ts
│ │ │ ├── relationshipRepository.ts
│ │ │ ├── schemaChangeRepository.ts
│ │ │ ├── sqlPairRepository.ts
│ │ │ ├── threadRepository.ts
│ │ │ ├── threadResponseRepository.ts
│ │ │ └── viewRepository.ts
│ │ ├── resolvers/
│ │ │ ├── apiHistoryResolver.ts
│ │ │ ├── askingResolver.ts
│ │ │ ├── dashboardResolver.ts
│ │ │ ├── diagramResolver.ts
│ │ │ ├── instructionResolver.ts
│ │ │ ├── learningResolver.ts
│ │ │ ├── modelResolver.ts
│ │ │ ├── projectResolver.ts
│ │ │ └── sqlPairResolver.ts
│ │ ├── resolvers.ts
│ │ ├── scalars.ts
│ │ ├── schema.ts
│ │ ├── services/
│ │ │ ├── askingService.ts
│ │ │ ├── askingTaskTracker.ts
│ │ │ ├── dashboardService.ts
│ │ │ ├── deployService.ts
│ │ │ ├── index.ts
│ │ │ ├── instructionService.ts
│ │ │ ├── mdlService.ts
│ │ │ ├── metadataService.ts
│ │ │ ├── modelService.ts
│ │ │ ├── projectService.ts
│ │ │ ├── queryService.ts
│ │ │ ├── sqlPairService.ts
│ │ │ └── tests/
│ │ │ ├── askingService.test.ts
│ │ │ ├── dashboardService.test.ts
│ │ │ ├── deployService.test.ts
│ │ │ └── queryService.test.ts
│ │ ├── telemetry/
│ │ │ └── telemetry.ts
│ │ ├── types/
│ │ │ ├── context.ts
│ │ │ ├── dataSource.ts
│ │ │ ├── diagram.ts
│ │ │ ├── index.ts
│ │ │ ├── manifest.ts
│ │ │ ├── metric.ts
│ │ │ └── relationship.ts
│ │ └── utils/
│ │ ├── apiUtils.ts
│ │ ├── dataUtils.ts
│ │ ├── docker.ts
│ │ ├── encode.ts
│ │ ├── encryptor.ts
│ │ ├── error.ts
│ │ ├── helper.ts
│ │ ├── index.ts
│ │ ├── knex.ts
│ │ ├── logger.ts
│ │ ├── model.ts
│ │ ├── regex.ts
│ │ ├── sqlFormat.ts
│ │ ├── sseTypes.ts
│ │ ├── sseUtils.ts
│ │ ├── string.ts
│ │ ├── tests/
│ │ │ ├── dataSource.test.ts
│ │ │ ├── encryptor.test.ts
│ │ │ └── regex.test.ts
│ │ └── timezone.ts
│ ├── common.ts
│ ├── components/
│ │ ├── ActionButton.tsx
│ │ ├── EditableWrapper.tsx
│ │ ├── EllipsisWrapper.tsx
│ │ ├── ErrorCollapse.tsx
│ │ ├── HeaderBar.tsx
│ │ ├── Logo.tsx
│ │ ├── LogoBar.tsx
│ │ ├── PageLoading.tsx
│ │ ├── chart/
│ │ │ ├── handler.ts
│ │ │ ├── index.tsx
│ │ │ └── properties/
│ │ │ ├── BasicProperties.tsx
│ │ │ ├── DonutProperties.tsx
│ │ │ ├── GroupedBarProperties.tsx
│ │ │ ├── LineProperties.tsx
│ │ │ └── StackedBarProperties.tsx
│ │ ├── code/
│ │ │ ├── BaseCodeBlock.tsx
│ │ │ ├── JsonCodeBlock.tsx
│ │ │ └── SQLCodeBlock.tsx
│ │ ├── dataPreview/
│ │ │ ├── PreviewData.tsx
│ │ │ └── PreviewDataContent.tsx
│ │ ├── deploy/
│ │ │ ├── Context.ts
│ │ │ └── Deploy.tsx
│ │ ├── diagram/
│ │ │ ├── Context.ts
│ │ │ ├── CustomDropdown.tsx
│ │ │ ├── CustomPopover.tsx
│ │ │ ├── Marker.tsx
│ │ │ ├── customEdge/
│ │ │ │ ├── ModelEdge.tsx
│ │ │ │ └── index.ts
│ │ │ ├── customNode/
│ │ │ │ ├── Column.tsx
│ │ │ │ ├── MarkerHandle.tsx
│ │ │ │ ├── ModelNode.tsx
│ │ │ │ ├── ViewNode.tsx
│ │ │ │ ├── index.ts
│ │ │ │ └── utils.tsx
│ │ │ ├── index.tsx
│ │ │ └── utils.ts
│ │ ├── editor/
│ │ │ ├── AceEditor.tsx
│ │ │ ├── MarkdownBlock.tsx
│ │ │ ├── MarkdownEditor.tsx
│ │ │ └── SQLEditor.tsx
│ │ ├── layouts/
│ │ │ ├── PageLayout.tsx
│ │ │ ├── SiderLayout.tsx
│ │ │ └── SimpleLayout.tsx
│ │ ├── learning/
│ │ │ ├── guide/
│ │ │ │ ├── index.tsx
│ │ │ │ ├── stories.tsx
│ │ │ │ └── utils.ts
│ │ │ └── index.tsx
│ │ ├── modals/
│ │ │ ├── AdjustReasoningStepsModal.tsx
│ │ │ ├── AdjustSQLModal.tsx
│ │ │ ├── CalculatedFieldModal.tsx
│ │ │ ├── DeleteModal.tsx
│ │ │ ├── FixSQLModal.tsx
│ │ │ ├── ImportDataSourceSQLModal.tsx
│ │ │ ├── InstructionModal.tsx
│ │ │ ├── QuestionSQLPairModal.tsx
│ │ │ ├── RelationModal.tsx
│ │ │ ├── SaveAsViewModal.tsx
│ │ │ └── SchemaChangeModal.tsx
│ │ ├── pages/
│ │ │ ├── apiManagement/
│ │ │ │ └── DetailsDrawer.tsx
│ │ │ ├── home/
│ │ │ │ ├── RecommendedQuestions.tsx
│ │ │ │ ├── dashboardGrid/
│ │ │ │ │ ├── CacheSettingsDrawer.tsx
│ │ │ │ │ ├── DashboardHeader.tsx
│ │ │ │ │ ├── EmptyDashboard.tsx
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── preparation/
│ │ │ │ │ ├── ErrorBoundary.tsx
│ │ │ │ │ ├── PreparationStatus.tsx
│ │ │ │ │ ├── PreparationSteps.tsx
│ │ │ │ │ ├── index.tsx
│ │ │ │ │ └── step/
│ │ │ │ │ ├── FixedSQLFinished.tsx
│ │ │ │ │ ├── Generating.tsx
│ │ │ │ │ ├── Organizing.tsx
│ │ │ │ │ ├── Retrieving.tsx
│ │ │ │ │ ├── SQLPairFinished.tsx
│ │ │ │ │ └── ViewFinished.tsx
│ │ │ │ ├── prompt/
│ │ │ │ │ ├── DemoPrompt.tsx
│ │ │ │ │ ├── Input.tsx
│ │ │ │ │ ├── RecommendedQuestionsPrompt.tsx
│ │ │ │ │ ├── Result.tsx
│ │ │ │ │ └── index.tsx
│ │ │ │ └── promptThread/
│ │ │ │ ├── AnswerResult.tsx
│ │ │ │ ├── ChartAnswer.tsx
│ │ │ │ ├── TextBasedAnswer.tsx
│ │ │ │ ├── ViewBlock.tsx
│ │ │ │ ├── ViewSQLTabContent.tsx
│ │ │ │ ├── index.tsx
│ │ │ │ └── store.tsx
│ │ │ ├── knowledge/
│ │ │ │ ├── GlobalLabel.tsx
│ │ │ │ ├── InstructionDrawer.tsx
│ │ │ │ └── SQLPairDrawer.tsx
│ │ │ ├── modeling/
│ │ │ │ ├── EditMetadataModal.tsx
│ │ │ │ ├── MetadataDrawer.tsx
│ │ │ │ ├── ModelDrawer.tsx
│ │ │ │ ├── form/
│ │ │ │ │ └── ModelForm.tsx
│ │ │ │ └── metadata/
│ │ │ │ ├── EditBasicMetadata.tsx
│ │ │ │ ├── EditModelMetadata.tsx
│ │ │ │ ├── EditViewMetadata.tsx
│ │ │ │ ├── ModelMetadata.tsx
│ │ │ │ └── ViewMetadata.tsx
│ │ │ └── setup/
│ │ │ ├── ButtonItem.tsx
│ │ │ ├── ConnectDataSource.tsx
│ │ │ ├── ContainerCard.tsx
│ │ │ ├── DefineRelations.tsx
│ │ │ ├── SelectModels.tsx
│ │ │ ├── Starter.tsx
│ │ │ ├── dataSources/
│ │ │ │ ├── AthenaProperties.tsx
│ │ │ │ ├── BigQueryProperties.tsx
│ │ │ │ ├── ClickHouseProperties.tsx
│ │ │ │ ├── DatabricksProperties.tsx
│ │ │ │ ├── DuckDBProperties.tsx
│ │ │ │ ├── MySQLProperties.tsx
│ │ │ │ ├── OracleProperties.tsx
│ │ │ │ ├── PostgreSQLProperties.tsx
│ │ │ │ ├── RedshiftProperties.tsx
│ │ │ │ ├── SQLServerProperties.tsx
│ │ │ │ ├── SnowflakeProperties.tsx
│ │ │ │ └── TrinoProperties.tsx
│ │ │ └── utils.tsx
│ │ ├── selectors/
│ │ │ ├── CombineFieldSelector.tsx
│ │ │ ├── DescriptiveSelector.tsx
│ │ │ ├── Selector.tsx
│ │ │ └── lineageSelector/
│ │ │ ├── FieldSelect.tsx
│ │ │ └── index.tsx
│ │ ├── settings/
│ │ │ ├── DataSourceSettings.tsx
│ │ │ ├── ProjectSettings.tsx
│ │ │ ├── index.tsx
│ │ │ └── utils.tsx
│ │ ├── sidebar/
│ │ │ ├── APIManagement.tsx
│ │ │ ├── Home.tsx
│ │ │ ├── Knowledge.tsx
│ │ │ ├── LabelTitle.tsx
│ │ │ ├── Modeling.tsx
│ │ │ ├── SidebarMenu.tsx
│ │ │ ├── SidebarTree.tsx
│ │ │ ├── home/
│ │ │ │ ├── ThreadTree.tsx
│ │ │ │ ├── TreeTitle.tsx
│ │ │ │ └── TreeTitleInput.tsx
│ │ │ ├── index.tsx
│ │ │ ├── modeling/
│ │ │ │ ├── GroupTreeTitle.tsx
│ │ │ │ ├── ModelTree.tsx
│ │ │ │ └── ViewTree.tsx
│ │ │ └── utils.tsx
│ │ └── table/
│ │ ├── BaseTable.tsx
│ │ ├── CalculatedFieldTable.tsx
│ │ ├── EditableBaseTable.tsx
│ │ ├── FieldTable.tsx
│ │ ├── ModelRelationSelectionTable.tsx
│ │ ├── MultiSelectBox.tsx
│ │ ├── NestedFieldTable.tsx
│ │ ├── RelationTable.tsx
│ │ ├── SelectionTable.tsx
│ │ └── TableTransfer.tsx
│ ├── hooks/
│ │ ├── .gitkeep
│ │ ├── useAdjustAnswer.tsx
│ │ ├── useAskProcessState.tsx
│ │ ├── useAskPrompt.tsx
│ │ ├── useAskingStreamTask.tsx
│ │ ├── useAutoComplete.tsx
│ │ ├── useCheckOnboarding.tsx
│ │ ├── useCombineFieldOptions.tsx
│ │ ├── useDrawerAction.tsx
│ │ ├── useDropdown.tsx
│ │ ├── useExpressionFieldOptions.tsx
│ │ ├── useGlobalConfig.tsx
│ │ ├── useHomeSidebar.tsx
│ │ ├── useModalAction.tsx
│ │ ├── useNativeSQL.tsx
│ │ ├── useRecommendedQuestionsInstruction.tsx
│ │ ├── useRelationshipModal.tsx
│ │ ├── useSetupConnection.tsx
│ │ ├── useSetupConnectionDataSource.tsx
│ │ ├── useSetupConnectionSampleDataset.tsx
│ │ ├── useSetupModels.tsx
│ │ ├── useSetupRelations.tsx
│ │ ├── useStoreContext.tsx
│ │ └── useTextBasedAnswerStreamTask.tsx
│ ├── import/
│ │ ├── antd.ts
│ │ └── icon.ts
│ ├── pages/
│ │ ├── _app.tsx
│ │ ├── _document.tsx
│ │ ├── api/
│ │ │ ├── ask_task/
│ │ │ │ ├── streaming.ts
│ │ │ │ └── streaming_answer.ts
│ │ │ ├── config.ts
│ │ │ ├── graphql.ts
│ │ │ └── v1/
│ │ │ ├── ask.ts
│ │ │ ├── generate_sql.ts
│ │ │ ├── generate_summary.ts
│ │ │ ├── generate_vega_chart.ts
│ │ │ ├── knowledge/
│ │ │ │ ├── instructions/
│ │ │ │ │ ├── [id].ts
│ │ │ │ │ └── index.ts
│ │ │ │ └── sql_pairs/
│ │ │ │ ├── [id].ts
│ │ │ │ └── index.ts
│ │ │ ├── models.ts
│ │ │ ├── run_sql.ts
│ │ │ ├── stream/
│ │ │ │ ├── ask.ts
│ │ │ │ └── generate_sql.ts
│ │ │ └── stream_explanation.ts
│ │ ├── api-management/
│ │ │ └── history.tsx
│ │ ├── home/
│ │ │ ├── [id].tsx
│ │ │ ├── dashboard.tsx
│ │ │ └── index.tsx
│ │ ├── index.tsx
│ │ ├── knowledge/
│ │ │ ├── instructions.tsx
│ │ │ └── question-sql-pairs.tsx
│ │ ├── modeling.tsx
│ │ └── setup/
│ │ ├── connection.tsx
│ │ ├── models.tsx
│ │ └── relationships.tsx
│ ├── styles/
│ │ ├── antd-variables.less
│ │ ├── components/
│ │ │ ├── alert.less
│ │ │ ├── avatar.less
│ │ │ ├── button.less
│ │ │ ├── chart.less
│ │ │ ├── driver.less
│ │ │ ├── scrollbar.less
│ │ │ ├── select.less
│ │ │ ├── table.less
│ │ │ ├── tag.less
│ │ │ └── transfer.less
│ │ ├── index.less
│ │ ├── layouts/
│ │ │ ├── global.less
│ │ │ └── main.less
│ │ └── utilities/
│ │ ├── animation.less
│ │ ├── border.less
│ │ ├── color.less
│ │ ├── display.less
│ │ ├── flex.less
│ │ ├── grid.less
│ │ ├── spacing.less
│ │ └── text.less
│ └── utils/
│ ├── columnType.tsx
│ ├── data/
│ │ ├── dictionary.ts
│ │ ├── index.ts
│ │ └── type/
│ │ ├── index.ts
│ │ └── modeling.ts
│ ├── dataSourceType.ts
│ ├── diagram/
│ │ ├── creator.ts
│ │ ├── index.ts
│ │ └── transformer.ts
│ ├── enum/
│ │ ├── columnType.ts
│ │ ├── dataSources.ts
│ │ ├── diagram.ts
│ │ ├── dropdown.ts
│ │ ├── form.ts
│ │ ├── home.ts
│ │ ├── index.ts
│ │ ├── menu.ts
│ │ ├── modeling.ts
│ │ ├── path.ts
│ │ ├── settings.ts
│ │ └── setup.ts
│ ├── env.ts
│ ├── error/
│ │ ├── dictionary.ts
│ │ └── index.ts
│ ├── errorHandler.tsx
│ ├── events.tsx
│ ├── expressionType.ts
│ ├── file.ts
│ ├── helper.ts
│ ├── icons.ts
│ ├── iteration.tsx
│ ├── language.ts
│ ├── modelingHelper.ts
│ ├── nodeType.tsx
│ ├── svgs/
│ │ ├── BrainSVG.tsx
│ │ ├── CopilotSVG.tsx
│ │ ├── EditSVG.tsx
│ │ ├── InstructionsSVG.tsx
│ │ ├── RobotSVG.tsx
│ │ └── index.ts
│ ├── table.tsx
│ ├── telemetry.ts
│ ├── time.ts
│ ├── validator/
│ │ ├── calculatedFieldValidator.ts
│ │ ├── cronValidator.ts
│ │ ├── hostValidator.ts
│ │ ├── index.ts
│ │ ├── relationshipValidator.ts
│ │ ├── sqlPairValidator.ts
│ │ └── viewValidator.ts
│ ├── vegaSpecUtils.test.ts
│ └── vegaSpecUtils.ts
├── tools/
│ └── knex.js
└── tsconfig.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .claude/CLAUDE.md
================================================
# CLAUDE.md
WrenAI is an open-source GenBI (Generative BI) agent that converts natural language questions into SQL queries and charts. It uses a semantic layer (MDL - Metadata Definition Language) to guide LLM-powered text-to-SQL generation via retrieval-augmented generation (RAG).
## Repository Structure
This is a monorepo with three main services:
- **wren-ui/** — Next.js 14 frontend + Apollo GraphQL backend (TypeScript, Yarn 4.5.3)
- **wren-ai-service/** — AI/LLM service (Python 3.12, FastAPI, Poetry, Just command runner)
- **wren-launcher/** — CLI deployment tool (Go 1.18+, Make)
- **docker/** — Docker Compose configs for running all services together
- **deployment/** — Kubernetes/Kustomize manifests
- **wren-engine/** — SQL engine (git submodule, not developed here)
- **wren-mdl/** — MDL JSON schema definitions
## Build, Test, and Lint Commands
### wren-ui (TypeScript/Next.js)
```bash
cd wren-ui
yarn install
yarn dev # Dev server on port 3000 (TZ=UTC)
yarn build # Production build (max-old-space-size=8192)
yarn lint # TypeScript type check + ESLint
yarn check-types # tsc --noEmit
yarn test # Jest unit tests
yarn test:e2e # Playwright E2E tests (installs chromium)
yarn migrate # Knex database migrations
yarn rollback # Knex migration rollback
yarn generate-gql # GraphQL codegen from codegen.yaml
```
Environment: set `DB_TYPE=sqlite` (default) or `DB_TYPE=pg` with PostgreSQL connection vars. The UI needs `WREN_ENGINE_ENDPOINT`, `WREN_AI_ENDPOINT`, and `IBIS_SERVER_ENDPOINT` to connect to backend services.
### wren-ai-service (Python/FastAPI)
```bash
cd wren-ai-service
poetry install
just init # Creates config.yaml and .env.dev from examples
just up # Start dev Docker services (Qdrant, engine, etc.)
just start # Run AI service (poetry run python -m src.__main__)
just test # pytest (spins up Docker deps, ignores usecases)
just test [test_args] # e.g., just test tests/pytest/pipelines/
just test-usecases # Run use-case integration tests
just down # Stop Docker services
just load-test # Locust load tests
```
Configuration is via `config.yaml` (multi-document YAML with sections for LLM, embedder, engine, document_store, pipeline, and settings). Environment variables in `.env.dev` (API keys). Settings load order: defaults → env vars → .env.dev → config.yaml.
Pre-commit hooks: `poetry run pre-commit install` then `poetry run pre-commit run --all-files`
### wren-launcher (Go)
```bash
cd wren-launcher
make build # Cross-compile for macOS/Linux/Windows
make test # go test ./...
make check # fmt + vet + lint (golangci-lint)
make lint-fix # Auto-fix lint issues
```
## Architecture
### Service Communication Flow
```
User → Wren UI (Next.js :3000)
↓ GraphQL (Apollo Server embedded in Next.js API routes)
Apollo Server → Wren AI Service (FastAPI :5556) [HTTP REST]
→ Wren Engine (:8080) [SQL validation/execution]
→ Ibis Server (:8000) [SQL abstraction for data sources]
Wren AI Service → Qdrant (:6333) [vector search for RAG]
→ LLM Provider (OpenAI/Azure/etc.) [text-to-SQL generation]
```
### Wren UI Internal Architecture
The Next.js app embeds an Apollo GraphQL server in its API routes (`src/apollo/`):
- **`src/apollo/server/resolvers/`** — GraphQL resolvers (asking, model, project, dashboard, etc.)
- **`src/apollo/server/services/`** — Business logic layer (askingService, deployService, mdlService, queryService, etc.)
- **`src/apollo/server/repositories/`** — Data access layer using Knex (SQLite or PostgreSQL)
- **`src/apollo/server/adaptors/`** — External service adapters (AI service, engine)
- **`src/apollo/client/`** — Frontend GraphQL operations
- **`src/components/`** — React components organized by page (home, setup, modeling, knowledge)
- **`src/pages/`** — Next.js page routes
Path aliases: `@/*` → `./src/*`, `@server/*` → `./src/apollo/server/*`
### Wren AI Service Internal Architecture
The Python service uses a pipeline-based architecture:
- **`src/pipelines/`** — RAG pipeline implementations:
- `indexing/` — MDL schema, table descriptions, historical questions, SQL pairs → Qdrant
- `retrieval/` — Semantic search for relevant context from Qdrant
- `generation/` — SQL generation, chart generation, intent classification
- `ask/` — Orchestrates retrieval + generation for text-to-SQL
- `ask_details/` — SQL breakdown and explanation
- `semantics/` — Semantic processing helpers
- **`src/web/v1/services/`** — Service layer (AskService, SemanticsPreparationService, ChartService, SqlPairsService, etc.)
- **`src/web/v1/routers/`** — FastAPI route handlers
- **`src/core/`** — Base abstractions (pipeline, provider, engine interfaces)
- **`src/globals.py`** — ServiceContainer wiring all services and pipelines together
- **`src/config.py`** — Pydantic Settings with all configuration knobs
Pipelines are configured declaratively in `config.yaml`, wiring LLM providers, embedders, document stores, and engines to named pipeline components.
### Data Flow for "Ask" (Text-to-SQL)
1. User submits natural language question in UI
2. UI sends GraphQL mutation to Apollo Server
3. Apollo Server calls AI Service REST API
4. AI Service runs intent classification → retrieves relevant schema/context from Qdrant → generates SQL via LLM
5. Generated SQL is validated against Wren Engine
6. SQL corrections are attempted if validation fails (up to `max_sql_correction_retries`)
7. Results returned through the chain back to UI
### MDL (Metadata Definition Language)
The semantic layer that maps business concepts to database schema. Defines models, columns, relationships, metrics, and calculated fields. MDL is indexed into Qdrant as vector embeddings to provide context for LLM SQL generation. Schema defined in `wren-mdl/mdl.schema.json`.
## Docker Development
To run the full stack locally:
```bash
cd docker
cp .env.example .env.local # Configure API keys and ports
cp config.example.yaml config.yaml
docker compose --env-file .env.local up -d
```
For developing a single service while others run in Docker, use `docker-compose-dev.yaml` in the AI service's `tools/dev/` directory.
## Commit Convention
Follows conventional commits: `type(scope): description`
- Scopes: `wren-ui`, `wren-ai-service`, `wren-launcher`
- Types: `feat`, `fix`, `chore`, `refactor`
- Examples: `feat(wren-ui): add dashboard widget`, `fix(wren-ai-service): handle empty MDL`
## CI/CD
- PR labels trigger service-specific CI: `ci/ui` for UI tests/lint, `ci/ai-service` for AI service tests
- Docker images published to `ghcr.io/canner/`
================================================
FILE: .claude/settings.json
================================================
{
"permissions": {
"allow": [
"Bash(cd wren-ui && yarn:*)",
"Bash(cd wren-ai-service && just:*)",
"Bash(cd wren-ai-service && poetry run:*)",
"Bash(cd wren-ai-service && poetry install:*)",
"Bash(cd wren-launcher && make:*)",
"Bash(git status:*)",
"Bash(git diff:*)",
"Bash(git log:*)",
"Bash(git branch:*)",
"Bash(gh pr:*)",
"Bash(gh run:*)",
"Bash(ls:*)",
"Bash(wc:*)"
]
}
}
================================================
FILE: .editorconfig
================================================
# Editor configuration, see http://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
max_line_length = off
trim_trailing_whitespace = false
# Makefile
[Makefile]
indent_style = tab
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
**Wren AI Information**
- Version: [e.g, 0.1.0]
**Additional context**
Add any other context about the problem here.
**Relevant log output**
- Please share `config.yaml` with us, it should be located at `~/.wrenai/config.yaml`.
- Please share your logs with us with the following command:
```bash
docker logs wrenai-wren-ui-1 >& wrenai-wren-ui.log && \
docker logs wrenai-wren-ai-service-1 >& wrenai-wren-ai-service.log && \
docker logs wrenai-wren-engine-1 >& wrenai-wren-engine.log && \
docker logs wrenai-ibis-server-1 >& wrenai-ibis-server.log
```
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: feature-request
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
================================================
FILE: .github/dependabot.yaml
================================================
version: 2
updates:
- package-ecosystem: "pip"
directory: "/wren-ai-service"
schedule:
interval: "weekly"
groups:
all:
patterns: ["*"]
commit-message:
prefix: "chore(wren-ai-service)"
labels:
- "dependencies"
- "python"
- "ci/ai-service"
- "module/ai-service"
================================================
FILE: .github/workflows/ai-service-release-image.yaml
================================================
name: AI Service Release image
on:
workflow_dispatch:
inputs:
tag_name:
description: Docker image tag name (Optional)
type: string
env:
WREN_AI_SERVICE_IMAGE: ghcr.io/canner/wren-ai-service
defaults:
run:
working-directory: wren-ai-service
jobs:
build-image:
outputs:
tag_name: ${{ steps.tag-preparation.outputs.TAG_NAME }}
strategy:
fail-fast: false
matrix:
arch:
- runner: ubuntu-latest
platform: linux/amd64
- runner: linux_arm64_runner
platform: linux/arm64
runs-on: ${{ matrix.arch.runner }}
steps:
- uses: actions/checkout@v4
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Prepare tag name
id: tag-preparation
run: |
if [ -n "${{ github.event.inputs.tag_name }}" ]; then
tag_name=${{ github.event.inputs.tag_name }}
else
tag_name=commit-$(git log -1 --pretty=%h)
fi
echo "TAG_NAME=$tag_name" >> $GITHUB_OUTPUT
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Prepare platform
run: |
platform=${{ matrix.arch.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
with:
platforms: ${{ matrix.arch.platform }}
labels: ${{ env.WREN_AI_SERVICE_IMAGE }}
context: ./wren-ai-service
file: ./wren-ai-service/docker/Dockerfile
outputs: type=image,name=${{ env.WREN_AI_SERVICE_IMAGE }},push-by-digest=true,name-canonical=true,push=true
- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-${{ env.PLATFORM_PAIR }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
merge:
runs-on: ubuntu-latest
needs: [ build-image ]
steps:
- name: Download digests
uses: actions/download-artifact@v4
with:
path: /tmp/digests
pattern: digests-*
merge-multiple: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.WREN_AI_SERVICE_IMAGE }}
tags: |
${{ needs.build-image.outputs.tag_name }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create manifest list and push
working-directory: /tmp/digests
run: |
TAGS=$(echo "${{ steps.meta.outputs.tags }}" | awk '{printf "--tag %s ", $0}')
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ env.WREN_AI_SERVICE_IMAGE }}@sha256:%s ' *) \
$TAGS
================================================
FILE: .github/workflows/ai-service-release-nightly-image.yaml
================================================
name: AI Service Release nightly image
on:
push:
branches: [main]
paths:
- 'wren-ai-service/**'
env:
WREN_AI_SERVICE_IMAGE: ghcr.io/canner/wren-ai-service
defaults:
run:
working-directory: wren-ai-service
jobs:
build-image:
outputs:
tag_name: ${{ steps.tag-preparation.outputs.TAG_NAME }}
strategy:
fail-fast: false
matrix:
arch:
- runner: ubuntu-latest
platform: linux/amd64
- runner: linux_arm64_runner
platform: linux/arm64
runs-on: ${{ matrix.arch.runner }}
steps:
- uses: actions/checkout@v4
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Prepare tag name
id: tag-preparation
run: |
tag_name=main-$(git log -1 --pretty=%h)
echo "TAG_NAME=$tag_name" >> $GITHUB_OUTPUT
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Prepare platform
run: |
platform=${{ matrix.arch.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
with:
platforms: ${{ matrix.arch.platform }}
labels: ${{ env.WREN_AI_SERVICE_IMAGE }}
context: ./wren-ai-service
file: ./wren-ai-service/docker/Dockerfile
outputs: type=image,name=${{ env.WREN_AI_SERVICE_IMAGE }},push-by-digest=true,name-canonical=true,push=true
- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-${{ env.PLATFORM_PAIR }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
merge:
runs-on: ubuntu-latest
needs: [ build-image ]
steps:
- name: Download digests
uses: actions/download-artifact@v4
with:
path: /tmp/digests
pattern: digests-*
merge-multiple: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.WREN_AI_SERVICE_IMAGE }}
tags: |
type=raw,${{ needs.build-image.outputs.tag_name }}
type=raw,nightly
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create manifest list and push
working-directory: /tmp/digests
run: |
TAGS=$(echo "${{ steps.meta.outputs.tags }}" | awk '{printf "--tag %s ", $0}')
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ env.WREN_AI_SERVICE_IMAGE }}@sha256:%s ' *) \
$TAGS
================================================
FILE: .github/workflows/ai-service-release-stable-image.yaml
================================================
name: AI Service Release stable image
on:
workflow_dispatch:
inputs:
version:
description: Give a version for this release
type: string
required: true
env:
WREN_AI_SERVICE_IMAGE: ghcr.io/canner/wren-ai-service
defaults:
run:
working-directory: wren-ai-service
jobs:
upgrade-ai-service-version:
runs-on: ubuntu-latest
steps:
- name: Generate a token
id: generate-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ vars.CI_APP_ID }}
private-key: ${{ secrets.CI_APP_PRIVATE_KEY }}
- uses: actions/checkout@v4
with:
token: ${{ steps.generate-token.outputs.token }}
fetch-depth: 0
- name: Set up Git
run: |
git config --global user.name "wren-ai[bot]"
git config --global user.email "dev@cannerdata.com"
- name: Set up Python 3.12.0
uses: actions/setup-python@v4
with:
python-version: 3.12.0
- name: Install Poetry
uses: abatilo/actions-poetry@v2
with:
poetry-version: 1.8.3
- name: Generate and Save Change Log
id: changelog
run: |
echo "Generating change log..."
PREVIOUS_VERSION=release/ai-service/$(poetry version -s)
echo "Previous version: $PREVIOUS_VERSION"
# Get the change log from the previous version to the current HEAD
# If there is no change log, the command will return an error, so we use || true to ignore the error
CHANGE_LOG=$(git log --pretty=format:"%s" $PREVIOUS_VERSION..HEAD | grep wren-ai-service || true)
# Separate the change log into categories
FEATURES=$(echo "$CHANGE_LOG" | grep "^feat" | sed 's/^/- /')
FIXES_AND_CHORES=$(echo "$CHANGE_LOG" | grep -E "^(fix|chore)" | sed 's/^/- /')
# Create the full change log
FULL_CHANGE_LOG="\nChangelog for the version\n"
if [ -n "$FEATURES" ]; then
FULL_CHANGE_LOG+="\nFeature and Enhancement\n$FEATURES"
fi
if [ -n "$FIXES_AND_CHORES" ]; then
FULL_CHANGE_LOG+="\n\nFixes and Chores\n$FIXES_AND_CHORES"
fi
{
echo "CHANGE_LOG<<EOF"
echo -e "$FULL_CHANGE_LOG"
echo EOF
} >> $GITHUB_ENV
- name: Upgrade AI Service version
run: |
version=${{ github.event.inputs.version }}
poetry version --next-phase $version
git add pyproject.toml
git commit -m "Upgrade AI Service version to $version"
git push
git tag -a "release/ai-service/$version" -m "${{ env.CHANGE_LOG }}"
git push origin "release/ai-service/$version"
build-image:
needs: upgrade-ai-service-version
strategy:
fail-fast: false
matrix:
arch:
- runner: ubuntu-latest
platform: linux/amd64
- runner: linux_arm64_runner
platform: linux/arm64
runs-on: ${{ matrix.arch.runner }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.ref }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Prepare platform
run: |
platform=${{ matrix.arch.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
with:
platforms: ${{ matrix.arch.platform }}
labels: ${{ env.WREN_AI_SERVICE_IMAGE }}
context: ./wren-ai-service
file: ./wren-ai-service/docker/Dockerfile
outputs: type=image,name=${{ env.WREN_AI_SERVICE_IMAGE }},push-by-digest=true,name-canonical=true,push=true
- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-${{ env.PLATFORM_PAIR }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
merge:
runs-on: ubuntu-latest
needs: [ build-image ]
steps:
- name: Download digests
uses: actions/download-artifact@v4
with:
path: /tmp/digests
pattern: digests-*
merge-multiple: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.WREN_AI_SERVICE_IMAGE }}
tags: |
type=raw,${{ github.event.inputs.version }}
type=raw,latest
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create manifest list and push
working-directory: /tmp/digests
run: |
TAGS=$(echo "${{ steps.meta.outputs.tags }}" | awk '{printf "--tag %s ", $0}')
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ env.WREN_AI_SERVICE_IMAGE }}@sha256:%s ' *) \
$TAGS
================================================
FILE: .github/workflows/ai-service-test.yaml
================================================
# This workflow will install Python dependencies, run tests and lint with a single version of Python
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
name: AI Service Test
on:
push:
branches:
- main
paths:
- "wren-ai-service/**"
pull_request:
types: [synchronize, labeled]
workflow_dispatch:
permissions:
contents: read
concurrency:
# avoid mis-canceling the ci runs while other labels are added to the PR, so we add the label name as the condition
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.event.label.name == 'ci/ai-service' && github.event.number || github.sha }}
cancel-in-progress: true
defaults:
run:
working-directory: wren-ai-service
jobs:
pytest:
if: ${{ contains(github.event.pull_request.labels.*.name, 'ci/ai-service') || github.event_name == 'push' }}
runs-on: ubuntu-22.04
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- name: Install Poetry
uses: abatilo/actions-poetry@v3
with:
poetry-version: "1.8.3"
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version-file: ./wren-ai-service/pyproject.toml
cache: "poetry"
- name: Install the project dependencies
run: poetry install --without eval
- name: Install Just
uses: extractions/setup-just@v2
with:
just-version: "1.36.0"
- name: Initialize the config
run: |
just init --non-dev
- name: Prepare testing environment and Run tests
run: |
just test
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
================================================
FILE: .github/workflows/create-rc-release-pr.yaml
================================================
name: Create RC Release PR
on:
workflow_dispatch:
inputs:
release_version:
description: "Release version (e.g., 0.23.0-rc.1)"
required: true
ui_version:
description: "UI version (e.g., 0.22.0)"
required: true
ai_version:
description: "AI service version (e.g., 0.17.0)"
required: true
engine_version:
description: "Engine version (e.g., 0.14.7)"
required: true
permissions:
contents: write
pull-requests: write
jobs:
create-release-pr:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Setup Git Identity
run: |
git config --global user.name "wren-ai[bot]"
git config --global user.email "dev@cannerdata.com"
- name: Update docker.go
run: |
FILE_PATH="wren-launcher/utils/docker.go"
# Replace the WREN_PRODUCT_VERSION value with the new release version
sed -i "s/WREN_PRODUCT_VERSION\s*string = \"[^\"]*\"/WREN_PRODUCT_VERSION\tstring = \"${{ github.event.inputs.release_version }}\"/" $FILE_PATH
# Verify the changes
grep "WREN_PRODUCT_VERSION" $FILE_PATH
- name: Update .env.example
run: |
FILE_PATH="docker/.env.example"
# Update all versions in the .env.example file
sed -i "s/WREN_PRODUCT_VERSION=.*/WREN_PRODUCT_VERSION=${{ github.event.inputs.release_version }}/" $FILE_PATH
sed -i "s/WREN_ENGINE_VERSION=.*/WREN_ENGINE_VERSION=${{ github.event.inputs.engine_version }}/" $FILE_PATH
sed -i "s/IBIS_SERVER_VERSION=.*/IBIS_SERVER_VERSION=${{ github.event.inputs.engine_version }}/" $FILE_PATH
sed -i "s/WREN_AI_SERVICE_VERSION=.*/WREN_AI_SERVICE_VERSION=${{ github.event.inputs.ai_version }}/" $FILE_PATH
sed -i "s/WREN_UI_VERSION=.*/WREN_UI_VERSION=${{ github.event.inputs.ui_version }}/" $FILE_PATH
# Verify the changes
grep "VERSION" $FILE_PATH
- name: Show git status
run: git status
- name: Show git diff
run: |
echo "===== Git diff for changed files ====="
git diff
- name: Create PR
uses: peter-evans/create-pull-request@v7
with:
base: main
branch: "release/${{ github.event.inputs.release_version }}"
commit-message: "release ${{ github.event.inputs.release_version }}"
title: "Release ${{ github.event.inputs.release_version }}"
body: "Release ${{ github.event.inputs.release_version }}"
draft: false
================================================
FILE: .github/workflows/create-rc-release.yaml
================================================
name: Create RC Release
on:
workflow_dispatch:
inputs:
release_version:
description: "Release version"
required: true
issue_comment:
types: [created]
jobs:
release:
runs-on: macos-latest
if: ${{ github.event_name == 'issue_comment' && contains(github.event.comment.body, '/release-rc') && startsWith(github.event.issue.title, 'Release') }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: main
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: "1.23.0"
- name: Add rocket emoji to comment
run: |
curl -X POST -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-d '{"body": "🚀 Starting the release process!"}' \
"https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.issue.number }}/comments"
- name: Parse release version from PR title
id: parse_release_version
env:
GITHUB_ISSUE_TITLE: ${{ github.event.issue.title }}
run: |
release_version=$(echo "$GITHUB_ISSUE_TITLE" | sed 's/ /\n/g' | tail -n 1)
echo "Release version: $release_version"
echo "release_version=$release_version" >> $GITHUB_OUTPUT
- name: Build for macOS
working-directory: ./wren-launcher
run: |
mkdir -p dist
env GOARCH=amd64 GOOS=darwin CGO_ENABLED=1 go build -o dist/wren-launcher-darwin main.go
cd dist && chmod +x wren-launcher-darwin && tar zcvf wren-launcher-darwin.tar.gz wren-launcher-darwin
- name: Build for macOS(arm64)
working-directory: ./wren-launcher
run: |
mkdir -p dist
env GOARCH=arm64 GOOS=darwin CGO_ENABLED=1 go build -o dist/wren-launcher-darwin-arm64 main.go
cd dist && chmod +x wren-launcher-darwin-arm64 && tar zcvf wren-launcher-darwin-arm64.tar.gz wren-launcher-darwin-arm64
- name: Build for Linux
working-directory: ./wren-launcher
run: |
mkdir -p dist
env GOARCH=amd64 GOOS=linux CGO_ENABLED=0 go build -o dist/wren-launcher-linux main.go
cd dist && chmod +x wren-launcher-linux && tar zcvf wren-launcher-linux.tar.gz wren-launcher-linux
- name: Build for Linux(arm64)
working-directory: ./wren-launcher
run: |
mkdir -p dist
env GOARCH=arm64 GOOS=linux CGO_ENABLED=0 go build -o dist/wren-launcher-linux-arm64 main.go
cd dist && chmod +x wren-launcher-linux-arm64 && tar zcvf wren-launcher-linux-arm64.tar.gz wren-launcher-linux-arm64
- name: Build for Windows
working-directory: ./wren-launcher
run: |
mkdir -p dist
env GOARCH=amd64 GOOS=windows CGO_ENABLED=0 go build -o dist/wren-launcher-windows.exe main.go
cd dist && zip wren-launcher-windows.zip wren-launcher-windows.exe
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
files: |
./wren-launcher/dist/wren-launcher-darwin.tar.gz
./wren-launcher/dist/wren-launcher-linux.tar.gz
./wren-launcher/dist/wren-launcher-windows.zip
./wren-launcher/dist/wren-launcher-darwin-arm64.tar.gz
./wren-launcher/dist/wren-launcher-linux-arm64.tar.gz
tag_name: ${{ steps.parse_release_version.outputs.release_version }}
prerelease: true
generate_release_notes: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Comment with release link
run: |
release_url="https://github.com/${{ github.repository }}/releases/tag/${{ steps.parse_release_version.outputs.release_version }}"
curl -X POST -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-d "{\"body\": \"🚀 A new release has been created! [View Release](${release_url})\"}" \
"https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.issue.number }}/comments"
================================================
FILE: .github/workflows/pr-tagger.yaml
================================================
name: PR Tagger
on:
pull_request:
types: [opened, synchronize, reopened]
paths:
- "wren-ui/src/**"
- "deployment/**"
- "wren-launcher/**"
- "wren-ai-service/**"
- "docker/**"
jobs:
tag-pr:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v46
- name: Tag PR based on changed files and title
uses: actions/github-script@v6
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const changedFiles = '${{ steps.changed-files.outputs.all_changed_files }}'.split(' ');
const labels = new Set();
// Define label colors
const labelColors = {
'wren-ui': 'f29513', // Orange
'launcher': 'f29513', // Orange (same as wren-ui)
'wren-ai-service': 'f29513', // Orange (same as wren-ui)
'deployment': '0075ca', // Blue
'ai-env-changed': 'd73a4a', // Red
'ui-env-changed': 'd73a4a' // Red
};
// Check for files in specific directories
for (const file of changedFiles) {
if (file.startsWith('wren-ui/src/')) {
labels.add('wren-ui');
} else if (file.startsWith('deployment/')) {
labels.add('deployment');
} else if (file.startsWith('wren-launcher/')) {
labels.add('launcher');
} else if (file.startsWith('wren-ai-service/')) {
labels.add('wren-ai-service');
}
if (file.startsWith('docker/') && file.includes('.example')) {
labels.add('ai-env-changed');
}
if (file.startsWith('wren-ui/src/apollo/server/config.ts')) {
labels.add('ui-env-changed');
}
}
// Extract milestone from PR title
const prTitle = context.payload.pull_request.title;
const milestoneMatch = prTitle.match(/\(milestone:\s*([^)]+)\)/i);
if (milestoneMatch && milestoneMatch[1]) {
const milestone = milestoneMatch[1].trim();
if (milestone) {
labels.add(milestone);
console.log(`Found milestone in PR title: ${milestone}`);
}
}
// Append env changed label to PR title
if (labels.has('ai-env-changed')) {
// check if pr title contains "ai-env-changed"
if (!prTitle.includes('ai-env-changed')) {
const newTitle = `${prTitle} (ai-env-changed)`;
await github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
title: newTitle
});
}
}
if (labels.has('ui-env-changed')) {
// check if pr title contains "ui-env-changed"
if (!prTitle.includes('ui-env-changed')) {
const newTitle = `${prTitle} (ui-env-changed)`;
await github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
title: newTitle
});
}
}
if (labels.size > 0) {
// Create or update labels with colors
for (const label of labels) {
try {
// Try to create the label with color
if (labelColors[label]) {
await github.rest.issues.createLabel({
owner: context.repo.owner,
repo: context.repo.repo,
name: label,
color: labelColors[label]
});
}
} catch (error) {
// Label already exists, update its color if needed
if (labelColors[label]) {
try {
await github.rest.issues.updateLabel({
owner: context.repo.owner,
repo: context.repo.repo,
name: label,
color: labelColors[label]
});
} catch (updateError) {
console.log(`Could not update color for label ${label}: ${updateError.message}`);
}
}
}
}
// Add labels to PR
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
labels: Array.from(labels)
});
console.log(`Added labels: ${Array.from(labels).join(', ')}`);
} else {
console.log('No matching directories or milestone found');
}
================================================
FILE: .github/workflows/pull-request-title-validator.yaml
================================================
name: Pull Request Title Validator
on:
pull_request:
paths:
- "wren-ai-service/**"
- ".github/workflows/pull-request-title-validator.yaml"
- ".github/workflows/ai-service-*.yaml"
types: [opened, edited, synchronize]
permissions:
pull-requests: read
jobs:
validator:
name: validate-pull-request-title
runs-on: ubuntu-latest
steps:
- name: validate pull request title
uses: kontrolplane/pull-request-title-validator@v1.3.1
with:
types: "fix,feat,chore"
scopes: "wren-ai-service"
================================================
FILE: .github/workflows/ui-lint.yaml
================================================
# create the github action to run the yarn lint when PR created or pushed to main branch
#
name: Wren-UI Lint
on:
pull_request:
types: [ labeled, synchronize ]
permissions:
contents: read
concurrency:
# avoid mis-canceling the ci runs while other labels are added to the PR, so we add the label name as the condition
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.event.label.name == 'ci/ui' && github.event.number || github.sha }}
cancel-in-progress: true
defaults:
run:
working-directory: wren-ui
jobs:
eslint:
# run this job only if the PR is labeled with "ci/ui"
if: ${{ github.event.label.name == 'ci/ui' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '18'
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v2
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: | # should cache node_modules as well
${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- if: ${{ steps.yarn-cache.outputs.cache-hit != 'true' }}
name: List the state of node modules
continue-on-error: true
run: yarn list
- name: Install Node.js dependencies
run: yarn install
- name: Run lint
run: yarn lint
================================================
FILE: .github/workflows/ui-release-image-stable.yaml
================================================
name: Wren-UI Release stable image
on:
workflow_dispatch:
inputs:
version:
description: Give a version for this release
type: string
required: true
env:
WREN_UI_IMAGE: ghcr.io/canner/wren-ui
defaults:
run:
working-directory: wren-ui
jobs:
build-image:
strategy:
fail-fast: false
matrix:
arch:
- runner: ubuntu-latest
platform: linux/amd64
- runner: linux_arm64_runner
platform: linux/arm64
runs-on: ${{ matrix.arch.runner }}
steps:
- uses: actions/checkout@v4
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Prepare platform
run: |
platform=${{ matrix.arch.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
with:
platforms: ${{ matrix.arch.platform }}
labels: ${{ env.WREN_UI_IMAGE }}
context: ./wren-ui
outputs: type=image,name=${{ env.WREN_UI_IMAGE }},push-by-digest=true,name-canonical=true,push=true
- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-${{ env.PLATFORM_PAIR }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
merge:
runs-on: ubuntu-latest
needs: [build-image]
steps:
- name: Download digests
uses: actions/download-artifact@v4
with:
path: /tmp/digests
pattern: digests-*
merge-multiple: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.WREN_UI_IMAGE }}
tags: |
${{ github.event.inputs.version }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create manifest list and push
working-directory: /tmp/digests
# tag with input version and latest
run: |
TAGS=$(echo "${{ steps.meta.outputs.tags }}" | awk '{printf "--tag %s ", $0}')
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ env.WREN_UI_IMAGE }}@sha256:%s ' *) \
$TAGS
tag-ui-version:
runs-on: ubuntu-latest
needs: [merge]
steps:
- name: Generate a token
id: generate-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ vars.CI_APP_ID }}
private-key: ${{ secrets.CI_APP_PRIVATE_KEY }}
- uses: actions/checkout@v4
with:
token: ${{ steps.generate-token.outputs.token }}
fetch-depth: 0
- name: Set up Git
run: |
git config --global user.name "wren-ai[bot]"
git config --global user.email "dev@cannerdata.com"
- name: Generate and Save Change Log
id: changelog
run: |
echo "Generating change log..."
PREVIOUS_VERSION=release/ui/$(jq -r '.version' package.json)
echo "Previous version: $PREVIOUS_VERSION"
echo "================ change log ================"
CHANGE_LOG=$(git log --pretty=format:"%s" $PREVIOUS_VERSION..HEAD | grep wren-ui)
echo "================ change log ================"
# Separate the change log into categories
FEATURES=$(echo "$CHANGE_LOG" | grep "^feat" | sed 's/^/- /')
FIXES_AND_CHORES=$(echo "$CHANGE_LOG" | grep -E "^(fix|chore)" | sed 's/^/- /')
# Create the full change log
FULL_CHANGE_LOG="\nChangelog for the version\n"
if [ -n "$FEATURES" ]; then
FULL_CHANGE_LOG+="\nFeature and Enhancement\n$FEATURES"
fi
if [ -n "$FIXES_AND_CHORES" ]; then
FULL_CHANGE_LOG+="\n\nFixes and Chores\n$FIXES_AND_CHORES"
fi
{
echo "CHANGE_LOG<<EOF"
echo -e "$FULL_CHANGE_LOG"
echo EOF
} >> $GITHUB_ENV
- name: Update Wren-UI version
run: |
version=${{ github.event.inputs.version }}
sed -i 's/"version": "[^"]*"/"version": "'"$version"'"/' package.json
git add package.json
git commit -m "update wren-ui version to $version"
git push
git tag -a "release/ui/$version" -m "${{ env.CHANGE_LOG }}"
git push origin "release/ui/$version"
================================================
FILE: .github/workflows/ui-release-image.yaml
================================================
name: Wren-UI Release image
on:
workflow_dispatch:
inputs:
docker_image_tag_name:
description: Docker image tag name (optional, default branch name/tag name replaced with hyphens)
type: string
env:
WREN_UI_IMAGE: ghcr.io/canner/wren-ui
defaults:
run:
working-directory: wren-ui
jobs:
build-image:
outputs:
tag_name: ${{ steps.tag-preparation.outputs.TAG_NAME }}
strategy:
fail-fast: false
matrix:
arch:
- runner: ubuntu-latest
platform: linux/amd64
- runner: linux_arm64_runner
platform: linux/arm64
runs-on: ${{ matrix.arch.runner }}
steps:
- uses: actions/checkout@v4
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Prepare tag name
id: tag-preparation
run: |
if [ -n "${{ github.event.inputs.docker_image_tag_name }}" ]; then
tag_name=${{ github.event.inputs.docker_image_tag_name }}
else
tag_name=$(echo ${{ github.ref_name }} | sed 's/[^a-zA-Z0-9]/-/g')-$(git log -1 --pretty=%h)
fi
echo "TAG_NAME=$tag_name" >> $GITHUB_OUTPUT
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Prepare platform
run: |
platform=${{ matrix.arch.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
with:
platforms: ${{ matrix.arch.platform }}
labels: ${{ env.WREN_UI_IMAGE }}
context: ./wren-ui
outputs: type=image,name=${{ env.WREN_UI_IMAGE }},push-by-digest=true,name-canonical=true,push=true
- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-${{ env.PLATFORM_PAIR }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
merge:
runs-on: ubuntu-latest
needs: [ build-image ]
steps:
- name: Download digests
uses: actions/download-artifact@v4
with:
path: /tmp/digests
pattern: digests-*
merge-multiple: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.WREN_UI_IMAGE }}
tags: |
${{ needs.build-image.outputs.tag_name }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create manifest list and push
working-directory: /tmp/digests
run: |
TAGS=$(echo "${{ steps.meta.outputs.tags }}" | awk '{printf "--tag %s ", $0}')
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ env.WREN_UI_IMAGE }}@sha256:%s ' *) \
$TAGS
================================================
FILE: .github/workflows/ui-test.yaml
================================================
# create the github action to run the UI tests when PR created
name: Wren-UI Test
on:
pull_request:
types: [ labeled, synchronize ]
permissions:
contents: read
concurrency:
# avoid mis-canceling the ci runs while other labels are added to the PR, so we add the label name as the condition
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.event.label.name == 'ci/ui' && github.event.number || github.sha }}
cancel-in-progress: true
defaults:
run:
working-directory: wren-ui
jobs:
unit-test:
# run this job only if the PR is labeled with "ci/ui"
if: ${{ github.event.label.name == 'ci/ui'}}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '18'
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v2
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: | # should cache node_modules as well
${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- if: ${{ steps.yarn-cache.cache-hit != 'true' }}
name: List the state of node modules
continue-on-error: true
run: yarn list
- name: Install dependencies
run: yarn
- name: Run tests
run: yarn test
================================================
FILE: .github/workflows/wren-launcher-ci.yaml
================================================
name: Wren Launcher CI
on:
pull_request:
types: [synchronize, labeled]
paths:
- 'wren-launcher/**'
- '.github/workflows/wren-launcher-ci.yaml'
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.event.number || github.sha }}
cancel-in-progress: true
defaults:
run:
working-directory: wren-launcher
jobs:
golangci:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.24'
cache-dependency-path: wren-launcher/go.sum
- name: golangci-lint
uses: golangci/golangci-lint-action@v8
with:
version: v2.3.1
working-directory: wren-launcher
fmt-and-test:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.24'
cache-dependency-path: wren-launcher/go.sum
- name: Install goimports
run: go install golang.org/x/tools/cmd/goimports@latest
- name: Download dependencies
run: go mod download
- name: Run format check
run: |
make fmt
# Check if there are any formatting changes
if [ -n "$(git diff --name-only)" ]; then
echo "Code is not formatted properly. Please run 'make fmt' and commit the changes."
git diff
exit 1
fi
- name: Run go vet
run: make vet
- name: Run tests
run: go test ./commands/dbt
security-scan:
runs-on: ubuntu-latest
needs: fmt-and-test
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.24'
cache-dependency-path: wren-launcher/go.sum
- name: Run Gosec Security Scanner
run: |
go install github.com/securego/gosec/v2/cmd/gosec@latest
gosec ./...
- name: Run Go mod audit
run: |
go mod verify
go list -json -deps ./... | jq -r '.Module | select(.Version) | "\(.Path) \(.Version)"' | sort -u
================================================
FILE: .gitignore
================================================
# wren-ai-service
wren-ai-service/.env.*
wren-ai-service/config.yaml*
!wren-ai-service/.env.*.example
!wren-ai-service/src/eval/wren-engine/.env
wren-ai-service/src/eval/wren-engine/**/config.properties
wren-ai-service/src/eval/wren-engine/etc/mdl/*
wren-ai-service/src/eval/wren-engine/etc/duckdb
wren-ai-service/src/eval/wren-engine/etc/archived
wren-ai-service/src/eval/data
wren-ai-service/**/outputs/
wren-ai-service/**/spider/
wren-ai-service/tests/data/usecases/
!wren-ai-service/**/metrics/spider/
!wren-ai-service/tests/data
!wren-ai-service/src/eval/data/book_2*.json
!wren-ai-service/src/eval/data/baseball_1*.json
!wren-ai-service/src/eval/data/college_3*.json
!wren-ai-service/src/eval/data/college_3_optimal_ddl.json
wren-ai-service/*.csv
wren-ai-service/*.json
wren-ai-service/assertion.log
wren-ai-service/redis.*
wren-ai-service/demo/spider
wren-ai-service/demo/poetry.lock
wren-ai-service/demo/custom_dataset
wren-ai-service/demo/.env
wren-ai-service/tools/dev/etc/**
.deepeval-cache.json
.deepeval_telemtry.txt
docker/config.yaml
docker/docker-compose-local.yaml
docker/data
# python
.python-version
# cache
__pycache__
local_cache
.ruff_cache
.pytest_cache
# ide
.idea
.vscode/
# os
.DS_Store
__MACOSX/
*.pem
# sqlite
*.sqlite
*.sqlite3
# ui
## dependencies
node_modules
.pnp
.pnp.js
## testing
wren-ui/coverage
wren-ui/test-results
wren-ui/playwright-report
wren-ui/e2e/e2e.config.json
## next.js
wren-ui/.next
wren-ui/out
wren-ui/.yarn/install-state.gz
## production
wren-ui/build
## debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
## local env files
.env*.local
.env*
.env.ai
## vercel
.vercel
## typescript
*.tsbuildinfo
next-env.d.ts
# wren-launcher
wren-launcher/dist
wren-launcher/main
## temporary files
.tmp
!wren-ai-service/tools/.env.example
================================================
FILE: .gitmodules
================================================
[submodule "wren-engine"]
path = wren-engine
url = git@github.com:Canner/wren-engine.git
================================================
FILE: CODE_OF_CONDUCT.md
================================================
## Code of Conduct
### Our Pledge
We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
### Our Standards
Examples of behavior that contributes to a positive environment for our community include:
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
- Focusing on what is best not just for us as individuals, but for the overall community
Examples of unacceptable behavior include:
- The use of sexualized language or imagery, and sexual attention or advances of any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others’ private information, such as a physical or email address, without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting
### Enforcement Responsibilities
Project maintainers are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
### Scope
This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
### Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the project team responsible for enforcement at [contact@getwren.ai](mailto:contact@getwren.ai). All complaints will be reviewed and investigated promptly and fairly.
All project maintainers are obligated to respect the privacy and security of the reporter of any incident.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
### Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1,
available at [https://www.contributor-covenant.org/version/2/1/code_of_conduct/][version]
[homepage]: http://contributor-covenant.org
[version]: https://www.contributor-covenant.org/version/2/1
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing Guidelines
*Pull requests, bug reports, and all other forms of contribution are welcomed and highly encouraged!* :octocat:
### Contents
- [Code of Conduct](#book-code-of-conduct)
- [Overview](#mag-overview)
- [Contribution Guide of Different Services](#love_letter-contribution-guide-of-different-services)
- [Creating a New Data Source Connector](#electric_plug-creating-a-new-data-source-connector)
> **This guide serves to set clear expectations for everyone involved with the project so that we can improve it together while also creating a welcoming space for everyone to participate. Following these guidelines will help ensure a positive experience for contributors and maintainers.**
## :book: Code of Conduct
Please review our [Code of Conduct](https://github.com/Canner/WrenAI/blob/main/CODE_OF_CONDUCT.md). It is in effect at all times. We expect it to be honored by everyone who contributes to this project. Acting like an asshole will not be tolerated.
## :rocket: Get Started
1. Visit [How Wren AI works?](https://docs.getwren.ai/oss/overview/how_wrenai_works) to understand the architecture of Wren AI
1. After you understand the architecture of Wren AI, understand the scope of the services you want to contribute to.
Check each service's section under [Contribution Guide of Different Services](#love_letter-contribution-guide-of-different-services) to learn how to contribute to each service.
1. If you are dealing with UI-related tasks, such as adding a dark mode, you only need to contribute to the [Wren UI Service](#wren-ui-service).
2. If you are dealing with LLM-related tasks, such as enhancing the prompts used in the LLM pipelines, you only need to contribute to the [Wren AI Service](#wren-ai-service).
3. If you are working on data-source-related tasks, such as fixing a bug in SQL server connector, you will need to contribute to the [Wren Engine Service](#wren-engine-service).
1. If you are not sure which service to contribute to, please reach out to us in [Discord](https://discord.gg/canner) or [GitHub Issues](https://github.com/Canner/WrenAI/issues).
1. It's possible that you need to contribute to multiple services. For example, if you are adding a new data source, you will need to contribute to the [Wren UI Service](#wren-ui-service) and [Wren Engine Service](#wren-engine-service). Follow [Guide for Contributing to Multiple Services](#guide-for-contributing-to-multiple-services) to learn how to contribute to multiple services.
## :love_letter: Contribution Guide of Different Services
### Wren AI Service
Wren AI Service is responsible for LLM-related tasks like converting natural language questions into SQL queries and providing step-by-step SQL breakdowns.
To contribute to Wren AI Service, please refer to the [Wren AI Service Contributing Guide](https://github.com/Canner/WrenAI/blob/main/wren-ai-service/CONTRIBUTING.md)
### Wren UI Service
Wren UI is the client service of WrenAI. It is built with Next.js and TypeScript.
To contribute to Wren UI, you can refer to the [WrenAI/wren-ui/README.md](https://github.com/Canner/WrenAI/blob/main/wren-ui/README.md) file for instructions on how to set up the development environment and run the development server.
### Wren Engine Service
Wren Engine is the backbone of the Wren AI project. The semantic engine for LLMs, bringing business context to AI agents.
To contribute, please refer to [Wren Engine Contributing Guide](https://github.com/Canner/wren-engine/blob/main/ibis-server/docs/CONTRIBUTING.md)
## Guide for Contributing to Multiple Services
We rely on docker-compose to start all services. If you are contributing to multiple services, you could just comment out the services you'd like to start from the source code and change the `env` variables to point to the services you started by yourself.
### Example: Contributing to the [Wren UI Service](#wren-ui-service) and [Wren Engine Service](#wren-engine-service)
If you are contributing to both the [Wren UI Service](#wren-ui-service) and [Wren Engine Service](#wren-engine-service), you should comment out the `wren-engine` service in the `docker/docker-compose-dev.yml` file (note that the UI service is already excluded from `docker/docker-compose-dev.yml`). Then, adjust the environment variables in your `.env` file to point to the services you have started manually. This will ensure that your local development environment correctly interfaces with the services you are working on.
1. Prepare your `.env` file: In the `WrenAI/docker` folder, use the `.env.example` file as a template. Copy this file to create a `.env.local` file.
```sh
# assuming the current directory is wren-ui
cd ../docker
cp .env.example .env.local
```
2. Modify your `.env.local` file: Fill in the `OPENAI_API_KEY` with your OpenAI API keys before starting.
3. In the `WrenAI/docker` folder, copy `config.example.yaml` to `config.yaml` for AI service configuration. Also change `http://wren-ui:3000` to `http://host.docker.internal:3000` in `config.yaml`.
4. Start the UI and engine services from the source code.
5. Update the `env` variables in the `.env.local` file to point to the services you started manually.
6. Start the other services using docker-compose:
```sh
# current directory is WrenAI/docker
docker-compose -f docker-compose-dev.yaml --env-file .env.example up
# you can add the -d flag to run the services in the background
docker-compose -f docker-compose-dev.yaml --env-file .env.example up -d
# to stop the services, use
docker-compose -f docker-compose-dev.yaml --env-file .env.example down
```
7. Happy coding!
## :electric_plug: Creating a New Data Source Connector
To develop a new data source connector, you'll need to modify both the front-end and back-end of the Wren UI, in addition to the Wren Engine.
Below is a brief overview of a data source connector:
<img src="./misc/data_source.png" width="400">
The UI is primarily responsible for storing database connection settings, providing an interface for users to input these settings, and submitting them to the Engine, which then connects to the database.
The UI must be aware of the connection details it needs to retain, as specified by the Engine. Therefore, the implementation sequence would be as follows:
- Engine:
- Implement the new data source (you'll determine what connection information is needed and how it should be passed from the UI).
- Implement the metadata API for the UI to access.
- UI:
- Back-End:
- Safely store the connection information.
- Provide the connection information to the Engine.
- Front-End:
- Prepare an icon for the data source.
- Set up the form template for users to input the connection information.
- Update the data source list.
### Wren Engine
- To implement a new data source, please refer to [How to Add a New Data Source](https://github.com/Canner/wren-engine/blob/main/ibis-server/docs/how-to-add-data-source.md).
- After adding a new data source, you can proceed with implementing the metadata API for the UI.
Here are some previous PRs that introduced new data sources:
- [Add MSSQL data source](https://github.com/Canner/wren-engine/pull/631)
- [Add MySQL data source](https://github.com/Canner/wren-engine/pull/618)
- [Add ClickHouse data source](https://github.com/Canner/wren-engine/pull/648)
### Wren UI Guide
We'll describe what should be done in the UI for each new data source.
If you prefer to learn by example, you can refer to this Trino [issue](https://github.com/Canner/WrenAI/issues/492) and [PR](https://github.com/Canner/WrenAI/pull/535).
#### Backend
1. Define the data source in `wren-ui/src/apollo/server/dataSource.ts`
- define the `toIbisConnectionInfo` and `sensitiveProps` methods
2. Modify the ibis adaptor in `wren-ui/src/apollo/server/adaptors/ibisAdaptor.ts`
- define an ibis connection info type for the new data source
- set up the `dataSourceUrlMap` for the new data source
3. Modify the repository in `wren-ui/src/apollo/server/repositories/projectRepository.ts`
- define the wren ui connection info type for the new data source
4. Update the graphql schema in `wren-ui/src/apollo/server/schema.ts` so that the new data source can be used in the UI
- add the new data source to the `DataSource` enum
5. Update the type definition in `wren-ui/src/apollo/server/types/dataSource.ts`
- add the new data source to the `DataSourceName` enum
#### Frontend
1. Prepare the data source's logo:
- Image size should be `40 x 40` px
- Preferably use SVG format
- Ensure the logo is centered within a `30px` container for consistent formatting
Example:
<img src="./misc/logo_template.jpg" width="120">
2. Create the data source form template:
- In `wren-ui/src/components/pages/setup/dataSources`, add a new file named `${dataSource}Properties.tsx`
- Implement the data source form template in this file
3. Set up the data source template:
- Navigate to `wren-ui/src/utils/dataSourceType.ts`
- Add new data source image, name, properties
- Update the necessary files to include the new data source template settings
4. Update the data source list:
- Add the new data source to the `DATA_SOURCES` enum in `wren-ui/src/utils/enum/dataSources.ts`
- Update relevant files in `wren-ui/src/components/pages/setup/` to include the new data source
- Ensure `wren-ui/src/apollo/server/adaptors/ibisAdaptor.ts` handle the new data source
5. Test the new connector:
- Ensure the new data source appears in the UI
- Verify that the form works correctly
- Test the connection to the new data source
================================================
FILE: LICENSE
================================================
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU Affero General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Wren AI is a Text-to-SQL solution for data teams to get results
and insights faster by asking business questions without writing SQL.
Copyright (C) 2024 Canner, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
<https://www.gnu.org/licenses/>.
================================================
FILE: README.md
================================================
<p align="center" id="top">
<a href="https://getwren.ai/?utm_source=github&utm_medium=title&utm_campaign=readme">
<picture>
<source media="(prefers-color-scheme: light)" srcset="./misc/wrenai_logo.png">
<img src="./misc/wrenai_logo_white.png" width="300px">
</picture>
<h1 align="center">Wren AI - Open-Source GenBI Agent</h1>
</a>
</p>
<p align="center">
<a aria-label="Follow us on X" href="https://x.com/getwrenai">
<img alt="" src="https://img.shields.io/badge/-@getwrenai-blue?style=for-the-badge&logo=x&logoColor=white&labelColor=gray&logoWidth=20">
</a>
<a aria-label="Releases" href="https://github.com/canner/WrenAI/releases">
<img alt="" src="https://img.shields.io/github/v/release/canner/WrenAI?logo=github&label=GitHub%20Release&color=blue&style=for-the-badge">
</a>
<a aria-label="License" href="https://github.com/Canner/WrenAI/blob/main/LICENSE">
<img alt="" src="https://img.shields.io/github/license/canner/WrenAI?color=blue&style=for-the-badge">
</a>
<a href="https://docs.getwren.ai">
<img src="https://img.shields.io/badge/docs-online-brightgreen?style=for-the-badge" alt="Docs">
</a>
<a aria-label="Join the community on GitHub" href="https://discord.gg/5DvshJqG8Z">
<img alt="" src="https://img.shields.io/badge/-JOIN%20THE%20COMMUNITY-blue?style=for-the-badge&logo=discord&logoColor=white&labelColor=grey&logoWidth=20">
</a>
<a aria-label="Canner" href="https://cannerdata.com/?utm_source=github&utm_medium=badge&utm_campaign=readme">
<img src="https://img.shields.io/badge/%F0%9F%A7%A1-Made%20by%20Canner-blue?style=for-the-badge">
</a>
</p>
<p align="center">
<a href="https://trendshift.io/repositories/9263" target="_blank"><img src="https://trendshift.io/api/badge/repositories/9263" alt="Canner%2FWrenAI | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
</p>
> ⚡ GenBI (Generative BI) queries any database in natural language, generates accurate SQL (Text-to-SQL), charts (Text-to-Chart), and AI-powered business intelligence in seconds. ️
<p align="center">
<img width="1920" height="1080" alt="1" src="https://github.com/user-attachments/assets/bba9d37a-33e3-49ab-b7cb-32fd6dddc8d1" />
</p>
## 😍 Demos
https://github.com/user-attachments/assets/f9c1cb34-5a95-4580-8890-ec9644da4160
[Watch GenBI Demo](https://github.com/user-attachments/assets/90ad1d35-bb1e-490b-9676-b29863ff090b)
## 🤖 Features
| | What you get | Why it matters |
|--------------------|--------------|----------------|
| **Talk to Your Data** | Ask in any language → precise SQL & answers | Slash the SQL learning curve |
| **GenBI Insights** | AI-written summaries, charts & reports | Decision-ready context in one click |
| **Semantic Layer** | MDL models encode schema, metrics, joins | Keeps LLM outputs accurate & governed |
| **Embed via API** | Generate queries & charts inside your apps ([API Docs](https://wrenai.readme.io/reference/cloud-getting-started)) | Build custom agents, SaaS features, chatbots ([Streamlit Live Demo](https://huggingface.co/spaces/getWrenAI/wrenai-cloud-api-demo)) |
🤩 [Learn more about GenBI](https://getwren.ai/genbi?utm_source=github&utm_medium=content&utm_campaign=readme)
## 🚀 Getting Started
Using Wren AI is super simple, you can set it up within 3 minutes, and start to interact with your data!
<p align="center">
<img width="1920" height="1080" alt="2" src="https://github.com/user-attachments/assets/6555f539-9ef2-485d-9135-0071741fda96" />
</p>
- Visit our [Install in your local environment](http://docs.getwren.ai/oss/installation?utm_source=github&utm_medium=content&utm_campaign=readme).
- Visit the [Usage Guides](https://docs.getwren.ai/oss/guide/connect/overview?utm_source=github&utm_medium=content&utm_campaign=readme) to learn more about how to use Wren AI.
- Or just start with [Wren AI Cloud](https://getwren.ai/?utm_source=github&utm_medium=content&utm_campaign=readme) our Managed Cloud Service. ([OSS vs. Commercial Plans](https://docs.getwren.ai/oss/overview/cloud_vs_self_host)).
## 🏗️ Architecture
<p align="center">
<img width="1011" height="682" alt="wrenai-architecture" src="https://github.com/user-attachments/assets/e99b999f-9912-4fa7-921a-9c86b6b83354" />
</p>
👉 [Learn more about our Design](https://getwren.ai/post/how-we-design-our-semantic-engine-for-llms-the-backbone-of-the-semantic-layer-for-llm-architecture?utm_source=github&utm_medium=content&utm_campaign=readme)
## 🔌 Data Sources
If your data source is not listed here, vote for it in our [GitHub discussion thread](https://github.com/Canner/WrenAI/discussions/327). It will be a valuable input for us to decide on the next supported data sources.
- Athena (Trino)
- Redshift
- BigQuery
- DuckDB
- Databricks
- PostgreSQL
- MySQL
- Microsoft SQL Server
- ClickHouse
- Oracle
- Trino
- Snowflake
## 🤖 LLM Models
Wren AI supports integration with various Large Language Models (LLMs), including but not limited to:
- OpenAI Models
- Azure OpenAI Models
- DeepSeek Models
- Google AI Studio – Gemini Models
- Vertex AI Models (Gemini + Anthropic)
- Bedrock Models
- Anthropic API Models
- Groq Models
- Ollama Models
- Databricks Models
Check [configuration examples here](https://github.com/Canner/WrenAI/tree/main/wren-ai-service/docs/config_examples)!
> [!CAUTION]
> The performance of Wren AI depends significantly on the capabilities of the LLM you choose. We strongly recommend using the most powerful model available for optimal results. Using less capable models may lead to reduced performance, slower response times, or inaccurate outputs.
## 📚 Documentation
Visit [Wren AI documentation](https://docs.getwren.ai/oss/overview/introduction?utm_source=github&utm_medium=content&utm_campaign=readme) to view the full documentation.
## 📪 Keep Posted?
[Subscribe our blog](https://www.getwren.ai/blog/?utm_source=github&utm_medium=content&utm_campaign=readme) and [Follow our LinkedIn](https://www.linkedin.com/company/wrenai)
## 🛠️ Contribution
1. Star ⭐ the repo to show support (it really helps).
2. Open an issue for bugs, ideas, or discussions.
3. Read [Contribution Guidelines](https://github.com/Canner/WrenAI/blob/main/CONTRIBUTING.md) for setup & PR guidelines.
## ⭐️ Community
- Join 1.3k+ developers in our [Discord](https://discord.gg/5DvshJqG8Z) for real-time help and roadmap previews.
- If there are any issues, please visit [GitHub Issues](https://github.com/Canner/WrenAI/issues).
- Explore our [public roadmap](https://wrenai.notion.site/) to stay updated on upcoming features and improvements!
Please note that our [Code of Conduct](./CODE_OF_CONDUCT.md) applies to all Wren AI community channels. Users are **highly encouraged** to read and adhere to them to avoid repercussions.
## 🎉 Our Contributors
<a href="https://github.com/canner/wrenAI/graphs/contributors">
<img src="https://contrib.rocks/image?repo=Canner/WrenAI" />
</a>
<p align="right">
<a href="#top">⬆️ Back to Top</a>
</p>
================================================
FILE: SECURITY.md
================================================
# Security Policy
## Reporting a Vulnerability
If you believe you have found a security vulnerability in any Canner-owned repository, please report it to us through coordinated disclosure.
**Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.**
Instead, please send an email to contact[@]cannerdata.com.
Please include as much of the information listed below as you can to help us better understand and resolve the issue:
* The type of issue (e.g., buffer overflow, SQL injection, or cross-site scripting)
* Full paths of source file(s) related to the manifestation of the issue
* The location of the affected source code (tag/branch/commit or direct URL)
* Any special configuration required to reproduce the issue
* Step-by-step instructions to reproduce the issue
* Proof-of-concept or exploit code (if possible)
* Impact of the issue, including how an attacker might exploit the issue
This information will help us triage your report more quickly.
================================================
FILE: deployment/README.md
================================================
# Various deployemnt starategies of the app
- [x] [Docker](../docker/)
- [x] [Kubernetes: Kustomizations](./kustomizations/)
================================================
FILE: deployment/kustomizations/.gitignore
================================================
*.kustomized.yaml
charts/*
================================================
FILE: deployment/kustomizations/README.md
================================================
# Deployment of Wren AI to Kubernetes with Kustomization
1. Ensure you satisfy the dependencies required to deploy Wren AI.
2. Adjust the values and manifests accordingly to fit your Kubernetes environment.
3. Deploy Secrets separately.
4. Deploy the inflated kustomized app.
Note: Without authentication, once you publish this on the internet, anyone can access your app, see your data, and modify your settings!
## Dependencies used in this kustomization:
- nginx.ingress
- external-dns
- cert-manager
- kubectl kustomize
- helm (for minikube)
## Steps to deploy:
`Suggestion`: Before deploying, check out the manifests in the `deployment/kustomizations ` folder and modify them for your Kubernetes environment.
The `deployment/kustomizations` folder contains a `kustomization.yaml` file that will inflate the manifests into a `deployment/kustomizations/wrenai.kustomized.yaml` file used to deploy the app to your Kubernetes cluster.
```shell
# Clone the repository with the kustomization
git clone https://github.com/Canner/WrenAI.git
cd WrenAI
# Inflate the manifest with kustomization
kubectl kustomize deployment/kustomizations --enable-helm > deployment/kustomizations/wrenai.kustomized.yaml
# Create namespace
kubectl create namespace wren
# !!!!!!!!!!!!
# MODIFY secret-wren_example.yaml manifest file FIRST
# OPENAI_API_KEY is REQUIRED: without a valid key the wren-ai-service-deployment pod will not start
# You must update PG_URL, otherwise wren-ui will not work
#vi deployment/kustomizations/examples/secret-wren_example.yaml
kubectl apply -f deployment/kustomizations/examples/secret-wren_example.yaml -n wren
# Deploy the app:
kubectl apply -f deployment/kustomizations/wrenai.kustomized.yaml
kubectl get pods -n wren
```
### Notes on kustomization:
- `deployment/kustomizations/kustomization.yaml` is the main file responsible for versions of other apps such as Qdrant and PostgreSQL, version of your Wren AI app. It also combines resourses from the manifest such as ConfigMaps, Deployments, and Services. And example Ingress, Certificates and Secrets.
- `deployment/kustomizations/base` is the base folder that contains the core Wren AI manifests, its less likely you need to modify them, but check just in case
- `deployment/kustomizations/examples` is a place with examples of manifests must take a look and adjust to your k8s environment and your needs.
- `deployment/kustomizations/examples/secret-wren_example.yaml` is the file you would not normally include in the kustomization file as its not a best practice and especially not a good idea to include in your GitOps repo as it contains cleartext passwords. We recommend to deploy it separately. Thant's why its commented in the `kustomization.yaml` file.
- `deployment/kustomizations/examples/wrenai-ingress-example.yaml` is an example of how to deploy Ingress. You can use this as a template for your own Ingress. It contains dependancy of extarnal-dns to add your dns name to your DNS records automatically, otherwise you'll need to add it manually. Also it assumes you are using nginx.ingress, it increases timeouts, disables the owasp and modsecurity that might be enabled globaly and prevent your UI from working properly. Comment the TLS section if you do not wish to use `https` encryption. Note: without authentication, enyone can acess your app, see your data and modify your settings!
- `deployment/kustomizations/examples/certificate-wren_example.yaml` is an example of how to deploy certificates for your ingress for the Wren-UI. You can use this as a template for your own certificate. It contains dependancy of cert-manager to add your certificates automatically, otherwise you'll need to add it manually. The certificate will be used by your Ingress.
- `deployment/kustomizations/examples/certificate-qdrant_example.yaml` is an example of how to deploy certificates for your ingress for Qdrant. This is included just in case and is not required, usually you would not be publishing your Vector Database publically in internet. That's why it's commented in the `kustomization.yaml` file. You can use this as a template for your own certificate. It contains dependancy of cert-manager to add your certificates automatically, otherwise you'll need to add it manually.
- `deployment/kustomizations/patches` folder is empty, feel free to add your own patches & overlays there.
#### Wren-UI Database
Starting with wren-ui version 0.6.0 by default the postgres database is used for wren-ui in this kubernetes kustomization and will be installed in the same namespace as wren-ai.
- `postgres`: Database that will be installed in the same namespace as wren-ai. You *must* update `PG_URL` in the Secret manifest `deployment/kustomizations/examples/secret-wren_example.yaml`.
Example: `PG_URL: "postgres://postgres:postgres@wrenai-postgresql:5432/admin_ui"`
- `postgres://` This is the protocol. It tells the system that you’re connecting to a PostgreSQL database.
- `postgres:postgres` These are the username(first) and password(second) for the database respectively, separated by a colon. In this case, both the username and password are “postgres”.
- `@wren-postgresql` This is the hostname of the database server. "wren-postgresql" means the database server is running in a Kubernetes cluster and it is named "wren-postgresql" in the *same* namespace. If you are using another namespace you must provide the full hostname, example: `wren-postgresql.wrenai.svc.cluster.local`, "wrenai" is the namespace name, "svc.cluster.local" is the default domain name for Kubernetes services no need to change it.
- `:5432` This is the port number. PostgreSQL servers listen on port 5432 by default.
- `/admin_ui` This is the name of the database you’re connecting to. In this case, the database name is `admin_ui`. It can be found in the helm values file in the auth.database parameter `deployment/kustomizations/helm-values_postgresql_15.yaml`
# Minikube
Prepare your k8s environment. Then use the `Steps to deploy` section to deploy Wren AI app into your k8s.
```shell
minikube start
minikube addons enable ingress
minikube addons enable metallb
minikube kubectl -- get nodes
minikube kubectl -- get pods -A
minikube update-context
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm install external-dns bitnami/external-dns
helm install \
external-dns bitnami/external-dns \
--namespace external-dns \
--version 7.5.2 \
--create-namespace \
--set installCRDs=true
kubectl get pods -n external-dns
helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install \
cert-manager jetstack/cert-manager \
--namespace cert-manager \
--version v1.13.6 \
--create-namespace \
--set installCRDs=true
kubectl get pods -n cert-manager
##########
# Use the `Steps to deploy` section to continue as you would on a production k8s cluster.
```
# GitOps Patches
In the [patches](./patches) folder you can find usefull kustomization examples files if you wish to use existing official kustomization directly from this repo as a base kustomization layer and only customize some values. It can be usefull for you GitOps workflow and can be used in conjunction with FlexCD or ArgoCD.
================================================
FILE: deployment/kustomizations/base/cm.yaml
================================================
apiVersion: v1
kind: ConfigMap
metadata:
name: wren-config
data:
# Wren Engine Service Port
WREN_ENGINE_PORT: "8080"
# Wren AI Service Port
WREN_AI_SERVICE_PORT: "5555"
WREN_UI_ENDPOINT: http://wren-ui-svc:3000
#Release version used by wren ui https://github.com/Canner/WrenAI/blob/main/docker/docker-compose.yaml#L85-L88
WREN_PRODUCT_VERSION: "0.12.0"
WREN_ENGINE_VERSION: "0.12.3"
WREN_AI_SERVICE_VERSION: "0.12.1"
WREN_UI_VERSION: "0.17.6"
# Document store related
QDRANT_HOST: "wren-qdrant"
# Telemetry
POSTHOG_HOST: "https://app.posthog.com"
TELEMETRY_ENABLED: "false"
# this is for telemetry to know the model, i think ai-service might be able to provide a endpoint to get the information
GENERATION_MODEL: "gpt-4o-mini-2024-07-18"
# service endpoints of AI service & engine service
WREN_ENGINE_ENDPOINT: "http://wren-engine-svc:8080"
WREN_AI_ENDPOINT: "http://wren-ai-service-svc:5555"
#WREN_AI_ENDPOINT: "http://wren-ai-service-svc.ai-system.svc.cluster.local:5555"
# "pg" for postgres as UI application database
WREN_UI_DB_TYPE: pg
#For bootstrap
WREN_ENGINE_DATA_PATH: "/app/data"
### if DB_TYPE = "postgres" you must provide PG_URL string in the *Secret* manifest file (deployment/kustomizations/examples/secret-wren_example.yaml) to connect to postgres
#DEBUG, INFO
LOGGING_LEVEL: INFO
IBIS_SERVER_ENDPOINT: http://wren-ibis-server-svc:8000
---
apiVersion: v1
kind: ConfigMap
metadata:
name: wren-ai-service-config
data:
config.yaml: |
type: llm
provider: litellm_llm
timeout: 120
models:
- alias: default
model: gpt-4.1-nano-2025-04-14
context_window_size: 1000000
kwargs:
max_tokens: 4096
n: 1
seed: 0
temperature: 0
- model: gpt-4.1-mini-2025-04-14
context_window_size: 1000000
kwargs:
max_tokens: 4096
n: 1
seed: 0
temperature: 0
- model: gpt-4.1-2025-04-14
context_window_size: 1000000
kwargs:
max_tokens: 4096
n: 1
seed: 0
temperature: 0
- model: gpt-5-nano-2025-08-07
context_window_size: 380000
kwargs:
max_completion_tokens: 4096
n: 1
seed: 0
reasoning_effort: minimal
- model: gpt-5-mini-2025-08-07
context_window_size: 380000
kwargs:
max_completion_tokens: 4096
n: 1
seed: 0
reasoning_effort: minimal
- model: gpt-5-2025-08-07
context_window_size: 380000
kwargs:
max_completion_tokens: 4096
n: 1
seed: 0
reasoning_effort: minimal
---
type: embedder
provider: litellm_embedder
models:
- model: text-embedding-3-large
alias: default
timeout: 120
---
type: engine
provider: wren_ui
endpoint: http://wren-ui-svc:3000
---
type: engine
provider: wren_ibis
endpoint: http://wren-ibis-server-svc:8000
---
type: document_store
provider: qdrant
location: http://wren-qdrant:6333
embedding_model_dim: 3072
timeout: 120
---
type: pipeline
pipes:
- name: db_schema_indexing
embedder: litellm_embedder.default
document_store: qdrant
- name: historical_question_indexing
embedder: litellm_embedder.default
document_store: qdrant
- name: table_description_indexing
embedder: litellm_embedder.default
document_store: qdrant
- name: db_schema_retrieval
llm: litellm_llm.default
embedder: litellm_embedder.default
document_store: qdrant
- name: historical_question_retrieval
embedder: litellm_embedder.default
document_store: qdrant
- name: sql_generation
llm: litellm_llm.default
engine: wren_ui
document_store: qdrant
- name: sql_correction
llm: litellm_llm.default
engine: wren_ui
document_store: qdrant
- name: followup_sql_generation
llm: litellm_llm.default
engine: wren_ui
document_store: qdrant
- name: sql_answer
llm: litellm_llm.default
- name: semantics_description
llm: litellm_llm.default
- name: relationship_recommendation
llm: litellm_llm.default
- name: question_recommendation
llm: litellm_llm.default
- name: question_recommendation_sql_generation
llm: litellm_llm.default
engine: wren_ui
document_store: qdrant
- name: intent_classification
llm: litellm_llm.default
embedder: litellm_embedder.default
document_store: qdrant
- name: misleading_assistance
llm: litellm_llm.default
- name: data_assistance
llm: litellm_llm.default
- name: sql_pairs_indexing
document_store: qdrant
embedder: litellm_embedder.default
- name: sql_pairs_retrieval
document_store: qdrant
embedder: litellm_embedder.default
llm: litellm_llm.default
- name: preprocess_sql_data
llm: litellm_llm.default
- name: sql_executor
engine: wren_ui
- name: chart_generation
llm: litellm_llm.default
- name: chart_adjustment
llm: litellm_llm.default
- name: user_guide_assistance
llm: litellm_llm.default
- name: sql_question_generation
llm: litellm_llm.default
- name: sql_generation_reasoning
llm: litellm_llm.default
- name: followup_sql_generation_reasoning
llm: litellm_llm.default
- name: sql_regeneration
llm: litellm_llm.default
engine: wren_ui
- name: instructions_indexing
embedder: litellm_embedder.default
document_store: qdrant
- name: instructions_retrieval
embedder: litellm_embedder.default
document_store: qdrant
- name: sql_functions_retrieval
engine: wren_ibis
document_store: qdrant
- name: project_meta_indexing
document_store: qdrant
- name: sql_tables_extraction
llm: litellm_llm.default
- name: sql_diagnosis
llm: litellm_llm.default
---
settings:
doc_endpoint: https://docs.getwren.ai
is_oss: true
engine_timeout: 30
column_indexing_batch_size: 50
table_retrieval_size: 10
table_column_retrieval_size: 100
allow_intent_classification: true
allow_sql_generation_reasoning: true
allow_sql_functions_retrieval: true
enable_column_pruning: false
max_sql_correction_retries: 3
query_cache_maxsize: 1000
query_cache_ttl: 3600
langfuse_host: https://cloud.langfuse.com
langfuse_enable: true
logging_level: DEBUG
development: false
historical_question_retrieval_similarity_threshold: 0.9
sql_pairs_similarity_threshold: 0.7
sql_pairs_retrieval_max_size: 10
instructions_similarity_threshold: 0.7
instructions_top_k: 10
================================================
FILE: deployment/kustomizations/base/deploy-wren-ai-service.yaml
================================================
apiVersion: apps/v1
kind: Deployment
metadata:
name: wren-ai-service-deployment
spec:
replicas: 1
selector:
matchLabels:
app: wren-ai-service
template:
metadata:
labels:
app: wren-ai-service
spec:
containers:
- name: wren-ai-service
image: ghcr.io/canner/wren-ai-service:latest
volumeMounts:
- name: config-volume
mountPath: /app/data
env:
- name: WREN_AI_SERVICE_PORT
valueFrom:
configMapKeyRef:
name: wren-config
key: WREN_AI_SERVICE_PORT
- name: OPENAI_API_KEY
valueFrom:
secretKeyRef:
name: wrenai-secrets
key: OPENAI_API_KEY
- name: QDRANT_HOST
valueFrom:
configMapKeyRef:
name: wren-config
key: QDRANT_HOST
- name: LOGGING_LEVEL
valueFrom:
configMapKeyRef:
name: wren-config
key: LOGGING_LEVEL
- name: WREN_UI_ENDPOINT
valueFrom:
configMapKeyRef:
name: wren-config
key: WREN_UI_ENDPOINT
- name: PYTHONUNBUFFERED
value: "1"
- name: LANGFUSE_PUBLIC_KEY
valueFrom:
secretKeyRef:
name: wrenai-secrets
key: LANGFUSE_PUBLIC_KEY
- name: LANGFUSE_SECRET_KEY
valueFrom:
secretKeyRef:
name: wrenai-secrets
key: LANGFUSE_SECRET_KEY
- name: CONFIG_PATH
value: /app/data/config.yaml
ports:
- containerPort: 5555
volumes:
- name: config-volume
configMap:
name: wren-ai-service-config
items:
- key: config.yaml
path: config.yaml
================================================
FILE: deployment/kustomizations/base/deploy-wren-engine.yaml
================================================
apiVersion: apps/v1
kind: Deployment
metadata:
name: wren-engine-deployment
spec:
replicas: 1
selector:
matchLabels:
app: wren-engine
template:
metadata:
labels:
app: wren-engine
spec:
volumes:
- name: wren-data
persistentVolumeClaim:
claimName: wren-data-pvc
initContainers:
- name: bootstrap
image: ghcr.io/canner/wren-bootstrap:0.1.4
env:
- name: DATA_PATH
valueFrom:
configMapKeyRef:
name: wren-config
key: WREN_ENGINE_DATA_PATH
- name: PG_PASSWORD
valueFrom:
secretKeyRef:
name: wrenai-postgresql
key: postgres-password
- name: PG_USERNAME
valueFrom:
secretKeyRef:
name: wrenai-secrets
key: PG_USERNAME
volumeMounts:
- name: wren-data
mountPath: /app/data
command: ["/bin/sh", "/app/init.sh"]
containers:
- name: wren-engine
image: ghcr.io/canner/wren-engine:0.4.4
ports:
- containerPort: 8080
- containerPort: 7432
volumeMounts:
- name: wren-data
mountPath: /usr/src/app/etc
================================================
FILE: deployment/kustomizations/base/deploy-wren-ibis-server.yaml
================================================
apiVersion: apps/v1
kind: Deployment
metadata:
name: wren-ibis-server
spec:
replicas: 1
selector:
matchLabels:
app: wren-ibis
template:
metadata:
labels:
app: wren-ibis
spec:
containers:
- name: wren-ibis
image: ghcr.io/canner/wren-engine-ibis:0.5.0
env:
- name: WREN_ENGINE_ENDPOINT
valueFrom:
configMapKeyRef:
name: wren-config
key: WREN_ENGINE_ENDPOINT
- name: LOGGING_LEVEL
valueFrom:
configMapKeyRef:
name: wren-config
key: LOGGING_LEVEL
ports:
- containerPort: 8000
================================================
FILE: deployment/kustomizations/base/deploy-wren-ui.yaml
================================================
apiVersion: apps/v1
kind: Deployment
metadata:
name: wren-ui-deployment
spec:
replicas: 1
selector:
matchLabels:
app: wren-ui
template:
metadata:
labels:
app: wren-ui
spec:
containers:
- name: wren-ui
image: ghcr.io/canner/wren-ui:0.5.6
env:
- name: DB_TYPE
valueFrom:
configMapKeyRef:
name: wren-config
key: WREN_UI_DB_TYPE
- name: WREN_ENGINE_ENDPOINT
valueFrom:
configMapKeyRef:
name: wren-config
key: WREN_ENGINE_ENDPOINT
- name: WREN_AI_ENDPOINT
valueFrom:
configMapKeyRef:
name: wren-config
key: WREN_AI_ENDPOINT
- name: GENERATION_MODEL
valueFrom:
configMapKeyRef:
name: wren-config
key: GENERATION_MODEL
- name: PG_URL
valueFrom:
secretKeyRef:
name: wrenai-secrets
key: PG_URL
# telemetry
- name: WREN_ENGINE_PORT
valueFrom:
configMapKeyRef:
name: wren-config
key: WREN_ENGINE_PORT
- name: WREN_AI_SERVICE_VERSION
valueFrom:
configMapKeyRef:
name: wren-config
key: WREN_AI_SERVICE_VERSION
- name: WREN_UI_VERSION
valueFrom:
configMapKeyRef:
name: wren-config
key: WREN_UI_VERSION
- name: WREN_ENGINE_VERSION
valueFrom:
configMapKeyRef:
name: wren-config
key: WREN_ENGINE_VERSION
- name: USER_UUID
valueFrom:
secretKeyRef:
name: wrenai-secrets
key: USER_UUID
- name: POSTHOG_API_KEY
valueFrom:
secretKeyRef:
name: wrenai-secrets
key: POSTHOG_API_KEY
- name: POSTHOG_HOST
valueFrom:
secretKeyRef:
name: wrenai-secrets
key: POSTHOG_HOST
- name: TELEMETRY_ENABLED
valueFrom:
configMapKeyRef:
name: wren-config
key: TELEMETRY_ENABLED
# client side
- name: NEXT_PUBLIC_USER_UUID
valueFrom:
secretKeyRef:
name: wrenai-secrets
key: USER_UUID
- name: NEXT_PUBLIC_POSTHOG_API_KEY
valueFrom:
secretKeyRef:
name: wrenai-secrets
key: POSTHOG_API_KEY
- name: NEXT_PUBLIC_POSTHOG_HOST
valueFrom:
secretKeyRef:
name: wrenai-secrets
key: POSTHOG_HOST
- name: NEXT_PUBLIC_TELEMETRY_ENABLED
valueFrom:
configMapKeyRef:
name: wren-config
key: TELEMETRY_ENABLED
# configs
- name: WREN_PRODUCT_VERSION
valueFrom:
configMapKeyRef:
name: wren-config
key: WREN_PRODUCT_VERSION
- name: IBIS_SERVER_ENDPOINT
valueFrom:
configMapKeyRef:
name: wren-config
key: IBIS_SERVER_ENDPOINT
ports:
- containerPort: 3000
================================================
FILE: deployment/kustomizations/base/pvc.yaml
================================================
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: wren-data-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 8Gi
# storageClassName: vsphere-retain
================================================
FILE: deployment/kustomizations/base/svc.yaml
================================================
# Dependancy https://external-dns.io
# You may want to add a DNS record for wren-ui.myhost.net host for your k8s Service instead of Ingress.
# Note: without authentication, enyone can acess your app, see your data and modify your settings!
# If this is the case, make sure to comment the ingress-wren_example.yaml manifest in the `kustomization.yaml` file to exclude it
# And uncomment external-dns in the Service manifest here below:
apiVersion: v1
kind: Service
metadata:
name: wren-ui-svc
#annotations:
### Dependancy external-dns
#external-dns.alpha.kubernetes.io/filter: 'include'
#external-dns.alpha.kubernetes.io/cloudflare-proxied: 'false'
#external-dns.alpha.kubernetes.io/target: wren-ui.myhost.net
spec:
selector:
app: wren-ui
ports:
- protocol: TCP
port: 3000
targetPort: 3000
name: http-ui
---
apiVersion: v1
kind: Service
metadata:
name: wren-engine-svc
spec:
selector:
app: wren-engine
ports:
- protocol: TCP
port: 8080
targetPort: 8080
name: wren-engine
- protocol: TCP
port: 7432
targetPort: 7432
name: wren-engine-sql
---
apiVersion: v1
kind: Service
metadata:
name: wren-ai-service-svc
spec:
selector:
app: wren-ai-service
ports:
- protocol: TCP
port: 5555
targetPort: 5555
name: wren-ai-service
---
apiVersion: v1
kind: Service
metadata:
name: wren-ibis-server-svc
spec:
selector:
app: wren-ibis
ports:
- protocol: TCP
port: 8000
targetPort: 8000
name: wren-ibis
================================================
FILE: deployment/kustomizations/examples/.gitignore
================================================
secret.yaml
================================================
FILE: deployment/kustomizations/examples/certificate-qdrant_example.yaml
================================================
# To generate valid certificates into qdrant-ai.myhost.net-tls
# Dependancy: install https://cert-manager.io
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: qdrant-ai.myhost.net
spec:
dnsNames:
- qdrant-ai.myhost.net
issuerRef:
group: cert-manager.io
kind: ClusterIssuer
#### Replace with the name of your issuer
name: myhost.net-prod
secretName: qdrant-ai.myhost.net-tls
================================================
FILE: deployment/kustomizations/examples/certificate-wren_example.yaml
================================================
# To generate valid certificates into wren-ui.myhost.net-tls
# Dependancy: install https://cert-manager.io
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: wren-ui.myhost.net
spec:
dnsNames:
- wren-ui.myhost.net
issuerRef:
group: cert-manager.io
kind: ClusterIssuer
### Replace with the name of your issuer, otherwise the secret will be produce randoom name and the ingress will not work.
name: myhost.net-prod
### Your ingress will be looking for this exact name:
secretName: wren-ui.myhost.net-tls
================================================
FILE: deployment/kustomizations/examples/ingress-wren_example.yaml
================================================
# Dependancy https://external-dns.io
# To add a DNS record for wren-ui.myhost.net host
# Note: without authentication, enyone can acess your app, see your data and modify your settings!
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: wren-ui-ingress
annotations:
### Dependancy external-dns
#external-dns.alpha.kubernetes.io/filter: 'include'
#external-dns.alpha.kubernetes.io/cloudflare-proxied: 'false'
##external-dns.alpha.kubernetes.io/cloudflare-proxied: 'true'
external-dns.alpha.kubernetes.io/target: ingress1.myhost.net
#external-dns.alpha.kubernetes.io/target: ingress2.myhost.net
### Dependancy nginx-ingress-controller
nginx.ingress.kubernetes.io/disable-lua: 'true'
nginx.ingress.kubernetes.io/enable-lua: 'false'
nginx.ingress.kubernetes.io/enable-vts-status: 'false'
nginx.ingress.kubernetes.io/enable-modsecurity: 'false'
#nginx.ingress.kubernetes.io/modsecurity-snippet: |
# SecRuleEngine Off
nginx.ingress.kubernetes.io/enable-owasp-modsecurity-crs: 'false'
nginx.ingress.kubernetes.io/proxy-connect-timeout: '360'
nginx.ingress.kubernetes.io/proxy-read-timeout: '360'
nginx.ingress.kubernetes.io/proxy-send-timeout: '360'
spec:
#instead you may use other ingressClassName such as AWS alb. If other than nginx ingress is used, don't forget to comment unsupported annotations above
#"nginx" or "alb"
ingressClassName: nginx
rules:
- host: wren-ui.myhost.net
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: wren-ui-svc
port:
number: 3000
### Comment TLS section if you are not going to use https
tls:
- hosts:
- wren-ui.myhost.net
secretName: wren-ui.myhost.net-tls
================================================
FILE: deployment/kustomizations/examples/secret-wren_example.yaml
================================================
---
apiVersion: v1
kind: Secret
metadata:
name: wrenai-secrets
type: Opaque
data:
# OPENAI_API_KEY is REQUIRED: without a valid key the wren-ai-service-deployment pod will not start
OPENAI_API_KEY: UkVRVUlSRUQ6IHNrLXByb2otYWxsLWFjY2Vzcy1wbGFjZWhvbGRlci00LXdyZW4tYWktc2VydmljZS1kZXBsb3ltZW50
# Azure openai env
AZURE_CHAT_BASE: bi9h
AZURE_CHAT_KEY: bi9h
AZURE_CHAT_VERSION: bi9h
AZURE_EMBED_BASE: bi9h
AZURE_EMBED_KEY: bi9h
AZURE_EMBED_VERSION: bi9h
# Langfuse: for LLM tracing
LANGFUSE_PUBLIC_KEY: xxxx
LANGFUSE_SECRET_KEY: xxxx
### postgres:// This is the protocol. It tells the system that you’re connecting to a PostgreSQL database.
### postgres:postgres These are the username and password for the database, separated by a colon. In this case, both the username and password are “postgres”.
### @wren-postgresql This is the hostname of the database server. "wren-postgresql" means the database server is running in a Kubernetes cluster and it is named "wren-postgresql" in the *same* namespace. If you are using another namespace you must provide the full hostname, example: `wren-postgresql.wrenai.svc.cluster.local`, "wrenai" is the namespace name, "svc.cluster.local" is the default domain name for Kubernetes services no need to change it.
### :5432 This is the port number. PostgreSQL servers listen on port 5432 by default.
### /admin_ui This is the name of the database you’re connecting to. In this case, the database name is “admin_ui”. It can be found in the helm values file in the auth.database parameter (deployment/kustomizations/helm-values_postgresql_14.yaml)
### PG_URL: "postgres://postgres:postgres@wren-postgresql:5432/admin_ui"
#Fix
PG_URL: cG9zdGdyZXM6Ly9wb3N0Z3Jlczpwb3N0Z3Jlc0B3cmVuLXBvc3RncmVzcWw6NTQzMi9hZG1pbl91aQo=
PG_USERNAME: cG9zdGdyZXM=
POSTHOG_API_KEY: cGhjX2tleS1wbGFjZWhvbGRlcg==
POSTHOG_HOST: aHR0cHM6Ly9hcHAucG9zdGhvZy5jb20=
USER_UUID: MDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAw
---
apiVersion: v1
kind: Secret
metadata:
name: wrenai-postgresql
data:
postgres-password: cG9zdGdyZXM=
type: Opaque
================================================
FILE: deployment/kustomizations/helm-values-qdrant_1.11.0.yaml
================================================
replicaCount: 1
image:
repository: docker.io/qdrant/qdrant
pullPolicy: IfNotPresent
tag: "v1.11.0"
useUnprivilegedImage: false
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
args: ["./config/initialize.sh"]
env: {}
# - name: QDRANT_ALLOW_RECOVERY_MODE
# value: true
# checks - Readiness and liveness checks can only be enabled for either http (REST) or grpc (multiple checks not supported)
# grpc checks are only available from k8s 1.24+ so as of per default we check http
service:
type: ClusterIP
additionalLabels: {}
annotations: {}
loadBalancerIP: ""
ports:
- name: http
port: 6333
targetPort: 6333
protocol: TCP
checksEnabled: true
- name: grpc
port: 6334
targetPort: 6334
protocol: TCP
checksEnabled: false
- name: p2p
port: 6335
targetPort: 6335
protocol: TCP
checksEnabled: false
ingress:
enabled: false
ingressClassName: "nginx"
additionalLabels: {}
annotations:
# Dependancy: https://kubernetes-sigs.github.io/external-dns
#external-dns.alpha.kubernetes.io/filter: 'include'
#external-dns.alpha.kubernetes.io/cloudflare-proxied: 'true'
external-dns.alpha.kubernetes.io/target: ingress1.myhost.net
hosts:
- host: qdrant-ai.myhost.net
paths:
- path: /
pathType: Prefix
servicePort: 6333
tls:
- hosts:
- qdrant-ai.myhost.net
secretName: qdrant-ai.myhost.net-tls
livenessProbe:
enabled: false
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 1
failureThreshold: 6
successThreshold: 1
readinessProbe:
enabled: true
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 1
failureThreshold: 6
successThreshold: 1
startupProbe:
enabled: false
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 1
failureThreshold: 30
successThreshold: 1
additionalLabels: {}
podAnnotations: {}
podLabels: {}
resources: {}
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
containerSecurityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 2000
allowPrivilegeEscalation: false
privileged: false
readOnlyRootFilesystem: true
podSecurityContext:
fsGroup: 3000
fsGroupChangePolicy: Always
lifecycle:
preStop:
exec:
# Sleeping before shutdown allows Qdrant to process requests that were
# in-flight before the node is removed from load-balancing.
# If using an external load balancer, you may need to increase this
# duration to be greater than the LB's health check interval.
command: ["sleep", "3"]
# If true ensures that the pre-existing files on the storage and snapshot volume are owned by the container's
# user and fsGroup
updateVolumeFsOwnership: true
nodeSelector: {}
tolerations: []
affinity: {}
topologySpreadConstraints: []
persistence:
accessModes: ["ReadWriteOnce"]
size: 20Gi
annotations: {}
# storageClassName: vsphere-retain
# If you use snapshots or the snapshot shard transfer mechanism, we recommend
# creating a separate volume of the same size as your main volume so that your
# cluster won't crash if the snapshot is too big.
snapshotPersistence:
enabled: false
accessModes: ["ReadWriteOnce"]
size: 20Gi
annotations: {}
# You can change the storageClassName to ensure snapshots are saved to cold storage.
# storageClassName: local-path
snapshotRestoration:
enabled: false
# Set pvcName if you want to restore from a separately-created PVC. Only supported for single-node clusters unless the PVC is ReadWriteMany.
# If you set snapshotPersistence.enabled and want to restore a snapshot from there, you can leave this blank to skip mounting an external volume.
pvcName: snapshots-pvc
# Must not conflict with /qdrant/snapshots or /qdrant/storage
mountPath: /qdrant/snapshot-restoration
snapshots:
# - /qdrant/snapshot-restoration/test_collection/test_collection-2022-10-24-13-56-50.snapshot:test_collection
# modification example for configuration to overwrite defaults
config:
cluster:
enabled: true
p2p:
port: 6335
consensus:
tick_period_ms: 100
sidecarContainers: []
# sidecarContainers:
# - name: my-sidecar
# image: qdrant/my-sidecar-image
# imagePullPolicy: Always
# ports:
# - name: my-port
# containerPort: 5000
# protocol: TCP
# resources:
# requests:
# memory: 10Mi
# cpu: 10m
# limits:
# memory: 100Mi
# cpu: 100m
metrics:
serviceMonitor:
enabled: false
additionalLabels: {}
scrapeInterval: 30s
scrapeTimeout: 10s
targetPort: http
targetPath: "/metrics"
## MetricRelabelConfigs to apply to samples after scraping, but before ingestion.
## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig
##
metricRelabelings: []
## RelabelConfigs to apply to samples before scraping
## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#relabelconfig
##
relabelings: []
serviceAccount:
annotations: {}
priorityClassName: ""
# We disourage changing this setting. Using the "OrderedReady" policy in a
# multi-node cluster will cause a deadlock where nodes refuse to become
# "Ready" until all nodes are running.
podManagementPolicy: Parallel
podDisruptionBudget:
enabled: false
maxUnavailable: 1
# do not enable if you are using not in 1.27
unhealthyPodEvictionPolicy: ""
# minAvailable: 1
# api key for authentication at qdrant
# false: no api key will be configured
# true: an api key will be auto-generated
# string: the given string will be set as an apikey
apiKey: false
# read-only api key for authentication at qdrant
# false: no read-only api key will be configured
# true: an read-only api key will be auto-generated
# string: the given string will be set as a read-only apikey
readOnlyApiKey: false
additionalVolumes: []
# - name: volumeName
# emptyDir: {}
additionalVolumeMounts: []
# - name: volumeName
# mountPath: "/mount/path"
================================================
FILE: deployment/kustomizations/helm-values_postgresql_15.yaml
================================================
auth:
secretKeys:
adminPasswordKey: postgres-password
existingSecret: wrenai-postgresql
#creates admin_ui database
global:
postgresql:
auth:
database: admin_ui
================================================
FILE: deployment/kustomizations/kustomization.yaml
================================================
##### Dependancies used in this kustomization:
# nginx.ingress
# external-dns
# cert-manager
# kubectl kustomize
#test output like this:
#kubectl kustomize deployment/kustomizations --enable-helm > deployment/kustomizations/wrenai.kustimized.yaml
#kubectl create namespace wren
#kubectl apply -f deployment/kustomizations/wrenai.kustimized.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
# Namespace for all resources here and in the Helm charts
namespace: wren
helmCharts:
### Uncomment if you are planing to use postgresql
- name: postgresql
repo: https://repo.vmware.com/bitnami-files
version: 15.5.5
releaseName: wren-postgresql
valuesFile: helm-values_postgresql_15.yaml
includeCRDs: true
# the Same Namespace
namespace: wren
- name: qdrant
repo: https://qdrant.github.io/qdrant-helm
version: 1.11.0
releaseName: wren-qdrant
valuesFile: helm-values-qdrant_1.11.0.yaml
includeCRDs: true
# The Same Namespace
namespace: wren
images:
# for the latest versions, please check here: https://github.com/Canner/WrenAI/blob/main/docker/.env.example#L23
- name: ghcr.io/canner/wren-bootstrap
newTag: 0.1.5 # WREN_BOOTSTRAP_VERSION
- name: ghcr.io/canner/wren-engine
newTag: 0.14.8 # WREN_ENGINE_VERSION
- name: ghcr.io/canner/wren-ui
newTag: 0.24.1 # WREN_UI_VERSION
- name: ghcr.io/canner/wren-ai-service
newTag: 0.19.7 # WREN_AI_SERVICE_VERSION
- name: ghcr.io/canner/wren-engine-ibis
newTag: 0.14.8 # IBIS_SERVER_VERSION
resources:
- base/cm.yaml
- base/deploy-wren-ui.yaml
- base/deploy-wren-engine.yaml
- base/deploy-wren-ibis-server.yaml
- base/deploy-wren-ai-service.yaml
- base/pvc.yaml
- base/svc.yaml
### Modify these examples first and uncomment them:
# - examples/ingress-wren_example.yaml
# - examples/certificate-wren_example.yaml
### Usually you do not need to generate a certificate for Qdrant
# - examples/certificate-qdrant_example.yaml
### Best practice is to create and deploy Secrets manually, not as part of kustomization or GitOps!
# - examples/secret-wren_example.yaml
================================================
FILE: deployment/kustomizations/patches/README.md
================================================
# Example of usefull Patches for Kustomization
Patches from this folder allows to utilize the official unmodified deployment/kustomization dirrectly from the repo as a base layer for your kustomization. And then add patches to update some values. This is usefull for your GitOps and can be combined with tools such as ArgoCD and FluxCD.
Patch ConfigMap, and Service if needed.
Remove Certificate and Ingress if not needed.
================================================
FILE: deployment/kustomizations/patches/cm.yaml
================================================
- op: replace
path: /data
value:
# Wren Engine Service Port
WREN_ENGINE_PORT: "8080"
# Wren AI Service Port
WREN_AI_SERVICE_PORT: "5555"
#Release version used by wren ui https://github.com/Canner/WrenAI/blob/main/docker/docker-compose.yaml#L85-L88
WREN_PRODUCT_VERSION: "0.12.0"
#fix:
WREN_ENGINE_VERSION: "0.12.3"
WREN_AI_SERVICE_VERSION: "0.12.1"
#fix:
WREN_UI_VERSION: "0.17.6"
# OpenAI
GENERATION_MODEL: "gpt-4o-mini"
# Telemetry
POSTHOG_HOST: "https://app.posthog.com"
TELEMETRY_ENABLED: "false"
# service endpoints of AI service & engine service
WREN_ENGINE_ENDPOINT: "http://wren-engine-svc:8080"
#fix:
WREN_AI_ENDPOINT: "http://wren-ai-service:5555"
# "pg" for postgres as application database.
#fix
DB_TYPE: pg
DATA_PATH: "/app/data"
### if DB_TYPE = "postgres" you must provide PG_URL string in the *Secret* manifest file (deployment/kustomizations/examples/secret-wren_example.yaml) to connect to postgres
================================================
FILE: deployment/kustomizations/patches/rm-certificate.yaml
================================================
$patch: delete
apiVersion: v1
kind: Certificate
metadata:
name: wren-ui.myhost.net
================================================
FILE: deployment/kustomizations/patches/rm-ingress.yaml
================================================
$patch: delete
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: wren-ui-ingress
annotations:
external-dns.alpha.kubernetes.io/target: ingress1.myhost.net
================================================
FILE: deployment/kustomizations/patches/service.yaml
================================================
- op: replace
path: /spec/ipFamilies
value:
- IPv6
- IPv4
- op: replace
path: /spec/type
value:
LoadBalancer
- op: replace
path: /spec/ipFamilyPolicy
value:
# SingleStack
PreferDualStack
================================================
FILE: docker/README.md
================================================
## Service
- `wren-engine`: the engine service. check out example here: [wren-engine
/example](https://github.com/Canner/wren-engine/tree/main/example)
- `wren-ai-service`: the AI service.
- `qdrant`: the vector store ai service is using.
- `wren-ui`: the UI service.
- `bootstrap`: put required files to volume for engine service.
## Volume
Shared data using `data` volume.
Path structure as following:
- `/mdl`
- `*.json` (will put `sample.json` during bootstrap)
- `accounts`
- `config.properties`
## Network
- Check out [Network drivers overview](https://docs.docker.com/engine/network/drivers/) to learn more about `bridge` network driver.
## How to start with OpenAI
1. copy `.env.example` to `.env` and modify the OpenAI API key.
2. copy `config.example.yaml` to `config.yaml` for AI service configuration.
3. start all services: `docker-compose --env-file .env up -d`.
4. stop all services: `docker-compose --env-file .env down`.
### Optional
- If your port 3000 is occupied, you can modify the `HOST_PORT` in `.env`.
## How to start with custom LLM
To start with a custom LLM, the process is similar to starting with OpenAI. The main difference is that you need to modify the `config.yaml` file
that we created on the previous step. After modifying the file, you can restart the services by running `docker-compose --env-file .env up -d --force-recreate wren-ai-service`.
For detailed information on how to modify the configuration for different LLM providers and models, please refer to the [AI Service Configuration](../wren-ai-service/docs/configuration.md).
This guide provides comprehensive instructions on setting up various LLM providers, embedders, and other components of the AI service.
================================================
FILE: docker/bootstrap/Dockerfile
================================================
FROM busybox
WORKDIR /app
COPY init.sh ./
================================================
FILE: docker/bootstrap/init.sh
================================================
#!/bin/sh
# declare a variable from the environment variable: DATA_PATH
data_path=${DATA_PATH:-"./"}
# touch a empty config.properties if not exists
# put a content into config.properties if not exists
if [ ! -f ${data_path}/config.properties ]; then
echo "init config.properties"
echo "node.environment=production" >${data_path}/config.properties
fi
# after the config.properties is created, check if config properties properly set
# if not, then append default values to the config.properties
# check if wren.experimental-enable-dynamic-fields is set, otherwise append it with true
if ! grep -q "wren.experimental-enable-dynamic-fields" ${data_path}/config.properties; then
echo "wren.experimental-enable-dynamic-fields is not set, set it to true"
echo "wren.experimental-enable-dynamic-fields=true" >>${data_path}/config.properties
fi
# create a folder mdl if not exists
if [ ! -d ${data_path}/mdl ]; then
echo "create mdl folder"
mkdir ${data_path}/mdl
fi
# put an emtpy sample.json if not exists
if [ ! -f ${data_path}/mdl/sample.json ]; then
echo "init mdl/sample.json"
echo "{\"catalog\": \"test_catalog\", \"schema\": \"test_schema\", \"models\": []}" >${data_path}/mdl/sample.json
fi
================================================
FILE: docker/config.example.yaml
================================================
type: llm
provider: litellm_llm
timeout: 120
models:
- alias: default
model: gpt-4.1-nano-2025-04-14
context_window_size: 1000000
kwargs:
max_tokens: 4096
n: 1
seed: 0
temperature: 0
- model: gpt-4.1-mini-2025-04-14
context_window_size: 1000000
kwargs:
max_tokens: 4096
n: 1
seed: 0
temperature: 0
- model: gpt-4.1-2025-04-14
context_window_size: 1000000
kwargs:
max_tokens: 4096
n: 1
seed: 0
temperature: 0
- model: gpt-5-nano-2025-08-07
context_window_size: 380000
kwargs:
max_completion_tokens: 4096
n: 1
seed: 0
reasoning_effort: minimal
- model: gpt-5-mini-2025-08-07
context_window_size: 380000
kwargs:
max_completion_tokens: 4096
n: 1
seed: 0
reasoning_effort: minimal
- model: gpt-5-2025-08-07
context_window_size: 380000
kwargs:
max_completion_tokens: 4096
n: 1
seed: 0
reasoning_effort: minimal
---
type: embedder
provider: litellm_embedder
models:
- model: text-embedding-3-large
alias: default
timeout: 120
---
type: engine
provider: wren_ui
endpoint: http://wren-ui:3000
---
type: engine
provider: wren_ibis
endpoint: http://ibis-server:8000
---
type: document_store
provider: qdrant
location: http://qdrant:6333
embedding_model_dim: 3072
timeout: 120
recreate_index: true
---
type: pipeline
pipes:
- name: db_schema_indexing
embedder: litellm_embedder.default
document_store: qdrant
- name: historical_question_indexing
embedder: litellm_embedder.default
document_store: qdrant
- name: table_description_indexing
embedder: litellm_embedder.default
document_store: qdrant
- name: db_schema_retrieval
llm: litellm_llm.default
embedder: litellm_embedder.default
document_store: qdrant
- name: historical_question_retrieval
embedder: litellm_embedder.default
document_store: qdrant
- name: sql_generation
llm: litellm_llm.default
engine: wren_ui
document_store: qdrant
- name: sql_correction
llm: litellm_llm.default
engine: wren_ui
document_store: qdrant
- name: followup_sql_generation
llm: litellm_llm.default
engine: wren_ui
document_store: qdrant
- name: sql_answer
llm: litellm_llm.default
- name: semantics_description
llm: litellm_llm.default
- name: relationship_recommendation
llm: litellm_llm.default
- name: question_recommendation
llm: litellm_llm.default
- name: question_recommendation_sql_generation
llm: litellm_llm.default
engine: wren_ui
document_store: qdrant
- name: intent_classification
llm: litellm_llm.default
embedder: litellm_embedder.default
document_store: qdrant
- name: misleading_assistance
llm: litellm_llm.default
- name: data_assistance
llm: litellm_llm.default
- name: sql_pairs_indexing
document_store: qdrant
embedder: litellm_embedder.default
- name: sql_pairs_retrieval
document_store: qdrant
embedder: litellm_embedder.default
llm: litellm_llm.default
- name: preprocess_sql_data
llm: litellm_llm.default
- name: sql_executor
engine: wren_ui
- name: chart_generation
llm: litellm_llm.default
- name: chart_adjustment
llm: litellm_llm.default
- name: user_guide_assistance
llm: litellm_llm.default
- name: sql_question_generation
llm: litellm_llm.default
- name: sql_generation_reasoning
llm: litellm_llm.default
- name: followup_sql_generation_reasoning
llm: litellm_llm.default
- name: sql_regeneration
llm: litellm_llm.default
engine: wren_ui
- name: instructions_indexing
embedder: litellm_embedder.default
document_store: qdrant
- name: instructions_retrieval
embedder: litellm_embedder.default
document_store: qdrant
- name: sql_functions_retrieval
engine: wren_ibis
document_store: qdrant
- name: project_meta_indexing
document_store: qdrant
- name: sql_tables_extraction
llm: litellm_llm.default
- name: sql_diagnosis
llm: litellm_llm.default
- name: sql_knowledge_retrieval
engine: wren_ibis
document_store: qdrant
---
settings:
doc_endpoint: https://docs.getwren.ai
is_oss: true
engine_timeout: 30
column_indexing_batch_size: 50
table_retrieval_size: 10
table_column_retrieval_size: 100
allow_intent_classification: true
allow_sql_generation_reasoning: true
allow_sql_functions_retrieval: true
enable_column_pruning: false
max_sql_correction_retries: 3
query_cache_maxsize: 1000
query_cache_ttl: 3600
langfuse_host: https://cloud.langfuse.com
langfuse_enable: true
logging_level: DEBUG
development: false
historical_question_retrieval_similarity_threshold: 0.9
sql_pairs_similarity_threshold: 0.7
sql_pairs_retrieval_max_size: 10
instructions_similarity_threshold: 0.7
instructions_top_k: 10
================================================
FILE: docker/docker-compose-dev.yaml
================================================
version: "3"
volumes:
data:
networks:
wren:
driver: bridge
services:
bootstrap:
image: ghcr.io/canner/wren-bootstrap:${WREN_BOOTSTRAP_VERSION}
pull_policy: always
platform: ${PLATFORM}
environment:
DATA_PATH: /app/data
volumes:
- data:/app/data
command: /bin/sh /app/init.sh
wren-engine:
image: ghcr.io/canner/wren-engine:${WREN_ENGINE_VERSION}
pull_policy: always
platform: ${PLATFORM}
expose:
- ${WREN_ENGINE_SQL_PORT}
ports:
- ${WREN_ENGINE_PORT}:${WREN_ENGINE_PORT}
volumes:
- data:/usr/src/app/etc
networks:
- wren
depends_on:
- bootstrap
wren-ai-service:
image: ghcr.io/canner/wren-ai-service:${WREN_AI_SERVICE_VERSION}
pull_policy: always
platform: ${PLATFORM}
ports:
- ${AI_SERVICE_FORWARD_PORT}:${WREN_AI_SERVICE_PORT}
environment:
WREN_UI_ENDPOINT: http://host.docker.internal:${WREN_UI_PORT}
# sometimes the console won't show print messages,
# using PYTHONUNBUFFERED: 1 can fix this
PYTHONUNBUFFERED: 1
CONFIG_PATH: /app/config.yaml
env_file:
- ${PROJECT_DIR}/.env
volumes:
- ${PROJECT_DIR}/config.yaml:/app/config.yaml:ro
- ${PROJECT_DIR}/data:/app/data:ro
networks:
- wren
depends_on:
- qdrant
ibis-server:
image: ghcr.io/canner/wren-engine-ibis:${IBIS_SERVER_VERSION}
pull_policy: always
platform: ${PLATFORM}
expose:
- 8000
ports:
- ${IBIS_SERVER_PORT}:8000
environment:
WREN_ENGINE_ENDPOINT: http://wren-engine:${WREN_ENGINE_PORT}
LOG_LEVEL: DEBUG
networks:
- wren
qdrant:
image: qdrant/qdrant:v1.11.0
pull_policy: always
ports:
- 6333:6333
- 6334:6334
networks:
- wren
# If you want to use postgres for testing purpose, uncomment the following block
# postgres:
# image: postgres:14-alpine
# platform: ${PLATFORM}
# ports:
# - 9432:5432
# volumes:
# - data:/var/lib/postgresql/data
# environment:
# - POSTGRES_PASSWORD=secret
# - POSTGRES_USER=test
# - POSTGRES_DB=test
# - PGDATA=/var/lib/postgresql/data/pgdata
# networks:
# - wren
================================================
FILE: docker/docker-compose.yaml
================================================
version: "3"
volumes:
data:
networks:
wren:
driver: bridge
services:
bootstrap:
image: ghcr.io/canner/wren-bootstrap:${WREN_BOOTSTRAP_VERSION}
restart: on-failure
platform: ${PLATFORM}
environment:
DATA_PATH: /app/data
volumes:
- data:/app/data
command: /bin/sh /app/init.sh
wren-engine:
image: ghcr.io/canner/wren-engine:${WREN_ENGINE_VERSION}
restart: on-failure
platform: ${PLATFORM}
expose:
- ${WREN_ENGINE_PORT}
- ${WREN_ENGINE_SQL_PORT}
volumes:
- data:/usr/src/app/etc
- ${PROJECT_DIR}/data:/usr/src/app/data
networks:
- wren
depends_on:
- bootstrap
ibis-server:
image: ghcr.io/canner/wren-engine-ibis:${IBIS_SERVER_VERSION}
restart: on-failure
platform: ${PLATFORM}
expose:
- ${IBIS_SERVER_PORT}
environment:
WREN_ENGINE_ENDPOINT: http://wren-engine:${WREN_ENGINE_PORT}
volumes:
- ${LOCAL_STORAGE:-.}:/usr/src/app/data
networks:
- wren
wren-ai-service:
image: ghcr.io/canner/wren-ai-service:${WREN_AI_SERVICE_VERSION}
restart: on-failure
platform: ${PLATFORM}
expose:
- ${WREN_AI_SERVICE_PORT}
ports:
- ${AI_SERVICE_FORWARD_PORT}:${WREN_AI_SERVICE_PORT}
environment:
# sometimes the console won't show print messages,
# using PYTHONUNBUFFERED: 1 can fix this
PYTHONUNBUFFERED: 1
CONFIG_PATH: /app/config.yaml
env_file:
- ${PROJECT_DIR}/.env
volumes:
- ${PROJECT_DIR}/config.yaml:/app/config.yaml:ro
- ${PROJECT_DIR}/data:/app/data:ro
networks:
- wren
depends_on:
- qdrant
qdrant:
image: qdrant/qdrant:v1.11.0
restart: on-failure
expose:
- 6333
- 6334
volumes:
- data:/qdrant/storage
networks:
- wren
wren-ui:
image: ghcr.io/canner/wren-ui:${WREN_UI_VERSION}
restart: on-failure
platform: ${PLATFORM}
environment:
DB_TYPE: sqlite
# /app is the working directory in the container
SQLITE_FILE: /app/data/db.sqlite3
WREN_ENGINE_ENDPOINT: http://wren-engine:${WREN_ENGINE_PORT}
WREN_AI_ENDPOINT: http://wren-ai-service:${WREN_AI_SERVICE_PORT}
IBIS_SERVER_ENDPOINT: http://ibis-server:${IBIS_SERVER_PORT}
# this is for telemetry to know the model, i think ai-service might be able to provide a endpoint to get the information
GENERATION_MODEL: ${GENERATION_MODEL}
# telemetry
WREN_ENGINE_PORT: ${WREN_ENGINE_PORT}
WREN_AI_SERVICE_VERSION: ${WREN_AI_SERVICE_VERSION}
WREN_UI_VERSION: ${WREN_UI_VERSION}
WREN_ENGINE_VERSION: ${WREN_ENGINE_VERSION}
USER_UUID: ${USER_UUID}
POSTHOG_API_KEY: ${POSTHOG_API_KEY}
POSTHOG_HOST: ${POSTHOG_HOST}
TELEMETRY_ENABLED: ${TELEMETRY_ENABLED}
# client side
NEXT_PUBLIC_USER_UUID: ${USER_UUID}
NEXT_PUBLIC_POSTHOG_API_KEY: ${POSTHOG_API_KEY}
NEXT_PUBLIC_POSTHOG_HOST: ${POSTHOG_HOST}
NEXT_PUBLIC_TELEMETRY_ENABLED: ${TELEMETRY_ENABLED}
EXPERIMENTAL_ENGINE_RUST_VERSION: ${EXPERIMENTAL_ENGINE_RUST_VERSION}
# configs
WREN_PRODUCT_VERSION: ${WREN_PRODUCT_VERSION}
ports:
# HOST_PORT is the port you want to expose to the host machine
- ${HOST_PORT}:3000
volumes:
- data:/app/data
networks:
- wren
depends_on:
- wren-ai-service
- wren-engine
================================================
FILE: wren-ai-service/.dockerignore
================================================
*
!src
!entrypoint.sh
!pyproject.toml
src/eval
================================================
FILE: wren-ai-service/.pre-commit-config.yaml
================================================
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.2.2
hooks:
# Run the linter.
- id: ruff
args: [ --fix ]
# Run the formatter.
- id: ruff-format
================================================
FILE: wren-ai-service/CONTRIBUTING.md
================================================
# Welcome to Wren AI Service contributing guide
Thank you for investing your time in contributing to our project! This document provides guidelines for contributing to the Wren AI service.
## New contributor guide
- To get an overview of the project, please read the [concepts](https://docs.getwren.ai/oss/concept/wren_ai_service).
- To set up the project for local development, please read [Environment Setup](README.md#environment-setup) and [Start the service for development](README.md#start-the-service-for-development)
- To understand the codebase more quickly, we've prepared [a codebase introduciton](docs/code_design.md) for you.
## Getting started
### Issues
#### Create a new issue
If you spot a problem, search if an issue already exists. If a related issue doesn't exist, you can open a new [issue](https://github.com/Canner/WrenAI/issues/new/choose).
#### Solve an issue
Scan through our [existing issues](https://github.com/Canner/WrenAI/issues?q=is%3Aopen+is%3Aissue+label%3Amodule%2Fai-service) to find one that interests you. As a general rule, we don't assign issues to anyone. If you find an issue to work on, you are welcome to open a PR with a fix.
### Pull Request
When you've finished with the changes, create a pull request, also known as a PR.
- Fill the description so that we can review your PR.
- Don't forget to [link PR to issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) if you are solving one.
- Add the `module/ai-service` label to your PR.
- Enable the checkbox to [allow maintainer edits](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/allowing-changes-to-a-pull-request-branch-created-from-a-fork) so the branch can be updated for a merge.
Once you submit your PR, a Canner team member will review your proposal. We may ask questions or request additional information.
- We may ask for changes to be made before a PR can be merged, either using [suggested changes](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/incorporating-feedback-in-your-pull-request) or pull request comments. You can apply suggested changes directly through the UI. You can make any other changes in your fork, then commit them to your branch.
- As you update your PR and apply changes, mark each conversation as [resolved](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/commenting-on-a-pull-request#resolving-conversations).
- Be sure to add one of the prefixes to the PR title, so that our CI could automatically capture the changelog of this PR.
- `feat(wren-ai-service)`: for new features
- `chore(wren-ai-service)`: for maintenance work
- `fix(wren-ai-service)`: for bug fixes
- If you run into any merge issues, checkout this [git tutorial](https://github.com/skills/resolve-merge-conflicts) to help you resolve merge conflicts and other issues.
### Your PR is merged!
Congratulations :tada::tada: The Canner team thanks you :sparkles:.
Once your PR is merged, your contributions will be worked on the next release.
Now that you are part of the Canner community.
## How to add your preferred LLM, Embedder or Document Store
- Please read [this documentation for further details](https://docs.getwren.ai/oss/ai_service/guide/custom_llm#adding-a-custom-llm-embedder-or-document-store-to-wren-ai).
================================================
FILE: wren-ai-service/Justfile
================================================
GREEN := "\u{001b}[32m"
YELLOW := "\u{001b}[33m"
RESET := "\u{001b}[0m"
## todo: consider to support --override flag to override existing files
init dev='--dev':
@if [ ! -f config.yaml ]; then \
echo "{{GREEN}}config.yaml does not exist. Creating from example...{{RESET}}"; \
cp tools/config/config.example.yaml config.yaml; \
else \
echo "{{YELLOW}}config.yaml already exists. Skipping creation.{{RESET}}"; \
fi
@if [ {{dev}} = "--dev" ] || [ {{dev}} != "--non-dev" ]; then \
if [ ! -f .env.dev ]; then \
echo "{{GREEN}}.env.dev does not exist. Creating from example...{{RESET}}"; \
cp tools/config/.env.dev.example .env.dev; \
else \
echo "{{YELLOW}}.env.dev already exists. Skipping creation.{{RESET}}"; \
fi \
fi
up: prepare-files
docker compose -f ./tools/dev/docker-compose-dev.yaml --env-file ./tools/dev/.env up -d
down:
docker compose -f ./tools/dev/docker-compose-dev.yaml --env-file ./tools/dev/.env down
start: force_update_config
poetry run python -m src.__main__
curate_eval_data:
poetry run streamlit run eval/data_curation/app.py
prep dataset='spider1.0':
poetry run python -m eval.preparation --dataset {{dataset}}
predict dataset pipeline='ask':
poetry run python -u eval/prediction.py --file {{dataset}} --pipeline {{pipeline}}
eval prediction_result semantics='--no-semantics':
poetry run python -u eval/evaluation.py --file {{prediction_result}} {{semantics}}
test test_args='': up && down
poetry run pytest -s {{test_args}} --ignore tests/pytest/test_usecases.py
test-usecases usecases='all' lang='en':
poetry run python -m tests.pytest.test_usecases --usecases {{usecases}} --lang {{lang}}
load-test:
poetry run python -m tests.locust.locust_script
prepare-files:
# only remove files related to engine and ui
rm -rf tools/dev/etc/duckdb tools/dev/etc/mdl tools/dev/etc/config.properties tools/dev/etc/db.sqlite3 tools/dev/etc/archived
mkdir -p tools/dev/etc
cp tools/dev/config.properties.example tools/dev/etc/config.properties
mkdir -p tools/dev/etc/mdl
echo "{\"catalog\": \"test_catalog\", \"schema\": \"test_schema\", \"models\": []}" \\
> tools/dev/etc/mdl/sample.json
force_update_config:
poetry run python -m src.force_update_config
run-sql mdl_path="" data_source="" sample_dataset="":
poetry run python tools/run_sql.py --mdl-path "{{mdl_path}}" --data-source "{{data_source}}" --sample-dataset "{{sample_dataset}}"
mdl-to-str mdl_path="":
poetry run python tools/mdl_to_str.py -p {{mdl_path}}
================================================
FILE: wren-ai-service/README.md
================================================
# AI Service of Wren AI
## Concepts
Please read the [documentation](https://docs.getwren.ai/oss/concept/wren_ai_service) here to understand the concepts of Wren AI Service.
## Setup for Local Development
### Prerequisites
1. **Python**: Install Python 3.12.\*
- Recommended: Use [`pyenv`](https://github.com/pyenv/pyenv?tab=readme-ov-file#installation) to manage Python versions
2. **Poetry**: Install Poetry 1.8.3
```bash
curl -sSL https://install.python-poetry.org | python3 - --version 1.8.3
```
3. **Just**: Install [Just](https://github.com/casey/just?tab=readme-ov-file#packages) command runner (version 1.36 or higher)
### Step-by-Step Setup
1. **Install Dependencies**:
```bash
poetry install
```
2. **Generate Configuration Files**:
```bash
just init
```
This creates both `.env.dev` and `config.yaml`. Use `just init --non-dev` to generate only `config.yaml`.
> For Windows, add the line `set shell:= ["bash", "-cu"]` at the start of the Justfile.
4. **Configure Environment**:
- Edit `.env.dev` to set environment variables
- Modify `config.yaml` to configure components, pipelines, and other settings
- Refer to [AI Service Configuration](./docs/configuration.md) for detailed setup instructions
5. **Set Up Development Environment** (optional):
- Install pre-commit hooks:
```bash
poetry run pre-commit install
```
- Run initial pre-commit checks:
```bash
poetry run pre-commit run --all-files
```
6. **Run Tests** (optional):
```bash
just test
```
### Starting the Service
1. **Start Required Containers**:
```bash
just up
```
2. **Launch the AI Service**:
```bash
just start
```
3. **Access the Service**:
- API Documentation: `http://WREN_AI_SERVICE_HOST:WREN_AI_SERVICE_PORT` (default: <http://localhost:5556>)
- User Interface: `http://WREN_UI_HOST:WREN_UI_PORT` (default: <http://localhost:3000>)
4. **Stop the Service**:
When finished, stop the containers:
```bash
just down
```
This setup ensures a consistent development environment and helps maintain code quality through pre-commit hooks and tests. Follow these steps to get started with local development of the Wren AI Service.
## Others
### Pipeline Evaluation
For a comprehensive understanding of how to evaluate the pipelines, please refer to the [evaluation framework](./eval/README.md). This document provides detailed guidelines on the evaluation process, including how to set up and run evaluations, interpret results, and utilize the evaluation metrics effectively. It is a valuable resource for ensuring that the evaluation is conducted accurately and that the results are meaningful.
### Estimate the Speed of the Pipeline(may be outdated)
- to run the load test
- setup `DATASET_NAME` in `.env.dev`
- adjust test config if needed
- adjust user count in `tests/locust/config_users.json`
- in wren-ai-service folder, run `just up` to start the docker containers
- in wren-ai-service folder, run `just start` to start the ai service
- run `just load-test`
- check reports in /outputs/locust folder, there are 3 files with filename **locust*report*{test_timestamp}**:
- .json: test report in json format, including info like llm provider, version
- .html: test report in html format, showing tables and charts
- .log: test log
## Contributing
Thank you for investing your time in contributing to our project! Please [read this for more information](CONTRIBUTING.md)!
================================================
FILE: wren-ai-service/docker/Dockerfile
================================================
# reference: https://medium.com/@albertazzir/blazing-fast-python-docker-builds-with-poetry-a78a66f5aed0
FROM python:3.12.0-bookworm as builder
RUN pip install poetry==1.8.3
ENV POETRY_NO_INTERACTION=1 \
POETRY_VIRTUALENVS_IN_PROJECT=1 \
POETRY_VIRTUALENVS_CREATE=1 \
POETRY_CACHE_DIR=/tmp/poetry_cache
WORKDIR /app
COPY pyproject.toml ./
RUN poetry install --without dev,eval,test --no-root && rm -rf $POETRY_CACHE_DIR
FROM python:3.12.0-slim-bookworm as runtime
RUN apt-get update && apt install -y netcat-traditional
ENV VIRTUAL_ENV=/app/.venv \
PATH="/app/.venv/bin:$PATH"
COPY --from=builder ${VIRTUAL_ENV} ${VIRTUAL_ENV}
COPY src src
COPY entrypoint.sh /app/entrypoint.sh
COPY pyproject.toml pyproject.toml
RUN chmod +x /app/entrypoint.sh
ENTRYPOINT [ "/app/entrypoint.sh" ]
================================================
FILE: wren-ai-service/docs/code_design.md
================================================
# Introduction to the codebase of wren-ai-service
## Table of Contents
- [Purpose](#purpose)
- [Environment Setup and Start wren-ai-service Locally](#environment-setup-and-start-wren-ai-service-locally)
- [Codebase Introduction](#codebase-introduction)
- [Entrypoint](#entrypoint)
- [Globals](#globals)
- [API endpoints](#api-endpoints)
- [Services](#services)
- [Pipelines](#pipelines)
- [Providers](#providers)
- [Others](#others)
## Purpose
This document aims to dive deep to the implementation details of wren-ai-service. We have two goals in mind while writing the document:
1. You will be more knowledgeable about how wren-ai-service works under the hood.
2. You will be more confident on what part of codebase is needed for adjustment if you would like to be Wren AI's contributor.
## Environment Setup and Start wren-ai-service Locally
If you haven't setup the environment or don't know how to run wren-ai-service locally, please refer to the [document](../README.md#setup-for-local-development) here first.
## Codebase Introduction
wren-ai-service is basically an AI service which provides REST api endpoints for access. There are 4 main concepts to wren-ai-service: `API endpoints`, `Services`, `Pipelines` and `Providers`.
1. `API endpoints`: They are entry points for users to access several kinds of RAG(retrieval-augmented-generation) systems; you can also see API endpoints as encapsulation of Services. For example, when users need to ask a question in order to get SQL, they need to call `/ask` and there is AskService under the hood for background computation.
2. `Services`: They are abstraction of business-logic concepts, such as AskService for users asking questions to get SQL results back, AskDetailsService for users to get SQL breakdown as several sub-steps in order to understand the logic behind the original SQL. Every service is composed of a series of pipelines.
3. `Pipelines`: Basically RAG systems are actually implemented here. However, not all pipelines have complete indexing, retrieval and generation components; it depends on what's the purpose of the pipeline. Also, every pipeline contains some providers such as LLM provider, which represents an LLM.
4. `Providers`: Now there are 4 kinds of providers:
- llm: representing large language models, and now we support OpenAI, Azure OpenAI, OpenAI api-compatible and Ollama models
- embedder: representing embedding models, and now we support OpenAI, Azure OpenAI, OpenAI api-compatible and Ollama models
- document store: representing vector database, and now we use Qdrant
- engine: representing data engine, which is responsible for validating generated SQL's syntax.
### Entrypoint
- The entry point of wren-ai-service is located at [`wren-ai-service/src/__main__.py`](../src/__main__.py)
- The main point of the entry point is the `lifespan` method, which is FastAPI's feature for defining startup and shutdown logic.
```python
# https://fastapi.tiangolo.com/advanced/events/#lifespan
@asynccontextmanager
async def lifespan(app: FastAPI):
# startup events
pipe_components = generate_components()
app.state.service_container = create_service_container(
pipe_components,
column_indexing_batch_size=(
int(os.getenv("COLUMN_INDEXING_BATCH_SIZE"))
if os.getenv("COLUMN_INDEXING_BATCH_SIZE")
else 50
),
table_retrieval_size=(
int(os.getenv("TABLE_RETRIEVAL_SIZE"))
if os.getenv("TABLE_RETRIEVAL_SIZE")
else 10
),
table_column_retrieval_size=(
int(os.getenv("TABLE_COLUMN_RETRIEVAL_SIZE"))
if os.getenv("TABLE_COLUMN_RETRIEVAL_SIZE")
else 1000
),
query_cache={
# the maxsize is a necessary parameter to init cache, but we don't want to expose it to the user
# so we set it to 1_000_000, which is a large number
"maxsize": 1_000_000,
"ttl": int(os.getenv("QUERY_CACHE_TTL") or 120),
},
)
app.state.service_metadata = create_service_metadata(pipe_components)
init_langfuse()
yield
# shutdown events
langfuse_context.flush()
```
- For startup logic, we initialize pipeline components, service containers(which include all services), service metadata(which is some metadata logged for traces inside [Langfuse, an open-source LLM engineering platform](https://langfuse.com/)) and Langfuse.
- For initializing pipeline components, we are in the progress of supporting multiple LLMs, namely users can choose which LLM is responsible for each pipeline.
- You still need to have `.env.dev` locally, then you can prepare `config.yaml` and run `just start`.
- For shutdown logic, we make sure all Langfuse events are transmitted successfully
### Globals
- The file is located at [`wren-ai-service/src/globals.py`](../src/globals.py)
- You can understand the details of service containers and service metadata here
- service containers(Other services are not supported in UI yet)
- SemanticsPreparationService: this is responsible for indexing [MDL](https://docs.getwren.ai/oss/engine/concept/what_is_mdl) to Qdarnt
- AskService: this is responsible for answering users' questions with SQLs, namely text-to-sql
- AskDetailsService: this is responsible for SQL breakdown to several sub-steps
- service metadata
- We will record llm's and embedding model's metadata, wren-ai-service version, etc.
### API endpoints
- All business related API endpoints are located at [`wren-ai-service/src/web/v1/routers`](../src/web/v1/routers)
- Since computation for each kind of API endpoint(ex. ask, etc.) takes several seconds, so we use FastAPI's `background_tasks`. For example, after the `ask` api is invoked, the response is immediately returned, then users need to conduct polling in order to get the latest task status; and once the status is `finished`, the result is returned correspondingly
- Each kind of API endpoint corresponds to one kind of business related task, for example, AskService, AskDetailsService
### Services
- All services are located at [`wren-ai-service/src/web/v1/services`](../src/web/v1/services)
### Pipelines
- All pipelines are located at [`wren-ai-service/src/pipelines`](../src/pipelines)
- Since all pipelines are actually RAG systems, so we classify the role of each pipeline as indexing, retrieval or generation
- The abstract class is defined at [`wren-ai-service/src/core/pipeline.py`](../src/core/pipeline.py)
### Providers
- All providers are located at [`wren-ai-service/src/providers`](../src/providers)
- The abstract classes for providers(LLM, embedding model and document store) are defined at [`wren-ai-service/src/core/provider.py`](../src/core/provider.py)
- The abstract class for engine is defined at [`wren-ai-service/src/core/engine.py`](../src/core/engine.py)
================================================
FILE: wren-ai-service/docs/config_examples/README.md
================================================
# MUST READ!!!
Since these config files are examples, so **please carefully read the file and comments inside**. Try to understand the purpose of each section and parameter, **don't simply copy and paste the content of these config files into your own config file. It will not work.** For more detailed information to the configurations, please [read this file](../configuration.md).
We also definitely welcome your contribution to add config files for other LLM providers.
## Qwen3 Think and No_Think Configuration
The `config.qwen3.yaml` file provides an example configuration for using Qwen3 models with their unique thinking and non-thinking capabilities. Qwen3 models support two modes:
### Thinking Mode
- Use `/think` in your prompts to enable step-by-step reasoning
- Optimized with `temperature=0.6`, `top_p=0.95`, `top_k=20`
- Best for complex problems requiring detailed reasoning
- Uses the `qwen3-thinking` alias in the pipeline configuration
### Non-Thinking Mode
- Use `/no_think` in your prompts for direct, fast responses
- Optimized with `temperature=0.7`, `top_p=0.8`, `top_k=20`
- Best for simple queries and general conversation
- Uses the `qwen3-fast` alias in the pipeline configuration
### Available Models
- `qwen/qwen3-30b-a3b`: 30B parameter MoE model (3.3B activated)
- `qwen/qwen3-32b`: 32B parameter dense model
- `qwen/qwen3-8b`: 8B parameter dense model
- `qwen/qwen3-14b`: 14B parameter dense model
### Usage Examples
```
# Enable thinking for complex reasoning
"Explain the mathematical proof for the Pythagorean theorem /think"
# Use fast mode for simple queries
"What is the capital of France? /no_think"
```
**Note**: You need to set `OPENROUTER_API_KEY` in your `~/.wrenai/.env` file to use OpenRouter as the provider for Qwen3 models.
================================================
FILE: wren-ai-service/docs/config_examples/config.anthropic.yaml
================================================
# you should rename this file to config.yaml and put it in ~/.wrenai
# please pay attention to the comments starting with # and adjust the config accordingly, 3 steps basically:
# 1. you need to use your own llm and embedding models
# 2. fill in embedding model dimension in the document_store section
# 3. you need to use the correct pipe definitions based on https://raw.githubusercontent.com/canner/WrenAI/<WRENAI_VERSION_NUMBER>/docker/config.example.yaml
# 4. you need to fill in correct llm and embedding models in the pipe definitions
type: llm
provider: litellm_llm
timeout: 120
models:
# put ANTHROPIC_API_KEY=<your_api_key> in ~/.wrenai/.env
- api_base: https://api.anthropic.com
model: anthropic/claude-3-7-sonnet-20250219
alias: default
timeout: 600
kwargs:
n: 1
temperature: 0
---
type: embedder
provider: litellm_embedder
models:
# anthropic embedding model is not supported yet, so we use openai embedding model as a workaround
- model: text-embedding-3-large
alias: default
timeout: 120
---
type: engine
provider: wren_ui
endpoint: http://wren-ui:3000
---
type: engine
provider: wren_ibis
endpoint: http://ibis-server:8000
---
type: document_store
provider: qdrant
location: http://qdrant:6333
embedding_model_dim: 3072 # put your embedding model dimension here
timeout: 120
recreate_index: true
---
type: pipeline
pipes:
- name: db_schema_indexing
embedder: litellm_embedder.default
document_store: qdrant
- name: historical_question_indexing
embedder: litellm_embedder.default
document_store: qdrant
- name: table_description_indexing
embedder: litellm_embedder.default
document_store: qdrant
- name: db_schema_retrieval
llm: litellm_llm.default
embedder: litellm_embedder.default
document_store: qdrant
- name: historical_question_retrieval
embedder: litellm_embedder.default
document_store: qdrant
- name: sql_generation
llm: litellm_llm.default
engine: wren_ui
document_store: qdrant
- name: sql_correction
llm: litellm_llm.default
engine: wren_ui
document_store: qdrant
- name: followup_sql_generation
llm: litellm_llm.default
engine: wren_ui
document_store: qdrant
- name: sql_answer
llm: litellm_llm.default
- name: semantics_description
llm: litellm_llm.default
- name: relationship_recommendation
llm: litellm_llm.default
engine: wren_ui
- name: question_recommendation
llm: litellm_llm.default
- name: question_recommendation_db_schema_retrieval
llm: litellm_llm.default
embedder: litellm_embedder.default
document_store: qdrant
- name: question_recommendation_sql_generation
llm: litellm_llm.default
engine: wren_ui
document_store: qdrant
- name: intent_classification
llm: litellm_llm.default
embedder: litellm_embedder.default
document_store: qdrant
- name: misleading_assistance
llm: litellm_llm.default
- name: data_assistance
llm: litellm_llm.default
- name: sql_pairs_indexing
document_store: qdrant
embedder: litellm_embedder.default
- name: sql_pairs_retrieval
document_store: qdrant
embedder: litellm_embedder.default
llm: litellm_llm.default
- name: preprocess_sql_data
llm: litellm_llm.default
- name: sql_executor
engine: wren_ui
- name: user_guide_assistance
llm: litellm_llm.default
- name: chart_generation
llm: litellm_llm.default
- name: chart_adjustment
llm: litellm_llm.default
- name: sql_question_generation
llm: litellm_llm.default
- name: sql_generation_reasoning
llm: litellm_llm.default
- name: followup_sql_generation_reasoning
llm: litellm_llm.default
- name: sql_regeneration
llm: litellm_llm.default
engine: wren_ui
- name: instructions_indexing
embedder: litellm_embedder.default
document_store: qdrant
- name: instructions_retrieval
embedder: litellm_embedder.default
document_store: qdrant
- name: sql_functions_retrieval
engine: wren_ibis
document_store: qdrant
- name: project_meta_indexing
document_store: qdrant
- name: sql_tables_extraction
llm: litellm_llm.default
- name: sql_diagnosis
llm: litellm_llm.default
- name: sql_knowledge_retrieval
engine: wren_ibis
document_store: qdrant
---
settings:
engine_timeout: 30
column_indexing_batch_size: 50
table_retrieval_size: 10
table_column_retrieval_size: 100
allow_intent_classification: true
allow_sql_generation_reasoning: true
allow_sql_functions_retrieval: true
enable_column_pruning: false
max_sql_correction_retries: 3
query_cache_maxsize: 1000
query_cache_ttl: 3600
langfuse_host: https://cloud.langfuse.com
langfuse_enable: true
logging_level: DEBUG
development: false
historical_question_retrieval_similarity_threshold: 0.9
sql_pairs_similarity_threshold: 0.7
sql_pairs_retrieval_max_size: 10
instructions_similarity_threshold: 0.7
instructions_top_k: 10
================================================
FILE: wren-ai-service/docs/config_examples/config.azure.yaml
================================================
# you should rename this file to config.yaml and put it in ~/.wrenai
# please pay attention to the comments starting with # and adjust the config accordingly, 3 steps basically:
# 1. you need to use your own llm and embedding models
# 2. fill in embedding model dimension in the document_store section
# 3. you need to use the correct pipe definitions based on https://raw.githubusercontent.com/canner/WrenAI/<WRENAI_VERSION_NUMBER>/docker/config.example.yaml
# 4. you need to fill in correct llm and embedding models in the pipe definitions
type: llm
provider: litellm_llm
models:
# put AZURE_OPENAI_API_KEY=<your_api_key> in ~/.wrenai/.env
- model: azure/gpt-4 # Your Azure deployment name, put 'azure/' before deployment name
alias: default
api_base: https://endpoint.openai.azure.com # Replace with your custom Azure endpoint
api_version: 2024-02-15-preview
timeout: 120
kwargs:
temperature: 0
n: 1
seed: 0
max_tokens: 4096
---
type: embedder
provider: litellm_embedder
models:
# put AZURE_OPENAI_API_KEY=<your_api_key> in ~/.wrenai/.env
- model: azure/text-embedding-ada-002 # Your Azure deployment name, put 'azure/' before deployment name
alias: default
api_base: https://endpoint.openai.azure.com # Replace with your custom Azure endpoint
api_version: 2023-05-15
timeout: 300
---
type: engine
provider: wren_ui
endpoint: http://wren-ui:3000
---
type: engine
provider: wren_ibis
endpoint: http://ibis-server:8000
---
type: document_store
provider: qdrant
location: http://qdrant:6333
embedding_model_dim: 1536 # put your embedding model dimension here
timeout: 120
recreate_index: true
---
# please change the llm and embedder names to the ones you want to use
# the format of llm and embedder should be <provider>.<model_name> such as litellm_llm.gpt-4o-2024-08-06
# the pipes may be not the latest version, please refer to the latest version: https://raw.githubusercontent.com/canner/WrenAI/<WRENAI_VERSION_NUMBER>/docker/config.example.yaml
type: pipeline
pipes:
- name: db_schema_indexing
embedder: litellm_embedder.default
document_store: qdrant # Match document_store name
llm: litellm_llm.default
- name: historical_question_indexing
embedder: litellm_embedder.default
document_store: qdrant
- name: table_description_indexing
embedder: litellm_embedder.default
document_store: qdrant
- name: db_schema_retrieval
llm: litellm_llm.default
embedder: litellm_embedder.default
document_store: qdrant
- name: historical_question_retrieval
embedder: litellm_embedder.default
document_store: qdrant
- name: sql_generation
llm: litellm_llm.default
engine: wren_ui
document_store: qdrant
- name: sql_correction
llm: litellm_llm.default
engine: wren_ui
document_store: qdrant
- name: followup_sql_generation
llm: litellm_llm.default
engine: wren_ui
document_store: qdrant
- name: sql_answer
llm: litellm_llm.default
- name: semantics_description
llm: litellm_llm.default
- name: relationship_recommendation
llm: litellm_llm.default
engine: wren_ui
- name: question_recommendation
llm: litellm_llm.default
- name: intent_classification
llm: litellm_llm.default
embedder: litellm_embedder.default
document_store: qdrant
- name: misleading_assistance
llm: litellm_llm.default
- name: data_assistance
llm: litellm_llm.default
- name: sql_pairs_preparation
document_store: qdrant
embedder: litellm_embedder.default
llm: litellm_llm.default
- name: sql_pairs_retrieval
document_store: qdrant
embedder: litellm_embedder.default
llm: litellm_llm.default
- name: preprocess_sql_data
llm: litellm_llm.default
- name: sql_executor
engine: wren_ui
- name: user_guide_assistance
llm: litellm_llm.default
- name: chart_generation
llm: litellm_llm.default
- name: chart_adjustment
llm: litellm_llm.default
- name: sql_pairs_indexing
document_store: qdrant
embedder: litellm_embedder.default
- name: sql_generation_reasoning
llm: litellm_llm.default
- name: followup_sql_generation_reasoning
llm: litellm_llm.default
- name: question_recommendation_db_schema_retrieval
llm: litellm_llm.default
embedder: litellm_embedder.default
document_store: qdrant
- name: question_recommendation_sql_generation
llm: litellm_llm.default
engine: wren_ui
document_store: qdrant
- name: sql_question_generation
llm: litellm_llm.default
- name: sql_regeneration
llm: litellm_llm.default
engine: wren_ui
- name: instructions_indexing
embedder: litellm_embedder.default
document_store: qdrant
- name: instructions_retrieval
embedder: litellm_embedder.default
document_store: qdrant
- name: sql_functions_retrieval
engine: wren_ibis
document_store: qdrant
- name: project_meta_indexing
document_store: qdrant
- name: sql_tables_extraction
llm: litellm_llm.default
- name: sql_diagnosis
llm: litellm_llm.default
- name: sql_knowledge_retrieval
engine: wren_ibis
document_store: qdrant
---
settings:
engine_timeout: 30
column_indexing_batch_size: 50
table_retrieval_size: 10
table_column_retrieval_size: 100
allow_intent_classification: true
allow_sql_generation_reasoning: true
allow_sql_functions_retrieval: true
enable_column_prun
gitextract_1iqodypf/
├── .claude/
│ ├── CLAUDE.md
│ └── settings.json
├── .editorconfig
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ └── feature_request.md
│ ├── dependabot.yaml
│ └── workflows/
│ ├── ai-service-release-image.yaml
│ ├── ai-service-release-nightly-image.yaml
│ ├── ai-service-release-stable-image.yaml
│ ├── ai-service-test.yaml
│ ├── create-rc-release-pr.yaml
│ ├── create-rc-release.yaml
│ ├── pr-tagger.yaml
│ ├── pull-request-title-validator.yaml
│ ├── ui-lint.yaml
│ ├── ui-release-image-stable.yaml
│ ├── ui-release-image.yaml
│ ├── ui-test.yaml
│ └── wren-launcher-ci.yaml
├── .gitignore
├── .gitmodules
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── SECURITY.md
├── deployment/
│ ├── README.md
│ └── kustomizations/
│ ├── .gitignore
│ ├── README.md
│ ├── base/
│ │ ├── cm.yaml
│ │ ├── deploy-wren-ai-service.yaml
│ │ ├── deploy-wren-engine.yaml
│ │ ├── deploy-wren-ibis-server.yaml
│ │ ├── deploy-wren-ui.yaml
│ │ ├── pvc.yaml
│ │ └── svc.yaml
│ ├── examples/
│ │ ├── .gitignore
│ │ ├── certificate-qdrant_example.yaml
│ │ ├── certificate-wren_example.yaml
│ │ ├── ingress-wren_example.yaml
│ │ └── secret-wren_example.yaml
│ ├── helm-values-qdrant_1.11.0.yaml
│ ├── helm-values_postgresql_15.yaml
│ ├── kustomization.yaml
│ └── patches/
│ ├── README.md
│ ├── cm.yaml
│ ├── rm-certificate.yaml
│ ├── rm-ingress.yaml
│ └── service.yaml
├── docker/
│ ├── README.md
│ ├── bootstrap/
│ │ ├── Dockerfile
│ │ └── init.sh
│ ├── config.example.yaml
│ ├── docker-compose-dev.yaml
│ └── docker-compose.yaml
├── wren-ai-service/
│ ├── .dockerignore
│ ├── .pre-commit-config.yaml
│ ├── CONTRIBUTING.md
│ ├── Justfile
│ ├── README.md
│ ├── docker/
│ │ └── Dockerfile
│ ├── docs/
│ │ ├── code_design.md
│ │ ├── config_examples/
│ │ │ ├── README.md
│ │ │ ├── config.anthropic.yaml
│ │ │ ├── config.azure.yaml
│ │ │ ├── config.bedrock.yaml
│ │ │ ├── config.deepseek.yaml
│ │ │ ├── config.google_ai_studio.yaml
│ │ │ ├── config.google_vertexai.yaml
│ │ │ ├── config.grok.yaml
│ │ │ ├── config.groq.yaml
│ │ │ ├── config.lm_studio.yaml
│ │ │ ├── config.ollama.yaml
│ │ │ ├── config.open_router.yaml
│ │ │ ├── config.qwen3.yaml
│ │ │ └── config.zhipu.yaml
│ │ └── configuration.md
│ ├── entrypoint.sh
│ ├── eval/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── __init__.py
│ │ ├── add_samples_to_toml.py
│ │ ├── data_curation/
│ │ │ ├── __init__.py
│ │ │ ├── app.py
│ │ │ └── utils.py
│ │ ├── dataset/
│ │ │ └── .gitignore
│ │ ├── dspy_modules/
│ │ │ ├── __init__.py
│ │ │ ├── ask_generation.py
│ │ │ └── prompt_optimizer.py
│ │ ├── evaluation.py
│ │ ├── mdl_to_csv.py
│ │ ├── metrics/
│ │ │ ├── __init__.py
│ │ │ ├── accuracy.py
│ │ │ ├── answer_relevancy.py
│ │ │ ├── context_precision.py
│ │ │ ├── context_recall.py
│ │ │ ├── context_relevancy.py
│ │ │ ├── faithfulness.py
│ │ │ ├── llm/
│ │ │ │ └── __init__.py
│ │ │ └── spider/
│ │ │ ├── __init__.py
│ │ │ ├── exact_match.py
│ │ │ ├── exec_match.py
│ │ │ └── process_sql.py
│ │ ├── optimized/
│ │ │ └── .gitignore
│ │ ├── pipelines.py
│ │ ├── prediction.py
│ │ ├── preparation.py
│ │ └── utils.py
│ ├── pyproject.toml
│ ├── ruff.toml
│ ├── src/
│ │ ├── __init__.py
│ │ ├── __main__.py
│ │ ├── config.py
│ │ ├── core/
│ │ │ ├── __init__.py
│ │ │ ├── engine.py
│ │ │ ├── pipeline.py
│ │ │ └── provider.py
│ │ ├── force_deploy.py
│ │ ├── force_update_config.py
│ │ ├── globals.py
│ │ ├── pipelines/
│ │ │ ├── __init__.py
│ │ │ ├── common.py
│ │ │ ├── generation/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── chart_adjustment.py
│ │ │ │ ├── chart_generation.py
│ │ │ │ ├── data_assistance.py
│ │ │ │ ├── followup_sql_generation.py
│ │ │ │ ├── followup_sql_generation_reasoning.py
│ │ │ │ ├── intent_classification.py
│ │ │ │ ├── misleading_assistance.py
│ │ │ │ ├── question_recommendation.py
│ │ │ │ ├── relationship_recommendation.py
│ │ │ │ ├── semantics_description.py
│ │ │ │ ├── sql_answer.py
│ │ │ │ ├── sql_correction.py
│ │ │ │ ├── sql_diagnosis.py
│ │ │ │ ├── sql_generation.py
│ │ │ │ ├── sql_generation_reasoning.py
│ │ │ │ ├── sql_question.py
│ │ │ │ ├── sql_regeneration.py
│ │ │ │ ├── sql_tables_extraction.py
│ │ │ │ ├── user_guide_assistance.py
│ │ │ │ └── utils/
│ │ │ │ ├── chart.py
│ │ │ │ ├── sql.py
│ │ │ │ └── vega-lite-schema-v5.json
│ │ │ ├── indexing/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── db_schema.py
│ │ │ │ ├── historical_question.py
│ │ │ │ ├── instructions.py
│ │ │ │ ├── project_meta.py
│ │ │ │ ├── sql_pairs.py
│ │ │ │ ├── table_description.py
│ │ │ │ └── utils/
│ │ │ │ └── helper.py
│ │ │ └── retrieval/
│ │ │ ├── __init__.py
│ │ │ ├── db_schema_retrieval.py
│ │ │ ├── historical_question_retrieval.py
│ │ │ ├── instructions.py
│ │ │ ├── preprocess_sql_data.py
│ │ │ ├── sql_executor.py
│ │ │ ├── sql_functions.py
│ │ │ ├── sql_knowledge.py
│ │ │ └── sql_pairs_retrieval.py
│ │ ├── providers/
│ │ │ ├── __init__.py
│ │ │ ├── document_store/
│ │ │ │ ├── __init__.py
│ │ │ │ └── qdrant.py
│ │ │ ├── embedder/
│ │ │ │ ├── __init__.py
│ │ │ │ └── litellm.py
│ │ │ ├── engine/
│ │ │ │ ├── __init__.py
│ │ │ │ └── wren.py
│ │ │ ├── llm/
│ │ │ │ ├── __init__.py
│ │ │ │ └── litellm.py
│ │ │ └── loader.py
│ │ ├── utils.py
│ │ └── web/
│ │ ├── __init__.py
│ │ ├── development.py
│ │ └── v1/
│ │ ├── __init__.py
│ │ ├── routers/
│ │ │ ├── __init__.py
│ │ │ ├── ask.py
│ │ │ ├── ask_feedbacks.py
│ │ │ ├── chart.py
│ │ │ ├── chart_adjustment.py
│ │ │ ├── instructions.py
│ │ │ ├── question_recommendation.py
│ │ │ ├── relationship_recommendation.py
│ │ │ ├── semantics_description.py
│ │ │ ├── semantics_preparation.py
│ │ │ ├── sql_answers.py
│ │ │ ├── sql_corrections.py
│ │ │ ├── sql_pairs.py
│ │ │ └── sql_question.py
│ │ └── services/
│ │ ├── __init__.py
│ │ ├── ask.py
│ │ ├── ask_feedback.py
│ │ ├── chart.py
│ │ ├── chart_adjustment.py
│ │ ├── instructions.py
│ │ ├── question_recommendation.py
│ │ ├── relationship_recommendation.py
│ │ ├── semantics_description.py
│ │ ├── semantics_preparation.py
│ │ ├── sql_answer.py
│ │ ├── sql_corrections.py
│ │ ├── sql_pairs.py
│ │ └── sql_question.py
│ ├── tests/
│ │ ├── __init__.py
│ │ ├── data/
│ │ │ ├── book_2_mdl.json
│ │ │ ├── config.test.yaml
│ │ │ ├── mock_pyproject.toml
│ │ │ └── pairs.json
│ │ ├── locust/
│ │ │ ├── __init__.py
│ │ │ ├── config_users.json
│ │ │ ├── locust.conf
│ │ │ ├── locust_script.py
│ │ │ └── locustfile.py
│ │ └── pytest/
│ │ ├── __init__.py
│ │ ├── eval/
│ │ │ ├── __init__.py
│ │ │ └── test_metrics.py
│ │ ├── pipelines/
│ │ │ ├── __init__.py
│ │ │ ├── generation/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── test_ask.py
│ │ │ │ └── test_semantics_enrichment.py
│ │ │ ├── indexing/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── test_db_schema.py
│ │ │ │ ├── test_helper.py
│ │ │ │ ├── test_historical_questions.py
│ │ │ │ ├── test_indexing.py
│ │ │ │ ├── test_instructions.py
│ │ │ │ ├── test_sql_pairs.py
│ │ │ │ └── test_table_description.py
│ │ │ └── retrieval/
│ │ │ ├── __init__.py
│ │ │ └── sql_function.py
│ │ ├── providers/
│ │ │ ├── __init__.py
│ │ │ ├── test_loader.py
│ │ │ └── test_providers.py
│ │ ├── services/
│ │ │ ├── __init__.py
│ │ │ ├── mocks.py
│ │ │ ├── test_ask.py
│ │ │ ├── test_instructions.py
│ │ │ ├── test_relationship_recommendation.py
│ │ │ ├── test_semantics_description.py
│ │ │ └── test_sql_pairs.py
│ │ ├── test_config.py
│ │ ├── test_main.py
│ │ ├── test_usecases.py
│ │ └── test_utils.py
│ └── tools/
│ ├── .env.example
│ ├── config/
│ │ ├── config.example.yaml
│ │ └── config.full.yaml
│ ├── dev/
│ │ ├── config.properties.example
│ │ └── docker-compose-dev.yaml
│ ├── mdl_to_str.py
│ └── run_sql.py
├── wren-launcher/
│ ├── .golangci.yml
│ ├── Makefile
│ ├── README.md
│ ├── commands/
│ │ ├── dbt/
│ │ │ ├── README.md
│ │ │ ├── converter.go
│ │ │ ├── data_source.go
│ │ │ ├── data_source_test.go
│ │ │ ├── profiles.go
│ │ │ ├── profiles_analyzer.go
│ │ │ ├── utils.go
│ │ │ └── wren_mdl.go
│ │ ├── dbt.go
│ │ └── launch.go
│ ├── config/
│ │ └── config.go
│ ├── go.mod
│ ├── go.sum
│ ├── main.go
│ └── utils/
│ ├── docker.go
│ ├── docker_test.go
│ ├── network.go
│ ├── os.go
│ ├── rc.go
│ └── rc_test.go
├── wren-mdl/
│ └── mdl.schema.json
└── wren-ui/
├── .dockerignore
├── .eslintignore
├── .eslintrc.json
├── .prettierrc
├── .yarn/
│ └── releases/
│ └── yarn-4.5.3.cjs
├── .yarnrc.yml
├── Dockerfile
├── README.md
├── codegen.yaml
├── e2e/
│ ├── README.md
│ ├── commonTests/
│ │ ├── home.ts
│ │ ├── modeling.ts
│ │ └── onboarding.ts
│ ├── config.ts
│ ├── global.setup.ts
│ ├── global.teardown.ts
│ ├── helper.ts
│ └── specs/
│ ├── connectBigQuery.spec.ts
│ ├── connectClickHouse.spec.ts
│ ├── connectDuckDB.spec.ts
│ ├── connectMySQL.spec.ts
│ ├── connectPostgreSQL.spec.ts
│ ├── connectSQLServer.spec.ts
│ ├── connectSampleECommerce.spec.ts
│ ├── connectSampleHR.spec.ts
│ ├── connectSnowflake.spec.ts
│ └── connectTrino.spec.ts
├── jest.config.js
├── knexfile.js
├── migrations/
│ ├── 20240125070643_create_project_table.js
│ ├── 20240125071855_create_model_table.js
│ ├── 20240125081244_create_model_column_table.js
│ ├── 20240125083821_create_relation_table.js
│ ├── 20240125085655_create_metrics_table.js
│ ├── 20240126100753_create_metrics_measure_table.js
│ ├── 20240129021453_create_view_table.js
│ ├── 20240319083758_create_deploy_table.js
│ ├── 20240327030000_create_ask_table.js
│ ├── 20240418000000_update_project_table_pg.js
│ ├── 20240419090558_add_foreign_key_to_model_column_and_metric_measure.js
│ ├── 20240425000000_add_thread_response_summary.js
│ ├── 20240430033014_update_model_column_table.js
│ ├── 20240446090560_update_relationship_table.js
│ ├── 20240502000000_add_properties_to_relationship.js
│ ├── 20240524044348_update_project_table.js
│ ├── 20240524071859_update_thread_table.js
│ ├── 20240530062133_update_project_table.js
│ ├── 20240530062809_transfer_project_table_data.js
│ ├── 20240530105955_drop_project_table_columns.js
│ ├── 20240531085916_transfer_model_properties.js
│ ├── 20240610070534_create_schema_change_table.js
│ ├── 20240928165009_create_model_nested_column.js
│ ├── 20241021073019_update_project_language.js
│ ├── 20241029092204_create_learning_table.js
│ ├── 20241106232204_update_project_table.js
│ ├── 20241107171828_update_thread_table.js
│ ├── 20241115031024_drop_thread_response_table_column.js
│ ├── 20241207000000_update_thread_response_for_answer.js
│ ├── 20241210072534_update_thread_response_table.js
│ ├── 20241226135712_remove_thread_sql.js
│ ├── 20250102074255_create_dashboard_table.js
│ ├── 20250102074256_create_dashboard_item_table.js
│ ├── 20250102074256_create_sql_pair_table.js
│ ├── 20250311046282_create_instruction_table.js
│ ├── 20250320074256_alter_sql_pair_table.js
│ ├── 20250422000000_alter_dashboard_table.js
│ ├── 20250423000000_create_dashboard_cache_refresh_table.js
│ ├── 20250509000000_create_asking_task.js
│ ├── 20250509000001_add_task_id_to_thread.js
│ ├── 20250510000000_add_adjustment_to_thread_response.js
│ ├── 20250510000001_alter_dashboard_item_table.js
│ ├── 20250510000002_add_version_to_project.js
│ └── 20250511000000-create-api-history.js
├── next.config.js
├── openapi.yaml
├── package.json
├── playwright.config.ts
├── src/
│ ├── apollo/
│ │ ├── client/
│ │ │ ├── graphql/
│ │ │ │ ├── __types__.ts
│ │ │ │ ├── apiManagement.generated.ts
│ │ │ │ ├── apiManagement.ts
│ │ │ │ ├── calculatedField.generated.ts
│ │ │ │ ├── calculatedField.ts
│ │ │ │ ├── dashboard.generated.ts
│ │ │ │ ├── dashboard.ts
│ │ │ │ ├── dataSource.generated.ts
│ │ │ │ ├── dataSource.ts
│ │ │ │ ├── deploy.generated.ts
│ │ │ │ ├── deploy.ts
│ │ │ │ ├── diagram.generated.ts
│ │ │ │ ├── diagram.ts
│ │ │ │ ├── home.generated.ts
│ │ │ │ ├── home.ts
│ │ │ │ ├── instructions.generated.ts
│ │ │ │ ├── instructions.ts
│ │ │ │ ├── learning.generated.ts
│ │ │ │ ├── learning.ts
│ │ │ │ ├── metadata.generated.ts
│ │ │ │ ├── metadata.ts
│ │ │ │ ├── model.generated.ts
│ │ │ │ ├── model.ts
│ │ │ │ ├── onboarding.generated.ts
│ │ │ │ ├── onboarding.ts
│ │ │ │ ├── relationship.generated.ts
│ │ │ │ ├── relationship.ts
│ │ │ │ ├── settings.generated.ts
│ │ │ │ ├── settings.ts
│ │ │ │ ├── sql.generated.ts
│ │ │ │ ├── sql.ts
│ │ │ │ ├── sqlPairs.generated.ts
│ │ │ │ ├── sqlPairs.ts
│ │ │ │ ├── view.generated.ts
│ │ │ │ └── view.ts
│ │ │ └── index.ts
│ │ └── server/
│ │ ├── adaptors/
│ │ │ ├── ibisAdaptor.ts
│ │ │ ├── index.ts
│ │ │ ├── tests/
│ │ │ │ ├── ibisAdaptor.test.ts
│ │ │ │ └── wrenAIAdaptor.test.ts
│ │ │ ├── wrenAIAdaptor.ts
│ │ │ └── wrenEngineAdaptor.ts
│ │ ├── backgrounds/
│ │ │ ├── adjustmentBackgroundTracker.ts
│ │ │ ├── chart.ts
│ │ │ ├── dashboardCacheBackgroundTracker.ts
│ │ │ ├── index.ts
│ │ │ ├── recommend-question.ts
│ │ │ └── textBasedAnswerBackgroundTracker.ts
│ │ ├── config.ts
│ │ ├── data/
│ │ │ ├── index.ts
│ │ │ ├── sample.ts
│ │ │ └── type.ts
│ │ ├── dataSource.ts
│ │ ├── index.ts
│ │ ├── managers/
│ │ │ └── dataSourceSchemaDetector.ts
│ │ ├── mdl/
│ │ │ ├── mdlBuilder.ts
│ │ │ ├── test/
│ │ │ │ └── mdlBuilder.test.ts
│ │ │ └── type.ts
│ │ ├── models/
│ │ │ ├── adaptor.ts
│ │ │ ├── dashboard.ts
│ │ │ ├── index.ts
│ │ │ ├── instruction.ts
│ │ │ └── model.ts
│ │ ├── repositories/
│ │ │ ├── apiHistoryRepository.ts
│ │ │ ├── askingTaskRepository.ts
│ │ │ ├── baseRepository.ts
│ │ │ ├── dashboardItemRefreshJobRepository.ts
│ │ │ ├── dashboardItemRepository.ts
│ │ │ ├── dashboardRepository.ts
│ │ │ ├── deployLogRepository.ts
│ │ │ ├── index.ts
│ │ │ ├── instructionRepository.ts
│ │ │ ├── learningRepository.ts
│ │ │ ├── metricsMeasureRepository.ts
│ │ │ ├── metricsRepository.ts
│ │ │ ├── modelColumnRepository.ts
│ │ │ ├── modelNestedColumnRepository.ts
│ │ │ ├── modelRepository.ts
│ │ │ ├── projectRepository.ts
│ │ │ ├── relationshipRepository.ts
│ │ │ ├── schemaChangeRepository.ts
│ │ │ ├── sqlPairRepository.ts
│ │ │ ├── threadRepository.ts
│ │ │ ├── threadResponseRepository.ts
│ │ │ └── viewRepository.ts
│ │ ├── resolvers/
│ │ │ ├── apiHistoryResolver.ts
│ │ │ ├── askingResolver.ts
│ │ │ ├── dashboardResolver.ts
│ │ │ ├── diagramResolver.ts
│ │ │ ├── instructionResolver.ts
│ │ │ ├── learningResolver.ts
│ │ │ ├── modelResolver.ts
│ │ │ ├── projectResolver.ts
│ │ │ └── sqlPairResolver.ts
│ │ ├── resolvers.ts
│ │ ├── scalars.ts
│ │ ├── schema.ts
│ │ ├── services/
│ │ │ ├── askingService.ts
│ │ │ ├── askingTaskTracker.ts
│ │ │ ├── dashboardService.ts
│ │ │ ├── deployService.ts
│ │ │ ├── index.ts
│ │ │ ├── instructionService.ts
│ │ │ ├── mdlService.ts
│ │ │ ├── metadataService.ts
│ │ │ ├── modelService.ts
│ │ │ ├── projectService.ts
│ │ │ ├── queryService.ts
│ │ │ ├── sqlPairService.ts
│ │ │ └── tests/
│ │ │ ├── askingService.test.ts
│ │ │ ├── dashboardService.test.ts
│ │ │ ├── deployService.test.ts
│ │ │ └── queryService.test.ts
│ │ ├── telemetry/
│ │ │ └── telemetry.ts
│ │ ├── types/
│ │ │ ├── context.ts
│ │ │ ├── dataSource.ts
│ │ │ ├── diagram.ts
│ │ │ ├── index.ts
│ │ │ ├── manifest.ts
│ │ │ ├── metric.ts
│ │ │ └── relationship.ts
│ │ └── utils/
│ │ ├── apiUtils.ts
│ │ ├── dataUtils.ts
│ │ ├── docker.ts
│ │ ├── encode.ts
│ │ ├── encryptor.ts
│ │ ├── error.ts
│ │ ├── helper.ts
│ │ ├── index.ts
│ │ ├── knex.ts
│ │ ├── logger.ts
│ │ ├── model.ts
│ │ ├── regex.ts
│ │ ├── sqlFormat.ts
│ │ ├── sseTypes.ts
│ │ ├── sseUtils.ts
│ │ ├── string.ts
│ │ ├── tests/
│ │ │ ├── dataSource.test.ts
│ │ │ ├── encryptor.test.ts
│ │ │ └── regex.test.ts
│ │ └── timezone.ts
│ ├── common.ts
│ ├── components/
│ │ ├── ActionButton.tsx
│ │ ├── EditableWrapper.tsx
│ │ ├── EllipsisWrapper.tsx
│ │ ├── ErrorCollapse.tsx
│ │ ├── HeaderBar.tsx
│ │ ├── Logo.tsx
│ │ ├── LogoBar.tsx
│ │ ├── PageLoading.tsx
│ │ ├── chart/
│ │ │ ├── handler.ts
│ │ │ ├── index.tsx
│ │ │ └── properties/
│ │ │ ├── BasicProperties.tsx
│ │ │ ├── DonutProperties.tsx
│ │ │ ├── GroupedBarProperties.tsx
│ │ │ ├── LineProperties.tsx
│ │ │ └── StackedBarProperties.tsx
│ │ ├── code/
│ │ │ ├── BaseCodeBlock.tsx
│ │ │ ├── JsonCodeBlock.tsx
│ │ │ └── SQLCodeBlock.tsx
│ │ ├── dataPreview/
│ │ │ ├── PreviewData.tsx
│ │ │ └── PreviewDataContent.tsx
│ │ ├── deploy/
│ │ │ ├── Context.ts
│ │ │ └── Deploy.tsx
│ │ ├── diagram/
│ │ │ ├── Context.ts
│ │ │ ├── CustomDropdown.tsx
│ │ │ ├── CustomPopover.tsx
│ │ │ ├── Marker.tsx
│ │ │ ├── customEdge/
│ │ │ │ ├── ModelEdge.tsx
│ │ │ │ └── index.ts
│ │ │ ├── customNode/
│ │ │ │ ├── Column.tsx
│ │ │ │ ├── MarkerHandle.tsx
│ │ │ │ ├── ModelNode.tsx
│ │ │ │ ├── ViewNode.tsx
│ │ │ │ ├── index.ts
│ │ │ │ └── utils.tsx
│ │ │ ├── index.tsx
│ │ │ └── utils.ts
│ │ ├── editor/
│ │ │ ├── AceEditor.tsx
│ │ │ ├── MarkdownBlock.tsx
│ │ │ ├── MarkdownEditor.tsx
│ │ │ └── SQLEditor.tsx
│ │ ├── layouts/
│ │ │ ├── PageLayout.tsx
│ │ │ ├── SiderLayout.tsx
│ │ │ └── SimpleLayout.tsx
│ │ ├── learning/
│ │ │ ├── guide/
│ │ │ │ ├── index.tsx
│ │ │ │ ├── stories.tsx
│ │ │ │ └── utils.ts
│ │ │ └── index.tsx
│ │ ├── modals/
│ │ │ ├── AdjustReasoningStepsModal.tsx
│ │ │ ├── AdjustSQLModal.tsx
│ │ │ ├── CalculatedFieldModal.tsx
│ │ │ ├── DeleteModal.tsx
│ │ │ ├── FixSQLModal.tsx
│ │ │ ├── ImportDataSourceSQLModal.tsx
│ │ │ ├── InstructionModal.tsx
│ │ │ ├── QuestionSQLPairModal.tsx
│ │ │ ├── RelationModal.tsx
│ │ │ ├── SaveAsViewModal.tsx
│ │ │ └── SchemaChangeModal.tsx
│ │ ├── pages/
│ │ │ ├── apiManagement/
│ │ │ │ └── DetailsDrawer.tsx
│ │ │ ├── home/
│ │ │ │ ├── RecommendedQuestions.tsx
│ │ │ │ ├── dashboardGrid/
│ │ │ │ │ ├── CacheSettingsDrawer.tsx
│ │ │ │ │ ├── DashboardHeader.tsx
│ │ │ │ │ ├── EmptyDashboard.tsx
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── preparation/
│ │ │ │ │ ├── ErrorBoundary.tsx
│ │ │ │ │ ├── PreparationStatus.tsx
│ │ │ │ │ ├── PreparationSteps.tsx
│ │ │ │ │ ├── index.tsx
│ │ │ │ │ └── step/
│ │ │ │ │ ├── FixedSQLFinished.tsx
│ │ │ │ │ ├── Generating.tsx
│ │ │ │ │ ├── Organizing.tsx
│ │ │ │ │ ├── Retrieving.tsx
│ │ │ │ │ ├── SQLPairFinished.tsx
│ │ │ │ │ └── ViewFinished.tsx
│ │ │ │ ├── prompt/
│ │ │ │ │ ├── DemoPrompt.tsx
│ │ │ │ │ ├── Input.tsx
│ │ │ │ │ ├── RecommendedQuestionsPrompt.tsx
│ │ │ │ │ ├── Result.tsx
│ │ │ │ │ └── index.tsx
│ │ │ │ └── promptThread/
│ │ │ │ ├── AnswerResult.tsx
│ │ │ │ ├── ChartAnswer.tsx
│ │ │ │ ├── TextBasedAnswer.tsx
│ │ │ │ ├── ViewBlock.tsx
│ │ │ │ ├── ViewSQLTabContent.tsx
│ │ │ │ ├── index.tsx
│ │ │ │ └── store.tsx
│ │ │ ├── knowledge/
│ │ │ │ ├── GlobalLabel.tsx
│ │ │ │ ├── InstructionDrawer.tsx
│ │ │ │ └── SQLPairDrawer.tsx
│ │ │ ├── modeling/
│ │ │ │ ├── EditMetadataModal.tsx
│ │ │ │ ├── MetadataDrawer.tsx
│ │ │ │ ├── ModelDrawer.tsx
│ │ │ │ ├── form/
│ │ │ │ │ └── ModelForm.tsx
│ │ │ │ └── metadata/
│ │ │ │ ├── EditBasicMetadata.tsx
│ │ │ │ ├── EditModelMetadata.tsx
│ │ │ │ ├── EditViewMetadata.tsx
│ │ │ │ ├── ModelMetadata.tsx
│ │ │ │ └── ViewMetadata.tsx
│ │ │ └── setup/
│ │ │ ├── ButtonItem.tsx
│ │ │ ├── ConnectDataSource.tsx
│ │ │ ├── ContainerCard.tsx
│ │ │ ├── DefineRelations.tsx
│ │ │ ├── SelectModels.tsx
│ │ │ ├── Starter.tsx
│ │ │ ├── dataSources/
│ │ │ │ ├── AthenaProperties.tsx
│ │ │ │ ├── BigQueryProperties.tsx
│ │ │ │ ├── ClickHouseProperties.tsx
│ │ │ │ ├── DatabricksProperties.tsx
│ │ │ │ ├── DuckDBProperties.tsx
│ │ │ │ ├── MySQLProperties.tsx
│ │ │ │ ├── OracleProperties.tsx
│ │ │ │ ├── PostgreSQLProperties.tsx
│ │ │ │ ├── RedshiftProperties.tsx
│ │ │ │ ├── SQLServerProperties.tsx
│ │ │ │ ├── SnowflakeProperties.tsx
│ │ │ │ └── TrinoProperties.tsx
│ │ │ └── utils.tsx
│ │ ├── selectors/
│ │ │ ├── CombineFieldSelector.tsx
│ │ │ ├── DescriptiveSelector.tsx
│ │ │ ├── Selector.tsx
│ │ │ └── lineageSelector/
│ │ │ ├── FieldSelect.tsx
│ │ │ └── index.tsx
│ │ ├── settings/
│ │ │ ├── DataSourceSettings.tsx
│ │ │ ├── ProjectSettings.tsx
│ │ │ ├── index.tsx
│ │ │ └── utils.tsx
│ │ ├── sidebar/
│ │ │ ├── APIManagement.tsx
│ │ │ ├── Home.tsx
│ │ │ ├── Knowledge.tsx
│ │ │ ├── LabelTitle.tsx
│ │ │ ├── Modeling.tsx
│ │ │ ├── SidebarMenu.tsx
│ │ │ ├── SidebarTree.tsx
│ │ │ ├── home/
│ │ │ │ ├── ThreadTree.tsx
│ │ │ │ ├── TreeTitle.tsx
│ │ │ │ └── TreeTitleInput.tsx
│ │ │ ├── index.tsx
│ │ │ ├── modeling/
│ │ │ │ ├── GroupTreeTitle.tsx
│ │ │ │ ├── ModelTree.tsx
│ │ │ │ └── ViewTree.tsx
│ │ │ └── utils.tsx
│ │ └── table/
│ │ ├── BaseTable.tsx
│ │ ├── CalculatedFieldTable.tsx
│ │ ├── EditableBaseTable.tsx
│ │ ├── FieldTable.tsx
│ │ ├── ModelRelationSelectionTable.tsx
│ │ ├── MultiSelectBox.tsx
│ │ ├── NestedFieldTable.tsx
│ │ ├── RelationTable.tsx
│ │ ├── SelectionTable.tsx
│ │ └── TableTransfer.tsx
│ ├── hooks/
│ │ ├── .gitkeep
│ │ ├── useAdjustAnswer.tsx
│ │ ├── useAskProcessState.tsx
│ │ ├── useAskPrompt.tsx
│ │ ├── useAskingStreamTask.tsx
│ │ ├── useAutoComplete.tsx
│ │ ├── useCheckOnboarding.tsx
│ │ ├── useCombineFieldOptions.tsx
│ │ ├── useDrawerAction.tsx
│ │ ├── useDropdown.tsx
│ │ ├── useExpressionFieldOptions.tsx
│ │ ├── useGlobalConfig.tsx
│ │ ├── useHomeSidebar.tsx
│ │ ├── useModalAction.tsx
│ │ ├── useNativeSQL.tsx
│ │ ├── useRecommendedQuestionsInstruction.tsx
│ │ ├── useRelationshipModal.tsx
│ │ ├── useSetupConnection.tsx
│ │ ├── useSetupConnectionDataSource.tsx
│ │ ├── useSetupConnectionSampleDataset.tsx
│ │ ├── useSetupModels.tsx
│ │ ├── useSetupRelations.tsx
│ │ ├── useStoreContext.tsx
│ │ └── useTextBasedAnswerStreamTask.tsx
│ ├── import/
│ │ ├── antd.ts
│ │ └── icon.ts
│ ├── pages/
│ │ ├── _app.tsx
│ │ ├── _document.tsx
│ │ ├── api/
│ │ │ ├── ask_task/
│ │ │ │ ├── streaming.ts
│ │ │ │ └── streaming_answer.ts
│ │ │ ├── config.ts
│ │ │ ├── graphql.ts
│ │ │ └── v1/
│ │ │ ├── ask.ts
│ │ │ ├── generate_sql.ts
│ │ │ ├── generate_summary.ts
│ │ │ ├── generate_vega_chart.ts
│ │ │ ├── knowledge/
│ │ │ │ ├── instructions/
│ │ │ │ │ ├── [id].ts
│ │ │ │ │ └── index.ts
│ │ │ │ └── sql_pairs/
│ │ │ │ ├── [id].ts
│ │ │ │ └── index.ts
│ │ │ ├── models.ts
│ │ │ ├── run_sql.ts
│ │ │ ├── stream/
│ │ │ │ ├── ask.ts
│ │ │ │ └── generate_sql.ts
│ │ │ └── stream_explanation.ts
│ │ ├── api-management/
│ │ │ └── history.tsx
│ │ ├── home/
│ │ │ ├── [id].tsx
│ │ │ ├── dashboard.tsx
│ │ │ └── index.tsx
│ │ ├── index.tsx
│ │ ├── knowledge/
│ │ │ ├── instructions.tsx
│ │ │ └── question-sql-pairs.tsx
│ │ ├── modeling.tsx
│ │ └── setup/
│ │ ├── connection.tsx
│ │ ├── models.tsx
│ │ └── relationships.tsx
│ ├── styles/
│ │ ├── antd-variables.less
│ │ ├── components/
│ │ │ ├── alert.less
│ │ │ ├── avatar.less
│ │ │ ├── button.less
│ │ │ ├── chart.less
│ │ │ ├── driver.less
│ │ │ ├── scrollbar.less
│ │ │ ├── select.less
│ │ │ ├── table.less
│ │ │ ├── tag.less
│ │ │ └── transfer.less
│ │ ├── index.less
│ │ ├── layouts/
│ │ │ ├── global.less
│ │ │ └── main.less
│ │ └── utilities/
│ │ ├── animation.less
│ │ ├── border.less
│ │ ├── color.less
│ │ ├── display.less
│ │ ├── flex.less
│ │ ├── grid.less
│ │ ├── spacing.less
│ │ └── text.less
│ └── utils/
│ ├── columnType.tsx
│ ├── data/
│ │ ├── dictionary.ts
│ │ ├── index.ts
│ │ └── type/
│ │ ├── index.ts
│ │ └── modeling.ts
│ ├── dataSourceType.ts
│ ├── diagram/
│ │ ├── creator.ts
│ │ ├── index.ts
│ │ └── transformer.ts
│ ├── enum/
│ │ ├── columnType.ts
│ │ ├── dataSources.ts
│ │ ├── diagram.ts
│ │ ├── dropdown.ts
│ │ ├── form.ts
│ │ ├── home.ts
│ │ ├── index.ts
│ │ ├── menu.ts
│ │ ├── modeling.ts
│ │ ├── path.ts
│ │ ├── settings.ts
│ │ └── setup.ts
│ ├── env.ts
│ ├── error/
│ │ ├── dictionary.ts
│ │ └── index.ts
│ ├── errorHandler.tsx
│ ├── events.tsx
│ ├── expressionType.ts
│ ├── file.ts
│ ├── helper.ts
│ ├── icons.ts
│ ├── iteration.tsx
│ ├── language.ts
│ ├── modelingHelper.ts
│ ├── nodeType.tsx
│ ├── svgs/
│ │ ├── BrainSVG.tsx
│ │ ├── CopilotSVG.tsx
│ │ ├── EditSVG.tsx
│ │ ├── InstructionsSVG.tsx
│ │ ├── RobotSVG.tsx
│ │ └── index.ts
│ ├── table.tsx
│ ├── telemetry.ts
│ ├── time.ts
│ ├── validator/
│ │ ├── calculatedFieldValidator.ts
│ │ ├── cronValidator.ts
│ │ ├── hostValidator.ts
│ │ ├── index.ts
│ │ ├── relationshipValidator.ts
│ │ ├── sqlPairValidator.ts
│ │ └── viewValidator.ts
│ ├── vegaSpecUtils.test.ts
│ └── vegaSpecUtils.ts
├── tools/
│ └── knex.js
└── tsconfig.json
Showing preview only (898K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (9573 symbols across 479 files)
FILE: wren-ai-service/eval/__init__.py
class EvalSettings (line 13) | class EvalSettings(Settings):
method langfuse_url (line 38) | def langfuse_url(self) -> str:
method get_openai_api_key (line 43) | def get_openai_api_key(self) -> str:
method bigquery_info (line 47) | def bigquery_info(self) -> dict:
method postgres_info (line 55) | def postgres_info(self) -> dict:
FILE: wren-ai-service/eval/data_curation/app.py
function on_change_upload_eval_dataset (line 67) | def on_change_upload_eval_dataset():
function on_change_custom_instructions_for_llm (line 76) | def on_change_custom_instructions_for_llm():
function on_click_generate_question_sql_pairs (line 82) | def on_click_generate_question_sql_pairs(llm_client: AsyncClient):
function on_click_setup_uploaded_file (line 96) | def on_click_setup_uploaded_file():
function on_change_llm_model (line 130) | def on_change_llm_model():
function on_change_sql (line 135) | def on_change_sql(i: int, key: str):
function on_click_add_candidate_dataset (line 172) | def on_click_add_candidate_dataset(i: int, categories: list):
function on_change_user_question (line 205) | def on_change_user_question():
function on_click_remove_candidate_dataset_button (line 222) | def on_click_remove_candidate_dataset_button(i: int):
FILE: wren-ai-service/eval/data_curation/utils.py
function is_sql_valid (line 37) | async def is_sql_valid(
function get_validated_question_sql_pairs (line 81) | async def get_validated_question_sql_pairs(
function get_contexts_from_sqls (line 116) | async def get_contexts_from_sqls(
function get_question_sql_pairs (line 140) | async def get_question_sql_pairs(
function prettify_sql (line 233) | def prettify_sql(sql: str) -> str:
function get_data_from_wren_engine_with_sqls (line 241) | async def get_data_from_wren_engine_with_sqls(
function remove_limit_statement (line 270) | def remove_limit_statement(sql: str) -> str:
FILE: wren-ai-service/eval/dspy_modules/ask_generation.py
class AskGenerationSignatureV1 (line 4) | class AskGenerationSignatureV1(dspy.Signature):
class AskGenerationV1 (line 26) | class AskGenerationV1(dspy.Module):
method __init__ (line 27) | def __init__(self):
method forward (line 31) | def forward(self, question, context):
FILE: wren-ai-service/eval/dspy_modules/prompt_optimizer.py
function parse_args (line 20) | def parse_args() -> Tuple[str]:
function configure_llm_provider (line 57) | def configure_llm_provider(llm: str, api_key: str):
function clean_sql (line 61) | def clean_sql(sql: str) -> str:
function prepare_dataset (line 65) | def prepare_dataset(path: str, train_ratio: float = 0.5):
function validate_context_and_answer (line 86) | def validate_context_and_answer(example, pred, trace=None):
function optimize (line 109) | def optimize(
function build_optimizing_module (line 119) | def build_optimizing_module(trainset):
FILE: wren-ai-service/eval/evaluation.py
function formatter (line 22) | def formatter(prediction: dict, meta: dict) -> dict:
function parse_args (line 67) | def parse_args() -> Tuple[str]:
class Evaluator (line 91) | class Evaluator:
method __init__ (line 92) | def __init__(self, metrics: list, **kwargs):
method eval (line 99) | def eval(self, meta: dict, predictions: list) -> None:
method _score_metrics (line 114) | def _score_metrics(self, test_case: LLMTestCase, result: TestResult) -...
method _average_score (line 133) | def _average_score(self, meta: dict) -> None:
FILE: wren-ai-service/eval/mdl_to_csv.py
function gen_eval_preparation_data_from_json_to_csv (line 8) | def gen_eval_preparation_data_from_json_to_csv(mdl_path: str):
function gen_new_mdl_from_csv (line 44) | def gen_new_mdl_from_csv(mdl_path: str, csv_path: str):
FILE: wren-ai-service/eval/metrics/accuracy.py
class AccuracyMetric (line 15) | class AccuracyMetric(BaseMetric):
method __init__ (line 16) | def __init__(self, engine_info: dict, enable_semantics_comparison: boo...
method measure (line 24) | def measure(self, test_case: LLMTestCase):
method _is_subset (line 27) | def _is_subset(self, expected: pd.DataFrame, actual: pd.DataFrame) -> ...
method _count_partial_matches (line 47) | def _count_partial_matches(
method _rewrite_sql (line 72) | def _rewrite_sql(self, sql: str) -> str:
method _retrieve_data (line 85) | async def _retrieve_data(self, sql: str) -> pd.DataFrame:
method _check_sql_semantics (line 92) | async def _check_sql_semantics(self, expected_sql: str, actual_sql: str):
method a_measure (line 126) | async def a_measure(self, test_case: LLMTestCase, *args, **kwargs):
method is_successful (line 166) | def is_successful(self):
method __name__ (line 170) | def __name__(self):
class AccuracyMultiCandidateMetric (line 177) | class AccuracyMultiCandidateMetric(BaseMetric):
method __init__ (line 178) | def __init__(self):
method collect (line 183) | def collect(self, test_case: LLMTestCase, result: TestResult):
method measure (line 193) | def measure(self):
method is_successful (line 200) | def is_successful(self):
method __name__ (line 204) | def __name__(self):
FILE: wren-ai-service/eval/metrics/answer_relevancy.py
class AnswerRelevancyMetric (line 9) | class AnswerRelevancyMetric(BaseMetric):
method __init__ (line 10) | def __init__(self, engine_info: dict):
method measure (line 15) | def measure(self, test_case: LLMTestCase):
method a_measure (line 18) | async def a_measure(self, test_case: LLMTestCase, *args, **kwargs):
method is_successful (line 33) | def is_successful(self):
method __name__ (line 37) | def __name__(self):
FILE: wren-ai-service/eval/metrics/context_precision.py
class ContextualPrecisionMetric (line 7) | class ContextualPrecisionMetric(BaseMetric):
method __init__ (line 8) | def __init__(self):
method measure (line 12) | def measure(self, test_case: LLMTestCase):
method a_measure (line 15) | async def a_measure(self, test_case: LLMTestCase, *args, **kwargs):
method is_successful (line 38) | def is_successful(self):
method __name__ (line 42) | def __name__(self):
FILE: wren-ai-service/eval/metrics/context_recall.py
class ContextualRecallMetric (line 9) | class ContextualRecallMetric(BaseMetric):
method __init__ (line 10) | def __init__(self, engine_info: dict):
method measure (line 15) | def measure(self, test_case: LLMTestCase):
method a_measure (line 18) | async def a_measure(self, test_case: LLMTestCase, *args, **kwargs):
method is_successful (line 29) | def is_successful(self):
method __name__ (line 33) | def __name__(self):
FILE: wren-ai-service/eval/metrics/context_relevancy.py
class ContextualRelevancyMetric (line 7) | class ContextualRelevancyMetric(BaseMetric):
method __init__ (line 8) | def __init__(self):
method measure (line 12) | def measure(self, test_case: LLMTestCase):
method a_measure (line 15) | async def a_measure(self, test_case: LLMTestCase, *args, **kwargs):
method is_successful (line 22) | def is_successful(self):
method __name__ (line 26) | def __name__(self):
FILE: wren-ai-service/eval/metrics/faithfulness.py
class FaithfulnessMetric (line 9) | class FaithfulnessMetric(BaseMetric):
method __init__ (line 10) | def __init__(self, engine_info: dict):
method measure (line 15) | def measure(self, test_case: LLMTestCase):
method a_measure (line 18) | async def a_measure(self, test_case: LLMTestCase, *args, **kwargs):
method is_successful (line 28) | def is_successful(self):
method __name__ (line 32) | def __name__(self):
FILE: wren-ai-service/eval/metrics/llm/__init__.py
class EvalResult (line 11) | class EvalResult(BaseModel):
function format (line 27) | def format(response: dict) -> EvalResult:
class QuestionToReasoningJudge (line 32) | class QuestionToReasoningJudge(BaseMetric):
method __init__ (line 45) | def __init__(self, llm_provider: LLMProvider, **_):
method measure (line 55) | def measure(self, test_case: LLMTestCase):
method a_measure (line 58) | async def a_measure(self, test_case: LLMTestCase, *args, **kwargs):
method is_successful (line 72) | def is_successful(self):
method __name__ (line 76) | def __name__(self):
class ReasoningToSqlJudge (line 80) | class ReasoningToSqlJudge(BaseMetric):
method __init__ (line 93) | def __init__(self, llm_provider: LLMProvider, **_):
method measure (line 103) | def measure(self, test_case: LLMTestCase):
method a_measure (line 106) | async def a_measure(self, test_case: LLMTestCase, *args, **kwargs):
method is_successful (line 120) | def is_successful(self):
method __name__ (line 124) | def __name__(self):
class SqlSemanticsJudge (line 128) | class SqlSemanticsJudge(BaseMetric):
method __init__ (line 141) | def __init__(self, llm_provider: LLMProvider, **_):
method measure (line 151) | def measure(self, test_case: LLMTestCase):
method a_measure (line 154) | async def a_measure(self, test_case: LLMTestCase, *args, **kwargs):
method is_successful (line 168) | def is_successful(self):
method __name__ (line 172) | def __name__(self):
FILE: wren-ai-service/eval/metrics/spider/__init__.py
function get_scores (line 43) | def get_scores(count, pred_total, label_total):
function eval_sel (line 51) | def eval_sel(pred, label):
function eval_where (line 71) | def eval_where(pred, label):
function eval_group (line 91) | def eval_group(pred, label):
function eval_having (line 108) | def eval_having(pred, label):
function eval_order (line 127) | def eval_order(pred, label):
function eval_and_or (line 145) | def eval_and_or(pred, label):
function get_nestedSQL (line 156) | def get_nestedSQL(sql):
function eval_nested (line 172) | def eval_nested(pred, label):
function eval_IUEN (line 185) | def eval_IUEN(pred, label):
function get_keywords (line 195) | def get_keywords(sql):
function eval_keywords (line 254) | def eval_keywords(pred, label):
class Evaluator (line 267) | class Evaluator:
method eval_exact_match (line 268) | def eval_exact_match(self, pred: dict, label: dict):
method eval_partial_match (line 281) | def eval_partial_match(self, pred, label):
function rebuild_col_unit_col (line 383) | def rebuild_col_unit_col(valid_col_units, col_unit, kmap):
function rebuild_val_unit_col (line 395) | def rebuild_val_unit_col(valid_col_units, val_unit, kmap):
function rebuild_table_unit_col (line 405) | def rebuild_table_unit_col(valid_col_units, table_unit, kmap):
function rebuild_cond_unit_col (line 415) | def rebuild_cond_unit_col(valid_col_units, cond_unit, kmap):
function rebuild_condition_col (line 424) | def rebuild_condition_col(valid_col_units, condition, kmap):
function rebuild_select_col (line 433) | def rebuild_select_col(valid_col_units, sel, kmap):
function rebuild_from_col (line 446) | def rebuild_from_col(valid_col_units, from_, kmap):
function rebuild_group_by_col (line 458) | def rebuild_group_by_col(valid_col_units, group_by, kmap):
function rebuild_order_by_col (line 467) | def rebuild_order_by_col(valid_col_units, order_by, kmap):
function rebuild_sql_col (line 478) | def rebuild_sql_col(valid_col_units, sql, kmap):
function rebuild_cond_unit_val (line 496) | def rebuild_cond_unit_val(cond_unit):
function rebuild_condition_val (line 512) | def rebuild_condition_val(condition):
function rebuild_sql_val (line 525) | def rebuild_sql_val(sql):
function build_valid_col_units (line 540) | def build_valid_col_units(table_units, schema):
function rewrite_sql (line 554) | def rewrite_sql(sql: str) -> str:
function tokenize (line 562) | def tokenize(sql: str, schema: dict, kmap: dict) -> dict:
function build_foreign_key_map (line 587) | def build_foreign_key_map(entry):
function build_foreign_key_map_from_json (line 627) | def build_foreign_key_map_from_json(table):
function plugin (line 646) | def plugin(query_value_replaced: List[str], values_in_order: List[str]) ...
function plugin_all_permutations (line 663) | def plugin_all_permutations(
function strip_query (line 673) | def strip_query(query: str) -> Tuple[List[str], List[str]]:
function reformat_query (line 728) | def reformat_query(query: str) -> str:
function replace_values (line 739) | def replace_values(sql: str) -> Tuple[List[str], Set[str]]:
function extract_query_values (line 749) | def extract_query_values(sql: str) -> Tuple[List[str], Set[str]]:
function get_all_preds_for_execution (line 758) | def get_all_preds_for_execution(gold: str, pred: str) -> Tuple[int, Iter...
function remove_distinct (line 770) | def remove_distinct(s):
function postprocess (line 777) | def postprocess(query: str) -> str:
function replace_cur_year (line 782) | def replace_cur_year(query: str) -> str:
function get_cursor_from_path (line 789) | def get_cursor_from_path(sqlite_path: str):
function exec_on_db_ (line 802) | async def exec_on_db_(sqlite_path: str, query: str) -> Tuple[str, Any]:
function exec_on_db (line 820) | async def exec_on_db(
function permute_tuple (line 831) | def permute_tuple(element: Tuple, perm: Tuple) -> Tuple:
function unorder_row (line 836) | def unorder_row(row: Tuple) -> Tuple:
function quick_rej (line 844) | def quick_rej(result1: List[Tuple], result2: List[Tuple], order_matters:...
function get_constraint_permutation (line 853) | def get_constraint_permutation(tab1_sets_by_columns: List[Set], result2:...
function multiset_eq (line 871) | def multiset_eq(l1: List, l2: List) -> bool:
function result_eq (line 885) | def result_eq(result1: List[Tuple], result2: List[Tuple], order_matters:...
function eval_exec_match (line 940) | async def eval_exec_match(
FILE: wren-ai-service/eval/metrics/spider/exact_match.py
class ExactMatchAccuracy (line 11) | class ExactMatchAccuracy(BaseMetric):
method __init__ (line 12) | def __init__(
method measure (line 23) | def measure(self, test_case: LLMTestCase):
method a_measure (line 26) | async def a_measure(self, test_case: LLMTestCase, *args, **kwargs):
method is_successful (line 43) | def is_successful(self):
method __name__ (line 47) | def __name__(self):
FILE: wren-ai-service/eval/metrics/spider/exec_match.py
class ExecutionAccuracy (line 10) | class ExecutionAccuracy(BaseMetric):
method __init__ (line 11) | def __init__(
method measure (line 20) | def measure(self, test_case: LLMTestCase):
method a_measure (line 23) | async def a_measure(self, test_case: LLMTestCase, *args, **kwargs):
method is_successful (line 41) | def is_successful(self):
method __name__ (line 45) | def __name__(self):
FILE: wren-ai-service/eval/metrics/spider/process_sql.py
class Schema (line 73) | class Schema:
method __init__ (line 78) | def __init__(self, schema):
method schema (line 83) | def schema(self):
method idMap (line 87) | def idMap(self):
method _map (line 90) | def _map(self, schema):
function get_schema (line 107) | def get_schema(db):
function get_schema_from_json (line 131) | def get_schema_from_json(fpath):
function tokenize (line 144) | def tokenize(string):
function scan_alias (line 180) | def scan_alias(toks):
function get_tables_with_alias (line 189) | def get_tables_with_alias(schema, toks):
function parse_col (line 197) | def parse_col(toks, start_idx, tables_with_alias, schema, default_tables...
function parse_col_unit (line 223) | def parse_col_unit(toks, start_idx, tables_with_alias, schema, default_t...
function parse_val_unit (line 261) | def parse_val_unit(toks, start_idx, tables_with_alias, schema, default_t...
function parse_table_unit (line 290) | def parse_table_unit(toks, start_idx, tables_with_alias, schema):
function parse_value (line 306) | def parse_value(toks, start_idx, tables_with_alias, schema, default_tabl...
function parse_condition (line 348) | def parse_condition(toks, start_idx, tables_with_alias, schema, default_...
function parse_select (line 401) | def parse_select(toks, start_idx, tables_with_alias, schema, default_tab...
function parse_from (line 428) | def parse_from(toks, start_idx, tables_with_alias, schema):
function parse_where (line 475) | def parse_where(toks, start_idx, tables_with_alias, schema, default_tabl...
function parse_group_by (line 487) | def parse_group_by(toks, start_idx, tables_with_alias, schema, default_t...
function parse_order_by (line 512) | def parse_order_by(toks, start_idx, tables_with_alias, schema, default_t...
function parse_having (line 541) | def parse_having(toks, start_idx, tables_with_alias, schema, default_tab...
function parse_limit (line 553) | def parse_limit(toks, start_idx):
function parse_sql (line 570) | def parse_sql(toks, start_idx, tables_with_alias, schema):
function load_data (line 630) | def load_data(fpath):
function get_sql (line 636) | def get_sql(schema, query):
function skip_semicolon (line 644) | def skip_semicolon(toks, start_idx):
FILE: wren-ai-service/eval/pipelines.py
function deploy_model (line 39) | def deploy_model(mdl: str, pipes: list) -> None:
function extract_units (line 47) | def extract_units(ddls: list[str]) -> list:
class Eval (line 95) | class Eval:
method __init__ (line 96) | def __init__(self, meta: dict, candidate_size: int = 1, **_):
method candidate_size (line 103) | def candidate_size(self):
method predict (line 106) | def predict(self, queries: list) -> List[Dict[str, Any]]:
method _process (line 124) | def _process(self, prediction: dict, **_) -> dict:
method process (line 128) | async def process(self, params: dict) -> dict:
class RetrievalPipeline (line 157) | class RetrievalPipeline(Eval):
method __init__ (line 158) | def __init__(
method _process (line 183) | async def _process(self, params: dict, **_) -> dict:
method __call__ (line 193) | async def __call__(self, params: dict, **_):
method metrics (line 199) | def metrics(engine_info: dict) -> dict:
class GenerationPipeline (line 212) | class GenerationPipeline(Eval):
method __init__ (line 213) | def __init__(
method _get_instructions (line 238) | def _get_instructions(self, params: dict) -> list:
method _get_samples (line 246) | def _get_samples(self, params: dict) -> list:
method _process (line 251) | async def _process(self, params: dict, document: list, **_) -> dict:
method __call__ (line 279) | async def __call__(self, params: dict, **_):
method metrics (line 283) | def metrics(
class AskPipeline (line 309) | class AskPipeline(Eval):
method __init__ (line 310) | def __init__(
method _get_instructions (line 351) | def _get_instructions(self, params: dict) -> list:
method _get_samples (line 359) | def _get_samples(self, params: dict) -> list:
method _process (line 364) | async def _process(self, params: dict, **_) -> dict:
method __call__ (line 410) | async def __call__(self, params: dict, **_):
method metrics (line 414) | def metrics(
function init (line 443) | def init(
function metrics_initiator (line 468) | def metrics_initiator(
FILE: wren-ai-service/eval/prediction.py
function generate_meta (line 27) | def generate_meta(
function write_prediction (line 54) | def write_prediction(
function obtain_commit_hash (line 76) | def obtain_commit_hash() -> str:
function parse_args (line 82) | def parse_args() -> Tuple[str, str]:
FILE: wren-ai-service/eval/preparation.py
function download_spider_data (line 32) | def download_spider_data(destination_path: Path):
function download_bird_data (line 64) | def download_bird_data(destination_path: Path):
function get_database_names (line 87) | def get_database_names(path: Path):
function get_tables_by_db (line 91) | def get_tables_by_db(path: Path, key: str):
function build_mdl_models (line 98) | def build_mdl_models(database, tables_info, database_info={}):
function build_mdl_relationships (line 185) | def build_mdl_relationships(tables_info):
function get_ground_truths_by_db (line 212) | def get_ground_truths_by_db(path: Path, key: str):
function build_mdl_by_db_using_spider (line 223) | def build_mdl_by_db_using_spider(destination_path: Path):
function build_question_sql_pairs_by_db_using_spider (line 249) | def build_question_sql_pairs_by_db_using_spider(destination_path: Path):
function build_mdl_by_db_using_bird (line 272) | def build_mdl_by_db_using_bird(destination_path: Path):
function build_question_sql_pairs_by_db_using_bird (line 325) | def build_question_sql_pairs_by_db_using_bird(destination_path: Path):
function get_mdls_and_question_sql_pairs_by_common_db (line 351) | def get_mdls_and_question_sql_pairs_by_common_db(mdl_by_db, question_sql...
FILE: wren-ai-service/eval/utils.py
function get_data_from_wren_engine (line 26) | async def get_data_from_wren_engine(
function get_contexts_from_sql (line 76) | async def get_contexts_from_sql(
function parse_toml (line 176) | def parse_toml(path: str) -> Dict[str, Any]:
function parse_db_name (line 181) | def parse_db_name(path: str) -> str:
function trace_metadata (line 196) | def trace_metadata(
function engine_config (line 215) | def engine_config(
function get_ddl_commands (line 245) | def get_ddl_commands(mdl: Dict[str, Any]) -> List[str]:
function get_documents_given_contexts (line 415) | def get_documents_given_contexts(
function get_eval_dataset_in_toml_string (line 525) | def get_eval_dataset_in_toml_string(mdl: dict, dataset: list) -> str:
function prepare_duckdb_session_sql (line 536) | def prepare_duckdb_session_sql(api_endpoint: str):
function prepare_duckdb_init_sql (line 547) | def prepare_duckdb_init_sql(api_endpoint: str, db: str, path: str):
function load_eval_data_db_to_postgres (line 558) | def load_eval_data_db_to_postgres(db: str, path: str):
function get_next_few_items_circular (line 589) | def get_next_few_items_circular(items: list, i: int, few: int = 5):
function get_openai_client (line 596) | def get_openai_client(
function replace_wren_engine_env_variables (line 605) | def replace_wren_engine_env_variables(engine_type: str, data: dict, conf...
FILE: wren-ai-service/src/__main__.py
function lifespan (line 29) | async def lifespan(app: FastAPI):
function exception_handler (line 64) | async def exception_handler(_, exc: Exception):
function request_exception_handler (line 72) | async def request_exception_handler(_, exc: Exception):
function root (line 80) | def root():
function health (line 85) | def health():
FILE: wren-ai-service/src/config.py
class Settings (line 11) | class Settings(BaseSettings):
method __init__ (line 80) | def __init__(self):
method config_loader (line 89) | def config_loader(self):
method override (line 101) | def override(self, raw: list[dict]) -> None:
method components (line 117) | def components(self) -> list[dict]:
FILE: wren-ai-service/src/core/engine.py
class EngineConfig (line 12) | class EngineConfig(BaseModel):
class Engine (line 17) | class Engine(metaclass=ABCMeta):
method execute_sql (line 19) | async def execute_sql(
function clean_generation_result (line 29) | def clean_generation_result(result: str) -> str:
function remove_limit_statement (line 44) | def remove_limit_statement(sql: str) -> str:
FILE: wren-ai-service/src/core/pipeline.py
class BasicPipeline (line 14) | class BasicPipeline(metaclass=ABCMeta):
method __init__ (line 15) | def __init__(self, pipe: Pipeline | AsyncDriver | Driver):
method run (line 19) | def run(self, *args, **kwargs) -> Dict[str, Any]:
class PipelineComponent (line 24) | class PipelineComponent(Mapping):
method __getitem__ (line 30) | def __getitem__(self, key):
method __iter__ (line 33) | def __iter__(self):
method __len__ (line 36) | def __len__(self):
FILE: wren-ai-service/src/core/provider.py
class LLMProvider (line 6) | class LLMProvider(metaclass=ABCMeta):
method get_generator (line 8) | def get_generator(self, *args, **kwargs):
method get_model (line 11) | def get_model(self):
method get_model_kwargs (line 14) | def get_model_kwargs(self):
method get_context_window_size (line 17) | def get_context_window_size(self):
class EmbedderProvider (line 21) | class EmbedderProvider(metaclass=ABCMeta):
method get_text_embedder (line 23) | def get_text_embedder(self, *args, **kwargs):
method get_document_embedder (line 27) | def get_document_embedder(self, *args, **kwargs):
method get_model (line 30) | def get_model(self):
class DocumentStoreProvider (line 34) | class DocumentStoreProvider(metaclass=ABCMeta):
method get_store (line 36) | def get_store(self, *args, **kwargs) -> DocumentStore:
method get_retriever (line 40) | def get_retriever(self, *args, **kwargs):
FILE: wren-ai-service/src/force_deploy.py
function force_deploy (line 18) | async def force_deploy():
FILE: wren-ai-service/src/force_update_config.py
function update_config (line 9) | def update_config():
FILE: wren-ai-service/src/globals.py
class ServiceContainer (line 17) | class ServiceContainer:
class ServiceMetadata (line 34) | class ServiceMetadata:
function create_service_container (line 39) | def create_service_container(
function get_service_container (line 282) | def get_service_container():
function create_service_metadata (line 288) | def create_service_metadata(
function get_service_metadata (line 337) | def get_service_metadata():
FILE: wren-ai-service/src/pipelines/common.py
function get_engine_supported_data_type (line 7) | def get_engine_supported_data_type(data_type: str) -> str:
function build_table_ddl (line 30) | def build_table_ddl(
function retrieve_metadata (line 67) | async def retrieve_metadata(project_id: str, retriever) -> dict[str, Any]:
class ScoreFilter (line 89) | class ScoreFilter:
method run (line 93) | def run(
function clean_up_new_lines (line 111) | def clean_up_new_lines(text: str) -> str:
FILE: wren-ai-service/src/pipelines/generation/chart_adjustment.py
function preprocess_data (line 82) | def preprocess_data(
function prompt (line 89) | def prompt(
function generate_chart_adjustment (line 115) | async def generate_chart_adjustment(
function post_process (line 124) | def post_process(
class ChartAdjustment (line 149) | class ChartAdjustment(BasicPipeline):
method __init__ (line 150) | def __init__(
method run (line 179) | async def run(
FILE: wren-ai-service/src/pipelines/generation/chart_generation.py
function preprocess_data (line 59) | def preprocess_data(
function prompt (line 66) | def prompt(
function generate_chart (line 90) | async def generate_chart(prompt: dict, generator: Any, generator_name: s...
function post_process (line 95) | def post_process(
class ChartGeneration (line 122) | class ChartGeneration(BasicPipeline):
method __init__ (line 123) | def __init__(
method run (line 153) | async def run(
FILE: wren-ai-service/src/pipelines/generation/data_assistance.py
function prompt (line 56) | def prompt(
function data_assistance (line 80) | async def data_assistance(
class DataAssistance (line 92) | class DataAssistance(BasicPipeline):
method __init__ (line 93) | def __init__(
method _streaming_callback (line 114) | def _streaming_callback(self, chunk, query_id):
method get_streaming_results (line 124) | async def get_streaming_results(self, query_id):
method run (line 150) | async def run(
FILE: wren-ai-service/src/pipelines/generation/followup_sql_generation.py
function prompt (line 90) | def prompt(
function generate_sql_in_followup (line 129) | async def generate_sql_in_followup(
function post_process (line 146) | async def post_process(
class FollowUpSQLGeneration (line 166) | class FollowUpSQLGeneration(BasicPipeline):
method __init__ (line 167) | def __init__(
method run (line 195) | async def run(
FILE: wren-ai-service/src/pipelines/generation/followup_sql_generation_reasoning.py
function prompt (line 67) | def prompt(
function generate_sql_reasoning (line 92) | async def generate_sql_reasoning(
function post_process (line 105) | def post_process(
class FollowUpSQLGenerationReasoning (line 114) | class FollowUpSQLGenerationReasoning(BasicPipeline):
method __init__ (line 115) | def __init__(
method _streaming_callback (line 136) | def _streaming_callback(self, chunk, query_id):
method get_streaming_results (line 145) | async def get_streaming_results(self, query_id):
method run (line 170) | async def run(
FILE: wren-ai-service/src/pipelines/generation/intent_classification.py
function embedding (line 166) | async def embedding(query: str, embedder: Any, histories: list[AskHistor...
function table_retrieval (line 177) | async def table_retrieval(
function dbschema_retrieval (line 199) | async def dbschema_retrieval(
function construct_db_schemas (line 235) | def construct_db_schemas(dbschema_retrieval: list[Document]) -> list[str]:
function prompt (line 269) | def prompt(
function classify_intent (line 295) | async def classify_intent(prompt: dict, generator: Any, generator_name: ...
function post_process (line 300) | def post_process(classify_intent: dict, construct_db_schemas: list[str])...
class IntentClassificationResult (line 321) | class IntentClassificationResult(BaseModel):
class IntentClassification (line 338) | class IntentClassification(BasicPipeline):
method __init__ (line 339) | def __init__(
method run (line 378) | async def run(
FILE: wren-ai-service/src/pipelines/generation/misleading_assistance.py
function prompt (line 56) | def prompt(
function misleading_assistance (line 80) | async def misleading_assistance(
class MisleadingAssistance (line 92) | class MisleadingAssistance(BasicPipeline):
method __init__ (line 93) | def __init__(
method _streaming_callback (line 114) | def _streaming_callback(self, chunk, query_id):
method get_streaming_results (line 124) | async def get_streaming_results(self, query_id):
method run (line 150) | async def run(
FILE: wren-ai-service/src/pipelines/generation/question_recommendation.py
function prompt (line 165) | def prompt(
function generate (line 191) | async def generate(prompt: dict, generator: Any, generator_name: str) ->...
function normalized (line 196) | def normalized(generate: dict) -> dict:
class Question (line 214) | class Question(BaseModel):
class QuestionResult (line 219) | class QuestionResult(BaseModel):
class QuestionRecommendation (line 234) | class QuestionRecommendation(BasicPipeline):
method __init__ (line 235) | def __init__(
method run (line 256) | async def run(
FILE: wren-ai-service/src/pipelines/generation/relationship_recommendation.py
function cleaned_models (line 76) | def cleaned_models(mdl: dict) -> dict:
function prompt (line 102) | def prompt(
function generate (line 113) | async def generate(prompt: dict, generator: Any, generator_name: str) ->...
function normalized (line 118) | def normalized(generate: dict) -> dict:
function validated (line 137) | def validated(normalized: dict, mdl: dict) -> dict:
class RelationType (line 166) | class RelationType(Enum):
method is_include (line 172) | def is_include(cls, value: str) -> bool:
class ModelRelationship (line 176) | class ModelRelationship(BaseModel):
class RelationshipResult (line 186) | class RelationshipResult(BaseModel):
class RelationshipRecommendation (line 201) | class RelationshipRecommendation(BasicPipeline):
method __init__ (line 202) | def __init__(
method run (line 223) | async def run(
FILE: wren-ai-service/src/pipelines/generation/semantics_description.py
function picked_models (line 95) | def picked_models(mdl: dict, selected_models: list[str]) -> list[dict]:
function prompt (line 133) | def prompt(
function generate (line 149) | async def generate(prompt: dict, generator: Any, generator_name: str) ->...
function normalize (line 154) | def normalize(generate: dict) -> dict:
function output (line 173) | def output(normalize: dict, picked_models: list[dict]) -> dict:
class ModelProperties (line 189) | class ModelProperties(BaseModel):
class ModelColumns (line 193) | class ModelColumns(BaseModel):
class SemanticModel (line 198) | class SemanticModel(BaseModel):
class SemanticResult (line 204) | class SemanticResult(BaseModel):
class SemanticsDescription (line 219) | class SemanticsDescription(BasicPipeline):
method __init__ (line 220) | def __init__(self, llm_provider: LLMProvider, **_):
method run (line 236) | async def run(
FILE: wren-ai-service/src/pipelines/generation/sql_answer.py
function prompt (line 59) | def prompt(
function generate_answer (line 81) | async def generate_answer(
class SQLAnswer (line 92) | class SQLAnswer(BasicPipeline):
method __init__ (line 93) | def __init__(
method _streaming_callback (line 114) | def _streaming_callback(self, chunk, query_id):
method get_streaming_results (line 124) | async def get_streaming_results(self, query_id):
method run (line 150) | async def run(
FILE: wren-ai-service/src/pipelines/generation/sql_correction.py
function get_sql_correction_system_prompt (line 28) | def get_sql_correction_system_prompt(sql_knowledge: SqlKnowledge | None ...
function prompt (line 86) | def prompt(
function generate_sql_correction (line 106) | async def generate_sql_correction(
function post_process (line 119) | async def post_process(
class SQLCorrection (line 139) | class SQLCorrection(BasicPipeline):
method __init__ (line 140) | def __init__(
method run (line 168) | async def run(
FILE: wren-ai-service/src/pipelines/generation/sql_diagnosis.py
function prompt (line 65) | def prompt(
function generate_sql_diagnosis (line 85) | async def generate_sql_diagnosis(
function post_process (line 92) | async def post_process(
class SqlDiagnosisResult (line 101) | class SqlDiagnosisResult(BaseModel):
class SQLDiagnosis (line 116) | class SQLDiagnosis(BasicPipeline):
method __init__ (line 117) | def __init__(
method run (line 138) | async def run(
FILE: wren-ai-service/src/pipelines/generation/sql_generation.py
function prompt (line 86) | def prompt(
function generate_sql (line 125) | async def generate_sql(
function post_process (line 138) | async def post_process(
class SQLGeneration (line 160) | class SQLGeneration(BasicPipeline):
method __init__ (line 161) | def __init__(
method run (line 189) | async def run(
FILE: wren-ai-service/src/pipelines/generation/sql_generation_reasoning.py
function prompt (line 58) | def prompt(
function generate_sql_reasoning (line 81) | async def generate_sql_reasoning(
function post_process (line 90) | def post_process(
class SQLGenerationReasoning (line 99) | class SQLGenerationReasoning(BasicPipeline):
method __init__ (line 100) | def __init__(
method _streaming_callback (line 121) | def _streaming_callback(self, chunk, query_id):
method get_streaming_results (line 130) | async def get_streaming_results(self, query_id):
method run (line 155) | async def run(
FILE: wren-ai-service/src/pipelines/generation/sql_question.py
function prompt (line 50) | def prompt(
function generate_sql_question (line 64) | async def generate_sql_question(
function post_process (line 71) | def post_process(
class SQLQuestionResult (line 80) | class SQLQuestionResult(BaseModel):
class SQLQuestion (line 95) | class SQLQuestion(BasicPipeline):
method __init__ (line 96) | def __init__(
method run (line 115) | async def run(
FILE: wren-ai-service/src/pipelines/generation/sql_regeneration.py
function get_sql_regeneration_system_prompt (line 30) | def get_sql_regeneration_system_prompt(
function prompt (line 105) | def prompt(
function regenerate_sql (line 144) | async def regenerate_sql(
function post_process (line 157) | async def post_process(
class SQLRegeneration (line 171) | class SQLRegeneration(BasicPipeline):
method __init__ (line 172) | def __init__(
method run (line 195) | async def run(
FILE: wren-ai-service/src/pipelines/generation/sql_tables_extraction.py
function prompt (line 60) | def prompt(
function extract_sql_tables (line 70) | async def extract_sql_tables(prompt: dict, generator: Any, generator_nam...
function post_process (line 75) | async def post_process(
class SQLTablesExtractionResult (line 84) | class SQLTablesExtractionResult(BaseModel):
class SQLTablesExtraction (line 99) | class SQLTablesExtraction(BasicPipeline):
method __init__ (line 100) | def __init__(
method run (line 121) | async def run(
FILE: wren-ai-service/src/pipelines/generation/user_guide_assistance.py
function prompt (line 52) | def prompt(
function user_guide_assistance (line 70) | async def user_guide_assistance(
class UserGuideAssistance (line 81) | class UserGuideAssistance(BasicPipeline):
method __init__ (line 82) | def __init__(
method _streaming_callback (line 107) | def _streaming_callback(self, chunk, query_id):
method get_streaming_results (line 117) | async def get_streaming_results(self, query_id):
method run (line 142) | async def run(
FILE: wren-ai-service/src/pipelines/generation/utils/chart.py
class ChartDataPreprocessor (line 248) | class ChartDataPreprocessor:
method run (line 253) | def run(
class ChartGenerationPostProcessor (line 282) | class ChartGenerationPostProcessor:
method run (line 286) | def run(
class ChartSchema (line 349) | class ChartSchema(BaseModel):
class ChartType (line 350) | class ChartType(BaseModel):
class ChartEncoding (line 353) | class ChartEncoding(BaseModel):
class TemporalChartEncoding (line 363) | class TemporalChartEncoding(ChartSchema.ChartEncoding):
class LineChartSchema (line 368) | class LineChartSchema(ChartSchema):
class LineChartMark (line 369) | class LineChartMark(BaseModel):
class LineChartEncoding (line 372) | class LineChartEncoding(BaseModel):
class MultiLineChartSchema (line 381) | class MultiLineChartSchema(ChartSchema):
class MultiLineChartMark (line 382) | class MultiLineChartMark(BaseModel):
class MultiLineChartTransform (line 385) | class MultiLineChartTransform(BaseModel):
class MultiLineChartEncoding (line 389) | class MultiLineChartEncoding(BaseModel):
class BarChartSchema (line 399) | class BarChartSchema(ChartSchema):
class BarChartMark (line 400) | class BarChartMark(BaseModel):
class BarChartEncoding (line 403) | class BarChartEncoding(BaseModel):
class GroupedBarChartSchema (line 412) | class GroupedBarChartSchema(ChartSchema):
class GroupedBarChartMark (line 413) | class GroupedBarChartMark(BaseModel):
class GroupedBarChartEncoding (line 416) | class GroupedBarChartEncoding(BaseModel):
class StackedBarChartYEncoding (line 426) | class StackedBarChartYEncoding(ChartSchema.ChartEncoding):
class StackedBarChartSchema (line 430) | class StackedBarChartSchema(ChartSchema):
class StackedBarChartMark (line 431) | class StackedBarChartMark(BaseModel):
class StackedBarChartEncoding (line 434) | class StackedBarChartEncoding(BaseModel):
class PieChartSchema (line 443) | class PieChartSchema(ChartSchema):
class PieChartMark (line 444) | class PieChartMark(BaseModel):
class PieChartEncoding (line 447) | class PieChartEncoding(BaseModel):
class AreaChartSchema (line 455) | class AreaChartSchema(ChartSchema):
class AreaChartMark (line 456) | class AreaChartMark(BaseModel):
class AreaChartEncoding (line 459) | class AreaChartEncoding(BaseModel):
class ChartGenerationResults (line 467) | class ChartGenerationResults(BaseModel):
FILE: wren-ai-service/src/pipelines/generation/utils/sql.py
class SQLGenPostProcessor (line 21) | class SQLGenPostProcessor:
method __init__ (line 22) | def __init__(self, engine: Engine):
method run (line 29) | async def run(
method _classify_generation_result (line 71) | async def _classify_generation_result(
function _extract_from_sql_knowledge (line 454) | def _extract_from_sql_knowledge(
function get_text_to_sql_rules (line 464) | def get_text_to_sql_rules(sql_knowledge: SqlKnowledge | None = None) -> ...
function get_calculated_field_instructions (line 473) | def get_calculated_field_instructions(sql_knowledge: SqlKnowledge | None...
function get_metric_instructions (line 484) | def get_metric_instructions(sql_knowledge: SqlKnowledge | None = None) -...
function get_json_field_instructions (line 493) | def get_json_field_instructions(sql_knowledge: SqlKnowledge | None = Non...
function get_sql_generation_system_prompt (line 502) | def get_sql_generation_system_prompt(sql_knowledge: SqlKnowledge | None ...
class SqlGenerationResult (line 529) | class SqlGenerationResult(BaseModel):
function construct_instructions (line 544) | def construct_instructions(
function construct_ask_history_messages (line 556) | def construct_ask_history_messages(
FILE: wren-ai-service/src/pipelines/indexing/__init__.py
class DocumentCleaner (line 16) | class DocumentCleaner:
method __init__ (line 22) | def __init__(self, stores: List[DocumentStore]) -> None:
method run (line 26) | async def run(self, project_id: Optional[str] = None) -> None:
class MDLValidator (line 52) | class MDLValidator:
method run (line 58) | def run(self, mdl: str) -> str:
class AsyncDocumentWriter (line 77) | class AsyncDocumentWriter(DocumentWriter):
method run (line 79) | async def run(
function clean_display_name (line 91) | def clean_display_name(display_name: str) -> str:
FILE: wren-ai-service/src/pipelines/indexing/db_schema.py
class DDLChunker (line 30) | class DDLChunker:
method run (line 32) | async def run(
method _model_preprocessor (line 66) | async def _model_preprocessor(
method _get_ddl_commands (line 107) | async def _get_ddl_commands(
method _convert_models_and_relationships (line 126) | def _convert_models_and_relationships(
method _convert_views (line 236) | def _convert_views(self, views: List[Dict[str, Any]]) -> List[Dict[str...
method _convert_metrics (line 251) | def _convert_metrics(self, metrics: List[Dict[str, Any]]) -> List[Dict...
function validate_mdl (line 297) | def validate_mdl(mdl_str: str, validator: MDLValidator) -> Dict[str, Any]:
function chunk (line 303) | async def chunk(
function embedding (line 317) | async def embedding(chunk: Dict[str, Any], embedder: Any) -> Dict[str, A...
function clean (line 322) | async def clean(
function write (line 332) | async def write(clean: Dict[str, Any], writer: DocumentWriter) -> None:
class DBSchema (line 339) | class DBSchema(BasicPipeline):
method __init__ (line 340) | def __init__(
method run (line 370) | async def run(
method clean (line 387) | async def clean(self, project_id: Optional[str] = None) -> None:
FILE: wren-ai-service/src/pipelines/indexing/historical_question.py
class ViewChunker (line 23) | class ViewChunker:
method run (line 56) | def run(self, mdl: Dict[str, Any], project_id: Optional[str] = None) -...
function validate_mdl (line 98) | def validate_mdl(mdl_str: str, validator: MDLValidator) -> Dict[str, Any]:
function chunk (line 104) | def chunk(
function embedding (line 113) | async def embedding(chunk: Dict[str, Any], embedder: Any) -> Dict[str, A...
function clean (line 118) | async def clean(
function write (line 128) | async def write(clean: Dict[str, Any], writer: DocumentWriter) -> None:
class HistoricalQuestion (line 135) | class HistoricalQuestion(BasicPipeline):
method __init__ (line 136) | def __init__(
method run (line 163) | async def run(
method clean (line 180) | async def clean(self, project_id: Optional[str] = None) -> None:
FILE: wren-ai-service/src/pipelines/indexing/instructions.py
class Instruction (line 20) | class Instruction(BaseModel):
class InstructionsConverter (line 30) | class InstructionsConverter:
method run (line 32) | def run(self, instructions: list[Instruction], project_id: str = ""):
class InstructionsCleaner (line 58) | class InstructionsCleaner:
method __init__ (line 59) | def __init__(self, instructions_store: DocumentStore) -> None:
method run (line 63) | async def run(
function to_documents (line 85) | def to_documents(
function embedding (line 94) | async def embedding(
function clean (line 102) | async def clean(
function write (line 117) | async def write(
class Instructions (line 127) | class Instructions(BasicPipeline):
method __init__ (line 128) | def __init__(
method run (line 151) | async def run(
method clean (line 169) | async def clean(
FILE: wren-ai-service/src/pipelines/indexing/project_meta.py
function validate_mdl (line 24) | def validate_mdl(mdl_str: str, validator: MDLValidator) -> dict[str, Any]:
function chunk (line 30) | def chunk(
function clean (line 49) | async def clean(
function write (line 59) | async def write(clean: dict[str, Any], writer: DocumentWriter) -> None:
class ProjectMeta (line 66) | class ProjectMeta(BasicPipeline):
method __init__ (line 67) | def __init__(
method run (line 89) | async def run(
method clean (line 105) | async def clean(self, project_id: Optional[str] = None) -> None:
FILE: wren-ai-service/src/pipelines/indexing/sql_pairs.py
class SqlPair (line 22) | class SqlPair(BaseModel):
class SqlPairsConverter (line 29) | class SqlPairsConverter:
method run (line 31) | def run(self, sql_pairs: List[SqlPair], project_id: str = ""):
class SqlPairsCleaner (line 53) | class SqlPairsCleaner:
method __init__ (line 54) | def __init__(self, sql_pairs_store: DocumentStore) -> None:
method run (line 58) | async def run(
function boilerplates (line 78) | def boilerplates(
function sql_pairs (line 91) | def sql_pairs(
function to_documents (line 108) | def to_documents(
function embedding (line 117) | async def embedding(
function clean (line 125) | async def clean(
function write (line 140) | async def write(
function _load_sql_pairs (line 150) | def _load_sql_pairs(sql_pairs_path: str) -> Dict[str, Any]:
class SqlPairs (line 166) | class SqlPairs(BasicPipeline):
method __init__ (line 167) | def __init__(
method run (line 193) | async def run(
method clean (line 216) | async def clean(
FILE: wren-ai-service/src/pipelines/indexing/table_description.py
class TableDescriptionChunker (line 23) | class TableDescriptionChunker:
method run (line 25) | def run(self, mdl: Dict[str, Any], project_id: Optional[str] = None):
method _get_table_descriptions (line 52) | def _get_table_descriptions(self, mdl: Dict[str, Any]) -> List[str]:
function validate_mdl (line 81) | def validate_mdl(mdl_str: str, validator: MDLValidator) -> Dict[str, Any]:
function chunk (line 87) | def chunk(
function embedding (line 96) | async def embedding(chunk: Dict[str, Any], embedder: Any) -> Dict[str, A...
function clean (line 101) | async def clean(
function write (line 111) | async def write(clean: Dict[str, Any], writer: DocumentWriter) -> None:
class TableDescription (line 118) | class TableDescription(BasicPipeline):
method __init__ (line 119) | def __init__(
method run (line 147) | async def run(
method clean (line 164) | async def clean(self, project_id: Optional[str] = None) -> None:
FILE: wren-ai-service/src/pipelines/indexing/utils/helper.py
class Helper (line 15) | class Helper:
method __init__ (line 16) | def __init__(
method condition (line 24) | def condition(self, column: Dict[str, Any], **kwargs) -> bool:
method __call__ (line 27) | def __call__(self, column: Dict[str, Any], **kwargs) -> Any:
function _properties_comment (line 31) | def _properties_comment(column: Dict[str, Any], **_) -> str:
function load_helpers (line 91) | def load_helpers(package_path: str = "src.pipelines.indexing.utils"):
FILE: wren-ai-service/src/pipelines/retrieval/db_schema_retrieval.py
function _build_metric_ddl (line 102) | def _build_metric_ddl(content: dict) -> str:
function _build_view_ddl (line 117) | def _build_view_ddl(content: dict) -> str:
function embedding (line 125) | async def embedding(query: str, embedder: Any, histories: list[AskHistor...
function table_retrieval (line 140) | async def table_retrieval(
function dbschema_retrieval (line 172) | async def dbschema_retrieval(
function construct_db_schemas (line 207) | def construct_db_schemas(dbschema_retrieval: list[Document]) -> list[dict]:
function check_using_db_schemas_without_pruning (line 235) | def check_using_db_schemas_without_pruning(
function prompt (line 303) | def prompt(
function filter_columns_in_tables (line 330) | async def filter_columns_in_tables(
function construct_retrieval_results (line 342) | def construct_retrieval_results(
class MatchingTableContents (line 426) | class MatchingTableContents(BaseModel):
class MatchingTable (line 431) | class MatchingTable(BaseModel):
class RetrievalResults (line 437) | class RetrievalResults(BaseModel):
class DbSchemaRetrieval (line 452) | class DbSchemaRetrieval(BasicPipeline):
method __init__ (line 453) | def __init__(
method run (line 499) | async def run(
FILE: wren-ai-service/src/pipelines/retrieval/historical_question_retrieval.py
class OutputFormatter (line 19) | class OutputFormatter:
method run (line 23) | def run(self, documents: List[Document]):
function count_documents (line 39) | async def count_documents(
function embedding (line 58) | async def embedding(count_documents: int, query: str, embedder: Any) -> ...
function retrieval (line 66) | async def retrieval(
function filtered_documents (line 93) | def filtered_documents(
function formatted_output (line 108) | def formatted_output(
class HistoricalQuestionRetrieval (line 120) | class HistoricalQuestionRetrieval(BasicPipeline):
method __init__ (line 121) | def __init__(
method run (line 151) | async def run(self, query: str, project_id: Optional[str] = None):
FILE: wren-ai-service/src/pipelines/retrieval/instructions.py
class OutputFormatter (line 19) | class OutputFormatter:
method run (line 23) | def run(self, documents: List[Document]):
class ScopeFilter (line 38) | class ScopeFilter:
method run (line 42) | def run(
function count_documents (line 59) | async def count_documents(
function embedding (line 77) | async def embedding(count_documents: int, query: str, embedder: Any) -> ...
function retrieval (line 85) | async def retrieval(embedding: dict, project_id: str, retriever: Any) ->...
function filtered_documents (line 109) | def filtered_documents(
function default_instructions (line 133) | async def default_instructions(
function formatted_output (line 169) | def formatted_output(
class Instructions (line 185) | class Instructions(BasicPipeline):
method __init__ (line 186) | def __init__(
method run (line 215) | async def run(
FILE: wren-ai-service/src/pipelines/retrieval/preprocess_sql_data.py
function preprocess (line 18) | def preprocess(
class PreprocessSqlData (line 79) | class PreprocessSqlData(BasicPipeline):
method __init__ (line 80) | def __init__(
method run (line 99) | def run(
FILE: wren-ai-service/src/pipelines/retrieval/sql_executor.py
class DataFetcher (line 18) | class DataFetcher:
method __init__ (line 19) | def __init__(self, engine: Engine):
method run (line 25) | async def run(
function execute_sql (line 47) | async def execute_sql(
class SQLExecutor (line 63) | class SQLExecutor(BasicPipeline):
method __init__ (line 64) | def __init__(
method run (line 78) | async def run(
FILE: wren-ai-service/src/pipelines/retrieval/sql_functions.py
class SqlFunction (line 20) | class SqlFunction:
method __init__ (line 23) | def __init__(self, definition: dict):
method empty (line 36) | def empty(cls, definition: dict):
method __str__ (line 43) | def __str__(self):
method __repr__ (line 46) | def __repr__(self):
function get_functions (line 52) | async def get_functions(
function cache (line 70) | def cache(
class SqlFunctions (line 82) | class SqlFunctions(BasicPipeline):
method __init__ (line 83) | def __init__(
method run (line 104) | async def run(
FILE: wren-ai-service/src/pipelines/retrieval/sql_knowledge.py
class SqlKnowledge (line 20) | class SqlKnowledge:
method __init__ (line 21) | def __init__(self, sql_knowledge: dict):
method empty (line 25) | def empty(cls, sql_knowledge: dict):
method text_to_sql_rule (line 33) | def text_to_sql_rule(self) -> str:
method instructions (line 37) | def instructions(self) -> dict:
method calculated_field_instructions (line 41) | def calculated_field_instructions(self) -> str:
method metric_instructions (line 45) | def metric_instructions(self) -> str:
method json_field_instructions (line 49) | def json_field_instructions(self) -> str:
method __str__ (line 52) | def __str__(self):
method __repr__ (line 55) | def __repr__(self):
function get_knowledge (line 61) | async def get_knowledge(
function cache (line 78) | def cache(
class SqlKnowledges (line 92) | class SqlKnowledges(BasicPipeline):
method __init__ (line 93) | def __init__(
method run (line 114) | async def run(
FILE: wren-ai-service/src/pipelines/retrieval/sql_pairs_retrieval.py
class OutputFormatter (line 19) | class OutputFormatter:
method run (line 23) | def run(self, documents: List[Document]):
function count_documents (line 38) | async def count_documents(
function embedding (line 56) | async def embedding(count_documents: int, query: str, embedder: Any) -> ...
function retrieval (line 64) | async def retrieval(embedding: dict, project_id: str, retriever: Any) ->...
function filtered_documents (line 87) | def filtered_documents(
function formatted_output (line 104) | def formatted_output(
class SqlPairsRetrieval (line 116) | class SqlPairsRetrieval(BasicPipeline):
method __init__ (line 117) | def __init__(
method run (line 146) | async def run(self, query: str, project_id: Optional[str] = None):
FILE: wren-ai-service/src/providers/__init__.py
function provider_factory (line 12) | def provider_factory(
function llm_processor (line 18) | def llm_processor(entry: dict) -> dict:
function embedder_processor (line 121) | def embedder_processor(entry: dict) -> dict:
function document_store_processor (line 175) | def document_store_processor(entry: dict) -> dict:
function engine_processor (line 215) | def engine_processor(entry: dict) -> dict:
function pipeline_processor (line 252) | def pipeline_processor(entry: dict) -> dict:
class Configuration (line 301) | class Configuration:
function transform (line 306) | def transform(config: list[dict]) -> Configuration:
function generate_components (line 339) | def generate_components(configs: list[dict]) -> dict[str, PipelineCompon...
FILE: wren-ai-service/src/providers/document_store/qdrant.py
function convert_haystack_documents_to_qdrant_points (line 33) | def convert_haystack_documents_to_qdrant_points(
class AsyncQdrantDocumentStore (line 66) | class AsyncQdrantDocumentStore(QdrantDocumentStore):
method __init__ (line 67) | def __init__(
method _query_by_embedding (line 165) | async def _query_by_embedding(
method _query_by_filters (line 212) | async def _query_by_filters(
method delete_documents (line 242) | async def delete_documents(self, filters: Optional[Dict[str, Any]] = N...
method count_documents (line 259) | async def count_documents(self, filters: Optional[Dict[str, Any]] = No...
method write_documents (line 271) | async def write_documents(
class AsyncQdrantEmbeddingRetriever (line 323) | class AsyncQdrantEmbeddingRetriever(QdrantEmbeddingRetriever):
method __init__ (line 324) | def __init__(
method run (line 342) | async def run(
class QdrantProvider (line 368) | class QdrantProvider(DocumentStoreProvider):
method __init__ (line 369) | def __init__(
method _reset_document_store (line 394) | def _reset_document_store(self, recreate_index: bool):
method get_store (line 402) | def get_store(
method get_retriever (line 432) | def get_retriever(
FILE: wren-ai-service/src/providers/embedder/litellm.py
function _prepare_texts_to_embed (line 18) | def _prepare_texts_to_embed(documents: List[Document]) -> List[str]:
class AsyncTextEmbedder (line 34) | class AsyncTextEmbedder:
method __init__ (line 35) | def __init__(
method run (line 51) | async def run(self, text: str):
class AsyncDocumentEmbedder (line 80) | class AsyncDocumentEmbedder:
method __init__ (line 81) | def __init__(
method _embed_batch (line 97) | async def _embed_batch(
method run (line 141) | async def run(self, documents: List[Document]):
class LitellmEmbedderProvider (line 166) | class LitellmEmbedderProvider(EmbedderProvider):
method __init__ (line 167) | def __init__(
method get_text_embedder (line 185) | def get_text_embedder(self):
method get_document_embedder (line 194) | def get_document_embedder(self):
FILE: wren-ai-service/src/providers/engine/wren.py
class WrenUI (line 18) | class WrenUI(Engine):
method __init__ (line 19) | def __init__(
method execute_sql (line 26) | async def execute_sql(
class WrenIbis (line 143) | class WrenIbis(Engine):
method __init__ (line 144) | def __init__(
method execute_sql (line 159) | async def execute_sql(
method dry_plan (line 209) | async def dry_plan(
method get_func_list (line 244) | async def get_func_list(
method get_sql_knowledge (line 266) | async def get_sql_knowledge(
class WrenEngine (line 290) | class WrenEngine(Engine):
method __init__ (line 291) | def __init__(
method execute_sql (line 300) | async def execute_sql(
FILE: wren-ai-service/src/providers/llm/__init__.py
class ChatRole (line 9) | class ChatRole(str, Enum):
class ChatMessage (line 19) | class ChatMessage:
method is_from (line 35) | def is_from(self, role: ChatRole) -> bool:
method from_assistant (line 45) | def from_assistant(
method from_user (line 60) | def from_user(cls, content: str, image_url: Optional[str] = None) -> "...
method from_system (line 70) | def from_system(cls, content: str) -> "ChatMessage":
method from_function (line 80) | def from_function(cls, content: str, name: str) -> "ChatMessage":
method to_dict (line 90) | def to_dict(self) -> Dict[str, Any]:
method from_dict (line 103) | def from_dict(cls, data: Dict[str, Any]) -> "ChatMessage":
class StreamingChunk (line 118) | class StreamingChunk:
function build_message (line 132) | def build_message(completion: Any, choice: Any) -> ChatMessage:
function check_finish_reason (line 157) | def check_finish_reason(message: ChatMessage) -> None:
function connect_chunks (line 182) | def connect_chunks(chunk: Any, chunks: List[StreamingChunk]) -> ChatMess...
function build_chunk (line 200) | def build_chunk(chunk: Any) -> StreamingChunk:
function convert_message_to_openai_format (line 224) | def convert_message_to_openai_format(message: ChatMessage) -> Dict[str, ...
FILE: wren-ai-service/src/providers/llm/litellm.py
class LitellmLLMProvider (line 23) | class LitellmLLMProvider(LLMProvider):
method __init__ (line 24) | def __init__(
method get_generator (line 62) | def get_generator(
FILE: wren-ai-service/src/providers/loader.py
function import_mods (line 12) | def import_mods(package_name=PROVIDERS_PATH):
function provider (line 42) | def provider(name: str):
function get_provider (line 69) | def get_provider(name: str):
FILE: wren-ai-service/src/utils.py
class CustomFormatter (line 16) | class CustomFormatter(logging.Formatter):
method __init__ (line 17) | def __init__(self, is_dev: bool):
method format (line 36) | def format(self, record):
function setup_custom_logger (line 48) | def setup_custom_logger(name, level_str: str, is_dev: bool):
function load_env_vars (line 65) | def load_env_vars() -> str:
function remove_trailing_slash (line 74) | def remove_trailing_slash(endpoint: str) -> str:
function init_langfuse (line 78) | def init_langfuse(settings: Settings):
function trace_metadata (line 90) | def trace_metadata(func):
function trace_cost (line 164) | def trace_cost(func):
function fetch_wren_ai_docs (line 185) | def fetch_wren_ai_docs(doc_endpoint: str, is_oss: bool) -> list[dict]:
function extract_braces_content (line 214) | def extract_braces_content(resp: str) -> str:
FILE: wren-ai-service/src/web/development.py
function _extract_run_method_params (line 11) | def _extract_run_method_params(pipeline_instance) -> Dict[str, str]:
function get_pipelines (line 50) | async def get_pipelines() -> dict:
function run_pipeline (line 68) | async def run_pipeline(pipeline_name: str, request_body: Dict[str, Any])...
FILE: wren-ai-service/src/web/v1/routers/ask.py
function ask (line 26) | async def ask(
function stop_ask (line 47) | async def stop_ask(
function get_ask_result (line 62) | async def get_ask_result(
function get_ask_streaming_result (line 72) | async def get_ask_streaming_result(
FILE: wren-ai-service/src/web/v1/routers/ask_feedbacks.py
function ask_feedback (line 25) | async def ask_feedback(
function stop_ask_feedback (line 48) | async def stop_ask_feedback(
function get_ask_feedback_result (line 63) | async def get_ask_feedback_result(
FILE: wren-ai-service/src/web/v1/routers/chart.py
function chart (line 25) | async def chart(
function stop_chart (line 46) | async def stop_chart(
function get_chart_result (line 61) | async def get_chart_result(
FILE: wren-ai-service/src/web/v1/routers/chart_adjustment.py
function chart_adjustment (line 25) | async def chart_adjustment(
function stop_chart_adjustment (line 48) | async def stop_chart_adjustment(
function get_chart_adjustment_result (line 63) | async def get_chart_adjustment_result(
FILE: wren-ai-service/src/web/v1/routers/instructions.py
class PostRequest (line 19) | class PostRequest(BaseRequest):
class PostResponse (line 23) | class PostResponse(BaseModel):
function index (line 28) | async def index(
class DeleteRequest (line 50) | class DeleteRequest(BaseRequest):
function delete (line 55) | async def delete(
class GetResponse (line 79) | class GetResponse(BaseModel):
function get (line 87) | async def get(
FILE: wren-ai-service/src/web/v1/routers/question_recommendation.py
class PostRequest (line 19) | class PostRequest(BaseRequest):
class PostResponse (line 28) | class PostResponse(BaseModel):
function recommend (line 36) | async def recommend(
class GetResponse (line 57) | class GetResponse(BaseModel):
function get (line 69) | async def get(
FILE: wren-ai-service/src/web/v1/routers/relationship_recommendation.py
class PostRequest (line 19) | class PostRequest(BaseRequest):
class PostResponse (line 23) | class PostResponse(BaseModel):
function recommend (line 31) | async def recommend(
class GetResponse (line 55) | class GetResponse(BaseModel):
function get (line 67) | async def get(
FILE: wren-ai-service/src/web/v1/routers/semantics_description.py
class PostRequest (line 19) | class PostRequest(BaseRequest):
class PostResponse (line 25) | class PostResponse(BaseModel):
function generate (line 33) | async def generate(
class GetResponse (line 55) | class GetResponse(BaseModel):
function get (line 67) | async def get(
FILE: wren-ai-service/src/web/v1/routers/semantics_preparation.py
function prepare_semantics (line 22) | async def prepare_semantics(
function get_prepare_semantics_status (line 43) | async def get_prepare_semantics_status(
function delete_semantics (line 53) | async def delete_semantics(
FILE: wren-ai-service/src/web/v1/routers/sql_answers.py
function sql_answer (line 24) | async def sql_answer(
function get_sql_answer_result (line 47) | async def get_sql_answer_result(
function get_sql_answer_streaming_result (line 57) | async def get_sql_answer_streaming_result(
FILE: wren-ai-service/src/web/v1/routers/sql_corrections.py
class PostRequest (line 19) | class PostRequest(BaseRequest):
class PostResponse (line 27) | class PostResponse(BaseModel):
function correct (line 32) | async def correct(
class GetResponse (line 54) | class GetResponse(BaseModel):
function get (line 64) | async def get(
FILE: wren-ai-service/src/web/v1/routers/sql_pairs.py
class PostRequest (line 20) | class PostRequest(BaseRequest):
class PostResponse (line 24) | class PostResponse(BaseModel):
function prepare (line 29) | async def prepare(
class DeleteRequest (line 49) | class DeleteRequest(BaseRequest):
function delete (line 54) | async def delete(
class GetResponse (line 78) | class GetResponse(BaseModel):
function get (line 86) | async def get(
FILE: wren-ai-service/src/web/v1/routers/sql_question.py
function sql_question (line 23) | async def sql_question(
function get_sql_question_result (line 46) | async def get_sql_question_result(
FILE: wren-ai-service/src/web/v1/services/__init__.py
class MetadataTraceable (line 9) | class MetadataTraceable:
method with_metadata (line 10) | def with_metadata(self) -> dict:
method _error_metadata (line 18) | def _error_metadata(self):
class Configuration (line 26) | class Configuration(BaseModel):
class Timezone (line 27) | class Timezone(BaseModel):
method show_current_time (line 31) | def show_current_time(self):
class SSEEvent (line 44) | class SSEEvent(BaseModel):
class SSEEventMessage (line 45) | class SSEEventMessage(BaseModel):
method to_dict (line 48) | def to_dict(self):
method serialize (line 53) | def serialize(self):
class BaseRequest (line 58) | class BaseRequest(BaseModel):
method query_id (line 69) | def query_id(self) -> str:
method query_id (line 73) | def query_id(self, query_id: str):
FILE: wren-ai-service/src/web/v1/services/ask.py
class AskHistory (line 16) | class AskHistory(BaseModel):
class AskRequest (line 22) | class AskRequest(BaseRequest):
class AskResponse (line 35) | class AskResponse(BaseModel):
class StopAskRequest (line 40) | class StopAskRequest(BaseRequest):
class StopAskResponse (line 44) | class StopAskResponse(BaseModel):
class AskResult (line 49) | class AskResult(BaseModel):
class AskError (line 55) | class AskError(BaseModel):
class AskResultRequest (line 60) | class AskResultRequest(BaseModel):
class _AskResultResponse (line 64) | class _AskResultResponse(BaseModel):
class AskResultResponse (line 90) | class AskResultResponse(_AskResultResponse):
class AskService (line 97) | class AskService:
method __init__ (line 98) | def __init__(
method _is_stopped (line 125) | def _is_stopped(self, query_id: str, container: dict):
method ask (line 135) | async def ask(
method stop_ask (line 640) | def stop_ask(
method get_ask_result (line 648) | def get_ask_result(
method get_ask_streaming_result (line 667) | async def get_ask_streaming_result(
FILE: wren-ai-service/src/web/v1/services/ask_feedback.py
class AskFeedbackRequest (line 18) | class AskFeedbackRequest(BaseRequest):
class AskFeedbackResponse (line 25) | class AskFeedbackResponse(BaseModel):
class StopAskFeedbackRequest (line 30) | class StopAskFeedbackRequest(BaseRequest):
class StopAskFeedbackResponse (line 34) | class StopAskFeedbackResponse(BaseModel):
class AskFeedbackResultRequest (line 39) | class AskFeedbackResultRequest(BaseModel):
class AskFeedbackResultResponse (line 43) | class AskFeedbackResultResponse(BaseModel):
class AskFeedbackService (line 58) | class AskFeedbackService:
method __init__ (line 59) | def __init__(
method _is_stopped (line 76) | def _is_stopped(self, query_id: str, container: dict):
method ask_feedback (line 86) | async def ask_feedback(
method stop_ask_feedback (line 307) | def stop_ask_feedback(
method get_ask_feedback_result (line 317) | def get_ask_feedback_result(
FILE: wren-ai-service/src/web/v1/services/chart.py
class ChartRequest (line 16) | class ChartRequest(BaseRequest):
class ChartResponse (line 24) | class ChartResponse(BaseModel):
class StopChartRequest (line 29) | class StopChartRequest(BaseRequest):
class StopChartResponse (line 33) | class StopChartResponse(BaseModel):
class ChartError (line 38) | class ChartError(BaseModel):
class ChartResultRequest (line 43) | class ChartResultRequest(BaseModel):
class ChartResult (line 47) | class ChartResult(BaseModel):
class ChartResultResponse (line 55) | class ChartResultResponse(BaseModel):
class ChartService (line 62) | class ChartService:
method __init__ (line 63) | def __init__(
method _is_stopped (line 74) | def _is_stopped(self, query_id: str):
method chart (line 84) | async def chart(
method stop_chart (line 189) | def stop_chart(
method get_chart_result (line 197) | def get_chart_result(
FILE: wren-ai-service/src/web/v1/services/chart_adjustment.py
class ChartAdjustmentOption (line 16) | class ChartAdjustmentOption(BaseModel):
class ChartAdjustmentRequest (line 27) | class ChartAdjustmentRequest(BaseRequest):
class ChartAdjustmentResponse (line 34) | class ChartAdjustmentResponse(BaseModel):
class StopChartAdjustmentRequest (line 39) | class StopChartAdjustmentRequest(BaseRequest):
class StopChartAdjustmentResponse (line 43) | class StopChartAdjustmentResponse(BaseModel):
class ChartAdjustmentError (line 48) | class ChartAdjustmentError(BaseModel):
class ChartAdjustmentResultRequest (line 53) | class ChartAdjustmentResultRequest(BaseModel):
class ChartAdjustmentResult (line 57) | class ChartAdjustmentResult(BaseModel):
class ChartAdjustmentResultResponse (line 65) | class ChartAdjustmentResultResponse(BaseModel):
class ChartAdjustmentService (line 74) | class ChartAdjustmentService:
method __init__ (line 75) | def __init__(
method _is_stopped (line 86) | def _is_stopped(self, query_id: str):
method chart_adjustment (line 96) | async def chart_adjustment(
method stop_chart_adjustment (line 202) | def stop_chart_adjustment(
method get_chart_adjustment_result (line 212) | def get_chart_adjustment_result(
FILE: wren-ai-service/src/web/v1/services/instructions.py
class InstructionsService (line 16) | class InstructionsService:
class Instruction (line 17) | class Instruction(BaseModel):
class Error (line 25) | class Error(BaseModel):
class Event (line 29) | class Event(BaseModel, MetadataTraceable):
method __init__ (line 36) | def __init__(
method _handle_exception (line 46) | def _handle_exception(
class IndexRequest (line 63) | class IndexRequest(BaseRequest):
method index (line 69) | async def index(
class DeleteRequest (line 126) | class DeleteRequest(BaseRequest):
method delete (line 132) | async def delete(
method __getitem__ (line 164) | def __getitem__(self, event_id: str) -> Event:
method __setitem__ (line 178) | def __setitem__(self, event_id: str, value: Event):
FILE: wren-ai-service/src/web/v1/services/question_recommendation.py
class QuestionRecommendation (line 17) | class QuestionRecommendation:
class Error (line 18) | class Error(BaseModel):
class Event (line 22) | class Event(BaseModel, MetadataTraceable):
method __init__ (line 30) | def __init__(
method _handle_exception (line 45) | def _handle_exception(
method _validate_question (line 63) | async def _validate_question(
class Request (line 168) | class Request(BaseRequest):
method _recommend (line 177) | async def _recommend(self, request: dict):
method recommend (line 196) | async def recommend(self, input: Request, **kwargs) -> Event:
method __getitem__ (line 271) | def __getitem__(self, id: str) -> Event:
method __setitem__ (line 285) | def __setitem__(self, id: str, value: Event):
FILE: wren-ai-service/src/web/v1/services/relationship_recommendation.py
class RelationshipRecommendation (line 16) | class RelationshipRecommendation:
class Input (line 17) | class Input(BaseRequest):
class Resource (line 21) | class Resource(BaseModel, MetadataTraceable):
class Error (line 22) | class Error(BaseModel):
method __init__ (line 33) | def __init__(
method _handle_exception (line 44) | def _handle_exception(
method recommend (line 63) | async def recommend(self, request: Input, **kwargs) -> Resource:
method __getitem__ (line 102) | def __getitem__(self, id: str) -> Resource:
method __setitem__ (line 116) | def __setitem__(self, id: str, value: Resource):
FILE: wren-ai-service/src/web/v1/services/semantics_description.py
class SemanticsDescription (line 17) | class SemanticsDescription:
class Resource (line 18) | class Resource(BaseModel, MetadataTraceable):
class Error (line 19) | class Error(BaseModel):
method __init__ (line 30) | def __init__(
method _handle_exception (line 39) | def _handle_exception(
class GenerateRequest (line 56) | class GenerateRequest(BaseRequest):
method _chunking (line 62) | def _chunking(
method _generate_task (line 89) | async def _generate_task(self, request_id: str, chunk: dict):
method generate (line 105) | async def generate(self, request: GenerateRequest, **kwargs) -> Resource:
method __getitem__ (line 138) | def __getitem__(self, id: str) -> Resource:
method __setitem__ (line 152) | def __setitem__(self, id: str, value: Resource):
FILE: wren-ai-service/src/web/v1/services/semantics_preparation.py
class SemanticsPreparationRequest (line 17) | class SemanticsPreparationRequest(BaseRequest):
class SemanticsPreparationResponse (line 24) | class SemanticsPreparationResponse(BaseModel):
class SemanticsPreparationStatusRequest (line 31) | class SemanticsPreparationStatusRequest(BaseModel):
class SemanticsPreparationStatusResponse (line 37) | class SemanticsPreparationStatusResponse(BaseModel):
class SemanticsPreparationError (line 38) | class SemanticsPreparationError(BaseModel):
class SemanticsPreparationService (line 46) | class SemanticsPreparationService:
method __init__ (line 47) | def __init__(
method prepare_semantics (line 60) | async def prepare_semantics(
method get_prepare_semantics_status (line 117) | def get_prepare_semantics_status(
method delete_semantics (line 140) | async def delete_semantics(self, project_id: str, **kwargs):
FILE: wren-ai-service/src/web/v1/services/sql_answer.py
class SqlAnswerRequest (line 17) | class SqlAnswerRequest(BaseRequest):
class SqlAnswerResponse (line 24) | class SqlAnswerResponse(BaseModel):
class SqlAnswerResultRequest (line 29) | class SqlAnswerResultRequest(BaseModel):
class SqlAnswerResultResponse (line 33) | class SqlAnswerResultResponse(BaseModel):
class SqlAnswerError (line 34) | class SqlAnswerError(BaseModel):
class SqlAnswerService (line 44) | class SqlAnswerService:
method __init__ (line 45) | def __init__(
method sql_answer (line 58) | async def sql_answer(
method get_sql_answer_result (line 127) | def get_sql_answer_result(
method get_sql_answer_streaming_result (line 147) | async def get_sql_answer_streaming_result(
FILE: wren-ai-service/src/web/v1/services/sql_corrections.py
class SqlCorrectionService (line 15) | class SqlCorrectionService:
class Error (line 16) | class Error(BaseModel):
class Event (line 20) | class Event(BaseModel, MetadataTraceable):
method __init__ (line 29) | def __init__(
method _handle_exception (line 40) | def _handle_exception(
class CorrectionRequest (line 59) | class CorrectionRequest(BaseRequest):
method correct (line 69) | async def correct(
method __getitem__ (line 157) | def __getitem__(self, event_id: str) -> Event:
method __setitem__ (line 171) | def __setitem__(self, event_id: str, value: Event):
FILE: wren-ai-service/src/web/v1/services/sql_pairs.py
class SqlPairsService (line 16) | class SqlPairsService:
class Event (line 17) | class Event(BaseModel, MetadataTraceable):
class Error (line 18) | class Error(BaseModel):
method __init__ (line 28) | def __init__(
method _handle_exception (line 37) | def _handle_exception(
class IndexRequest (line 54) | class IndexRequest(BaseRequest):
method index (line 60) | async def index(
class DeleteRequest (line 97) | class DeleteRequest(BaseRequest):
method delete (line 103) | async def delete(
method __getitem__ (line 130) | def __getitem__(self, id: str) -> Event:
method __setitem__ (line 144) | def __setitem__(self, id: str, value: Event):
FILE: wren-ai-service/src/web/v1/services/sql_question.py
class SqlQuestionRequest (line 17) | class SqlQuestionRequest(BaseRequest):
class SqlQuestionResponse (line 21) | class SqlQuestionResponse(BaseModel):
class SqlQuestionResultRequest (line 26) | class SqlQuestionResultRequest(BaseModel):
class SqlQuestionResultResponse (line 30) | class SqlQuestionResultResponse(BaseModel):
class SqlQuestionError (line 31) | class SqlQuestionError(BaseModel):
class SqlQuestionService (line 41) | class SqlQuestionService:
method __init__ (line 42) | def __init__(
method sql_question (line 55) | async def sql_question(
method get_sql_question_result (line 114) | def get_sql_question_result(
FILE: wren-ai-service/tests/locust/locustfile.py
function on_test_start (line 27) | def on_test_start(environment, **kwargs):
function on_test_stop (line 50) | def on_test_stop(environment, **kwargs):
class IndexingUser (line 55) | class IndexingUser(FastHttpUser):
method indexing (line 57) | def indexing(self):
class AskUser (line 93) | class AskUser(FastHttpUser):
method ask (line 95) | def ask(self):
class DummyUser (line 139) | class DummyUser(FastHttpUser):
method dummy (line 141) | def dummy(self):
class DummyAskUser (line 145) | class DummyAskUser(FastHttpUser):
method ask (line 147) | def ask(self):
FILE: wren-ai-service/tests/pytest/eval/test_metrics.py
function engine_config (line 21) | def engine_config():
function test_case (line 30) | def test_case():
function mocker (line 42) | def mocker():
function _success_analysis_sql (line 47) | def _success_analysis_sql(m, engine_config, repeat=1):
function _success_retrive_data (line 66) | def _success_retrive_data(m, ibis_config, repeat=1):
function test_accuracy_metric (line 78) | def test_accuracy_metric(test_case, mocker):
function test_answer_relevancy_metric (line 99) | def test_answer_relevancy_metric(engine_config, test_case, mocker):
function test_faithfulness_metric (line 108) | def test_faithfulness_metric(engine_config, test_case, mocker):
function test_contextual_relevancy_metric (line 117) | def test_contextual_relevancy_metric(test_case):
function test_contextual_recall_metric (line 124) | def test_contextual_recall_metric(engine_config, test_case, mocker):
function test_contextual_precision_metric (line 133) | def test_contextual_precision_metric(test_case):
FILE: wren-ai-service/tests/pytest/pipelines/generation/test_ask.py
function mdl_str (line 19) | def mdl_str():
function pipeline_components (line 25) | def pipeline_components():
function test_retrieval_pipeline (line 36) | async def test_retrieval_pipeline(pipeline_components):
function test_generation_pipeline (line 53) | async def test_generation_pipeline():
function test_followup_generation_pipeline (line 79) | async def test_followup_generation_pipeline():
function test_sql_correction_pipeline (line 102) | async def test_sql_correction_pipeline():
FILE: wren-ai-service/tests/pytest/pipelines/generation/test_semantics_enrichment.py
function test_without_hallucination (line 4) | def test_without_hallucination():
function test_with_hallucination (line 26) | def test_with_hallucination():
function test_with_hallucination_and_no_columns (line 48) | def test_with_hallucination_and_no_columns():
FILE: wren-ai-service/tests/pytest/pipelines/indexing/test_db_schema.py
function test_empty_mdl (line 12) | async def test_empty_mdl():
function test_single_model (line 21) | async def test_single_model():
function test_multiple_models (line 53) | async def test_multiple_models():
function test_column_is_primary_key (line 102) | async def test_column_is_primary_key():
function test_column_with_properties (line 144) | async def test_column_with_properties():
function test_column_with_nested_columns (line 199) | async def test_column_with_nested_columns():
function test_column_with_calculated_property (line 246) | async def test_column_with_calculated_property():
function test_column_with_relationship (line 289) | async def test_column_with_relationship():
function test_column_batch_size (line 385) | async def test_column_batch_size():
function test_view (line 448) | async def test_view():
function test_view_with_properties (line 472) | async def test_view_with_properties():
function test_metric (line 502) | async def test_metric():
function test_pipeline_run (line 550) | async def test_pipeline_run(mocker: MockFixture):
FILE: wren-ai-service/tests/pytest/pipelines/indexing/test_helper.py
function test_helper (line 12) | def test_helper():
function test_column_properties_preprocessor (line 25) | def test_column_properties_preprocessor():
function test_column_relationship_preprocessor (line 40) | def test_column_relationship_preprocessor():
function test_column_expression_preprocessor (line 52) | def test_column_expression_preprocessor():
function test_column_is_calculated_preprocessor (line 64) | def test_column_is_calculated_preprocessor():
function test_properties_comment_helper (line 76) | def test_properties_comment_helper():
function test_calculated_field_helpers (line 93) | def test_calculated_field_helpers():
function test_load_helpers (line 110) | def test_load_helpers(mocker: MockerFixture):
FILE: wren-ai-service/tests/pytest/pipelines/indexing/test_historical_questions.py
function test_empty_views (line 11) | def test_empty_views():
function test_single_view (line 19) | def test_single_view():
function test_view_missing_properties (line 47) | def test_view_missing_properties():
function test_view_missing_question (line 70) | def test_view_missing_question():
function test_view_missing_summary (line 97) | def test_view_missing_summary():
function test_view_missing_id (line 124) | def test_view_missing_id():
function test_multi_views (line 151) | def test_multi_views():
function test_view_with_historical_query (line 196) | def test_view_with_historical_query():
function test_view_with_historical_queries (line 225) | def test_view_with_historical_queries():
function test_view_with_project_id (line 254) | def test_view_with_project_id():
function test_pipeline_run (line 285) | async def test_pipeline_run(mocker: MockFixture):
function test_pipeline_run_embedder_error (line 339) | async def test_pipeline_run_embedder_error(mocker: MockFixture):
FILE: wren-ai-service/tests/pytest/pipelines/indexing/test_indexing.py
class MockDocumentStore (line 8) | class MockDocumentStore(DocumentStore):
method __init__ (line 11) | def __init__(self, documents=[]):
method write_documents (line 15) | async def write_documents(self, documents, policy):
method delete_documents (line 19) | async def delete_documents(self, filters=None):
method to_dict (line 23) | def to_dict(self):
function test_document_cleaner (line 28) | async def test_document_cleaner():
function test_mdl_validator (line 44) | def test_mdl_validator():
function test_async_document_writer (line 76) | async def test_async_document_writer():
FILE: wren-ai-service/tests/pytest/pipelines/indexing/test_instructions.py
function test_instructions_indexing (line 11) | async def test_instructions_indexing():
function test_instructions_indexing_with_multiple_project_ids (line 53) | async def test_instructions_indexing_with_multiple_project_ids():
function test_instructions_deletion (line 95) | async def test_instructions_deletion():
FILE: wren-ai-service/tests/pytest/pipelines/indexing/test_sql_pairs.py
function test_sql_pairs_indexing_saving_to_document_store (line 10) | async def test_sql_pairs_indexing_saving_to_document_store():
function test_sql_pairs_indexing_saving_to_document_store_with_multiple_project_ids (line 38) | async def test_sql_pairs_indexing_saving_to_document_store_with_multiple...
function test_sql_pairs_deletion (line 74) | async def test_sql_pairs_deletion():
FILE: wren-ai-service/tests/pytest/pipelines/indexing/test_table_description.py
function test_empty_table_descriptions (line 14) | def test_empty_table_descriptions():
function test_single_table_description (line 22) | def test_single_table_description():
function test_multiple_table_descriptions (line 50) | def test_multiple_table_descriptions():
function test_table_description_missing_name (line 95) | def test_table_description_missing_name():
function test_table_description_missing_description (line 112) | def test_table_description_missing_description():
function test_pipeline_run (line 130) | async def test_pipeline_run(mocker: MockFixture):
FILE: wren-ai-service/tests/pytest/pipelines/retrieval/sql_function.py
function mock_engine (line 20) | def mock_engine():
function sql_functions_pipeline (line 27) | def sql_functions_pipeline(mock_engine):
function test_sql_function_init (line 31) | def test_sql_function_init():
function test_sql_function_empty_params (line 38) | def test_sql_function_empty_params():
function test_sql_functions_pipeline_run (line 44) | async def test_sql_functions_pipeline_run(sql_functions_pipeline):
function test_sql_functions_pipeline_different_datasource (line 58) | async def test_sql_functions_pipeline_different_datasource(sql_functions...
function test_sql_functions_pipeline_case_insensitive (line 66) | async def test_sql_functions_pipeline_case_insensitive(sql_functions_pip...
function test_sql_function_param_type_none (line 74) | def test_sql_function_param_type_none():
function test_sql_function_return_type_none (line 81) | def test_sql_function_return_type_none():
function test_sql_function_return_type_same_as_args (line 88) | def test_sql_function_return_type_same_as_args():
FILE: wren-ai-service/tests/pytest/providers/test_loader.py
function test_import_mods (line 4) | def test_import_mods():
function test_get_provider (line 9) | def test_get_provider():
FILE: wren-ai-service/tests/pytest/providers/test_providers.py
function test_transform (line 9) | def test_transform():
function test_generate_components (line 57) | def test_generate_components(mocker: MockerFixture):
FILE: wren-ai-service/tests/pytest/services/mocks.py
class RetrievalMock (line 8) | class RetrievalMock(retrieval.DbSchemaRetrieval):
method __init__ (line 9) | def __init__(self, documents: list = []):
method run (line 12) | async def run(self, query: str, project_id: Optional[str] = None):
class SqlPairsRetrievalMock (line 16) | class SqlPairsRetrievalMock(retrieval.SqlPairsRetrieval):
method __init__ (line 17) | def __init__(self, documents: list = []):
method run (line 20) | async def run(self, query: str, project_id: Optional[str] = None):
class InstructionsRetrievalMock (line 24) | class InstructionsRetrievalMock(retrieval.Instructions):
method __init__ (line 25) | def __init__(self, documents: list = []):
method run (line 28) | async def run(self, query: str, project_id: Optional[str] = None):
class HistoricalQuestionMock (line 32) | class HistoricalQuestionMock(retrieval.HistoricalQuestionRetrieval):
method __init__ (line 33) | def __init__(self, documents: list = []):
method run (line 36) | async def run(self, query: str, project_id: Optional[str] = None):
class IntentClassificationMock (line 40) | class IntentClassificationMock(generation.IntentClassification):
method __init__ (line 41) | def __init__(self, intent: str = "TEXT_TO_SQL"):
method run (line 44) | async def run(
class GenerationMock (line 56) | class GenerationMock(generation.SQLGeneration):
method __init__ (line 57) | def __init__(self, valid: list = [], invalid: list = []):
method run (line 61) | async def run(
FILE: wren-ai-service/tests/pytest/services/test_ask.py
function ask_service (line 23) | def ask_service():
function indexing_service (line 66) | def indexing_service():
function service_metadata (line 85) | def service_metadata():
function mdl_str (line 100) | def mdl_str():
function test_ask_with_successful_query (line 106) | async def test_ask_with_successful_query(
FILE: wren-ai-service/tests/pytest/services/test_instructions.py
function instructions_service (line 13) | def instructions_service():
function test_preparation (line 29) | async def test_preparation(
function test_with_empty_questions (line 70) | async def test_with_empty_questions(
function test_with_empty_instructions (line 104) | async def test_with_empty_instructions(
function test_deletion (line 122) | async def test_deletion(
function test_delete_single_instruction (line 175) | async def test_delete_single_instruction(
function test_delete_cross_project_instruction (line 226) | async def test_delete_cross_project_instruction(
FILE: wren-ai-service/tests/pytest/services/test_relationship_recommendation.py
function mock_pipeline (line 9) | def mock_pipeline():
function relationship_recommendation_service (line 14) | def relationship_recommendation_service(mock_pipeline):
function test_recommend_success (line 20) | async def test_recommend_success(relationship_recommendation_service, mo...
function test_recommend_invalid_mdl (line 34) | async def test_recommend_invalid_mdl(relationship_recommendation_service):
function test_recommend_pipeline_error (line 47) | async def test_recommend_pipeline_error(
function test_getitem_existing (line 65) | def test_getitem_existing(relationship_recommendation_service):
function test_getitem_not_found (line 79) | def test_getitem_not_found(relationship_recommendation_service):
function test_setitem (line 90) | def test_setitem(relationship_recommendation_service):
FILE: wren-ai-service/tests/pytest/services/test_semantics_description.py
function service (line 11) | def service():
function test_generate_semantics_description (line 27) | async def test_generate_semantics_description(
function test_generate_semantics_description_with_invalid_mdl (line 53) | async def test_generate_semantics_description_with_invalid_mdl(
function test_generate_semantics_description_with_exception (line 75) | async def test_generate_semantics_description_with_exception(
function test_get_semantics_description_result (line 103) | def test_get_semantics_description_result(
function test_get_non_existent_semantics_description_result (line 118) | def test_get_non_existent_semantics_description_result(
function test_batch_processing_with_multiple_models (line 131) | async def test_batch_processing_with_multiple_models(
function test_batch_processing_with_custom_chunk_size (line 167) | def test_batch_processing_with_custom_chunk_size(
function test_batch_processing_partial_failure (line 190) | async def test_batch_processing_partial_failure(
function test_concurrent_updates_no_race_condition (line 217) | async def test_concurrent_updates_no_race_condition(
FILE: wren-ai-service/tests/pytest/services/test_sql_pairs.py
function sql_pairs_service (line 13) | def sql_pairs_service():
function test_preparation (line 29) | async def test_preparation(
function test_with_empty_question (line 60) | async def test_with_empty_question(
function test_with_empty_sql_pairs (line 90) | async def test_with_empty_sql_pairs(
function test_deletion (line 108) | async def test_deletion(
function test_delete_single_sql_pair (line 151) | async def test_delete_single_sql_pair(
function test_delete_cross_project_sql_pair (line 192) | async def test_delete_cross_project_sql_pair(
FILE: wren-ai-service/tests/pytest/test_config.py
function test_settings_default_values (line 8) | def test_settings_default_values():
function test_settings_env_var_override (line 30) | def test_settings_env_var_override():
function test_settings_env_dev_override (line 46) | def test_settings_env_dev_override():
function test_settings_yaml_config_override (line 75) | def test_settings_yaml_config_override():
function test_settings_components (line 104) | def test_settings_components():
FILE: wren-ai-service/tests/pytest/test_main.py
function app (line 11) | def app():
function test_semantics_preparation (line 26) | def test_semantics_preparation(app):
function test_asks_with_successful_query (line 58) | def test_asks_with_successful_query(app):
function test_stop_asks (line 91) | def test_stop_asks(app):
function test_web_error_handler (line 113) | def test_web_error_handler(app):
FILE: wren-ai-service/tests/pytest/test_usecases.py
function _get_connection_info (line 23) | def _get_connection_info(data_source: str):
function _prepare_duckdb (line 40) | def _prepare_duckdb(dataset_name: str):
function _update_wren_engine_configs (line 76) | def _update_wren_engine_configs(configs: list[dict]):
function _replace_wren_engine_env_variables (line 85) | def _replace_wren_engine_env_variables(engine_type: str, data: dict):
function is_ai_service_ready (line 104) | def is_ai_service_ready(url: str):
function test_load_mdl_and_questions (line 112) | def test_load_mdl_and_questions(usecases: list[str]):
function setup_datasource (line 134) | def setup_datasource(mdl_str: str, dataset: str, dataset_type: str, url:...
function deploy_mdl (line 168) | def deploy_mdl(mdl_str: str, url: str):
function ask_question (line 190) | async def ask_question(
function ask_questions (line 223) | async def ask_questions(
function str_presenter (line 237) | def str_presenter(dumper, data):
FILE: wren-ai-service/tests/pytest/test_utils.py
function _mock (line 14) | def _mock(mocker: MockFixture) -> tuple:
function service_metadata (line 38) | def service_metadata(mocker: MockFixture):
function test_service_metadata (line 47) | def test_service_metadata(service_metadata: ServiceMetadata):
function test_trace_metadata (line 59) | def test_trace_metadata(service_metadata: ServiceMetadata, mocker: MockF...
function test_clean_display_name (line 89) | def test_clean_display_name():
FILE: wren-ai-service/tools/mdl_to_str.py
function to_str (line 6) | def to_str(mdl: dict) -> str:
function _args (line 34) | def _args():
FILE: wren-ai-service/tools/run_sql.py
function _get_connection_info (line 21) | def _get_connection_info(data_source: str):
function get_data_from_wren_engine (line 38) | def get_data_from_wren_engine(
function _update_wren_engine_configs (line 87) | def _update_wren_engine_configs(configs: list[dict]):
function _prepare_duckdb (line 96) | def _prepare_duckdb(dataset_name: str):
function _replace_wren_engine_env_variables (line 132) | def _replace_wren_engine_env_variables(engine_type: str, data: dict):
function rerun_wren_engine (line 151) | def rerun_wren_engine(mdl_json: Dict, dataset_type: str, dataset: Option...
function main (line 186) | def main():
FILE: wren-launcher/commands/dbt.go
function DbtAutoConvert (line 13) | func DbtAutoConvert() {
function DbtConvertProject (line 63) | func DbtConvertProject(projectPath, outputDir, profileName, target strin...
FILE: wren-launcher/commands/dbt/converter.go
type ConvertOptions (line 19) | type ConvertOptions struct
type ConvertResult (line 30) | type ConvertResult struct
function ConvertDbtProjectCore (line 40) | func ConvertDbtProjectCore(opts ConvertOptions) (*ConvertResult, error) {
function handleLocalhostForContainer (line 293) | func handleLocalhostForContainer(host string) string {
function ConvertDbtCatalogToWrenMDL (line 307) | func ConvertDbtCatalogToWrenMDL(catalogPath string, dataSource DataSourc...
function preprocessManifestForTests (line 427) | func preprocessManifestForTests(manifestData map[string]interface{}, enu...
function preprocessSemanticManifestForPrimaryKeys (line 479) | func preprocessSemanticManifestForPrimaryKeys(semanticData map[string]in...
function generateRelationships (line 512) | func generateRelationships(manifestData map[string]interface{}) []Relati...
function parseTestsForRelationships (line 578) | func parseTestsForRelationships(fromModelName, columnName string, colMap...
function extractRelationshipsFromTests (line 602) | func extractRelationshipsFromTests(fromModelName, fromColumnName string,...
function createOrLinkEnum (line 628) | func createOrLinkEnum(modelName, columnName, columnKey string, values []...
function processColumnForTests (line 662) | func processColumnForTests(nodeKey, modelName, columnName string, colMap...
function convertDbtMetricsToWrenMetrics (line 709) | func convertDbtMetricsToWrenMetrics(semanticData map[string]interface{})...
function buildMeasureLookups (line 770) | func buildMeasureLookups(semanticData map[string]interface{}) (map[strin...
function findBaseModelForMetric (line 807) | func findBaseModelForMetric(typeParams map[string]interface{}, measureTo...
function findTimeDimensionsForModel (line 842) | func findTimeDimensionsForModel(semanticData map[string]interface{}, bas...
function buildAggregationExpression (line 873) | func buildAggregationExpression(metricType string, typeParams map[string...
function extractDescriptionsFromManifest (line 914) | func extractDescriptionsFromManifest(manifestData map[string]interface{}...
function buildWrenColumn (line 953) | func buildWrenColumn(colMap map[string]interface{}, nodeKey string, data...
function convertAndSortColumns (line 988) | func convertAndSortColumns(nodeData map[string]interface{}, nodeKey stri...
function convertDbtNodeToWrenModel (line 1032) | func convertDbtNodeToWrenModel(nodeKey string, nodeData map[string]inter...
function getStringFromMap (line 1083) | func getStringFromMap(m map[string]interface{}, key, defaultValue string...
function getMapFromMap (line 1096) | func getMapFromMap(m map[string]interface{}, key string, defaultValue ma...
function getModelNameFromNodeKey (line 1107) | func getModelNameFromNodeKey(nodeKey string) string {
function parseRef (line 1119) | func parseRef(refStr string) string {
FILE: wren-launcher/commands/dbt/data_source.go
constant integerType (line 17) | integerType = "integer"
constant smallintType (line 18) | smallintType = "smallint"
constant bigintType (line 19) | bigintType = "bigint"
constant floatType (line 20) | floatType = "float"
constant decimalType (line 21) | decimalType = "decimal"
constant varcharType (line 22) | varcharType = "varchar"
constant charType (line 23) | charType = "char"
constant textType (line 24) | textType = "text"
constant dateType (line 25) | dateType = "date"
constant timestampType (line 26) | timestampType = "timestamp"
constant timestamptzType (line 27) | timestamptzType = "timestamptz"
constant doubleType (line 28) | doubleType = "double"
constant booleanType (line 29) | booleanType = "boolean"
constant jsonType (line 30) | jsonType = "json"
constant intervalType (line 31) | intervalType = "interval"
constant postgresType (line 32) | postgresType = "postgres"
constant integerSQL (line 37) | integerSQL = "INTEGER"
constant intSQL (line 38) | intSQL = "INT"
constant bigintSQL (line 39) | bigintSQL = "BIGINT"
constant varcharSQL (line 40) | varcharSQL = "VARCHAR"
constant textSQL (line 41) | textSQL = "TEXT"
constant stringSQL (line 42) | stringSQL = "STRING"
constant dateSQL (line 43) | dateSQL = "DATE"
constant timestampSQL (line 44) | timestampSQL = "TIMESTAMP"
constant datetimeSQL (line 45) | datetimeSQL = "DATETIME"
constant doubleSQL (line 46) | doubleSQL = "DOUBLE"
constant floatSQL (line 47) | floatSQL = "FLOAT"
constant numericSQL (line 48) | numericSQL = "NUMERIC"
constant decimalSQL (line 49) | decimalSQL = "DECIMAL"
constant booleanSQL (line 50) | booleanSQL = "BOOLEAN"
constant boolSQL (line 51) | boolSQL = "BOOL"
constant jsonSQL (line 52) | jsonSQL = "JSON"
type DataSource (line 56) | type DataSource interface
function FromDbtProfiles (line 64) | func FromDbtProfiles(profiles *DbtProfiles) ([]DataSource, error) {
function convertConnectionToDataSource (line 89) | func convertConnectionToDataSource(conn DbtConnection, dbtHomePath, prof...
function convertToPostgresDataSource (line 111) | func convertToPostgresDataSource(conn DbtConnection) (*WrenPostgresDataS...
function convertToMSSQLDataSource (line 135) | func convertToMSSQLDataSource(conn DbtConnection) (*WrenMSSQLDataSource,...
function convertToLocalFileDataSource (line 156) | func convertToLocalFileDataSource(conn DbtConnection, dbtHome string) (*...
function convertToMysqlDataSource (line 195) | func convertToMysqlDataSource(conn DbtConnection) (*WrenMysqlDataSource,...
function convertToBigQueryDataSource (line 220) | func convertToBigQueryDataSource(conn DbtConnection, dbtHomePath string)...
type WrenLocalFileDataSource (line 310) | type WrenLocalFileDataSource struct
method GetType (line 316) | func (ds *WrenLocalFileDataSource) GetType() string {
method Validate (line 321) | func (ds *WrenLocalFileDataSource) Validate() error {
method MapType (line 331) | func (ds *WrenLocalFileDataSource) MapType(sourceType string) string {
type WrenPostgresDataSource (line 354) | type WrenPostgresDataSource struct
method GetType (line 363) | func (ds *WrenPostgresDataSource) GetType() string {
method Validate (line 368) | func (ds *WrenPostgresDataSource) Validate() error {
method MapType (line 391) | func (ds *WrenPostgresDataSource) MapType(sourceType string) string {
type WrenMSSQLDataSource (line 396) | type WrenMSSQLDataSource struct
method GetType (line 407) | func (ds *WrenMSSQLDataSource) GetType() string {
method Validate (line 411) | func (ds *WrenMSSQLDataSource) Validate() error {
method MapType (line 437) | func (ds *WrenMSSQLDataSource) MapType(sourceType string) string {
type WrenMysqlDataSource (line 475) | type WrenMysqlDataSource struct
method GetType (line 486) | func (ds *WrenMysqlDataSource) GetType() string {
method Validate (line 491) | func (ds *WrenMysqlDataSource) Validate() error {
method MapType (line 514) | func (ds *WrenMysqlDataSource) MapType(sourceType string) string {
type WrenBigQueryDataSource (line 552) | type WrenBigQueryDataSource struct
method GetType (line 559) | func (ds *WrenBigQueryDataSource) GetType() string {
method Validate (line 564) | func (ds *WrenBigQueryDataSource) Validate() error {
method MapType (line 578) | func (ds *WrenBigQueryDataSource) MapType(sourceType string) string {
function GetActiveDataSources (line 606) | func GetActiveDataSources(profiles *DbtProfiles, dbtHomePath, profileNam...
function GetDataSourceByType (line 647) | func GetDataSourceByType(profiles *DbtProfiles, dsType string) ([]DataSo...
function ValidateAllDataSources (line 664) | func ValidateAllDataSources(profiles *DbtProfiles) error {
type DefaultDataSource (line 689) | type DefaultDataSource struct
method GetType (line 692) | func (d *DefaultDataSource) GetType() string {
method Validate (line 697) | func (d *DefaultDataSource) Validate() error {
method MapType (line 701) | func (d *DefaultDataSource) MapType(sourceType string) string {
FILE: wren-launcher/commands/dbt/data_source_test.go
constant testHost (line 12) | testHost = "localhost"
constant testUser (line 13) | testUser = "test_user"
constant testPassword (line 14) | testPassword = "test_pass"
constant pgType (line 15) | pgType = "postgres"
constant duckdbType (line 16) | duckdbType = "duckdb"
function validatePostgresDataSource (line 20) | func validatePostgresDataSource(t *testing.T, ds *WrenPostgresDataSource...
function TestFromDbtProfiles_Postgres (line 50) | func TestFromDbtProfiles_Postgres(t *testing.T) {
function TestFromDbtProfiles_PostgresWithDefaultPort (line 87) | func TestFromDbtProfiles_PostgresWithDefaultPort(t *testing.T) {
function TestFromDbtProfiles_LocalFile (line 148) | func TestFromDbtProfiles_LocalFile(t *testing.T) {
function TestFromDbtProfiles_UnsupportedType (line 196) | func TestFromDbtProfiles_UnsupportedType(t *testing.T) {
function TestFromMssqlProfiles (line 223) | func TestFromMssqlProfiles(t *testing.T) {
function TestFromDbtProfiles_NilProfiles (line 290) | func TestFromDbtProfiles_NilProfiles(t *testing.T) {
function TestValidateAllDataSources (line 298) | func TestValidateAllDataSources(t *testing.T) {
function TestFromDbtProfiles_BigQuery (line 344) | func TestFromDbtProfiles_BigQuery(t *testing.T) {
function TestBigQueryDataSourceValidation (line 499) | func TestBigQueryDataSourceValidation(t *testing.T) {
function TestPostgresDataSourceValidation (line 553) | func TestPostgresDataSourceValidation(t *testing.T) {
function TestMysqlDataSourceValidation (line 595) | func TestMysqlDataSourceValidation(t *testing.T) {
function TestGetActiveDataSources (line 652) | func TestGetActiveDataSources(t *testing.T) {
function TestGetDataSourceByType (line 718) | func TestGetDataSourceByType(t *testing.T) {
function TestMapType (line 775) | func TestMapType(t *testing.T) {
type Validator (line 831) | type Validator interface
function testDataSourceValidation (line 836) | func testDataSourceValidation(t *testing.T, testName string, validDS Val...
FILE: wren-launcher/commands/dbt/profiles.go
type DbtProfiles (line 4) | type DbtProfiles struct
type DbtProfile (line 10) | type DbtProfile struct
type DbtConnection (line 16) | type DbtConnection struct
FILE: wren-launcher/commands/dbt/profiles_analyzer.go
function AnalyzeDbtProfiles (line 14) | func AnalyzeDbtProfiles(profilesPath string) (*DbtProfiles, error) {
function parseProfile (line 55) | func parseProfile(profileMap map[string]interface{}) (*DbtProfile, error) {
function parseConnection (line 86) | func parseConnection(connectionMap map[string]interface{}) (*DbtConnecti...
function GetDefaultProfilesPath (line 178) | func GetDefaultProfilesPath() string {
function FindProfilesFile (line 191) | func FindProfilesFile(projectPath string) (string, error) {
FILE: wren-launcher/commands/dbt/utils.go
function IsDbtProjectValid (line 9) | func IsDbtProjectValid(projectPath string) bool {
function DirExists (line 21) | func DirExists(path string) bool {
function FileExists (line 30) | func FileExists(path string) bool {
FILE: wren-launcher/commands/dbt/wren_mdl.go
type WrenMDLManifest (line 4) | type WrenMDLManifest struct
type EnumDefinition (line 17) | type EnumDefinition struct
type EnumValue (line 22) | type EnumValue struct
type WrenModel (line 28) | type WrenModel struct
type TableReference (line 39) | type TableReference struct
type WrenColumn (line 46) | type WrenColumn struct
type Relationship (line 58) | type Relationship struct
type Metric (line 67) | type Metric struct
type View (line 77) | type View struct
FILE: wren-launcher/commands/launch.go
function prepareProjectDir (line 22) | func prepareProjectDir() string {
function evaluateTelemetryPreferences (line 40) | func evaluateTelemetryPreferences() (bool, error) {
function askForLLMProvider (line 52) | func askForLLMProvider() (string, error) {
function askForAPIKey (line 77) | func askForAPIKey() (string, error) {
function askForGenerationModel (line 107) | func askForGenerationModel() (string, error) {
function askForDbtProjectPath (line 127) | func askForDbtProjectPath() (string, error) {
function askForDbtProfileName (line 148) | func askForDbtProfileName() (string, error) {
function askForDbtTarget (line 169) | func askForDbtTarget() (string, error) {
function askForIncludeStagingModels (line 190) | func askForIncludeStagingModels() (bool, error) {
function Launch (line 202) | func Launch() {
function getOpenaiGenerationModel (line 395) | func getOpenaiGenerationModel() (string, bool) {
function getOpenaiApiKey (line 420) | func getOpenaiApiKey() (string, bool) {
function getLLMProvider (line 439) | func getLLMProvider() (string, bool) {
function validateOpenaiApiKey (line 463) | func validateOpenaiApiKey(apiKey string) bool {
function getDbtProfileAndTarget (line 491) | func getDbtProfileAndTarget() (string, string, error) {
function processDbtProject (line 511) | func processDbtProject(projectDir string) (string, error) {
FILE: wren-launcher/config/config.go
constant platformLinuxAmd64 (line 10) | platformLinuxAmd64 = "linux/amd64"
constant platformLinuxArm64 (line 11) | platformLinuxArm64 = "linux/arm64"
function InitFlags (line 24) | func InitFlags() {
function IsExperimentalEngineRustVersion (line 34) | func IsExperimentalEngineRustVersion() bool {
function GetPlatform (line 38) | func GetPlatform() string {
function IsTelemetryDisabled (line 58) | func IsTelemetryDisabled() bool {
function GetOpenaiAPIKey (line 62) | func GetOpenaiAPIKey() string {
function GetOpenaiGenerationModel (line 66) | func GetOpenaiGenerationModel() string {
function GetLLMProvider (line 70) | func GetLLMProvider() string {
function IsDbtEnabled (line 74) | func IsDbtEnabled() bool {
FILE: wren-launcher/main.go
function main (line 12) | func main() {
function showHelp (line 41) | func showHelp() {
FILE: wren-launcher/utils/docker.go
constant WREN_PRODUCT_VERSION (line 26) | WREN_PRODUCT_VERSION string = "0.29.1"
constant DOCKER_COMPOSE_YAML_URL (line 27) | DOCKER_COMPOSE_YAML_URL string = "https://raw.githubusercontent.com/Cann...
constant DOCKER_COMPOSE_ENV_URL (line 28) | DOCKER_COMPOSE_ENV_URL string = "https://raw.githubusercontent.com/Cann...
constant AI_SERVICE_CONFIG_URL (line 29) | AI_SERVICE_CONFIG_URL string = "https://raw.githubusercontent.com/Cann...
function replaceEnvFileContent (line 41) | func replaceEnvFileContent(content string, projectDir string, openaiApiK...
function downloadFile (line 93) | func downloadFile(filepath string, url string) error {
function CheckDockerDaemonRunning (line 113) | func CheckDockerDaemonRunning() (bool, error) {
function prepareUserUUID (line 133) | func prepareUserUUID(projectDir string) (string, error) {
function PrepareConfigFileForOpenAI (line 148) | func PrepareConfigFileForOpenAI(projectDir string, generationModel strin...
function mergeEnvContent (line 179) | func mergeEnvContent(newEnvFile string, envFileContent string) (string, ...
function PrepareDockerFiles (line 244) | func PrepareDockerFiles(openaiApiKey string, openaiGenerationModel strin...
function getEnvFilePath (line 320) | func getEnvFilePath(projectDir string) string {
function getConfigFilePath (line 324) | func getConfigFilePath(projectDir string) string {
function RunDockerCompose (line 343) | func RunDockerCompose(projectName string, projectDir string, llmProvider...
function listProcess (line 409) | func listProcess() ([]container.Summary, error) {
function findWrenUIContainer (line 433) | func findWrenUIContainer() (container.Summary, error) {
function findAIServiceContainer (line 449) | func findAIServiceContainer() (container.Summary, error) {
function IfPortUsedByWrenUI (line 464) | func IfPortUsedByWrenUI(port int) bool {
function IfPortUsedByAIService (line 479) | func IfPortUsedByAIService(port int) bool {
function CheckUIServiceStarted (line 494) | func CheckUIServiceStarted(url string) error {
function CheckAIServiceStarted (line 508) | func CheckAIServiceStarted(url string) error {
FILE: wren-launcher/utils/docker_test.go
function TestFindWrenUIContainer (line 7) | func TestFindWrenUIContainer(t *testing.T) {
FILE: wren-launcher/utils/network.go
function ifPortUsed (line 10) | func ifPortUsed(port int) bool {
function FindAvailablePort (line 16) | func FindAvailablePort(defaultPort int) int {
FILE: wren-launcher/utils/os.go
type OS (line 9) | type OS
constant Windows (line 13) | Windows OS = iota
constant Darwin (line 15) | Darwin
constant Linux (line 17) | Linux
constant Unknown (line 19) | Unknown
function DetectOS (line 22) | func DetectOS() OS {
function Openbrowser (line 35) | func Openbrowser(url string) error {
function OpenDockerDaemon (line 51) | func OpenDockerDaemon() error {
FILE: wren-launcher/utils/rc.go
type WrenRC (line 19) | type WrenRC struct
method getWrenRcFilePath (line 23) | func (w *WrenRC) getWrenRcFilePath() string {
method ensureRcFile (line 27) | func (w *WrenRC) ensureRcFile() (string, error) {
method parseInto (line 47) | func (w *WrenRC) parseInto() (map[string]string, error) {
method Set (line 99) | func (w *WrenRC) Set(key string, value string, override bool) error {
method write (line 124) | func (w *WrenRC) write(m map[string]string) error {
method Read (line 143) | func (w *WrenRC) Read(key string) (string, error) {
FILE: wren-launcher/utils/rc_test.go
function TestReadWriteRcFile (line 8) | func TestReadWriteRcFile(t *testing.T) {
function TestSet (line 34) | func TestSet(t *testing.T) {
FILE: wren-ui/.yarn/releases/yarn-4.5.3.cjs
function Nl (line 4) | function Nl(t,e){return Object.assign(new Error(`${t}: ${e}`),{code:t})}
function z3e (line 4) | function z3e(t){return Nl("EBUSY",t)}
function J3e (line 4) | function J3e(t,e){return Nl("ENOSYS",`${t}, ${e}`)}
function X3e (line 4) | function X3e(t){return Nl("EINVAL",`invalid argument, ${t}`)}
function ho (line 4) | function ho(t){return Nl("EBADF",`bad file descriptor, ${t}`)}
function Z3e (line 4) | function Z3e(t){return Nl("ENOENT",`no such file or directory, ${t}`)}
function $3e (line 4) | function $3e(t){return Nl("ENOTDIR",`not a directory, ${t}`)}
function e_e (line 4) | function e_e(t){return Nl("EISDIR",`illegal operation on a directory, ${...
function t_e (line 4) | function t_e(t){return Nl("EEXIST",`file already exists, ${t}`)}
function r_e (line 4) | function r_e(t){return Nl("EROFS",`read-only filesystem, ${t}`)}
function n_e (line 4) | function n_e(t){return Nl("ENOTEMPTY",`directory not empty, ${t}`)}
function i_e (line 4) | function i_e(t){return Nl("EOPNOTSUPP",`operation not supported, ${t}`)}
function dT (line 4) | function dT(){return Nl("ERR_DIR_CLOSED","Directory handle was closed")}
function AW (line 4) | function AW(){return new lm}
function s_e (line 4) | function s_e(){return XD(AW())}
function XD (line 4) | function XD(t){for(let e in t)if(Object.hasOwn(t,e)){let r=t[e];typeof r...
function o_e (line 4) | function o_e(t){let e=new cm;for(let r in t)if(Object.hasOwn(t,r)){let o...
function CT (line 4) | function CT(t,e){if(t.atimeMs!==e.atimeMs||t.birthtimeMs!==e.birthtimeMs...
method constructor (line 4) | constructor(){this.name="";this.path="";this.mode=0}
method isBlockDevice (line 4) | isBlockDevice(){return!1}
method isCharacterDevice (line 4) | isCharacterDevice(){return!1}
method isDirectory (line 4) | isDirectory(){return(this.mode&61440)===16384}
method isFIFO (line 4) | isFIFO(){return!1}
method isFile (line 4) | isFile(){return(this.mode&61440)===32768}
method isSocket (line 4) | isSocket(){return!1}
method isSymbolicLink (line 4) | isSymbolicLink(){return(this.mode&61440)===40960}
method constructor (line 4) | constructor(){this.uid=0;this.gid=0;this.size=0;this.blksize=0;this.atim...
method isBlockDevice (line 4) | isBlockDevice(){return!1}
method isCharacterDevice (line 4) | isCharacterDevice(){return!1}
method isDirectory (line 4) | isDirectory(){return(this.mode&61440)===16384}
method isFIFO (line 4) | isFIFO(){return!1}
method isFile (line 4) | isFile(){return(this.mode&61440)===32768}
method isSocket (line 4) | isSocket(){return!1}
method isSymbolicLink (line 4) | isSymbolicLink(){return(this.mode&61440)===40960}
method constructor (line 4) | constructor(){this.uid=BigInt(0);this.gid=BigInt(0);this.size=BigInt(0);...
method isBlockDevice (line 4) | isBlockDevice(){return!1}
method isCharacterDevice (line 4) | isCharacterDevice(){return!1}
method isDirectory (line 4) | isDirectory(){return(this.mode&BigInt(61440))===BigInt(16384)}
method isFIFO (line 4) | isFIFO(){return!1}
method isFile (line 4) | isFile(){return(this.mode&BigInt(61440))===BigInt(32768)}
method isSocket (line 4) | isSocket(){return!1}
method isSymbolicLink (line 4) | isSymbolicLink(){return(this.mode&BigInt(61440))===BigInt(40960)}
function A_e (line 4) | function A_e(t){let e,r;if(e=t.match(c_e))t=e[1];else if(r=t.match(u_e))...
function f_e (line 4) | function f_e(t){t=t.replace(/\\/g,"/");let e,r;return(e=t.match(a_e))?t=...
function ZD (line 4) | function ZD(t,e){return t===Ae?pW(e):wT(e)}
function $D (line 4) | async function $D(t,e){let r="0123456789abcdef";await t.mkdirPromise(e.i...
function hW (line 4) | async function hW(t,e,r,o,a){let n=t.pathUtils.normalize(e),u=r.pathUtil...
function BT (line 4) | async function BT(t,e,r,o,a,n,u){let A=u.didParentExist?await gW(r,o):nu...
function gW (line 4) | async function gW(t,e){try{return await t.lstatPromise(e)}catch{return n...
function h_e (line 4) | async function h_e(t,e,r,o,a,n,u,A,p){if(a!==null&&!a.isDirectory())if(p...
function g_e (line 4) | async function g_e(t,e,r,o,a,n,u,A,p,h){let E=await n.checksumFilePromis...
function d_e (line 4) | async function d_e(t,e,r,o,a,n,u,A,p){if(a!==null)if(p.overwrite)t.push(...
function m_e (line 4) | async function m_e(t,e,r,o,a,n,u,A,p){return p.linkStrategy?.type==="Har...
function y_e (line 4) | async function y_e(t,e,r,o,a,n,u,A,p){if(a!==null)if(p.overwrite)t.push(...
function eP (line 4) | function eP(t,e,r,o){let a=()=>{let n=r.shift();if(typeof n>"u")return n...
method constructor (line 4) | constructor(e,r,o={}){this.path=e;this.nextDirent=r;this.opts=o;this.clo...
method throwIfClosed (line 4) | throwIfClosed(){if(this.closed)throw dT()}
method [Symbol.asyncIterator] (line 4) | async*[Symbol.asyncIterator](){try{let e;for(;(e=await this.read())!==nu...
method read (line 4) | read(e){let r=this.readSync();return typeof e<"u"?e(null,r):Promise.reso...
method readSync (line 4) | readSync(){return this.throwIfClosed(),this.nextDirent()}
method close (line 4) | close(e){return this.closeSync(),typeof e<"u"?e(null):Promise.resolve()}
method closeSync (line 4) | closeSync(){this.throwIfClosed(),this.opts.onClose?.(),this.closed=!0}
function mW (line 4) | function mW(t,e){if(t!==e)throw new Error(`Invalid StatWatcher status: e...
method constructor (line 4) | constructor(r,o,{bigint:a=!1}={}){super();this.status="ready";this.chang...
method create (line 4) | static create(r,o,a){let n=new t(r,o,a);return n.start(),n}
method start (line 4) | start(){mW(this.status,"ready"),this.status="running",this.startTimeout=...
method stop (line 4) | stop(){mW(this.status,"running"),this.status="stopped",this.startTimeout...
method stat (line 4) | stat(){try{return this.fakeFs.statSync(this.path,{bigint:this.bigint})}c...
method makeInterval (line 4) | makeInterval(r){let o=setInterval(()=>{let a=this.stat(),n=this.lastStat...
method registerChangeListener (line 4) | registerChangeListener(r,o){this.addListener("change",r),this.changeList...
method unregisterChangeListener (line 4) | unregisterChangeListener(r){this.removeListener("change",r);let o=this.c...
method unregisterAllChangeListeners (line 4) | unregisterAllChangeListeners(){for(let r of this.changeListeners.keys())...
method hasChangeListeners (line 4) | hasChangeListeners(){return this.changeListeners.size>0}
method ref (line 4) | ref(){for(let r of this.changeListeners.values())r.ref();return this}
method unref (line 4) | unref(){for(let r of this.changeListeners.values())r.unref();return this}
function um (line 4) | function um(t,e,r,o){let a,n,u,A;switch(typeof r){case"function":a=!1,n=...
function q0 (line 4) | function q0(t,e,r){let o=rP.get(t);if(typeof o>"u")return;let a=o.get(e)...
function j0 (line 4) | function j0(t){let e=rP.get(t);if(!(typeof e>"u"))for(let r of e.keys())...
function E_e (line 4) | function E_e(t){let e=t.match(/\r?\n/g);if(e===null)return IW.EOL;let r=...
function G0 (line 7) | function G0(t,e){return e.replace(/\r?\n/g,E_e(t))}
method constructor (line 7) | constructor(e){this.pathUtils=e}
method genTraversePromise (line 7) | async*genTraversePromise(e,{stableSort:r=!1}={}){let o=[e];for(;o.length...
method checksumFilePromise (line 7) | async checksumFilePromise(e,{algorithm:r="sha512"}={}){let o=await this....
method removePromise (line 7) | async removePromise(e,{recursive:r=!0,maxRetries:o=5}={}){let a;try{a=aw...
method removeSync (line 7) | removeSync(e,{recursive:r=!0}={}){let o;try{o=this.lstatSync(e)}catch(a)...
method mkdirpPromise (line 7) | async mkdirpPromise(e,{chmod:r,utimes:o}={}){if(e=this.resolve(e),e===th...
method mkdirpSync (line 7) | mkdirpSync(e,{chmod:r,utimes:o}={}){if(e=this.resolve(e),e===this.pathUt...
method copyPromise (line 7) | async copyPromise(e,r,{baseFs:o=this,overwrite:a=!0,stableSort:n=!1,stab...
method copySync (line 7) | copySync(e,r,{baseFs:o=this,overwrite:a=!0}={}){let n=o.lstatSync(r),u=t...
method changeFilePromise (line 7) | async changeFilePromise(e,r,o={}){return Buffer.isBuffer(r)?this.changeF...
method changeFileBufferPromise (line 7) | async changeFileBufferPromise(e,r,{mode:o}={}){let a=Buffer.alloc(0);try...
method changeFileTextPromise (line 7) | async changeFileTextPromise(e,r,{automaticNewlines:o,mode:a}={}){let n="...
method changeFileSync (line 7) | changeFileSync(e,r,o={}){return Buffer.isBuffer(r)?this.changeFileBuffer...
method changeFileBufferSync (line 7) | changeFileBufferSync(e,r,{mode:o}={}){let a=Buffer.alloc(0);try{a=this.r...
method changeFileTextSync (line 7) | changeFileTextSync(e,r,{automaticNewlines:o=!1,mode:a}={}){let n="";try{...
method movePromise (line 7) | async movePromise(e,r){try{await this.renamePromise(e,r)}catch(o){if(o.c...
method moveSync (line 7) | moveSync(e,r){try{this.renameSync(e,r)}catch(o){if(o.code==="EXDEV")this...
method lockPromise (line 7) | async lockPromise(e,r){let o=`${e}.flock`,a=1e3/60,n=Date.now(),u=null,A...
method readJsonPromise (line 7) | async readJsonPromise(e){let r=await this.readFilePromise(e,"utf8");try{...
method readJsonSync (line 7) | readJsonSync(e){let r=this.readFileSync(e,"utf8");try{return JSON.parse(...
method writeJsonPromise (line 7) | async writeJsonPromise(e,r,{compact:o=!1}={}){let a=o?0:2;return await t...
method writeJsonSync (line 8) | writeJsonSync(e,r,{compact:o=!1}={}){let a=o?0:2;return this.writeFileSy...
method preserveTimePromise (line 9) | async preserveTimePromise(e,r){let o=await this.lstatPromise(e),a=await ...
method preserveTimeSync (line 9) | async preserveTimeSync(e,r){let o=this.lstatSync(e),a=r();typeof a<"u"&&...
method constructor (line 9) | constructor(){super(K)}
method getExtractHint (line 9) | getExtractHint(e){return this.baseFs.getExtractHint(e)}
method resolve (line 9) | resolve(e){return this.mapFromBase(this.baseFs.resolve(this.mapToBase(e)))}
method getRealPath (line 9) | getRealPath(){return this.mapFromBase(this.baseFs.getRealPath())}
method openPromise (line 9) | async openPromise(e,r,o){return this.baseFs.openPromise(this.mapToBase(e...
method openSync (line 9) | openSync(e,r,o){return this.baseFs.openSync(this.mapToBase(e),r,o)}
method opendirPromise (line 9) | async opendirPromise(e,r){return Object.assign(await this.baseFs.opendir...
method opendirSync (line 9) | opendirSync(e,r){return Object.assign(this.baseFs.opendirSync(this.mapTo...
method readPromise (line 9) | async readPromise(e,r,o,a,n){return await this.baseFs.readPromise(e,r,o,...
method readSync (line 9) | readSync(e,r,o,a,n){return this.baseFs.readSync(e,r,o,a,n)}
method writePromise (line 9) | async writePromise(e,r,o,a,n){return typeof r=="string"?await this.baseF...
method writeSync (line 9) | writeSync(e,r,o,a,n){return typeof r=="string"?this.baseFs.writeSync(e,r...
method closePromise (line 9) | async closePromise(e){return this.baseFs.closePromise(e)}
method closeSync (line 9) | closeSync(e){this.baseFs.closeSync(e)}
method createReadStream (line 9) | createReadStream(e,r){return this.baseFs.createReadStream(e!==null?this....
method createWriteStream (line 9) | createWriteStream(e,r){return this.baseFs.createWriteStream(e!==null?thi...
method realpathPromise (line 9) | async realpathPromise(e){return this.mapFromBase(await this.baseFs.realp...
method realpathSync (line 9) | realpathSync(e){return this.mapFromBase(this.baseFs.realpathSync(this.ma...
method existsPromise (line 9) | async existsPromise(e){return this.baseFs.existsPromise(this.mapToBase(e))}
method existsSync (line 9) | existsSync(e){return this.baseFs.existsSync(this.mapToBase(e))}
method accessSync (line 9) | accessSync(e,r){return this.baseFs.accessSync(this.mapToBase(e),r)}
method accessPromise (line 9) | async accessPromise(e,r){return this.baseFs.accessPromise(this.mapToBase...
method statPromise (line 9) | async statPromise(e,r){return this.baseFs.statPromise(this.mapToBase(e),r)}
method statSync (line 9) | statSync(e,r){return this.baseFs.statSync(this.mapToBase(e),r)}
method fstatPromise (line 9) | async fstatPromise(e,r){return this.baseFs.fstatPromise(e,r)}
method fstatSync (line 9) | fstatSync(e,r){return this.baseFs.fstatSync(e,r)}
method lstatPromise (line 9) | lstatPromise(e,r){return this.baseFs.lstatPromise(this.mapToBase(e),r)}
method lstatSync (line 9) | lstatSync(e,r){return this.baseFs.lstatSync(this.mapToBase(e),r)}
method fchmodPromise (line 9) | async fchmodPromise(e,r){return this.baseFs.fchmodPromise(e,r)}
method fchmodSync (line 9) | fchmodSync(e,r){return this.baseFs.fchmodSync(e,r)}
method chmodPromise (line 9) | async chmodPromise(e,r){return this.baseFs.chmodPromise(this.mapToBase(e...
method chmodSync (line 9) | chmodSync(e,r){return this.baseFs.chmodSync(this.mapToBase(e),r)}
method fchownPromise (line 9) | async fchownPromise(e,r,o){return this.baseFs.fchownPromise(e,r,o)}
method fchownSync (line 9) | fchownSync(e,r,o){return this.baseFs.fchownSync(e,r,o)}
method chownPromise (line 9) | async chownPromise(e,r,o){return this.baseFs.chownPromise(this.mapToBase...
method chownSync (line 9) | chownSync(e,r,o){return this.baseFs.chownSync(this.mapToBase(e),r,o)}
method renamePromise (line 9) | async renamePromise(e,r){return this.baseFs.renamePromise(this.mapToBase...
method renameSync (line 9) | renameSync(e,r){return this.baseFs.renameSync(this.mapToBase(e),this.map...
method copyFilePromise (line 9) | async copyFilePromise(e,r,o=0){return this.baseFs.copyFilePromise(this.m...
method copyFileSync (line 9) | copyFileSync(e,r,o=0){return this.baseFs.copyFileSync(this.mapToBase(e),...
method appendFilePromise (line 9) | async appendFilePromise(e,r,o){return this.baseFs.appendFilePromise(this...
method appendFileSync (line 9) | appendFileSync(e,r,o){return this.baseFs.appendFileSync(this.fsMapToBase...
method writeFilePromise (line 9) | async writeFilePromise(e,r,o){return this.baseFs.writeFilePromise(this.f...
method writeFileSync (line 9) | writeFileSync(e,r,o){return this.baseFs.writeFileSync(this.fsMapToBase(e...
method unlinkPromise (line 9) | async unlinkPromise(e){return this.baseFs.unlinkPromise(this.mapToBase(e))}
method unlinkSync (line 9) | unlinkSync(e){return this.baseFs.unlinkSync(this.mapToBase(e))}
method utimesPromise (line 9) | async utimesPromise(e,r,o){return this.baseFs.utimesPromise(this.mapToBa...
method utimesSync (line 9) | utimesSync(e,r,o){return this.baseFs.utimesSync(this.mapToBase(e),r,o)}
method lutimesPromise (line 9) | async lutimesPromise(e,r,o){return this.baseFs.lutimesPromise(this.mapTo...
method lutimesSync (line 9) | lutimesSync(e,r,o){return this.baseFs.lutimesSync(this.mapToBase(e),r,o)}
method mkdirPromise (line 9) | async mkdirPromise(e,r){return this.baseFs.mkdirPromise(this.mapToBase(e...
method mkdirSync (line 9) | mkdirSync(e,r){return this.baseFs.mkdirSync(this.mapToBase(e),r)}
method rmdirPromise (line 9) | async rmdirPromise(e,r){return this.baseFs.rmdirPromise(this.mapToBase(e...
method rmdirSync (line 9) | rmdirSync(e,r){return this.baseFs.rmdirSync(this.mapToBase(e),r)}
method rmPromise (line 9) | async rmPromise(e,r){return this.baseFs.rmPromise(this.mapToBase(e),r)}
method rmSync (line 9) | rmSync(e,r){return this.baseFs.rmSync(this.mapToBase(e),r)}
method linkPromise (line 9) | async linkPromise(e,r){return this.baseFs.linkPromise(this.mapToBase(e),...
method linkSync (line 9) | linkSync(e,r){return this.baseFs.linkSync(this.mapToBase(e),this.mapToBa...
method symlinkPromise (line 9) | async symlinkPromise(e,r,o){let a=this.mapToBase(r);if(this.pathUtils.is...
method symlinkSync (line 9) | symlinkSync(e,r,o){let a=this.mapToBase(r);if(this.pathUtils.isAbsolute(...
method readFilePromise (line 9) | async readFilePromise(e,r){return this.baseFs.readFilePromise(this.fsMap...
method readFileSync (line 9) | readFileSync(e,r){return this.baseFs.readFileSync(this.fsMapToBase(e),r)}
method readdirPromise (line 9) | readdirPromise(e,r){return this.baseFs.readdirPromise(this.mapToBase(e),r)}
method readdirSync (line 9) | readdirSync(e,r){return this.baseFs.readdirSync(this.mapToBase(e),r)}
method readlinkPromise (line 9) | async readlinkPromise(e){return this.mapFromBase(await this.baseFs.readl...
method readlinkSync (line 9) | readlinkSync(e){return this.mapFromBase(this.baseFs.readlinkSync(this.ma...
method truncatePromise (line 9) | async truncatePromise(e,r){return this.baseFs.truncatePromise(this.mapTo...
method truncateSync (line 9) | truncateSync(e,r){return this.baseFs.truncateSync(this.mapToBase(e),r)}
method ftruncatePromise (line 9) | async ftruncatePromise(e,r){return this.baseFs.ftruncatePromise(e,r)}
method ftruncateSync (line 9) | ftruncateSync(e,r){return this.baseFs.ftruncateSync(e,r)}
method watch (line 9) | watch(e,r,o){return this.baseFs.watch(this.mapToBase(e),r,o)}
method watchFile (line 9) | watchFile(e,r,o){return this.baseFs.watchFile(this.mapToBase(e),r,o)}
method unwatchFile (line 9) | unwatchFile(e,r){return this.baseFs.unwatchFile(this.mapToBase(e),r)}
method fsMapToBase (line 9) | fsMapToBase(e){return typeof e=="number"?e:this.mapToBase(e)}
method constructor (line 9) | constructor(e,{baseFs:r,pathUtils:o}){super(o),this.target=e,this.baseFs=r}
method getRealPath (line 9) | getRealPath(){return this.target}
method getBaseFs (line 9) | getBaseFs(){return this.baseFs}
method mapFromBase (line 9) | mapFromBase(e){return e}
method mapToBase (line 9) | mapToBase(e){return e}
function BW (line 9) | function BW(t){let e=t;return typeof t.path=="string"&&(e.path=Ae.toPort...
method constructor (line 9) | constructor(e=vW.default){super(),this.realFs=e}
method getExtractHint (line 9) | getExtractHint(){return!1}
method getRealPath (line 9) | getRealPath(){return Bt.root}
method resolve (line 9) | resolve(e){return K.resolve(e)}
method openPromise (line 9) | async openPromise(e,r,o){return await new Promise((a,n)=>{this.realFs.op...
method openSync (line 9) | openSync(e,r,o){return this.realFs.openSync(Ae.fromPortablePath(e),r,o)}
method opendirPromise (line 9) | async opendirPromise(e,r){return await new Promise((o,a)=>{typeof r<"u"?...
method opendirSync (line 9) | opendirSync(e,r){let a=typeof r<"u"?this.realFs.opendirSync(Ae.fromPorta...
method readPromise (line 9) | async readPromise(e,r,o=0,a=0,n=-1){return await new Promise((u,A)=>{thi...
method readSync (line 9) | readSync(e,r,o,a,n){return this.realFs.readSync(e,r,o,a,n)}
method writePromise (line 9) | async writePromise(e,r,o,a,n){return await new Promise((u,A)=>typeof r==...
method writeSync (line 9) | writeSync(e,r,o,a,n){return typeof r=="string"?this.realFs.writeSync(e,r...
method closePromise (line 9) | async closePromise(e){await new Promise((r,o)=>{this.realFs.close(e,this...
method closeSync (line 9) | closeSync(e){this.realFs.closeSync(e)}
method createReadStream (line 9) | createReadStream(e,r){let o=e!==null?Ae.fromPortablePath(e):e;return thi...
method createWriteStream (line 9) | createWriteStream(e,r){let o=e!==null?Ae.fromPortablePath(e):e;return th...
method realpathPromise (line 9) | async realpathPromise(e){return await new Promise((r,o)=>{this.realFs.re...
method realpathSync (line 9) | realpathSync(e){return Ae.toPortablePath(this.realFs.realpathSync(Ae.fro...
method existsPromise (line 9) | async existsPromise(e){return await new Promise(r=>{this.realFs.exists(A...
method accessSync (line 9) | accessSync(e,r){return this.realFs.accessSync(Ae.fromPortablePath(e),r)}
method accessPromise (line 9) | async accessPromise(e,r){return await new Promise((o,a)=>{this.realFs.ac...
method existsSync (line 9) | existsSync(e){return this.realFs.existsSync(Ae.fromPortablePath(e))}
method statPromise (line 9) | async statPromise(e,r){return await new Promise((o,a)=>{r?this.realFs.st...
method statSync (line 9) | statSync(e,r){return r?this.realFs.statSync(Ae.fromPortablePath(e),r):th...
method fstatPromise (line 9) | async fstatPromise(e,r){return await new Promise((o,a)=>{r?this.realFs.f...
method fstatSync (line 9) | fstatSync(e,r){return r?this.realFs.fstatSync(e,r):this.realFs.fstatSync...
method lstatPromise (line 9) | async lstatPromise(e,r){return await new Promise((o,a)=>{r?this.realFs.l...
method lstatSync (line 9) | lstatSync(e,r){return r?this.realFs.lstatSync(Ae.fromPortablePath(e),r):...
method fchmodPromise (line 9) | async fchmodPromise(e,r){return await new Promise((o,a)=>{this.realFs.fc...
method fchmodSync (line 9) | fchmodSync(e,r){return this.realFs.fchmodSync(e,r)}
method chmodPromise (line 9) | async chmodPromise(e,r){return await new Promise((o,a)=>{this.realFs.chm...
method chmodSync (line 9) | chmodSync(e,r){return this.realFs.chmodSync(Ae.fromPortablePath(e),r)}
method fchownPromise (line 9) | async fchownPromise(e,r,o){return await new Promise((a,n)=>{this.realFs....
method fchownSync (line 9) | fchownSync(e,r,o){return this.realFs.fchownSync(e,r,o)}
method chownPromise (line 9) | async chownPromise(e,r,o){return await new Promise((a,n)=>{this.realFs.c...
method chownSync (line 9) | chownSync(e,r,o){return this.realFs.chownSync(Ae.fromPortablePath(e),r,o)}
method renamePromise (line 9) | async renamePromise(e,r){return await new Promise((o,a)=>{this.realFs.re...
method renameSync (line 9) | renameSync(e,r){return this.realFs.renameSync(Ae.fromPortablePath(e),Ae....
method copyFilePromise (line 9) | async copyFilePromise(e,r,o=0){return await new Promise((a,n)=>{this.rea...
method copyFileSync (line 9) | copyFileSync(e,r,o=0){return this.realFs.copyFileSync(Ae.fromPortablePat...
method appendFilePromise (line 9) | async appendFilePromise(e,r,o){return await new Promise((a,n)=>{let u=ty...
method appendFileSync (line 9) | appendFileSync(e,r,o){let a=typeof e=="string"?Ae.fromPortablePath(e):e;...
method writeFilePromise (line 9) | async writeFilePromise(e,r,o){return await new Promise((a,n)=>{let u=typ...
method writeFileSync (line 9) | writeFileSync(e,r,o){let a=typeof e=="string"?Ae.fromPortablePath(e):e;o...
method unlinkPromise (line 9) | async unlinkPromise(e){return await new Promise((r,o)=>{this.realFs.unli...
method unlinkSync (line 9) | unlinkSync(e){return this.realFs.unlinkSync(Ae.fromPortablePath(e))}
method utimesPromise (line 9) | async utimesPromise(e,r,o){return await new Promise((a,n)=>{this.realFs....
method utimesSync (line 9) | utimesSync(e,r,o){this.realFs.utimesSync(Ae.fromPortablePath(e),r,o)}
method lutimesPromise (line 9) | async lutimesPromise(e,r,o){return await new Promise((a,n)=>{this.realFs...
method lutimesSync (line 9) | lutimesSync(e,r,o){this.realFs.lutimesSync(Ae.fromPortablePath(e),r,o)}
method mkdirPromise (line 9) | async mkdirPromise(e,r){return await new Promise((o,a)=>{this.realFs.mkd...
method mkdirSync (line 9) | mkdirSync(e,r){return this.realFs.mkdirSync(Ae.fromPortablePath(e),r)}
method rmdirPromise (line 9) | async rmdirPromise(e,r){return await new Promise((o,a)=>{r?this.realFs.r...
method rmdirSync (line 9) | rmdirSync(e,r){return this.realFs.rmdirSync(Ae.fromPortablePath(e),r)}
method rmPromise (line 9) | async rmPromise(e,r){return await new Promise((o,a)=>{r?this.realFs.rm(A...
method rmSync (line 9) | rmSync(e,r){return this.realFs.rmSync(Ae.fromPortablePath(e),r)}
method linkPromise (line 9) | async linkPromise(e,r){return await new Promise((o,a)=>{this.realFs.link...
method linkSync (line 9) | linkSync(e,r){return this.realFs.linkSync(Ae.fromPortablePath(e),Ae.from...
method symlinkPromise (line 9) | async symlinkPromise(e,r,o){return await new Promise((a,n)=>{this.realFs...
method symlinkSync (line 9) | symlinkSync(e,r,o){return this.realFs.symlinkSync(Ae.fromPortablePath(e....
method readFilePromise (line 9) | async readFilePromise(e,r){return await new Promise((o,a)=>{let n=typeof...
method readFileSync (line 9) | readFileSync(e,r){let o=typeof e=="string"?Ae.fromPortablePath(e):e;retu...
method readdirPromise (line 9) | async readdirPromise(e,r){return await new Promise((o,a)=>{r?r.recursive...
method readdirSync (line 9) | readdirSync(e,r){return r?r.recursive&&process.platform==="win32"?r.with...
method readlinkPromise (line 9) | async readlinkPromise(e){return await new Promise((r,o)=>{this.realFs.re...
method readlinkSync (line 9) | readlinkSync(e){return Ae.toPortablePath(this.realFs.readlinkSync(Ae.fro...
method truncatePromise (line 9) | async truncatePromise(e,r){return await new Promise((o,a)=>{this.realFs....
method truncateSync (line 9) | truncateSync(e,r){return this.realFs.truncateSync(Ae.fromPortablePath(e)...
method ftruncatePromise (line 9) | async ftruncatePromise(e,r){return await new Promise((o,a)=>{this.realFs...
method ftruncateSync (line 9) | ftruncateSync(e,r){return this.realFs.ftruncateSync(e,r)}
method watch (line 9) | watch(e,r,o){return this.realFs.watch(Ae.fromPortablePath(e),r,o)}
method watchFile (line 9) | watchFile(e,r,o){return this.realFs.watchFile(Ae.fromPortablePath(e),r,o)}
method unwatchFile (line 9) | unwatchFile(e,r){return this.realFs.unwatchFile(Ae.fromPortablePath(e),r)}
method makeCallback (line 9) | makeCallback(e,r){return(o,a)=>{o?r(o):e(a)}}
method constructor (line 9) | constructor(e,{baseFs:r=new _n}={}){super(K),this.target=this.pathUtils....
method getRealPath (line 9) | getRealPath(){return this.pathUtils.resolve(this.baseFs.getRealPath(),th...
method resolve (line 9) | resolve(e){return this.pathUtils.isAbsolute(e)?K.normalize(e):this.baseF...
method mapFromBase (line 9) | mapFromBase(e){return e}
method mapToBase (line 9) | mapToBase(e){return this.pathUtils.isAbsolute(e)?e:this.pathUtils.join(t...
method constructor (line 9) | constructor(e,{baseFs:r=new _n}={}){super(K),this.target=this.pathUtils....
method getRealPath (line 9) | getRealPath(){return this.pathUtils.resolve(this.baseFs.getRealPath(),th...
method getTarget (line 9) | getTarget(){return this.target}
method getBaseFs (line 9) | getBaseFs(){return this.baseFs}
method mapToBase (line 9) | mapToBase(e){let r=this.pathUtils.normalize(e);if(this.pathUtils.isAbsol...
method mapFromBase (line 9) | mapFromBase(e){return this.pathUtils.resolve(PW,this.pathUtils.relative(...
method constructor (line 9) | constructor(r,o){super(o);this.instance=null;this.factory=r}
method baseFs (line 9) | get baseFs(){return this.instance||(this.instance=this.factory()),this.i...
method baseFs (line 9) | set baseFs(r){this.instance=r}
method mapFromBase (line 9) | mapFromBase(r){return r}
method mapToBase (line 9) | mapToBase(r){return r}
method constructor (line 9) | constructor({baseFs:r=new _n,filter:o=null,magicByte:a=42,maxOpenFiles:n...
method getExtractHint (line 9) | getExtractHint(r){return this.baseFs.getExtractHint(r)}
method getRealPath (line 9) | getRealPath(){return this.baseFs.getRealPath()}
method saveAndClose (line 9) | saveAndClose(){if(j0(this),this.mountInstances)for(let[r,{childFs:o}]of ...
method discardAndClose (line 9) | discardAndClose(){if(j0(this),this.mountInstances)for(let[r,{childFs:o}]...
method resolve (line 9) | resolve(r){return this.baseFs.resolve(r)}
method remapFd (line 9) | remapFd(r,o){let a=this.nextFd++|this.magic;return this.fdMap.set(a,[r,o...
method openPromise (line 9) | async openPromise(r,o,a){return await this.makeCallPromise(r,async()=>aw...
method openSync (line 9) | openSync(r,o,a){return this.makeCallSync(r,()=>this.baseFs.openSync(r,o,...
method opendirPromise (line 9) | async opendirPromise(r,o){return await this.makeCallPromise(r,async()=>a...
method opendirSync (line 9) | opendirSync(r,o){return this.makeCallSync(r,()=>this.baseFs.opendirSync(...
method readPromise (line 9) | async readPromise(r,o,a,n,u){if((r&va)!==this.magic)return await this.ba...
method readSync (line 9) | readSync(r,o,a,n,u){if((r&va)!==this.magic)return this.baseFs.readSync(r...
method writePromise (line 9) | async writePromise(r,o,a,n,u){if((r&va)!==this.magic)return typeof o=="s...
method writeSync (line 9) | writeSync(r,o,a,n,u){if((r&va)!==this.magic)return typeof o=="string"?th...
method closePromise (line 9) | async closePromise(r){if((r&va)!==this.magic)return await this.baseFs.cl...
method closeSync (line 9) | closeSync(r){if((r&va)!==this.magic)return this.baseFs.closeSync(r);let ...
method createReadStream (line 9) | createReadStream(r,o){return r===null?this.baseFs.createReadStream(r,o):...
method createWriteStream (line 9) | createWriteStream(r,o){return r===null?this.baseFs.createWriteStream(r,o...
method realpathPromise (line 9) | async realpathPromise(r){return await this.makeCallPromise(r,async()=>aw...
method realpathSync (line 9) | realpathSync(r){return this.makeCallSync(r,()=>this.baseFs.realpathSync(...
method existsPromise (line 9) | async existsPromise(r){return await this.makeCallPromise(r,async()=>awai...
method existsSync (line 9) | existsSync(r){return this.makeCallSync(r,()=>this.baseFs.existsSync(r),(...
method accessPromise (line 9) | async accessPromise(r,o){return await this.makeCallPromise(r,async()=>aw...
method accessSync (line 9) | accessSync(r,o){return this.makeCallSync(r,()=>this.baseFs.accessSync(r,...
method statPromise (line 9) | async statPromise(r,o){return await this.makeCallPromise(r,async()=>awai...
method statSync (line 9) | statSync(r,o){return this.makeCallSync(r,()=>this.baseFs.statSync(r,o),(...
method fstatPromise (line 9) | async fstatPromise(r,o){if((r&va)!==this.magic)return this.baseFs.fstatP...
method fstatSync (line 9) | fstatSync(r,o){if((r&va)!==this.magic)return this.baseFs.fstatSync(r,o);...
method lstatPromise (line 9) | async lstatPromise(r,o){return await this.makeCallPromise(r,async()=>awa...
method lstatSync (line 9) | lstatSync(r,o){return this.makeCallSync(r,()=>this.baseFs.lstatSync(r,o)...
method fchmodPromise (line 9) | async fchmodPromise(r,o){if((r&va)!==this.magic)return this.baseFs.fchmo...
method fchmodSync (line 9) | fchmodSync(r,o){if((r&va)!==this.magic)return this.baseFs.fchmodSync(r,o...
method chmodPromise (line 9) | async chmodPromise(r,o){return await this.makeCallPromise(r,async()=>awa...
method chmodSync (line 9) | chmodSync(r,o){return this.makeCallSync(r,()=>this.baseFs.chmodSync(r,o)...
method fchownPromise (line 9) | async fchownPromise(r,o,a){if((r&va)!==this.magic)return this.baseFs.fch...
method fchownSync (line 9) | fchownSync(r,o,a){if((r&va)!==this.magic)return this.baseFs.fchownSync(r...
method chownPromise (line 9) | async chownPromise(r,o,a){return await this.makeCallPromise(r,async()=>a...
method chownSync (line 9) | chownSync(r,o,a){return this.makeCallSync(r,()=>this.baseFs.chownSync(r,...
method renamePromise (line 9) | async renamePromise(r,o){return await this.makeCallPromise(r,async()=>aw...
method renameSync (line 9) | renameSync(r,o){return this.makeCallSync(r,()=>this.makeCallSync(o,()=>t...
method copyFilePromise (line 9) | async copyFilePromise(r,o,a=0){let n=async(u,A,p,h)=>{if(a&K0.constants....
method copyFileSync (line 9) | copyFileSync(r,o,a=0){let n=(u,A,p,h)=>{if(a&K0.constants.COPYFILE_FICLO...
method appendFilePromise (line 9) | async appendFilePromise(r,o,a){return await this.makeCallPromise(r,async...
method appendFileSync (line 9) | appendFileSync(r,o,a){return this.makeCallSync(r,()=>this.baseFs.appendF...
method writeFilePromise (line 9) | async writeFilePromise(r,o,a){return await this.makeCallPromise(r,async(...
method writeFileSync (line 9) | writeFileSync(r,o,a){return this.makeCallSync(r,()=>this.baseFs.writeFil...
method unlinkPromise (line 9) | async unlinkPromise(r){return await this.makeCallPromise(r,async()=>awai...
method unlinkSync (line 9) | unlinkSync(r){return this.makeCallSync(r,()=>this.baseFs.unlinkSync(r),(...
method utimesPromise (line 9) | async utimesPromise(r,o,a){return await this.makeCallPromise(r,async()=>...
method utimesSync (line 9) | utimesSync(r,o,a){return this.makeCallSync(r,()=>this.baseFs.utimesSync(...
method lutimesPromise (line 9) | async lutimesPromise(r,o,a){return await this.makeCallPromise(r,async()=...
method lutimesSync (line 9) | lutimesSync(r,o,a){return this.makeCallSync(r,()=>this.baseFs.lutimesSyn...
method mkdirPromise (line 9) | async mkdirPromise(r,o){return await this.makeCallPromise(r,async()=>awa...
method mkdirSync (line 9) | mkdirSync(r,o){return this.makeCallSync(r,()=>this.baseFs.mkdirSync(r,o)...
method rmdirPromise (line 9) | async rmdirPromise(r,o){return await this.makeCallPromise(r,async()=>awa...
method rmdirSync (line 9) | rmdirSync(r,o){return this.makeCallSync(r,()=>this.baseFs.rmdirSync(r,o)...
method rmPromise (line 9) | async rmPromise(r,o){return await this.makeCallPromise(r,async()=>await ...
method rmSync (line 9) | rmSync(r,o){return this.makeCallSync(r,()=>this.baseFs.rmSync(r,o),(a,{s...
method linkPromise (line 9) | async linkPromise(r,o){return await this.makeCallPromise(o,async()=>awai...
method linkSync (line 9) | linkSync(r,o){return this.makeCallSync(o,()=>this.baseFs.linkSync(r,o),(...
method symlinkPromise (line 9) | async symlinkPromise(r,o,a){return await this.makeCallPromise(o,async()=...
method symlinkSync (line 9) | symlinkSync(r,o,a){return this.makeCallSync(o,()=>this.baseFs.symlinkSyn...
method readFilePromise (line 9) | async readFilePromise(r,o){return this.makeCallPromise(r,async()=>await ...
method readFileSync (line 9) | readFileSync(r,o){return this.makeCallSync(r,()=>this.baseFs.readFileSyn...
method readdirPromise (line 9) | async readdirPromise(r,o){return await this.makeCallPromise(r,async()=>a...
method readdirSync (line 9) | readdirSync(r,o){return this.makeCallSync(r,()=>this.baseFs.readdirSync(...
method readlinkPromise (line 9) | async readlinkPromise(r){return await this.makeCallPromise(r,async()=>aw...
method readlinkSync (line 9) | readlinkSync(r){return this.makeCallSync(r,()=>this.baseFs.readlinkSync(...
method truncatePromise (line 9) | async truncatePromise(r,o){return await this.makeCallPromise(r,async()=>...
method truncateSync (line 9) | truncateSync(r,o){return this.makeCallSync(r,()=>this.baseFs.truncateSyn...
method ftruncatePromise (line 9) | async ftruncatePromise(r,o){if((r&va)!==this.magic)return this.baseFs.ft...
method ftruncateSync (line 9) | ftruncateSync(r,o){if((r&va)!==this.magic)return this.baseFs.ftruncateSy...
method watch (line 9) | watch(r,o,a){return this.makeCallSync(r,()=>this.baseFs.watch(r,o,a),(n,...
method watchFile (line 9) | watchFile(r,o,a){return this.makeCallSync(r,()=>this.baseFs.watchFile(r,...
method unwatchFile (line 9) | unwatchFile(r,o){return this.makeCallSync(r,()=>this.baseFs.unwatchFile(...
method makeCallPromise (line 9) | async makeCallPromise(r,o,a,{requireSubpath:n=!0}={}){if(typeof r!="stri...
method makeCallSync (line 9) | makeCallSync(r,o,a,{requireSubpath:n=!0}={}){if(typeof r!="string")retur...
method findMount (line 9) | findMount(r){if(this.filter&&!this.filter.test(r))return null;let o="";f...
method limitOpenFiles (line 9) | limitOpenFiles(r){if(this.mountInstances===null)return;let o=Date.now(),...
method getMountPromise (line 9) | async getMountPromise(r,o){if(this.mountInstances){let a=this.mountInsta...
method getMountSync (line 9) | getMountSync(r,o){if(this.mountInstances){let a=this.mountInstances.get(...
method constructor (line 9) | constructor(){super(K)}
method getExtractHint (line 9) | getExtractHint(){throw $t()}
method getRealPath (line 9) | getRealPath(){throw $t()}
method resolve (line 9) | resolve(){throw $t()}
method openPromise (line 9) | async openPromise(){throw $t()}
method openSync (line 9) | openSync(){throw $t()}
method opendirPromise (line 9) | async opendirPromise(){throw $t()}
method opendirSync (line 9) | opendirSync(){throw $t()}
method readPromise (line 9) | async readPromise(){throw $t()}
method readSync (line 9) | readSync(){throw $t()}
method writePromise (line 9) | async writePromise(){throw $t()}
method writeSync (line 9) | writeSync(){throw $t()}
method closePromise (line 9) | async closePromise(){throw $t()}
method closeSync (line 9) | closeSync(){throw $t()}
method createWriteStream (line 9) | createWriteStream(){throw $t()}
method createReadStream (line 9) | createReadStream(){throw $t()}
method realpathPromise (line 9) | async realpathPromise(){throw $t()}
method realpathSync (line 9) | realpathSync(){throw $t()}
method readdirPromise (line 9) | async readdirPromise(){throw $t()}
method readdirSync (line 9) | readdirSync(){throw $t()}
method existsPromise (line 9) | async existsPromise(e){throw $t()}
method existsSync (line 9) | existsSync(e){throw $t()}
method accessPromise (line 9) | async accessPromise(){throw $t()}
method accessSync (line 9) | accessSync(){throw $t()}
method statPromise (line 9) | async statPromise(){throw $t()}
method statSync (line 9) | statSync(){throw $t()}
method fstatPromise (line 9) | async fstatPromise(e){throw $t()}
method fstatSync (line 9) | fstatSync(e){throw $t()}
method lstatPromise (line 9) | async lstatPromise(e){throw $t()}
method lstatSync (line 9) | lstatSync(e){throw $t()}
method fchmodPromise (line 9) | async fchmodPromise(){throw $t()}
method fchmodSync (line 9) | fchmodSync(){throw $t()}
method chmodPromise (line 9) | async chmodPromise(){throw $t()}
method chmodSync (line 9) | chmodSync(){throw $t()}
method fchownPromise (line 9) | async fchownPromise(){throw $t()}
method fchownSync (line 9) | fchownSync(){throw $t()}
method chownPromise (line 9) | async chownPromise(){throw $t()}
method chownSync (line 9) | chownSync(){throw $t()}
method mkdirPromise (line 9) | async mkdirPromise(){throw $t()}
method mkdirSync (line 9) | mkdirSync(){throw $t()}
method rmdirPromise (line 9) | async rmdirPromise(){throw $t()}
method rmdirSync (line 9) | rmdirSync(){throw $t()}
method rmPromise (line 9) | async rmPromise(){throw $t()}
method rmSync (line 9) | rmSync(){throw $t()}
method linkPromise (line 9) | async linkPromise(){throw $t()}
method linkSync (line 9) | linkSync(){throw $t()}
method symlinkPromise (line 9) | async symlinkPromise(){throw $t()}
method symlinkSync (line 9) | symlinkSync(){throw $t()}
method renamePromise (line 9) | async renamePromise(){throw $t()}
method renameSync (line 9) | renameSync(){throw $t()}
method copyFilePromise (line 9) | async copyFilePromise(){throw $t()}
method copyFileSync (line 9) | copyFileSync(){throw $t()}
method appendFilePromise (line 9) | async appendFilePromise(){throw $t()}
method appendFileSync (line 9) | appendFileSync(){throw $t()}
method writeFilePromise (line 9) | async writeFilePromise(){throw $t()}
method writeFileSync (line 9) | writeFileSync(){throw $t()}
method unlinkPromise (line 9) | async unlinkPromise(){throw $t()}
method unlinkSync (line 9) | unlinkSync(){throw $t()}
method utimesPromise (line 9) | async utimesPromise(){throw $t()}
method utimesSync (line 9) | utimesSync(){throw $t()}
method lutimesPromise (line 9) | async lutimesPromise(){throw $t()}
method lutimesSync (line 9) | lutimesSync(){throw $t()}
method readFilePromise (line 9) | async readFilePromise(){throw $t()}
method readFileSync (line 9) | readFileSync(){throw $t()}
method readlinkPromise (line 9) | async readlinkPromise(){throw $t()}
method readlinkSync (line 9) | readlinkSync(){throw $t()}
method truncatePromise (line 9) | async truncatePromise(){throw $t()}
method truncateSync (line 9) | truncateSync(){throw $t()}
method ftruncatePromise (line 9) | async ftruncatePromise(e,r){throw $t()}
method ftruncateSync (line 9) | ftruncateSync(e,r){throw $t()}
method watch (line 9) | watch(){throw $t()}
method watchFile (line 9) | watchFile(){throw $t()}
method unwatchFile (line 9) | unwatchFile(){throw $t()}
method constructor (line 9) | constructor(e){super(Ae),this.baseFs=e}
method mapFromBase (line 9) | mapFromBase(e){return Ae.fromPortablePath(e)}
method mapToBase (line 9) | mapToBase(e){return Ae.toPortablePath(e)}
method makeVirtualPath (line 9) | static makeVirtualPath(e,r,o){if(K.basename(e)!=="__virtual__")throw new...
method resolveVirtual (line 9) | static resolveVirtual(e){let r=e.match(PT);if(!r||!r[3]&&r[5])return e;l...
method constructor (line 9) | constructor({baseFs:e=new _n}={}){super(K),this.baseFs=e}
method getExtractHint (line 9) | getExtractHint(e){return this.baseFs.getExtractHint(e)}
method getRealPath (line 9) | getRealPath(){return this.baseFs.getRealPath()}
method realpathSync (line 9) | realpathSync(e){let r=e.match(PT);if(!r)return this.baseFs.realpathSync(...
method realpathPromise (line 9) | async realpathPromise(e){let r=e.match(PT);if(!r)return await this.baseF...
method mapToBase (line 9) | mapToBase(e){if(e==="")return e;if(this.pathUtils.isAbsolute(e))return t...
method mapFromBase (line 9) | mapFromBase(e){return e}
function w_e (line 9) | function w_e(t,e){return typeof ST.default.isUtf8<"u"?ST.default.isUtf8(...
method constructor (line 9) | constructor(e){super(Ae),this.baseFs=e}
method mapFromBase (line 9) | mapFromBase(e){return e}
method mapToBase (line 9) | mapToBase(e){if(typeof e=="string")return e;if(e instanceof URL)return(0...
method constructor (line 9) | constructor(e,r){this[UW]=1;this[MW]=void 0;this[OW]=void 0;this[NW]=voi...
method fd (line 9) | get fd(){return this[df]}
method appendFile (line 9) | async appendFile(e,r){try{this[_c](this.appendFile);let o=(typeof r=="st...
method chown (line 9) | async chown(e,r){try{return this[_c](this.chown),await this[go].fchownPr...
method chmod (line 9) | async chmod(e){try{return this[_c](this.chmod),await this[go].fchmodProm...
method createReadStream (line 9) | createReadStream(e){return this[go].createReadStream(null,{...e,fd:this....
method createWriteStream (line 9) | createWriteStream(e){return this[go].createWriteStream(null,{...e,fd:thi...
method datasync (line 9) | datasync(){throw new Error("Method not implemented.")}
method sync (line 9) | sync(){throw new Error("Method not implemented.")}
method read (line 9) | async read(e,r,o,a){try{this[_c](this.read);let n;return Buffer.isBuffer...
method readFile (line 9) | async readFile(e){try{this[_c](this.readFile);let r=(typeof e=="string"?...
method readLines (line 9) | readLines(e){return(0,_W.createInterface)({input:this.createReadStream(e...
method stat (line 9) | async stat(e){try{return this[_c](this.stat),await this[go].fstatPromise...
method truncate (line 9) | async truncate(e){try{return this[_c](this.truncate),await this[go].ftru...
method utimes (line 9) | utimes(e,r){throw new Error("Method not implemented.")}
method writeFile (line 9) | async writeFile(e,r){try{this[_c](this.writeFile);let o=(typeof r=="stri...
method write (line 9) | async write(...e){try{if(this[_c](this.write),ArrayBuffer.isView(e[0])){...
method writev (line 9) | async writev(e,r){try{this[_c](this.writev);let o=0;if(typeof r<"u")for(...
method readv (line 9) | readv(e,r){throw new Error("Method not implemented.")}
method close (line 9) | close(){if(this[df]===-1)return Promise.resolve();if(this[Yp])return thi...
method [(go,df,UW=fm,MW=Yp,OW=sP,NW=oP,_c)] (line 9) | [(go,df,UW=fm,MW=Yp,OW=sP,NW=oP,_c)](e){if(this[df]===-1){let r=new Erro...
method [Hc] (line 9) | [Hc](){if(this[fm]--,this[fm]===0){let e=this[df];this[df]=-1,this[go].c...
function uw (line 9) | function uw(t,e){e=new iP(e);let r=(o,a,n)=>{let u=o[a];o[a]=n,typeof u?...
function aP (line 9) | function aP(t,e){let r=Object.create(t);return uw(r,e),r}
function GW (line 9) | function GW(t){let e=Math.ceil(Math.random()*4294967296).toString(16).pa...
function WW (line 9) | function WW(){if(xT)return xT;let t=Ae.toPortablePath(YW.default.tmpdir(...
method detachTemp (line 9) | detachTemp(t){qc.delete(t)}
method mktempSync (line 9) | mktempSync(t){let{tmpdir:e,realTmpdir:r}=WW();for(;;){let o=GW("xfs-");t...
method mktempPromise (line 9) | async mktempPromise(t){let{tmpdir:e,realTmpdir:r}=WW();for(;;){let o=GW(...
method rmtempPromise (line 9) | async rmtempPromise(){await Promise.all(Array.from(qc.values()).map(asyn...
method rmtempSync (line 9) | rmtempSync(){for(let t of qc)try{ae.removeSync(t),qc.delete(t)}catch{}}
function v_e (line 9) | function v_e(t,e){var r=e.pathExt!==void 0?e.pathExt:process.env.PATHEXT...
function zW (line 9) | function zW(t,e,r){return!t.isSymbolicLink()&&!t.isFile()?!1:v_e(e,r)}
function JW (line 9) | function JW(t,e,r){VW.stat(t,function(o,a){r(o,o?!1:zW(a,t,e))})}
function D_e (line 9) | function D_e(t,e){return zW(VW.statSync(t),t,e)}
function eY (line 9) | function eY(t,e,r){$W.stat(t,function(o,a){r(o,o?!1:tY(a,e))})}
function P_e (line 9) | function P_e(t,e){return tY($W.statSync(t),e)}
function tY (line 9) | function tY(t,e){return t.isFile()&&S_e(t,e)}
function S_e (line 9) | function S_e(t,e){var r=t.mode,o=t.uid,a=t.gid,n=e.uid!==void 0?e.uid:pr...
function bT (line 9) | function bT(t,e,r){if(typeof e=="function"&&(r=e,e={}),!r){if(typeof Pro...
function x_e (line 9) | function x_e(t,e){try{return lP.sync(t,e||{})}catch(r){if(e&&e.ignoreErr...
function dY (line 9) | function dY(t,e){let r=t.options.env||process.env,o=process.cwd(),a=t.op...
function R_e (line 9) | function R_e(t){return dY(t)||dY(t,!0)}
function T_e (line 9) | function T_e(t){return t=t.replace(QT,"^$1"),t}
function L_e (line 9) | function L_e(t,e){return t=`${t}`,t=t.replace(/(\\*)"/g,'$1$1\\"'),t=t.r...
function M_e (line 9) | function M_e(t){let r=Buffer.alloc(150),o;try{o=RT.openSync(t,"r"),RT.re...
function G_e (line 9) | function G_e(t){t.file=PY(t);let e=t.file&&__e(t.file);return e?(t.args....
function W_e (line 9) | function W_e(t){if(!H_e)return t;let e=G_e(t),r=!q_e.test(e);if(t.option...
function Y_e (line 9) | function Y_e(t,e,r){e&&!Array.isArray(e)&&(r=e,e=null),e=e?e.slice(0):[]...
function LT (line 9) | function LT(t,e){return Object.assign(new Error(`${e} ${t.command} ENOEN...
function K_e (line 9) | function K_e(t,e){if(!TT)return;let r=t.emit;t.emit=function(o,a){if(o==...
function kY (line 9) | function kY(t,e){return TT&&t===1&&!e.file?LT(e.original,"spawn"):null}
function V_e (line 9) | function V_e(t,e){return TT&&t===1&&!e.file?LT(e.original,"spawnSync"):n...
function TY (line 9) | function TY(t,e,r){let o=NT(t,e,r),a=RY.spawn(o.command,o.args,o.options...
function z_e (line 9) | function z_e(t,e,r){let o=NT(t,e,r),a=RY.spawnSync(o.command,o.args,o.op...
function J_e (line 9) | function J_e(t,e){function r(){this.constructor=t}r.prototype=e.prototyp...
function V0 (line 9) | function V0(t,e,r,o){this.message=t,this.expected=e,this.found=r,this.lo...
function o (line 9) | function o(h){return h.charCodeAt(0).toString(16).toUpperCase()}
function a (line 9) | function a(h){return h.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace...
function n (line 9) | function n(h){return h.replace(/\\/g,"\\\\").replace(/\]/g,"\\]").replac...
function u (line 9) | function u(h){return r[h.type](h)}
function A (line 9) | function A(h){var E=new Array(h.length),w,D;for(w=0;w<h.length;w++)E[w]=...
function p (line 9) | function p(h){return h?'"'+a(h)+'"':"end of input"}
function X_e (line 9) | function X_e(t,e){e=e!==void 0?e:{};var r={},o={Start:ha},a=ha,n=functio...
function uP (line 12) | function uP(t,e={isGlobPattern:()=>!1}){try{return(0,OY.parse)(t,e)}catc...
function dm (line 12) | function dm(t,{endSemicolon:e=!1}={}){return t.map(({command:r,type:o},a...
function AP (line 12) | function AP(t){return`${mm(t.chain)}${t.then?` ${UT(t.then)}`:""}`}
function UT (line 12) | function UT(t){return`${t.type} ${AP(t.line)}`}
function mm (line 12) | function mm(t){return`${HT(t)}${t.then?` ${_T(t.then)}`:""}`}
function _T (line 12) | function _T(t){return`${t.type} ${mm(t.chain)}`}
function HT (line 12) | function HT(t){switch(t.type){case"command":return`${t.envs.length>0?`${...
function cP (line 12) | function cP(t){return`${t.name}=${t.args[0]?z0(t.args[0]):""}`}
function qT (line 12) | function qT(t){switch(t.type){case"redirection":return fw(t);case"argume...
function fw (line 12) | function fw(t){return`${t.subtype} ${t.args.map(e=>z0(e)).join(" ")}`}
function z0 (line 12) | function z0(t){return t.segments.map(e=>jT(e)).join("")}
function jT (line 12) | function jT(t){let e=(o,a)=>a?`"${o}"`:o,r=o=>o===""?"''":o.match(/[()}<...
function fP (line 12) | function fP(t){let e=a=>{switch(a){case"addition":return"+";case"subtrac...
function e8e (line 13) | function e8e(t,e){function r(){this.constructor=t}r.prototype=e.prototyp...
function J0 (line 13) | function J0(t,e,r,o){this.message=t,this.expected=e,this.found=r,this.lo...
function o (line 13) | function o(h){return h.charCodeAt(0).toString(16).toUpperCase()}
function a (line 13) | function a(h){return h.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace...
function n (line 13) | function n(h){return h.replace(/\\/g,"\\\\").replace(/\]/g,"\\]").replac...
function u (line 13) | function u(h){return r[h.type](h)}
function A (line 13) | function A(h){var E=new Array(h.length),w,D;for(w=0;w<h.length;w++)E[w]=...
function p (line 13) | function p(h){return h?'"'+a(h)+'"':"end of input"}
function t8e (line 13) | function t8e(t,e){e=e!==void 0?e:{};var r={},o={resolution:Te},a=Te,n="/...
function pP (line 13) | function pP(t){let e=t.match(/^\*{1,2}\/(.*)/);if(e)throw new Error(`The...
function hP (line 13) | function hP(t){let e="";return t.from&&(e+=t.from.fullName,t.from.descri...
function WY (line 13) | function WY(t){return typeof t>"u"||t===null}
function r8e (line 13) | function r8e(t){return typeof t=="object"&&t!==null}
function n8e (line 13) | function n8e(t){return Array.isArray(t)?t:WY(t)?[]:[t]}
function i8e (line 13) | function i8e(t,e){var r,o,a,n;if(e)for(n=Object.keys(e),r=0,o=n.length;r...
function s8e (line 13) | function s8e(t,e){var r="",o;for(o=0;o<e;o+=1)r+=t;return r}
function o8e (line 13) | function o8e(t){return t===0&&Number.NEGATIVE_INFINITY===1/t}
function pw (line 13) | function pw(t,e){Error.call(this),this.name="YAMLException",this.reason=...
function GT (line 13) | function GT(t,e,r,o,a){this.name=t,this.buffer=e,this.position=r,this.li...
function c8e (line 17) | function c8e(t){var e={};return t!==null&&Object.keys(t).forEach(functio...
function u8e (line 17) | function u8e(t,e){if(e=e||{},Object.keys(e).forEach(function(r){if(a8e.i...
function WT (line 17) | function WT(t,e,r){var o=[];return t.include.forEach(function(a){r=WT(a,...
function f8e (line 17) | function f8e(){var t={scalar:{},sequence:{},mapping:{},fallback:{}},e,r;...
function Em (line 17) | function Em(t){this.include=t.include||[],this.implicit=t.implicit||[],t...
function y8e (line 17) | function y8e(t){if(t===null)return!0;var e=t.length;return e===1&&t==="~...
function E8e (line 17) | function E8e(){return null}
function C8e (line 17) | function C8e(t){return t===null}
function w8e (line 17) | function w8e(t){if(t===null)return!1;var e=t.length;return e===4&&(t==="...
function B8e (line 17) | function B8e(t){return t==="true"||t==="True"||t==="TRUE"}
function v8e (line 17) | function v8e(t){return Object.prototype.toString.call(t)==="[object Bool...
function S8e (line 17) | function S8e(t){return 48<=t&&t<=57||65<=t&&t<=70||97<=t&&t<=102}
function x8e (line 17) | function x8e(t){return 48<=t&&t<=55}
function b8e (line 17) | function b8e(t){return 48<=t&&t<=57}
function k8e (line 17) | function k8e(t){if(t===null)return!1;var e=t.length,r=0,o=!1,a;if(!e)ret...
function Q8e (line 17) | function Q8e(t){var e=t,r=1,o,a,n=[];return e.indexOf("_")!==-1&&(e=e.re...
function F8e (line 17) | function F8e(t){return Object.prototype.toString.call(t)==="[object Numb...
function L8e (line 17) | function L8e(t){return!(t===null||!T8e.test(t)||t[t.length-1]==="_")}
function N8e (line 17) | function N8e(t){var e,r,o,a;return e=t.replace(/_/g,"").toLowerCase(),r=...
function M8e (line 17) | function M8e(t,e){var r;if(isNaN(t))switch(e){case"lowercase":return".na...
function U8e (line 17) | function U8e(t){return Object.prototype.toString.call(t)==="[object Numb...
function j8e (line 17) | function j8e(t){return t===null?!1:yK.exec(t)!==null||EK.exec(t)!==null}
function G8e (line 17) | function G8e(t){var e,r,o,a,n,u,A,p=0,h=null,E,w,D;if(e=yK.exec(t),e===n...
function W8e (line 17) | function W8e(t){return t.toISOString()}
function K8e (line 17) | function K8e(t){return t==="<<"||t===null}
function z8e (line 18) | function z8e(t){if(t===null)return!1;var e,r,o=0,a=t.length,n=VT;for(r=0...
function J8e (line 18) | function J8e(t){var e,r,o=t.replace(/[\r\n=]/g,""),a=o.length,n=VT,u=0,A...
function X8e (line 18) | function X8e(t){var e="",r=0,o,a,n=t.length,u=VT;for(o=0;o<n;o++)o%3===0...
function Z8e (line 18) | function Z8e(t){return eg&&eg.isBuffer(t)}
function rHe (line 18) | function rHe(t){if(t===null)return!0;var e=[],r,o,a,n,u,A=t;for(r=0,o=A....
function nHe (line 18) | function nHe(t){return t!==null?t:[]}
function oHe (line 18) | function oHe(t){if(t===null)return!0;var e,r,o,a,n,u=t;for(n=new Array(u...
function aHe (line 18) | function aHe(t){if(t===null)return[];var e,r,o,a,n,u=t;for(n=new Array(u...
function uHe (line 18) | function uHe(t){if(t===null)return!0;var e,r=t;for(e in r)if(cHe.call(r,...
function AHe (line 18) | function AHe(t){return t!==null?t:{}}
function hHe (line 18) | function hHe(){return!0}
function gHe (line 18) | function gHe(){}
function dHe (line 18) | function dHe(){return""}
function mHe (line 18) | function mHe(t){return typeof t>"u"}
function EHe (line 18) | function EHe(t){if(t===null||t.length===0)return!1;var e=t,r=/\/([gim]*)...
function CHe (line 18) | function CHe(t){var e=t,r=/\/([gim]*)$/.exec(t),o="";return e[0]==="/"&&...
function IHe (line 18) | function IHe(t){var e="/"+t.source+"/";return t.global&&(e+="g"),t.multi...
function wHe (line 18) | function wHe(t){return Object.prototype.toString.call(t)==="[object RegE...
function vHe (line 18) | function vHe(t){if(t===null)return!1;try{var e="("+t+")",r=mP.parse(e,{r...
function DHe (line 18) | function DHe(t){var e="("+t+")",r=mP.parse(e,{range:!0}),o=[],a;if(r.typ...
function PHe (line 18) | function PHe(t){return t.toString()}
function SHe (line 18) | function SHe(t){return Object.prototype.toString.call(t)==="[object Func...
function GK (line 18) | function GK(t){return Object.prototype.toString.call(t)}
function Wu (line 18) | function Wu(t){return t===10||t===13}
function rg (line 18) | function rg(t){return t===9||t===32}
function Da (line 18) | function Da(t){return t===9||t===32||t===10||t===13}
function Im (line 18) | function Im(t){return t===44||t===91||t===93||t===123||t===125}
function THe (line 18) | function THe(t){var e;return 48<=t&&t<=57?t-48:(e=t|32,97<=e&&e<=102?e-9...
function LHe (line 18) | function LHe(t){return t===120?2:t===117?4:t===85?8:0}
function NHe (line 18) | function NHe(t){return 48<=t&&t<=57?t-48:-1}
function WK (line 18) | function WK(t){return t===48?"\0":t===97?"\x07":t===98?"\b":t===116||t==...
function OHe (line 19) | function OHe(t){return t<=65535?String.fromCharCode(t):String.fromCharCo...
function MHe (line 19) | function MHe(t,e){this.input=t,this.filename=e.filename||null,this.schem...
function nV (line 19) | function nV(t,e){return new zK(e,new xHe(t.filename,t.input,t.position,t...
function Qr (line 19) | function Qr(t,e){throw nV(t,e)}
function CP (line 19) | function CP(t,e){t.onWarning&&t.onWarning.call(null,nV(t,e))}
function Kp (line 19) | function Kp(t,e,r,o){var a,n,u,A;if(e<r){if(A=t.input.slice(e,r),o)for(a...
function KK (line 19) | function KK(t,e,r,o){var a,n,u,A;for(mf.isObject(r)||Qr(t,"cannot merge ...
function wm (line 19) | function wm(t,e,r,o,a,n,u,A){var p,h;if(Array.isArray(a))for(a=Array.pro...
function JT (line 19) | function JT(t){var e;e=t.input.charCodeAt(t.position),e===10?t.position+...
function Yi (line 19) | function Yi(t,e,r){for(var o=0,a=t.input.charCodeAt(t.position);a!==0;){...
function IP (line 19) | function IP(t){var e=t.position,r;return r=t.input.charCodeAt(e),!!((r==...
function XT (line 19) | function XT(t,e){e===1?t.result+=" ":e>1&&(t.result+=mf.repeat(`
function UHe (line 20) | function UHe(t,e,r){var o,a,n,u,A,p,h,E,w=t.kind,D=t.result,b;if(b=t.inp...
function _He (line 20) | function _He(t,e){var r,o,a;if(r=t.input.charCodeAt(t.position),r!==39)r...
function HHe (line 20) | function HHe(t,e){var r,o,a,n,u,A;if(A=t.input.charCodeAt(t.position),A!...
function qHe (line 20) | function qHe(t,e){var r=!0,o,a=t.tag,n,u=t.anchor,A,p,h,E,w,D={},b,C,T,N...
function jHe (line 20) | function jHe(t,e){var r,o,a=zT,n=!1,u=!1,A=e,p=0,h=!1,E,w;if(w=t.input.c...
function VK (line 26) | function VK(t,e){var r,o=t.tag,a=t.anchor,n=[],u,A=!1,p;for(t.anchor!==n...
function GHe (line 26) | function GHe(t,e,r){var o,a,n,u,A=t.tag,p=t.anchor,h={},E={},w=null,D=nu...
function WHe (line 26) | function WHe(t){var e,r=!1,o=!1,a,n,u;if(u=t.input.charCodeAt(t.position...
function YHe (line 26) | function YHe(t){var e,r;if(r=t.input.charCodeAt(t.position),r!==38)retur...
function KHe (line 26) | function KHe(t){var e,r,o;if(o=t.input.charCodeAt(t.position),o!==42)ret...
function Bm (line 26) | function Bm(t,e,r,o,a){var n,u,A,p=1,h=!1,E=!1,w,D,b,C,T;if(t.listener!=...
function VHe (line 26) | function VHe(t){var e=t.position,r,o,a,n=!1,u;for(t.version=null,t.check...
function iV (line 26) | function iV(t,e){t=String(t),e=e||{},t.length!==0&&(t.charCodeAt(t.lengt...
function sV (line 27) | function sV(t,e,r){e!==null&&typeof e=="object"&&typeof r>"u"&&(r=e,e=nu...
function oV (line 27) | function oV(t,e){var r=iV(t,e);if(r.length!==0){if(r.length===1)return r...
function zHe (line 27) | function zHe(t,e,r){return typeof e=="object"&&e!==null&&typeof r>"u"&&(...
function JHe (line 27) | function JHe(t,e){return oV(t,mf.extend({schema:JK},e))}
function d6e (line 27) | function d6e(t,e){var r,o,a,n,u,A,p;if(e===null)return{};for(r={},o=Obje...
function lV (line 27) | function lV(t){var e,r,o;if(e=t.toString(16).toUpperCase(),t<=255)r="x",...
function m6e (line 27) | function m6e(t){this.schema=t.schema||XHe,this.indent=Math.max(1,t.inden...
function cV (line 27) | function cV(t,e){for(var r=mw.repeat(" ",e),o=0,a=-1,n="",u,A=t.length;o...
function ZT (line 29) | function ZT(t,e){return`
function y6e (line 30) | function y6e(t,e){var r,o,a;for(r=0,o=t.implicitTypes.length;r<o;r+=1)if...
function eL (line 30) | function eL(t){return t===t6e||t===$He}
function vm (line 30) | function vm(t){return 32<=t&&t<=126||161<=t&&t<=55295&&t!==8232&&t!==823...
function E6e (line 30) | function E6e(t){return vm(t)&&!eL(t)&&t!==65279&&t!==e6e&&t!==dw}
function uV (line 30) | function uV(t,e){return vm(t)&&t!==65279&&t!==yV&&t!==CV&&t!==IV&&t!==wV...
function C6e (line 30) | function C6e(t){return vm(t)&&t!==65279&&!eL(t)&&t!==l6e&&t!==A6e&&t!==E...
function vV (line 30) | function vV(t){var e=/^\n* /;return e.test(t)}
function I6e (line 30) | function I6e(t,e,r,o,a){var n,u,A,p=!1,h=!1,E=o!==-1,w=-1,D=C6e(t.charCo...
function w6e (line 30) | function w6e(t,e,r,o){t.dump=function(){if(e.length===0)return"''";if(!t...
function AV (line 30) | function AV(t,e){var r=vV(t)?String(e):"",o=t[t.length-1]===`
function fV (line 34) | function fV(t){return t[t.length-1]===`
function B6e (line 35) | function B6e(t,e){for(var r=/(\n+)([^\n]*)/g,o=function(){var h=t.indexOf(`
function pV (line 38) | function pV(t,e){if(t===""||t[0]===" ")return t;for(var r=/ [^ ]/g,o,a=0...
function v6e (line 41) | function v6e(t){for(var e="",r,o,a,n=0;n<t.length;n++){if(r=t.charCodeAt...
function D6e (line 41) | function D6e(t,e,r){var o="",a=t.tag,n,u;for(n=0,u=r.length;n<u;n+=1)ng(...
function P6e (line 41) | function P6e(t,e,r,o){var a="",n=t.tag,u,A;for(u=0,A=r.length;u<A;u+=1)n...
function S6e (line 41) | function S6e(t,e,r){var o="",a=t.tag,n=Object.keys(r),u,A,p,h,E;for(u=0,...
function x6e (line 41) | function x6e(t,e,r,o){var a="",n=t.tag,u=Object.keys(r),A,p,h,E,w,D;if(t...
function hV (line 41) | function hV(t,e,r){var o,a,n,u,A,p;for(a=r?t.explicitTypes:t.implicitTyp...
function ng (line 41) | function ng(t,e,r,o,a,n){t.tag=null,t.dump=r,hV(t,r,!1)||hV(t,r,!0);var ...
function b6e (line 41) | function b6e(t,e){var r=[],o=[],a,n;for($T(t,r,o),a=0,n=o.length;a<n;a+=...
function $T (line 41) | function $T(t,e,r){var o,a,n;if(t!==null&&typeof t=="object")if(a=e.inde...
function bV (line 41) | function bV(t,e){e=e||{};var r=new m6e(e);return r.noRefs||b6e(t,r),ng(r...
function k6e (line 42) | function k6e(t,e){return bV(t,mw.extend({schema:ZHe},e))}
function vP (line 42) | function vP(t){return function(){throw new Error("Function "+t+" is depr...
function F6e (line 42) | function F6e(t,e){function r(){this.constructor=t}r.prototype=e.prototyp...
function ig (line 42) | function ig(t,e,r,o){this.message=t,this.expected=e,this.found=r,this.lo...
function o (line 42) | function o(h){return h.charCodeAt(0).toString(16).toUpperCase()}
function a (line 42) | function a(h){return h.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace...
function n (line 42) | function n(h){return h.replace(/\\/g,"\\\\").replace(/\]/g,"\\]").replac...
function u (line 42) | function u(h){return r[h.type](h)}
function A (line 42) | function A(h){var E=new Array(h.length),w,D;for(w=0;w<h.length;w++)E[w]=...
function p (line 42) | function p(h){return h?'"'+a(h)+'"':"end of input"}
function R6e (line 42) | function R6e(t,e){e=e!==void 0?e:{};var r={},o={Start:Bl},a=Bl,n=functio...
function MV (line 51) | function MV(t){return t.match(T6e)?t:JSON.stringify(t)}
function _V (line 51) | function _V(t){return typeof t>"u"?!0:typeof t=="object"&&t!==null&&!Arr...
function rL (line 51) | function rL(t,e,r){if(t===null)return`null
function Pa (line 61) | function Pa(t){try{let e=rL(t,0,!1);return e!==`
function L6e (line 62) | function L6e(t){return t.endsWith(`
function O6e (line 64) | function O6e(t){if(N6e.test(t))return L6e(t);let e=(0,PP.safeLoad)(t,{sc...
function Ki (line 64) | function Ki(t){return O6e(t)}
method constructor (line 64) | constructor(e){this.data=e}
function WV (line 64) | function WV(t){return typeof t=="string"?!!ls[t]:"env"in t?ls[t.env]&&ls...
method constructor (line 64) | constructor(e){super(e),this.clipanion={type:"usage"},this.name="UsageEr...
method constructor (line 64) | constructor(e,r){if(super(),this.input=e,this.candidates=r,this.clipanio...
method constructor (line 75) | constructor(e,r){super(),this.input=e,this.usages=r,this.clipanion={type...
function _6e (line 80) | function _6e(t){let e=t.split(`
function yo (line 82) | function yo(t,{format:e,paragraphs:r}){return t=t.replace(/\r\n?/g,`
function Wo (line 90) | function Wo(t){return{...t,[Cw]:!0}}
function Yu (line 90) | function Yu(t,e){return typeof t>"u"?[t,e]:typeof t=="object"&&t!==null&...
function QP (line 90) | function QP(t,{mergeName:e=!1}={}){let r=t.match(/^([^:]+): (.*)$/m);if(...
function Iw (line 90) | function Iw(t,e){return e.length===1?new ot(`${t}${QP(e[0],{mergeName:!0...
function ag (line 92) | function ag(t,e,r){if(typeof r>"u")return e;let o=[],a=[],n=A=>{let p=e;...
function Vn (line 92) | function Vn(t){return t===null?"null":t===void 0?"undefined":t===""?"an ...
function Pm (line 92) | function Pm(t,e){if(t.length===0)return"nothing";if(t.length===1)return ...
function zp (line 92) | function zp(t,e){var r,o,a;return typeof e=="number"?`${(r=t?.p)!==null&...
function uL (line 92) | function uL(t,e,r){return t===1?e:r}
function gr (line 92) | function gr({errors:t,p:e}={},r){return t?.push(`${e??"."}: ${r}`),!1}
function Y6e (line 92) | function Y6e(t,e){return r=>{t[e]=r}}
function Vu (line 92) | function Vu(t,e){return r=>{let o=t[e];return t[e]=r,Vu(t,e).bind(null,o)}}
function ww (line 92) | function ww(t,e,r){let o=()=>(t(r()),a),a=()=>(t(e),o);return o}
function AL (line 92) | function AL(){return qr({test:(t,e)=>!0})}
function XV (line 92) | function XV(t){return qr({test:(e,r)=>e!==t?gr(r,`Expected ${Vn(t)} (got...
function Sm (line 92) | function Sm(){return qr({test:(t,e)=>typeof t!="string"?gr(e,`Expected a...
function js (line 92) | function js(t){let e=Array.isArray(t)?t:Object.values(t),r=e.every(a=>ty...
function V6e (line 92) | function V6e(){return qr({test:(t,e)=>{var r;if(typeof t!="boolean"){if(...
function fL (line 92) | function fL(){return qr({test:(t,e)=>{var r;if(typeof t!="number"){if(ty...
function z6e (line 92) | function z6e(t){return qr({test:(e,r)=>{var o;if(typeof r?.coercions>"u"...
function J6e (line 92) | function J6e(){return qr({test:(t,e)=>{var r;if(!(t instanceof Date)){if...
function FP (line 92) | function FP(t,{delimiter:e}={}){return qr({test:(r,o)=>{var a;let n=r;if...
function X6e (line 92) | function X6e(t,{delimiter:e}={}){let r=FP(t,{delimiter:e});return qr({te...
function Z6e (line 92) | function Z6e(t,e){let r=FP(RP([t,e])),o=TP(e,{keys:t});return qr({test:(...
function RP (line 92) | function RP(t,{delimiter:e}={}){let r=ez(t.length);return qr({test:(o,a)...
function TP (line 92) | function TP(t,{keys:e=null}={}){let r=FP(RP([e??Sm(),t]));return qr({tes...
function $6e (line 92) | function $6e(t,e={}){return TP(t,e)}
function ZV (line 92) | function ZV(t,{extra:e=null}={}){let r=Object.keys(t),o=qr({test:(a,n)=>...
function eqe (line 92) | function eqe(t){return ZV(t,{extra:TP(AL())})}
function $V (line 92) | function $V(t){return()=>t}
function qr (line 92) | function qr({test:t}){return $V(t)()}
function rqe (line 92) | function rqe(t,e){if(!e(t))throw new Jp}
function nqe (line 92) | function nqe(t,e){let r=[];if(!e(t,{errors:r}))throw new Jp({errors:r})}
function iqe (line 92) | function iqe(t,e){}
function sqe (line 92) | function sqe(t,e,{coerce:r=!1,errors:o,throw:a}={}){let n=o?[]:void 0;if...
function oqe (line 92) | function oqe(t,e){let r=RP(t);return(...o)=>{if(!r(o))throw new Jp;retur...
function aqe (line 92) | function aqe(t){return qr({test:(e,r)=>e.length>=t?!0:gr(r,`Expected to ...
function lqe (line 92) | function lqe(t){return qr({test:(e,r)=>e.length<=t?!0:gr(r,`Expected to ...
function ez (line 92) | function ez(t){return qr({test:(e,r)=>e.length!==t?gr(r,`Expected to hav...
function cqe (line 92) | function cqe({map:t}={}){return qr({test:(e,r)=>{let o=new Set,a=new Set...
function uqe (line 92) | function uqe(){return qr({test:(t,e)=>t<=0?!0:gr(e,`Expected to be negat...
function Aqe (line 92) | function Aqe(){return qr({test:(t,e)=>t>=0?!0:gr(e,`Expected to be posit...
function hL (line 92) | function hL(t){return qr({test:(e,r)=>e>=t?!0:gr(r,`Expected to be at le...
function fqe (line 92) | function fqe(t){return qr({test:(e,r)=>e<=t?!0:gr(r,`Expected to be at m...
function pqe (line 92) | function pqe(t,e){return qr({test:(r,o)=>r>=t&&r<=e?!0:gr(o,`Expected to...
function hqe (line 92) | function hqe(t,e){return qr({test:(r,o)=>r>=t&&r<e?!0:gr(o,`Expected to ...
function gL (line 92) | function gL({unsafe:t=!1}={}){return qr({test:(e,r)=>e!==Math.round(e)?g...
function Bw (line 92) | function Bw(t){return qr({test:(e,r)=>t.test(e)?!0:gr(r,`Expected to mat...
function gqe (line 92) | function gqe(){return qr({test:(t,e)=>t!==t.toLowerCase()?gr(e,`Expected...
function dqe (line 92) | function dqe(){return qr({test:(t,e)=>t!==t.toUpperCase()?gr(e,`Expected...
function mqe (line 92) | function mqe(){return qr({test:(t,e)=>W6e.test(t)?!0:gr(e,`Expected to b...
function yqe (line 92) | function yqe(){return qr({test:(t,e)=>JV.test(t)?!0:gr(e,`Expected to be...
function Eqe (line 92) | function Eqe({alpha:t=!1}){return qr({test:(e,r)=>(t?q6e.test(e):j6e.tes...
function Cqe (line 92) | function Cqe(){return qr({test:(t,e)=>G6e.test(t)?!0:gr(e,`Expected to b...
function Iqe (line 92) | function Iqe(t=AL()){return qr({test:(e,r)=>{let o;try{o=JSON.parse(e)}c...
function LP (line 92) | function LP(t,...e){let r=Array.isArray(e[0])?e[0]:e;return qr({test:(o,...
function vw (line 92) | function vw(t,...e){let r=Array.isArray(e[0])?e[0]:e;return LP(t,r)}
function wqe (line 92) | function wqe(t){return qr({test:(e,r)=>typeof e>"u"?!0:t(e,r)})}
function Bqe (line 92) | function Bqe(t){return qr({test:(e,r)=>e===null?!0:t(e,r)})}
function vqe (line 92) | function vqe(t,e){var r;let o=new Set(t),a=Dw[(r=e?.missingIf)!==null&&r...
function dL (line 92) | function dL(t,e){var r;let o=new Set(t),a=Dw[(r=e?.missingIf)!==null&&r!...
function Dqe (line 92) | function Dqe(t,e){var r;let o=new Set(t),a=Dw[(r=e?.missingIf)!==null&&r...
function Pqe (line 92) | function Pqe(t,e){var r;let o=new Set(t),a=Dw[(r=e?.missingIf)!==null&&r...
function Pw (line 92) | function Pw(t,e,r,o){var a,n;let u=new Set((a=o?.ignore)!==null&&a!==voi...
method constructor (line 92) | constructor({errors:e}={}){let r="Type mismatch";if(e&&e.length>0){r+=`
method constructor (line 94) | constructor(){this.help=!1}
method Usage (line 94) | static Usage(e){return e}
method catch (line 94) | async catch(e){throw e}
method validateAndExecute (line 94) | async validateAndExecute(){let r=this.constructor.schema;if(Array.isArra...
function Sa (line 94) | function Sa(t){oL&&console.log(t)}
function rz (line 94) | function rz(){let t={nodes:[]};for(let e=0;e<pn.CustomNode;++e)t.nodes.p...
function xqe (line 94) | function xqe(t){let e=rz(),r=[],o=e.nodes.length;for(let a of t){r.push(...
function jc (line 94) | function jc(t,e){return t.nodes.push(e),t.nodes.length-1}
function bqe (line 94) | function bqe(t){let e=new Set,r=o=>{if(e.has(o))return;e.add(o);let a=t....
function kqe (line 94) | function kqe(t,{prefix:e=""}={}){if(oL){Sa(`${e}Nodes are:`);for(let r=0...
function Qqe (line 94) | function Qqe(t,e,r=!1){Sa(`Running a vm on ${JSON.stringify(e)}`);let o=...
function Fqe (line 94) | function Fqe(t,e,{endToken:r=Kn.EndOfInput}={}){let o=Qqe(t,[...e,r]);re...
function Rqe (line 94) | function Rqe(t){let e=0;for(let{state:r}of t)r.path.length>e&&(e=r.path....
function Tqe (line 94) | function Tqe(t,e){let r=e.filter(D=>D.selectedIndex!==null),o=r.filter(D...
function Lqe (line 94) | function Lqe(t){let e=[],r=[];for(let o of t)o.selectedIndex===og?r.push...
function nz (line 94) | function nz(t,e,...r){return e===void 0?Array.from(t):nz(t.filter((o,a)=...
function sl (line 94) | function sl(){return{dynamics:[],shortcuts:[],statics:{}}}
function iz (line 94) | function iz(t){return t===pn.SuccessNode||t===pn.ErrorNode}
function mL (line 94) | function mL(t,e=0){return{to:iz(t.to)?t.to:t.to>=pn.CustomNode?t.to+e-pn...
function Nqe (line 94) | function Nqe(t,e=0){let r=sl();for(let[o,a]of t.dynamics)r.dynamics.push...
function Bs (line 94) | function Bs(t,e,r,o,a){t.nodes[e].dynamics.push([r,{to:o,reducer:a}])}
function xm (line 94) | function xm(t,e,r,o){t.nodes[e].shortcuts.push({to:r,reducer:o})}
function Ko (line 94) | function Ko(t,e,r,o,a){(Object.prototype.hasOwnProperty.call(t.nodes[e]....
function NP (line 94) | function NP(t,e,r,o,a){if(Array.isArray(e)){let[n,...u]=e;return t[n](r,...
method constructor (line 94) | constructor(e,r){this.allOptionNames=new Map,this.arity={leading:[],trai...
method addPath (line 94) | addPath(e){this.paths.push(e)}
method setArity (line 94) | setArity({leading:e=this.arity.leading,trailing:r=this.arity.trailing,ex...
method addPositional (line 94) | addPositional({name:e="arg",required:r=!0}={}){if(!r&&this.arity.extra==...
method addRest (line 94) | addRest({name:e="arg",required:r=0}={}){if(this.arity.extra===ol)throw n...
method addProxy (line 94) | addProxy({required:e=0}={}){this.addRest({required:e}),this.arity.proxy=!0}
method addOption (line 94) | addOption({names:e,description:r,arity:o=0,hidden:a=!1,required:n=!1,all...
method setContext (line 94) | setContext(e){this.context=e}
method usage (line 94) | usage({detailed:e=!0,inlineOptions:r=!0}={}){let o=[this.cliOpts.binaryN...
method compile (line 94) | compile(){if(typeof this.context>"u")throw new Error("Assertion failed: ...
method registerOptions (line 94) | registerOptions(e,r){Bs(e,r,["isOption","--"],r,"inhibateOptions"),Bs(e,...
method constructor (line 94) | constructor({binaryName:e="..."}={}){this.builders=[],this.opts={binaryN...
method build (line 94) | static build(e,r={}){return new t(r).commands(e).compile()}
method getBuilderByIndex (line 94) | getBuilderByIndex(e){if(!(e>=0&&e<this.builders.length))throw new Error(...
method commands (line 94) | commands(e){for(let r of e)r(this.command());return this}
method command (line 94) | command(){let e=new EL(this.builders.length,this.opts);return this.build...
method compile (line 94) | compile(){let e=[],r=[];for(let a of this.builders){let{machine:n,contex...
function oz (line 94) | function oz(){return UP.default&&"getColorDepth"in UP.default.WriteStrea...
function az (line 94) | function az(t){let e=sz;if(typeof e>"u"){if(t.stdout===process.stdout&&t...
method constructor (line 94) | constructor(e){super(),this.contexts=e,this.commands=[]}
method from (line 94) | static from(e,r){let o=new t(r);o.path=e.path;for(let a of e.options)swi...
method execute (line 94) | async execute(){let e=this.commands;if(typeof this.index<"u"&&this.index...
function fz (line 98) | async function fz(...t){let{resolvedOptions:e,resolvedCommandClasses:r,r...
function pz (line 98) | async function pz(...t){let{resolvedOptions:e,resolvedCommandClasses:r,r...
function hz (line 98) | function hz(t){let e,r,o,a;switch(typeof process<"u"&&typeof process.arg...
function Az (line 98) | function Az(t){return t()}
method constructor (line 98) | constructor({binaryLabel:e,binaryName:r="...",binaryVersion:o,enableCapt...
method from (line 98) | static from(e,r={}){let o=new t(r),a=Array.isArray(e)?e:[e];for(let n of...
method register (line 98) | register(e){var r;let o=new Map,a=new e;for(let p in a){let h=a[p];typeo...
method process (line 98) | process(e,r){let{input:o,context:a,partial:n}=typeof e=="object"&&Array....
method run (line 98) | async run(e,r){var o,a;let n,u={...t.defaultContext,...r},A=(o=this.enab...
method runExit (line 98) | async runExit(e,r){process.exitCode=await this.run(e,r)}
method definition (line 98) | definition(e,{colored:r=!1}={}){if(!e.usage)return null;let{usage:o}=thi...
method definitions (line 98) | definitions({colored:e=!1}={}){let r=[];for(let o of this.registrations....
method usage (line 98) | usage(e=null,{colored:r,detailed:o=!1,prefix:a="$ "}={}){var n;if(e===nu...
method error (line 124) | error(e,r){var o,{colored:a,command:n=(o=e[uz])!==null&&o!==void 0?o:nul...
method format (line 127) | format(e){var r;return((r=e??this.enableColors)!==null&&r!==void 0?r:t.d...
method getUsageByRegistration (line 127) | getUsageByRegistration(e,r){let o=this.registrations.get(e);if(typeof o>...
method getUsageByIndex (line 127) | getUsageByIndex(e,r){return this.builder.getBuilderByIndex(e).usage(r)}
method execute (line 127) | async execute(){this.context.stdout.write(`${JSON.stringify(this.cli.def...
method execute (line 128) | async execute(){this.context.stdout.write(this.cli.usage())}
function HP (line 128) | function HP(t={}){return Wo({definition(e,r){var o;e.addProxy({name:(o=t...
method constructor (line 128) | constructor(){super(...arguments),this.args=HP()}
method execute (line 128) | async execute(){this.context.stdout.write(`${JSON.stringify(this.cli.pro...
method execute (line 129) | async execute(){var e;this.context.stdout.write(`${(e=this.cli.binaryVer...
function Iz (line 130) | function Iz(t,e,r){let[o,a]=Yu(e,r??{}),{arity:n=1}=a,u=t.split(","),A=n...
function Bz (line 130) | function Bz(t,e,r){let[o,a]=Yu(e,r??{}),n=t.split(","),u=new Set(n);retu...
function Dz (line 130) | function Dz(t,e,r){let[o,a]=Yu(e,r??{}),n=t.split(","),u=new Set(n);retu...
function Sz (line 130) | function Sz(t={}){return Wo({definition(e,r){var o;e.addRest({name:(o=t....
function Mqe (line 130) | function Mqe(t,e,r){let[o,a]=Yu(e,r??{}),{arity:n=1}=a,u=t.split(","),A=...
function Uqe (line 130) | function Uqe(t={}){let{required:e=!0}=t;return Wo({definition(r,o){var a...
function bz (line 130) | function bz(t,...e){return typeof t=="string"?Mqe(t,...e):Uqe(t)}
function Wqe (line 130) | function Wqe(t){let e={},r=t.toString();r=r.replace(/\r\n?/mg,`
function Yqe (line 132) | function Yqe(t){let e=Lz(t),r=vs.configDotenv({path:e});if(!r.parsed)thr...
function Kqe (line 132) | function Kqe(t){console.log(`[dotenv@${vL}][INFO] ${t}`)}
function Vqe (line 132) | function Vqe(t){console.log(`[dotenv@${vL}][WARN] ${t}`)}
function wL (line 132) | function wL(t){console.log(`[dotenv@${vL}][DEBUG] ${t}`)}
function Tz (line 132) | function Tz(t){return t&&t.DOTENV_KEY&&t.DOTENV_KEY.length>0?t.DOTENV_KE...
function zqe (line 132) | function zqe(t,e){let r;try{r=new URL(e)}catch(A){throw A.code==="ERR_IN...
function Lz (line 132) | function Lz(t){let e=BL.resolve(process.cwd(),".env");return t&&t.path&&...
function Jqe (line 132) | function Jqe(t){return t[0]==="~"?BL.join(Hqe.homedir(),t.slice(1)):t}
function Xqe (line 132) | function Xqe(t){Kqe("Loading env from encrypted .env.vault");let e=vs._p...
function Zqe (line 132) | function Zqe(t){let e=BL.resolve(process.cwd(),".env"),r="utf8",o=!!(t&&...
function $qe (line 132) | function $qe(t){let e=Lz(t);return Tz(t).length===0?vs.configDotenv(t):R...
function eje (line 132) | function eje(t,e){let r=Buffer.from(e.slice(-64),"hex"),o=Buffer.from(t,...
function tje (line 132) | function tje(t,e,r={}){let o=!!(r&&r.debug),a=!!(r&&r.override);if(typeo...
function zu (line 132) | function zu(t){return`YN${t.toString(10).padStart(4,"0")}`}
function qP (line 132) | function qP(t){let e=Number(t.slice(2));if(typeof vr[e]>"u")throw new Er...
method constructor (line 132) | constructor(e,r){if(r=Ije(r),e instanceof t){if(e.loose===!!r.loose&&e.i...
method format (line 132) | format(){return this.version=`${this.major}.${this.minor}.${this.patch}`...
method toString (line 132) | toString(){return this.version}
method compare (line 132) | compare(e){if(WP("SemVer.compare",this.version,this.options,e),!(e insta...
method compareMain (line 132) | compareMain(e){return e instanceof t||(e=new t(e,this.options)),km(this....
method comparePre (line 132) | comparePre(e){if(e instanceof t||(e=new t(e,this.options)),this.prerelea...
method compareBuild (line 132) | compareBuild(e){e instanceof t||(e=new t(e,this.options));let r=0;do{let...
method inc (line 132) | inc(e,r,o){switch(e){case"premajor":this.prerelease.length=0,this.patch=...
function xn (line 132) | function xn(t){var e=this;if(e instanceof xn||(e=new xn),e.tail=null,e.h...
function g9e (line 132) | function g9e(t,e,r){var o=e===t.head?new ug(r,null,e,t):new ug(r,e,e.nex...
function d9e (line 132) | function d9e(t,e){t.tail=new ug(e,t.tail,null,t),t.head||(t.head=t.tail)...
function m9e (line 132) | function m9e(t,e){t.head=new ug(e,null,t.head,t),t.tail||(t.tail=t.head)...
function ug (line 132) | function ug(t,e,r,o){if(!(this instanceof ug))return new ug(t,e,r,o);thi...
method constructor (line 132) | constructor(e){if(typeof e=="number"&&(e={max:e}),e||(e={}),e.max&&(type...
method max (line 132) | set max(e){if(typeof e!="number"||e<0)throw new TypeError("max must be a...
method max (line 132) | get max(){return this[Ag]}
method allowStale (line 132) | set allowStale(e){this[Nw]=!!e}
method allowStale (line 132) | get allowStale(){return this[Nw]}
method maxAge (line 132) | set maxAge(e){if(typeof e!="number")throw new TypeError("maxAge must be ...
method maxAge (line 132) | get maxAge(){return this[fg]}
method lengthCalculator (line 132) | set lengthCalculator(e){typeof e!="function"&&(e=RL),e!==this[Qm]&&(this...
method lengthCalculator (line 132) | get lengthCalculator(){return this[Qm]}
method length (line 132) | get length(){return this[wf]}
method itemCount (line 132) | get itemCount(){return this[Ds].length}
method rforEach (line 132) | rforEach(e,r){r=r||this;for(let o=this[Ds].tail;o!==null;){let a=o.prev;...
method forEach (line 132) | forEach(e,r){r=r||this;for(let o=this[Ds].head;o!==null;){let a=o.next;q...
method keys (line 132) | keys(){return this[Ds].toArray().map(e=>e.key)}
method values (line 132) | values(){return this[Ds].toArray().map(e=>e.value)}
method reset (line 132) | reset(){this[If]&&this[Ds]&&this[Ds].length&&this[Ds].forEach(e=>this[If...
method dump (line 132) | dump(){return this[Ds].map(e=>eS(this,e)?!1:{k:e.key,v:e.value,e:e.now+(...
method dumpLru (line 132) | dumpLru(){return this[Ds]}
method set (line 132) | set(e,r,o){if(o=o||this[fg],o&&typeof o!="number")throw new TypeError("m...
method has (line 132) | has(e){if(!this[Gc].has(e))return!1;let r=this[Gc].get(e).value;return!e...
method get (line 132) | get(e){return TL(this,e,!0)}
method peek (line 132) | peek(e){return TL(this,e,!1)}
method pop (line 132) | pop(){let e=this[Ds].tail;return e?(Fm(this,e),e.value):null}
method del (line 132) | del(e){Fm(this,this[Gc].get(e))}
method load (line 132) | load(e){this.reset();let r=Date.now();for(let o=e.length-1;o>=0;o--){let...
method prune (line 132) | prune(){this[Gc].forEach((e,r)=>TL(this,r,!1))}
method constructor (line 132) | constructor(e,r,o,a,n){this.key=e,this.value=r,this.length=o,this.now=a,...
method constructor (line 132) | constructor(e,r){if(r=C9e(r),e instanceof t)return e.loose===!!r.loose&&...
method format (line 132) | format(){return this.range=this.set.map(e=>e.join(" ").trim()).join("||"...
method toString (line 132) | toString(){return this.range}
method parseRange (line 132) | parseRange(e){let o=((this.options.includePrerelease&&D9e)|(this.options...
method intersects (line 132) | intersects(e,r){if(!(e instanceof t))throw new TypeError("a Range is req...
method test (line 132) | test(e){if(!e)return!1;if(typeof e=="string")try{e=new I9e(e,this.option...
method ANY (line 132) | static get ANY(){return Mw}
method constructor (line 132) | constructor(e,r){if(r=JJ(r),e instanceof t){if(e.loose===!!r.loose)retur...
method parse (line 132) | parse(e){let r=this.options.loose?XJ[ZJ.COMPARATORLOOSE]:XJ[ZJ.COMPARATO...
method toString (line 132) | toString(){return this.value}
method test (line 132) | test(e){if(_L("Comparator.test",e,this.options.loose),this.semver===Mw||...
method intersects (line 132) | intersects(e,r){if(!(e instanceof t))throw new TypeError("a Comparator i...
function e5e (line 132) | function e5e(t,e){function r(){this.constructor=t}r.prototype=e.prototyp...
function pg (line 132) | function pg(t,e,r,o){this.message=t,this.expected=e,this.found=r,this.lo...
function o (line 132) | function o(h){return h.charCodeAt(0).toString(16).toUpperCase()}
function a (line 132) | function a(h){return h.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace...
function n (line 132) | function n(h){return h.replace(/\\/g,"\\\\").replace(/\]/g,"\\]").replac...
function u (line 132) | function u(h){return r[h.type](h)}
function A (line 132) | function A(h){var E=new Array(h.length),w,D;for(w=0;w<h.length;w++)E[w]=...
function p (line 132) | function p(h){return h?'"'+a(h)+'"':"end of input"}
function t5e (line 132) | function t5e(t,e){e=e!==void 0?e:{};var r={},o={Expression:y},a=y,n="|",...
function n5e (line 134) | function n5e(t,e){return(t[0]-e[0])**2+(t[1]-e[1])**2+(t[2]-e[2])**2}
function i5e (line 134) | function i5e(){let t={},e=Object.keys(nS);for(let r=e.length,o=0;o<r;o++...
function s5e (line 134) | function s5e(t){let e=i5e(),r=[t];for(e[t].distance=0;r.length;){let o=r...
function o5e (line 134) | function o5e(t,e){return function(r){return e(t(r))}}
function a5e (line 134) | function a5e(t,e){let r=[e[t].parent,t],o=nS[e[t].parent][t],a=e[t].pare...
function u5e (line 134) | function u5e(t){let e=function(...r){let o=r[0];return o==null?o:(o.leng...
function A5e (line 134) | function A5e(t){let e=function(...r){let o=r[0];if(o==null)return o;o.le...
function f5e (line 134) | function f5e(){let t=new Map,e={modifier:{reset:[0,0],bold:[1,22],dim:[2...
function XL (line 134) | function XL(t){return t===0?!1:{level:t,hasBasic:!0,has256:t>=2,has16m:t...
function ZL (line 134) | function ZL(t,e){if(Zp===0)return 0;if(_l("color=16m")||_l("color=full")...
function h5e (line 134) | function h5e(t){let e=ZL(t,t&&t.isTTY);return XL(e)}
function oZ (line 138) | function oZ(t){let e=t[0]==="u",r=t[1]==="{";return e&&!r&&t.length===5|...
function I5e (line 138) | function I5e(t,e){let r=[],o=e.trim().split(/\s*,\s*/g),a;for(let n of o...
function w5e (line 138) | function w5e(t){iZ.lastIndex=0;let e=[],r;for(;(r=iZ.exec(t))!==null;){l...
function sZ (line 138) | function sZ(t,e){let r={};for(let a of e)for(let n of a.styles)r[n[0]]=a...
method constructor (line 138) | constructor(e){return uZ(e)}
function sS (line 138) | function sS(t){return uZ(t)}
method get (line 138) | get(){let r=oS(this,iN(e.open,e.close,this._styler),this._isEmpty);ret
Condensed preview — 778 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (8,735K chars).
[
{
"path": ".claude/CLAUDE.md",
"chars": 6854,
"preview": "# CLAUDE.md\n\nWrenAI is an open-source GenBI (Generative BI) agent that converts natural language questions into SQL quer"
},
{
"path": ".claude/settings.json",
"chars": 467,
"preview": "{\n \"permissions\": {\n \"allow\": [\n \"Bash(cd wren-ui && yarn:*)\",\n \"Bash(cd wren-ai-service && just:*)\",\n "
},
{
"path": ".editorconfig",
"chars": 287,
"preview": "# Editor configuration, see http://editorconfig.org\nroot = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = "
},
{
"path": ".github/ISSUE_TEMPLATE/bug_report.md",
"chars": 1152,
"preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: bug\nassignees: ''\n\n---\n\n**Describe the "
},
{
"path": ".github/ISSUE_TEMPLATE/feature_request.md",
"chars": 608,
"preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: feature-request\nassignees: ''\n\n---\n\n"
},
{
"path": ".github/dependabot.yaml",
"chars": 332,
"preview": "version: 2\nupdates:\n - package-ecosystem: \"pip\"\n directory: \"/wren-ai-service\"\n schedule:\n interval: \"weekly"
},
{
"path": ".github/workflows/ai-service-release-image.yaml",
"chars": 3442,
"preview": "name: AI Service Release image\n\non:\n workflow_dispatch:\n inputs:\n tag_name:\n description: Docker image t"
},
{
"path": ".github/workflows/ai-service-release-nightly-image.yaml",
"chars": 3280,
"preview": "name: AI Service Release nightly image\n\non:\n push:\n branches: [main]\n paths:\n - 'wren-ai-service/**'\n\nenv:\n "
},
{
"path": ".github/workflows/ai-service-release-stable-image.yaml",
"chars": 5632,
"preview": "name: AI Service Release stable image\n\non:\n workflow_dispatch:\n inputs:\n version:\n description: Give a v"
},
{
"path": ".github/workflows/ai-service-test.yaml",
"chars": 1756,
"preview": "# This workflow will install Python dependencies, run tests and lint with a single version of Python\n# For more informat"
},
{
"path": ".github/workflows/create-rc-release-pr.yaml",
"chars": 2624,
"preview": "name: Create RC Release PR\n\non:\n workflow_dispatch:\n inputs:\n release_version:\n description: \"Release ve"
},
{
"path": ".github/workflows/create-rc-release.yaml",
"chars": 4066,
"preview": "name: Create RC Release\n\non:\n workflow_dispatch:\n inputs:\n release_version:\n description: \"Release versi"
},
{
"path": ".github/workflows/pr-tagger.yaml",
"chars": 5335,
"preview": "name: PR Tagger\n\non:\n pull_request:\n types: [opened, synchronize, reopened]\n paths:\n - \"wren-ui/src/**\"\n "
},
{
"path": ".github/workflows/pull-request-title-validator.yaml",
"chars": 565,
"preview": "name: Pull Request Title Validator\n\non:\n pull_request:\n paths:\n - \"wren-ai-service/**\"\n - \".github/workflo"
},
{
"path": ".github/workflows/ui-lint.yaml",
"chars": 1684,
"preview": "# create the github action to run the yarn lint when PR created or pushed to main branch\n#\n\nname: Wren-UI Lint\n\non:\n pu"
},
{
"path": ".github/workflows/ui-release-image-stable.yaml",
"chars": 5135,
"preview": "name: Wren-UI Release stable image\n\non:\n workflow_dispatch:\n inputs:\n version:\n description: Give a vers"
},
{
"path": ".github/workflows/ui-release-image.yaml",
"chars": 3465,
"preview": "name: Wren-UI Release image\n\non:\n workflow_dispatch:\n inputs:\n docker_image_tag_name:\n description: Dock"
},
{
"path": ".github/workflows/ui-test.yaml",
"chars": 1623,
"preview": "# create the github action to run the UI tests when PR created\n\nname: Wren-UI Test\n\non:\n pull_request:\n types: [ lab"
},
{
"path": ".github/workflows/wren-launcher-ci.yaml",
"chars": 2291,
"preview": "name: Wren Launcher CI\n\non:\n pull_request:\n types: [synchronize, labeled]\n paths:\n - 'wren-launcher/**'\n "
},
{
"path": ".gitignore",
"chars": 1794,
"preview": "# wren-ai-service\nwren-ai-service/.env.*\nwren-ai-service/config.yaml*\n!wren-ai-service/.env.*.example\n!wren-ai-service/s"
},
{
"path": ".gitmodules",
"chars": 91,
"preview": "[submodule \"wren-engine\"]\n\tpath = wren-engine\n\turl = git@github.com:Canner/wren-engine.git\n"
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 3304,
"preview": "## Code of Conduct\n\n### Our Pledge\n\nWe as members, contributors, and leaders pledge to make participation in our communi"
},
{
"path": "CONTRIBUTING.md",
"chars": 9713,
"preview": "# Contributing Guidelines\n\n*Pull requests, bug reports, and all other forms of contribution are welcomed and highly enco"
},
{
"path": "LICENSE",
"chars": 34583,
"preview": " GNU AFFERO GENERAL PUBLIC LICENSE\n Version 3, 19 November 2007\n\n Copyright (C)"
},
{
"path": "README.md",
"chars": 7024,
"preview": "\n<p align=\"center\" id=\"top\">\n <a href=\"https://getwren.ai/?utm_source=github&utm_medium=title&utm_campaign=readme\">\n "
},
{
"path": "SECURITY.md",
"chars": 1027,
"preview": "# Security Policy\n## Reporting a Vulnerability\n\nIf you believe you have found a security vulnerability in any Canner-own"
},
{
"path": "deployment/README.md",
"chars": 125,
"preview": "# Various deployemnt starategies of the app\n\n- [x] [Docker](../docker/)\n- [x] [Kubernetes: Kustomizations](./kustomizati"
},
{
"path": "deployment/kustomizations/.gitignore",
"chars": 26,
"preview": "*.kustomized.yaml\ncharts/*"
},
{
"path": "deployment/kustomizations/README.md",
"chars": 7251,
"preview": "# Deployment of Wren AI to Kubernetes with Kustomization\n1. Ensure you satisfy the dependencies required to deploy Wren "
},
{
"path": "deployment/kustomizations/base/cm.yaml",
"chars": 6999,
"preview": "apiVersion: v1\nkind: ConfigMap\nmetadata:\n name: wren-config\ndata:\n # Wren Engine Service Port\n WREN_ENGINE_PORT: \"808"
},
{
"path": "deployment/kustomizations/base/deploy-wren-ai-service.yaml",
"chars": 2028,
"preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: wren-ai-service-deployment\nspec:\n replicas: 1\n selector:\n ma"
},
{
"path": "deployment/kustomizations/base/deploy-wren-engine.yaml",
"chars": 1364,
"preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: wren-engine-deployment\nspec:\n replicas: 1\n selector:\n matchL"
},
{
"path": "deployment/kustomizations/base/deploy-wren-ibis-server.yaml",
"chars": 724,
"preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: wren-ibis-server\nspec:\n replicas: 1\n selector:\n matchLabels:"
},
{
"path": "deployment/kustomizations/base/deploy-wren-ui.yaml",
"chars": 3707,
"preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: wren-ui-deployment\nspec:\n replicas: 1\n selector:\n matchLabel"
},
{
"path": "deployment/kustomizations/base/pvc.yaml",
"chars": 196,
"preview": "apiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n name: wren-data-pvc\nspec:\n accessModes:\n - ReadWriteOnce\n reso"
},
{
"path": "deployment/kustomizations/base/svc.yaml",
"chars": 1552,
"preview": "# Dependancy https://external-dns.io\n# You may want to add a DNS record for wren-ui.myhost.net host for your k8s Service"
},
{
"path": "deployment/kustomizations/examples/.gitignore",
"chars": 11,
"preview": "secret.yaml"
},
{
"path": "deployment/kustomizations/examples/certificate-qdrant_example.yaml",
"chars": 417,
"preview": "# To generate valid certificates into qdrant-ai.myhost.net-tls\n# Dependancy: install https://cert-manager.io\napiVersion:"
},
{
"path": "deployment/kustomizations/examples/certificate-wren_example.yaml",
"chars": 546,
"preview": "# To generate valid certificates into wren-ui.myhost.net-tls\n# Dependancy: install https://cert-manager.io\napiVersion: c"
},
{
"path": "deployment/kustomizations/examples/ingress-wren_example.yaml",
"chars": 1833,
"preview": "# Dependancy https://external-dns.io\n# To add a DNS record for wren-ui.myhost.net host\n# Note: without authentication, e"
},
{
"path": "deployment/kustomizations/examples/secret-wren_example.yaml",
"chars": 2134,
"preview": "---\napiVersion: v1\nkind: Secret\nmetadata:\n name: wrenai-secrets\ntype: Opaque\ndata:\n # OPENAI_API_KEY is REQUIRED: with"
},
{
"path": "deployment/kustomizations/helm-values-qdrant_1.11.0.yaml",
"chars": 6143,
"preview": "replicaCount: 1\n\nimage:\n repository: docker.io/qdrant/qdrant\n pullPolicy: IfNotPresent\n tag: \"v1.11.0\"\n useUnprivile"
},
{
"path": "deployment/kustomizations/helm-values_postgresql_15.yaml",
"chars": 179,
"preview": "auth:\n secretKeys:\n adminPasswordKey: postgres-password\n existingSecret: wrenai-postgresql\n#creates admin_ui databa"
},
{
"path": "deployment/kustomizations/kustomization.yaml",
"chars": 2127,
"preview": "##### Dependancies used in this kustomization:\n# nginx.ingress\n# external-dns\n# cert-manager\n# kubectl kustomize\n\n#test "
},
{
"path": "deployment/kustomizations/patches/README.md",
"chars": 424,
"preview": "# Example of usefull Patches for Kustomization\n\nPatches from this folder allows to utilize the official unmodified deplo"
},
{
"path": "deployment/kustomizations/patches/cm.yaml",
"chars": 1028,
"preview": "- op: replace\n path: /data\n value:\n # Wren Engine Service Port\n WREN_ENGINE_PORT: \"8080\"\n # Wren AI Service P"
},
{
"path": "deployment/kustomizations/patches/rm-certificate.yaml",
"chars": 84,
"preview": "$patch: delete\napiVersion: v1\nkind: Certificate\nmetadata:\n name: wren-ui.myhost.net"
},
{
"path": "deployment/kustomizations/patches/rm-ingress.yaml",
"chars": 175,
"preview": "$patch: delete\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n name: wren-ui-ingress\n annotations:\n exter"
},
{
"path": "deployment/kustomizations/patches/service.yaml",
"chars": 219,
"preview": "- op: replace\n path: /spec/ipFamilies\n value:\n - IPv6\n - IPv4\n\n- op: replace\n path: /spec/type\n value:\n Loa"
},
{
"path": "docker/README.md",
"chars": 1724,
"preview": "## Service\n\n- `wren-engine`: the engine service. check out example here: [wren-engine\n /example](https://github.com/Can"
},
{
"path": "docker/bootstrap/Dockerfile",
"chars": 42,
"preview": "FROM busybox\n\nWORKDIR /app\nCOPY init.sh ./"
},
{
"path": "docker/bootstrap/init.sh",
"chars": 1213,
"preview": "#!/bin/sh\n# declare a variable from the environment variable: DATA_PATH\ndata_path=${DATA_PATH:-\"./\"}\n\n# touch a empty co"
},
{
"path": "docker/config.example.yaml",
"chars": 4918,
"preview": "type: llm\nprovider: litellm_llm\ntimeout: 120\nmodels:\n - alias: default\n model: gpt-4.1-nano-2025-04-14\n context_w"
},
{
"path": "docker/docker-compose-dev.yaml",
"chars": 2240,
"preview": "version: \"3\"\n\nvolumes:\n data:\n\nnetworks:\n wren:\n driver: bridge\n\nservices:\n bootstrap:\n image: ghcr.io/canner/w"
},
{
"path": "docker/docker-compose.yaml",
"chars": 3421,
"preview": "version: \"3\"\n\nvolumes:\n data:\n\nnetworks:\n wren:\n driver: bridge\n\nservices:\n bootstrap:\n image: ghcr.io/canner/w"
},
{
"path": "wren-ai-service/.dockerignore",
"chars": 46,
"preview": "*\n!src\n!entrypoint.sh\n!pyproject.toml\nsrc/eval"
},
{
"path": "wren-ai-service/.pre-commit-config.yaml",
"chars": 207,
"preview": "repos:\n- repo: https://github.com/astral-sh/ruff-pre-commit\n # Ruff version.\n rev: v0.2.2\n hooks:\n # Run the linte"
},
{
"path": "wren-ai-service/CONTRIBUTING.md",
"chars": 3389,
"preview": "# Welcome to Wren AI Service contributing guide\n\nThank you for investing your time in contributing to our project! This "
},
{
"path": "wren-ai-service/Justfile",
"chars": 2499,
"preview": "GREEN := \"\\u{001b}[32m\"\nYELLOW := \"\\u{001b}[33m\"\nRESET := \"\\u{001b}[0m\"\n\n## todo: consider to support --override flag to"
},
{
"path": "wren-ai-service/README.md",
"chars": 3547,
"preview": "# AI Service of Wren AI\n\n## Concepts\n\nPlease read the [documentation](https://docs.getwren.ai/oss/concept/wren_ai_servic"
},
{
"path": "wren-ai-service/docker/Dockerfile",
"chars": 806,
"preview": "# reference: https://medium.com/@albertazzir/blazing-fast-python-docker-builds-with-poetry-a78a66f5aed0\nFROM python:3.12"
},
{
"path": "wren-ai-service/docs/code_design.md",
"chars": 6955,
"preview": "# Introduction to the codebase of wren-ai-service\n\n## Table of Contents\n\n- [Purpose](#purpose)\n- [Environment Setup and "
},
{
"path": "wren-ai-service/docs/config_examples/README.md",
"chars": 1788,
"preview": "# MUST READ!!!\n\nSince these config files are examples, so **please carefully read the file and comments inside**. Try to"
},
{
"path": "wren-ai-service/docs/config_examples/config.anthropic.yaml",
"chars": 4986,
"preview": "# you should rename this file to config.yaml and put it in ~/.wrenai\n# please pay attention to the comments starting wit"
},
{
"path": "wren-ai-service/docs/config_examples/config.azure.yaml",
"chars": 5835,
"preview": "# you should rename this file to config.yaml and put it in ~/.wrenai\n# please pay attention to the comments starting wit"
},
{
"path": "wren-ai-service/docs/config_examples/config.bedrock.yaml",
"chars": 5785,
"preview": "# you should rename this file to config.yaml and put it in ~/.wrenai\n# please pay attention to the comments starting wit"
},
{
"path": "wren-ai-service/docs/config_examples/config.deepseek.yaml",
"chars": 6085,
"preview": "# you should rename this file to config.yaml and put it in ~/.wrenai\n# please pay attention to the comments starting wit"
},
{
"path": "wren-ai-service/docs/config_examples/config.google_ai_studio.yaml",
"chars": 5580,
"preview": "# you should rename this file to config.yaml and put it in ~/.wrenai\n# please pay attention to the comments starting wit"
},
{
"path": "wren-ai-service/docs/config_examples/config.google_vertexai.yaml",
"chars": 5984,
"preview": "# you should rename this file to config.yaml and put it in ~/.wrenai\n# please pay attention to the comments starting wit"
},
{
"path": "wren-ai-service/docs/config_examples/config.grok.yaml",
"chars": 5608,
"preview": "# you should rename this file to config.yaml and put it in ~/.wrenai\n# please pay attention to the comments starting wit"
},
{
"path": "wren-ai-service/docs/config_examples/config.groq.yaml",
"chars": 5632,
"preview": "# you should rename this file to config.yaml and put it in ~/.wrenai\n# please pay attention to the comments starting wit"
},
{
"path": "wren-ai-service/docs/config_examples/config.lm_studio.yaml",
"chars": 5451,
"preview": "# you should rename this file to config.yaml and put it in ~/.wrenai\n# please pay attention to the comments starting wit"
},
{
"path": "wren-ai-service/docs/config_examples/config.ollama.yaml",
"chars": 6046,
"preview": "# you should rename this file to config.yaml and put it in ~/.wrenai\n# please pay attention to the comments starting wit"
},
{
"path": "wren-ai-service/docs/config_examples/config.open_router.yaml",
"chars": 5056,
"preview": "# you should rename this file to config.yaml and put it in ~/.wrenai\n# please pay attention to the comments starting wit"
},
{
"path": "wren-ai-service/docs/config_examples/config.qwen3.yaml",
"chars": 6678,
"preview": "# you should rename this file to config.yaml and put it in ~/.wrenai\n# please pay attention to the comments starting wit"
},
{
"path": "wren-ai-service/docs/config_examples/config.zhipu.yaml",
"chars": 6885,
"preview": "# you should rename this file to config.yaml and put it in ~/.wrenai\n# please pay attention to the comments starting wit"
},
{
"path": "wren-ai-service/docs/configuration.md",
"chars": 6026,
"preview": "# AI Service Configuration\n\nThe AI service configuration is managed through a combination of environment variables and a"
},
{
"path": "wren-ai-service/entrypoint.sh",
"chars": 1557,
"preview": "#!/bin/bash\nset -e\n\nINTERVAL=1\nTIMEOUT=60\n\n# Wait for qdrant to be responsive\necho \"Waiting for qdrant to start...\"\ncurr"
},
{
"path": "wren-ai-service/eval/.gitignore",
"chars": 16,
"preview": ".env\nconfig.yaml"
},
{
"path": "wren-ai-service/eval/README.md",
"chars": 8053,
"preview": "# Evaluation Framework\n\nThis document describes the evaluation framework for the Wren AI service. The evaluation framewo"
},
{
"path": "wren-ai-service/eval/__init__.py",
"chars": 2019,
"preview": "from pathlib import Path\n\nfrom pydantic import Field, SecretStr\n\nfrom src.config import Settings\n\nSPIDER_DESTINATION_PAT"
},
{
"path": "wren-ai-service/eval/add_samples_to_toml.py",
"chars": 1164,
"preview": "import argparse\n\nimport tomlkit\n\nfrom eval.utils import (\n get_next_few_items_circular,\n)\n\nif __name__ == \"__main__\":"
},
{
"path": "wren-ai-service/eval/data_curation/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "wren-ai-service/eval/data_curation/app.py",
"chars": 18709,
"preview": "import asyncio\nimport re\nimport sys\nimport uuid\nfrom datetime import datetime\nfrom pathlib import Path\n\nimport orjson\nim"
},
{
"path": "wren-ai-service/eval/data_curation/utils.py",
"chars": 7552,
"preview": "import asyncio\nimport base64\nimport logging\nimport os\nimport re\nimport sys\nfrom pathlib import Path\nfrom typing import L"
},
{
"path": "wren-ai-service/eval/dataset/.gitignore",
"chars": 13,
"preview": "*\n!.gitignore"
},
{
"path": "wren-ai-service/eval/dspy_modules/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "wren-ai-service/eval/dspy_modules/ask_generation.py",
"chars": 1331,
"preview": "import dspy\n\n\nclass AskGenerationSignatureV1(dspy.Signature):\n \"\"\"Given a user query that is ambiguous in nature, you"
},
{
"path": "wren-ai-service/eval/dspy_modules/prompt_optimizer.py",
"chars": 5662,
"preview": "import argparse\nimport os\nimport re\nimport sys\nfrom datetime import datetime\nfrom pathlib import Path\nfrom typing import"
},
{
"path": "wren-ai-service/eval/evaluation.py",
"chars": 7030,
"preview": "import argparse\nimport sys\nfrom pathlib import Path\nfrom typing import Tuple\n\nfrom deepeval import evaluate\nfrom deepeva"
},
{
"path": "wren-ai-service/eval/mdl_to_csv.py",
"chars": 4555,
"preview": "import argparse\nimport csv\nfrom pathlib import Path\n\nimport orjson\n\n\ndef gen_eval_preparation_data_from_json_to_csv(mdl_"
},
{
"path": "wren-ai-service/eval/metrics/__init__.py",
"chars": 887,
"preview": "from .accuracy import AccuracyMetric, AccuracyMultiCandidateMetric\nfrom .answer_relevancy import AnswerRelevancyMetric\nf"
},
{
"path": "wren-ai-service/eval/metrics/accuracy.py",
"chars": 7372,
"preview": "import asyncio\nimport re\nimport traceback\n\nimport orjson\nimport pandas as pd\nfrom deepeval.evaluate import TestResult\nfr"
},
{
"path": "wren-ai-service/eval/metrics/answer_relevancy.py",
"chars": 1090,
"preview": "import asyncio\n\nfrom deepeval.metrics import BaseMetric\nfrom deepeval.test_case import LLMTestCase\n\nfrom eval.utils impo"
},
{
"path": "wren-ai-service/eval/metrics/context_precision.py",
"chars": 1296,
"preview": "import asyncio\n\nfrom deepeval.metrics import BaseMetric\nfrom deepeval.test_case import LLMTestCase\n\n\nclass ContextualPre"
},
{
"path": "wren-ai-service/eval/metrics/context_recall.py",
"chars": 986,
"preview": "import asyncio\n\nfrom deepeval.metrics import BaseMetric\nfrom deepeval.test_case import LLMTestCase\n\nfrom eval.utils impo"
},
{
"path": "wren-ai-service/eval/metrics/context_relevancy.py",
"chars": 777,
"preview": "import asyncio\n\nfrom deepeval.metrics import BaseMetric\nfrom deepeval.test_case import LLMTestCase\n\n\nclass ContextualRel"
},
{
"path": "wren-ai-service/eval/metrics/faithfulness.py",
"chars": 969,
"preview": "import asyncio\n\nfrom deepeval.metrics import BaseMetric\nfrom deepeval.test_case import LLMTestCase\n\nfrom eval.utils impo"
},
{
"path": "wren-ai-service/eval/metrics/llm/__init__.py",
"chars": 5114,
"preview": "import asyncio\n\nfrom deepeval.metrics import BaseMetric\nfrom deepeval.test_case import LLMTestCase\nfrom haystack.compone"
},
{
"path": "wren-ai-service/eval/metrics/spider/__init__.py",
"chars": 31489,
"preview": "import asyncio\nimport itertools\nimport os\nimport random\nimport re\nimport sqlite3\nfrom collections import defaultdict\nfro"
},
{
"path": "wren-ai-service/eval/metrics/spider/exact_match.py",
"chars": 1949,
"preview": "import asyncio\nimport os\n\nfrom deepeval.metrics import BaseMetric\nfrom deepeval.test_case import LLMTestCase\n\nfrom eval."
},
{
"path": "wren-ai-service/eval/metrics/spider/exec_match.py",
"chars": 1560,
"preview": "import asyncio\nimport os\n\nfrom deepeval.metrics import BaseMetric\nfrom deepeval.test_case import LLMTestCase\n\nfrom eval."
},
{
"path": "wren-ai-service/eval/metrics/spider/process_sql.py",
"chars": 17698,
"preview": "################################\n# Assumptions:\n# 1. sql is correct\n# 2. only table name has alias\n# 3. only one i"
},
{
"path": "wren-ai-service/eval/optimized/.gitignore",
"chars": 7,
"preview": "*.json\n"
},
{
"path": "wren-ai-service/eval/pipelines.py",
"chars": 16398,
"preview": "import asyncio\nimport re\nimport sys\nfrom abc import abstractmethod\nfrom datetime import datetime\nfrom pathlib import Pat"
},
{
"path": "wren-ai-service/eval/prediction.py",
"chars": 5168,
"preview": "import argparse\nimport base64\nimport sys\nimport uuid\nfrom datetime import datetime\nfrom pathlib import Path\nfrom typing "
},
{
"path": "wren-ai-service/eval/preparation.py",
"chars": 16192,
"preview": "\"\"\"\nThis file aims to prepare spider 1.0 or bird eval dataset for text-to-sql eval purpose\n\"\"\"\n\nimport argparse\nimport a"
},
{
"path": "wren-ai-service/eval/utils.py",
"chars": 22766,
"preview": "import base64\nimport os\nimport re\nimport uuid\nfrom copy import deepcopy\nfrom datetime import datetime\nfrom typing import"
},
{
"path": "wren-ai-service/pyproject.toml",
"chars": 1991,
"preview": "[tool.poetry]\nname = \"wren-ai-service\"\nversion = \"0.29.3\"\ndescription = \"\"\nauthors = [\"dev@getwren.ai\"]\nlicense = \"AGPL-"
},
{
"path": "wren-ai-service/ruff.toml",
"chars": 1823,
"preview": "# Exclude a variety of commonly ignored directories.\nexclude = [\n \".bzr\",\n \".direnv\",\n \".eggs\",\n \".git\",\n "
},
{
"path": "wren-ai-service/src/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "wren-ai-service/src/__main__.py",
"chars": 2496,
"preview": "from contextlib import asynccontextmanager\n\nimport uvicorn\nfrom fastapi import FastAPI\nfrom fastapi.exceptions import Re"
},
{
"path": "wren-ai-service/src/config.py",
"chars": 4415,
"preview": "import logging\n\nimport yaml\nfrom dotenv import load_dotenv\nfrom pydantic import Field\nfrom pydantic_settings import Base"
},
{
"path": "wren-ai-service/src/core/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "wren-ai-service/src/core/engine.py",
"chars": 1119,
"preview": "import logging\nimport re\nfrom abc import ABCMeta, abstractmethod\nfrom typing import Any, Dict, Optional, Tuple\n\nimport a"
},
{
"path": "wren-ai-service/src/core/pipeline.py",
"chars": 988,
"preview": "from abc import ABCMeta, abstractmethod\nfrom collections.abc import Mapping\nfrom dataclasses import dataclass\nfrom typin"
},
{
"path": "wren-ai-service/src/core/provider.py",
"chars": 914,
"preview": "from abc import ABCMeta, abstractmethod\n\nfrom haystack.document_stores.types import DocumentStore\n\n\nclass LLMProvider(me"
},
{
"path": "wren-ai-service/src/force_deploy.py",
"chars": 1156,
"preview": "# This file is only used for OSS, it will force deploy the mdl for the OSS users\n# Since we allow users to customize llm"
},
{
"path": "wren-ai-service/src/force_update_config.py",
"chars": 1406,
"preview": "# This file is only used for local development\n# It will update the config.yaml file to use correct engine name for all "
},
{
"path": "wren-ai-service/src/globals.py",
"chars": 13914,
"preview": "import logging\nfrom dataclasses import asdict, dataclass\n\nimport toml\n\nfrom src.config import Settings\nfrom src.core.pip"
},
{
"path": "wren-ai-service/src/pipelines/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "wren-ai-service/src/pipelines/common.py",
"chars": 3419,
"preview": "import re\nfrom typing import Any, List, Optional, Tuple\n\nfrom haystack import Document, component\n\n\ndef get_engine_suppo"
},
{
"path": "wren-ai-service/src/pipelines/generation/__init__.py",
"chars": 1485,
"preview": "from .chart_adjustment import ChartAdjustment\nfrom .chart_generation import ChartGeneration\nfrom .data_assistance import"
},
{
"path": "wren-ai-service/src/pipelines/generation/chart_adjustment.py",
"chars": 6350,
"preview": "import logging\nimport sys\nfrom typing import Any, Dict\n\nimport orjson\nfrom hamilton import base\nfrom hamilton.async_driv"
},
{
"path": "wren-ai-service/src/pipelines/generation/chart_generation.py",
"chars": 5475,
"preview": "import logging\nimport sys\nfrom typing import Any, Dict, Optional\n\nimport orjson\nfrom hamilton import base\nfrom hamilton."
},
{
"path": "wren-ai-service/src/pipelines/generation/data_assistance.py",
"chars": 5734,
"preview": "import asyncio\nimport logging\nimport sys\nfrom typing import Any, Optional\n\nfrom hamilton import base\nfrom hamilton.async"
},
{
"path": "wren-ai-service/src/pipelines/generation/followup_sql_generation.py",
"chars": 7234,
"preview": "import logging\nimport sys\nfrom typing import Any\n\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDrive"
},
{
"path": "wren-ai-service/src/pipelines/generation/followup_sql_generation_reasoning.py",
"chars": 5604,
"preview": "import asyncio\nimport logging\nimport sys\nfrom typing import Any, Optional\n\nfrom hamilton import base\nfrom hamilton.async"
},
{
"path": "wren-ai-service/src/pipelines/generation/intent_classification.py",
"chars": 14285,
"preview": "import ast\nimport logging\nimport sys\nfrom typing import Any, Literal, Optional\n\nimport orjson\nfrom hamilton import base\n"
},
{
"path": "wren-ai-service/src/pipelines/generation/misleading_assistance.py",
"chars": 5765,
"preview": "import asyncio\nimport logging\nimport sys\nfrom typing import Any, Optional\n\nfrom hamilton import base\nfrom hamilton.async"
},
{
"path": "wren-ai-service/src/pipelines/generation/question_recommendation.py",
"chars": 8968,
"preview": "import logging\nimport sys\nfrom typing import Any\n\nimport orjson\nfrom hamilton import base\nfrom hamilton.async_driver imp"
},
{
"path": "wren-ai-service/src/pipelines/generation/relationship_recommendation.py",
"chars": 7671,
"preview": "import logging\nimport sys\nfrom enum import Enum\nfrom typing import Any\n\nimport orjson\nfrom hamilton import base\nfrom ham"
},
{
"path": "wren-ai-service/src/pipelines/generation/semantics_description.py",
"chars": 7841,
"preview": "import logging\nimport sys\nfrom typing import Any\n\nimport orjson\nfrom hamilton import base\nfrom hamilton.async_driver imp"
},
{
"path": "wren-ai-service/src/pipelines/generation/sql_answer.py",
"chars": 5793,
"preview": "import asyncio\nimport logging\nimport sys\nfrom typing import Any, Optional\n\nfrom hamilton import base\nfrom hamilton.async"
},
{
"path": "wren-ai-service/src/pipelines/generation/sql_correction.py",
"chars": 6090,
"preview": "import logging\nimport sys\nfrom typing import Any, Dict, List\n\nfrom hamilton import base\nfrom hamilton.async_driver impor"
},
{
"path": "wren-ai-service/src/pipelines/generation/sql_diagnosis.py",
"chars": 4308,
"preview": "import logging\nimport sys\nfrom typing import Any, List\n\nimport orjson\nfrom hamilton import base\nfrom hamilton.async_driv"
},
{
"path": "wren-ai-service/src/pipelines/generation/sql_generation.py",
"chars": 6938,
"preview": "import logging\nimport sys\nfrom typing import Any\n\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDrive"
},
{
"path": "wren-ai-service/src/pipelines/generation/sql_generation_reasoning.py",
"chars": 5238,
"preview": "import asyncio\nimport logging\nimport sys\nfrom typing import Any, Optional\n\nfrom hamilton import base\nfrom hamilton.async"
},
{
"path": "wren-ai-service/src/pipelines/generation/sql_question.py",
"chars": 3227,
"preview": "import logging\nimport sys\nfrom typing import Any\n\nimport orjson\nfrom hamilton import base\nfrom hamilton.async_driver imp"
},
{
"path": "wren-ai-service/src/pipelines/generation/sql_regeneration.py",
"chars": 6555,
"preview": "import logging\nimport sys\nfrom typing import Any\n\nfrom hamilton import base\nfrom hamilton.async_driver import AsyncDrive"
},
{
"path": "wren-ai-service/src/pipelines/generation/sql_tables_extraction.py",
"chars": 3160,
"preview": "import logging\nimport sys\nfrom typing import Any\n\nimport orjson\nfrom hamilton import base\nfrom hamilton.async_driver imp"
},
{
"path": "wren-ai-service/src/pipelines/generation/user_guide_assistance.py",
"chars": 5369,
"preview": "import asyncio\nimport logging\nimport sys\nfrom typing import Any, Optional\n\nfrom hamilton import base\nfrom hamilton.async"
},
{
"path": "wren-ai-service/src/pipelines/generation/utils/chart.py",
"chars": 17367,
"preview": "import logging\nfrom typing import Any, Dict, Literal, Optional\n\nimport orjson\nimport pandas as pd\nfrom haystack import c"
},
{
"path": "wren-ai-service/src/pipelines/generation/utils/sql.py",
"chars": 30712,
"preview": "import logging\nfrom typing import Any, Dict, List\n\nimport aiohttp\nimport orjson\nfrom haystack import component\nfrom hays"
},
{
"path": "wren-ai-service/src/pipelines/generation/utils/vega-lite-schema-v5.json",
"chars": 2233851,
"preview": "{\n \"$ref\": \"#/definitions/TopLevelSpec\",\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"definitions\":"
},
{
"path": "wren-ai-service/src/pipelines/indexing/__init__.py",
"chars": 6433,
"preview": "import asyncio\nimport json\nimport logging\nimport re\nfrom typing import Any, Dict, List, Optional\n\nimport orjson\nfrom hay"
},
{
"path": "wren-ai-service/src/pipelines/indexing/db_schema.py",
"chars": 12977,
"preview": "import asyncio\nimport logging\nimport sys\nimport uuid\nfrom typing import Any, Dict, List, Optional\n\nfrom hamilton import "
},
{
"path": "wren-ai-service/src/pipelines/indexing/historical_question.py",
"chars": 6128,
"preview": "import logging\nimport sys\nimport uuid\nfrom typing import Any, Dict, List, Optional\n\nfrom hamilton import base\nfrom hamil"
},
{
"path": "wren-ai-service/src/pipelines/indexing/instructions.py",
"chars": 5433,
"preview": "import logging\nimport sys\nimport uuid\nfrom typing import Any, Dict, List, Literal, Optional\n\nfrom hamilton import base\nf"
},
{
"path": "wren-ai-service/src/pipelines/indexing/project_meta.py",
"chars": 3213,
"preview": "import logging\nimport sys\nimport uuid\nfrom typing import Any, Optional\n\nfrom hamilton import base\nfrom hamilton.async_dr"
},
{
"path": "wren-ai-service/src/pipelines/indexing/sql_pairs.py",
"chars": 6257,
"preview": "import logging\nimport os\nimport sys\nimport uuid\nfrom typing import Any, Dict, List, Optional, Set\n\nimport orjson\nfrom ha"
},
{
"path": "wren-ai-service/src/pipelines/indexing/table_description.py",
"chars": 5497,
"preview": "import logging\nimport sys\nimport uuid\nfrom typing import Any, Dict, List, Optional\n\nfrom hamilton import base\nfrom hamil"
},
{
"path": "wren-ai-service/src/pipelines/indexing/utils/helper.py",
"chars": 5251,
"preview": "import importlib\nimport logging\nimport pkgutil\nimport re\nimport sys\nfrom typing import Any, Callable, Dict\n\nimport orjso"
},
{
"path": "wren-ai-service/src/pipelines/retrieval/__init__.py",
"chars": 587,
"preview": "from .db_schema_retrieval import DbSchemaRetrieval\nfrom .historical_question_retrieval import HistoricalQuestionRetrieva"
},
{
"path": "wren-ai-service/src/pipelines/retrieval/db_schema_retrieval.py",
"chars": 17572,
"preview": "import ast\nimport logging\nimport sys\nfrom typing import Any, Optional\n\nimport orjson\nimport tiktoken\nfrom hamilton impor"
},
{
"path": "wren-ai-service/src/pipelines/retrieval/historical_question_retrieval.py",
"chars": 4720,
"preview": "import logging\nimport sys\nfrom typing import Any, Dict, List, Optional\n\nfrom hamilton import base\nfrom hamilton.async_dr"
},
{
"path": "wren-ai-service/src/pipelines/retrieval/instructions.py",
"chars": 5965,
"preview": "import logging\nimport sys\nfrom typing import Any, Dict, List, Optional\n\nfrom hamilton import base\nfrom hamilton.async_dr"
},
{
"path": "wren-ai-service/src/pipelines/retrieval/preprocess_sql_data.py",
"chars": 3076,
"preview": "import logging\nimport sys\nfrom typing import Dict\n\nimport tiktoken\nfrom hamilton import base\nfrom hamilton.driver import"
},
{
"path": "wren-ai-service/src/pipelines/retrieval/sql_executor.py",
"chars": 2215,
"preview": "import logging\nimport sys\nfrom typing import Any, Dict, Optional\n\nimport aiohttp\nfrom hamilton import base\nfrom hamilton"
},
{
"path": "wren-ai-service/src/pipelines/retrieval/sql_functions.py",
"chars": 3453,
"preview": "import logging\nimport sys\nfrom typing import List, Optional\n\nimport aiohttp\nfrom cachetools import TTLCache\nfrom hamilto"
},
{
"path": "wren-ai-service/src/pipelines/retrieval/sql_knowledge.py",
"chars": 3820,
"preview": "import logging\nimport sys\nfrom typing import Dict, Optional\n\nimport aiohttp\nfrom cachetools import TTLCache\nfrom hamilto"
},
{
"path": "wren-ai-service/src/pipelines/retrieval/sql_pairs_retrieval.py",
"chars": 4526,
"preview": "import logging\nimport sys\nfrom typing import Any, Dict, List, Optional\n\nfrom hamilton import base\nfrom hamilton.async_dr"
},
{
"path": "wren-ai-service/src/providers/__init__.py",
"chars": 12058,
"preview": "import logging\nfrom dataclasses import dataclass\n\nfrom src.core.engine import Engine\nfrom src.core.pipeline import Pipel"
},
{
"path": "wren-ai-service/src/providers/document_store/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "wren-ai-service/src/providers/document_store/qdrant.py",
"chars": 15366,
"preview": "import logging\nimport os\nfrom typing import Any, Dict, List, Optional\n\nimport numpy as np\nimport qdrant_client\nfrom hays"
},
{
"path": "wren-ai-service/src/providers/embedder/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "wren-ai-service/src/providers/embedder/litellm.py",
"chars": 6618,
"preview": "import asyncio\nimport logging\nimport os\nfrom typing import Any, Dict, List, Optional, Tuple\n\nimport backoff\nimport opena"
},
{
"path": "wren-ai-service/src/providers/engine/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "wren-ai-service/src/providers/engine/wren.py",
"chars": 11747,
"preview": "import asyncio\nimport base64\nimport logging\nimport os\nfrom typing import Any, Dict, Optional, Tuple\n\nimport aiohttp\nimpo"
},
{
"path": "wren-ai-service/src/providers/llm/__init__.py",
"chars": 7963,
"preview": "import logging\nfrom dataclasses import asdict, dataclass, field\nfrom enum import Enum\nfrom typing import Any, Dict, List"
},
{
"path": "wren-ai-service/src/providers/llm/litellm.py",
"chars": 6317,
"preview": "import os\nfrom typing import Any, Callable, Dict, List, Optional\n\nimport backoff\nimport openai\nfrom litellm import Route"
},
{
"path": "wren-ai-service/src/providers/loader.py",
"chars": 3117,
"preview": "import importlib\nimport logging\nimport pkgutil\n\nlogger = logging.getLogger(\"wren-ai-service\")\n\n\nPROVIDERS_PATH = \"src.pr"
},
{
"path": "wren-ai-service/src/utils.py",
"chars": 6682,
"preview": "import functools\nimport logging\nimport os\nimport re\nfrom pathlib import Path\n\nimport requests\nfrom dotenv import load_do"
},
{
"path": "wren-ai-service/src/web/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "wren-ai-service/src/web/development.py",
"chars": 3090,
"preview": "import inspect\nimport logging\nfrom typing import Any, Dict, get_type_hints\n\nfrom fastapi import APIRouter, HTTPException"
},
{
"path": "wren-ai-service/src/web/v1/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "wren-ai-service/src/web/v1/routers/__init__.py",
"chars": 945,
"preview": "from fastapi import APIRouter\n\nfrom src.web.v1.routers import (\n ask,\n ask_feedbacks,\n chart,\n chart_adjustm"
},
{
"path": "wren-ai-service/src/web/v1/routers/ask.py",
"chars": 2195,
"preview": "import uuid\nfrom dataclasses import asdict\n\nfrom fastapi import APIRouter, BackgroundTasks, Depends\nfrom fastapi.respons"
},
{
"path": "wren-ai-service/src/web/v1/routers/ask_feedbacks.py",
"chars": 2105,
"preview": "import uuid\nfrom dataclasses import asdict\n\nfrom fastapi import APIRouter, BackgroundTasks, Depends\n\nfrom src.globals im"
},
{
"path": "wren-ai-service/src/web/v1/routers/chart.py",
"chars": 1849,
"preview": "import uuid\nfrom dataclasses import asdict\n\nfrom fastapi import APIRouter, BackgroundTasks, Depends\n\nfrom src.globals im"
},
{
"path": "wren-ai-service/src/web/v1/routers/chart_adjustment.py",
"chars": 2248,
"preview": "import uuid\nfrom dataclasses import asdict\n\nfrom fastapi import APIRouter, BackgroundTasks, Depends\n\nfrom src.globals im"
},
{
"path": "wren-ai-service/src/web/v1/routers/instructions.py",
"chars": 2604,
"preview": "import uuid\nfrom dataclasses import asdict\nfrom typing import List, Literal, Optional\n\nfrom fastapi import APIRouter, Ba"
},
{
"path": "wren-ai-service/src/web/v1/routers/question_recommendation.py",
"chars": 2367,
"preview": "import uuid\nfrom dataclasses import asdict\nfrom typing import Literal, Optional\n\nfrom fastapi import APIRouter, Backgrou"
},
{
"path": "wren-ai-service/src/web/v1/routers/relationship_recommendation.py",
"chars": 1976,
"preview": "import uuid\nfrom dataclasses import asdict\nfrom typing import Literal, Optional\n\nfrom fastapi import APIRouter, Backgrou"
},
{
"path": "wren-ai-service/src/web/v1/routers/semantics_description.py",
"chars": 2620,
"preview": "import uuid\nfrom dataclasses import asdict\nfrom typing import Literal, Optional\n\nfrom fastapi import APIRouter, Backgrou"
},
{
"path": "wren-ai-service/src/web/v1/routers/semantics_preparation.py",
"chars": 2031,
"preview": "from dataclasses import asdict\n\nfrom fastapi import APIRouter, BackgroundTasks, Depends, HTTPException\n\nfrom src.globals"
},
{
"path": "wren-ai-service/src/web/v1/routers/sql_answers.py",
"chars": 1894,
"preview": "import uuid\nfrom dataclasses import asdict\n\nfrom fastapi import APIRouter, BackgroundTasks, Depends\nfrom fastapi.respons"
},
{
"path": "wren-ai-service/src/web/v1/routers/sql_corrections.py",
"chars": 1887,
"preview": "import uuid\nfrom dataclasses import asdict\nfrom typing import List, Literal, Optional\n\nfrom fastapi import APIRouter, Ba"
},
{
"path": "wren-ai-service/src/web/v1/routers/sql_pairs.py",
"chars": 2696,
"preview": "import uuid\nfrom dataclasses import asdict\nfrom typing import List, Literal, Optional\n\nfrom fastapi import APIRouter, Ba"
},
{
"path": "wren-ai-service/src/web/v1/routers/sql_question.py",
"chars": 1516,
"preview": "import uuid\nfrom dataclasses import asdict\n\nfrom fastapi import APIRouter, BackgroundTasks, Depends\n\nfrom src.globals im"
},
{
"path": "wren-ai-service/src/web/v1/services/__init__.py",
"chars": 3349,
"preview": "from datetime import datetime\nfrom typing import Literal, Optional\n\nimport orjson\nimport pytz\nfrom pydantic import Alias"
},
{
"path": "wren-ai-service/src/web/v1/services/ask.py",
"chars": 30189,
"preview": "import asyncio\nimport logging\nfrom typing import Dict, List, Literal, Optional\n\nfrom cachetools import TTLCache\nfrom lan"
},
{
"path": "wren-ai-service/src/web/v1/services/ask_feedback.py",
"chars": 12910,
"preview": "import asyncio\nimport logging\nfrom typing import Dict, List, Literal, Optional\n\nfrom cachetools import TTLCache\nfrom lan"
},
{
"path": "wren-ai-service/src/web/v1/services/chart.py",
"chars": 6682,
"preview": "import logging\nfrom typing import Any, Dict, Literal, Optional\n\nfrom cachetools import TTLCache\nfrom langfuse.decorators"
},
{
"path": "wren-ai-service/src/web/v1/services/chart_adjustment.py",
"chars": 7561,
"preview": "import logging\nfrom typing import Dict, Literal, Optional\n\nfrom cachetools import TTLCache\nfrom langfuse.decorators impo"
},
{
"path": "wren-ai-service/src/web/v1/services/instructions.py",
"chars": 5867,
"preview": "import logging\nfrom typing import Dict, List, Literal, Optional\n\nfrom cachetools import TTLCache\nfrom langfuse.decorator"
},
{
"path": "wren-ai-service/src/web/v1/services/question_recommendation.py",
"chars": 10703,
"preview": "import asyncio\nimport logging\nfrom typing import Dict, Literal, Optional\n\nimport orjson\nfrom cachetools import TTLCache\n"
},
{
"path": "wren-ai-service/src/web/v1/services/relationship_recommendation.py",
"chars": 3731,
"preview": "import logging\nfrom typing import Dict, Literal, Optional\n\nimport orjson\nfrom cachetools import TTLCache\nfrom langfuse.d"
},
{
"path": "wren-ai-service/src/web/v1/services/semantics_description.py",
"chars": 4860,
"preview": "import asyncio\nimport logging\nfrom typing import Dict, Literal, Optional\n\nimport orjson\nfrom cachetools import TTLCache\n"
},
{
"path": "wren-ai-service/src/web/v1/services/semantics_preparation.py",
"chars": 5313,
"preview": "import asyncio\nimport logging\nfrom typing import Dict, Literal, Optional\n\nfrom cachetools import TTLCache\nfrom langfuse."
}
]
// ... and 578 more files (download for full content)
About this extraction
This page contains the full source code of the Canner/WrenAI GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 778 files (8.0 MB), approximately 2.1M tokens, and a symbol index with 9573 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.