tinybird 0.0.1.dev242__tar.gz → 0.0.1.dev244__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of tinybird might be problematic. Click here for more details.
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/PKG-INFO +1 -1
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/__cli__.py +2 -2
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/agent/agent.py +38 -11
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/agent/prompts.py +36 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/agent/tools/create_datafile.py +17 -15
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/agent/tools/plan.py +0 -1
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/agent/utils.py +2 -0
- tinybird-0.0.1.dev244/tinybird/tb/modules/build.py +205 -0
- tinybird-0.0.1.dev242/tinybird/tb/modules/build.py → tinybird-0.0.1.dev244/tinybird/tb/modules/build_common.py +166 -354
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/cli.py +1 -1
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/secret.py +2 -50
- tinybird-0.0.1.dev244/tinybird/tb/modules/secret_common.py +56 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/test.py +1 -1
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird.egg-info/PKG-INFO +1 -1
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird.egg-info/SOURCES.txt +2 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/setup.cfg +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/__cli__.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/ch_utils/constants.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/ch_utils/engine.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/check_pypi.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/client.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/config.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/connectors.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/context.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/datafile/common.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/datafile/exceptions.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/datafile/parse_connection.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/datafile/parse_datasource.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/datafile/parse_pipe.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/datatypes.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/feedback_manager.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/git_settings.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/prompts.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/sql.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/sql_template.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/sql_template_fmt.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/sql_toolset.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/syncasync.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/check_pypi.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/cli.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/client.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/config.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/agent/__init__.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/agent/animations.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/agent/banner.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/agent/memory.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/agent/models.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/agent/tools/__init__.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/agent/tools/explore.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/agent/tools/preview_datafile.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/cicd.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/common.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/config.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/connection.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/copy.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/create.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/datafile/build.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/datafile/build_common.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/datafile/build_datasource.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/datafile/build_pipe.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/datafile/diff.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/datafile/fixture.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/datafile/format_common.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/datafile/format_datasource.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/datafile/format_pipe.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/datafile/pipe_checker.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/datafile/playground.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/datafile/pull.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/datasource.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/deployment.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/deprecations.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/dev_server.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/endpoint.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/exceptions.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/feedback_manager.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/info.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/infra.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/job.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/llm.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/llm_utils.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/local.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/local_common.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/login.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/logout.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/materialization.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/mock.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/open.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/pipe.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/project.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/regions.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/shell.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/sink.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/table.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/telemetry.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/tinyunit/tinyunit.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/tinyunit/tinyunit_lib.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/token.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/watch.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/workspace.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/workspace_members.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb_cli.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb_cli_modules/auth.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb_cli_modules/branch.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb_cli_modules/cicd.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb_cli_modules/cli.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb_cli_modules/common.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb_cli_modules/config.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb_cli_modules/connection.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb_cli_modules/datasource.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb_cli_modules/exceptions.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb_cli_modules/fmt.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb_cli_modules/job.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb_cli_modules/pipe.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb_cli_modules/regions.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb_cli_modules/tag.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb_cli_modules/telemetry.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb_cli_modules/test.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb_cli_modules/workspace.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb_cli_modules/workspace_members.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tornado_template.py +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird.egg-info/dependency_links.txt +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird.egg-info/entry_points.txt +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird.egg-info/requires.txt +0 -0
- {tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird.egg-info/top_level.txt +0 -0
|
@@ -4,5 +4,5 @@ __description__ = 'Tinybird Command Line Tool'
|
|
|
4
4
|
__url__ = 'https://www.tinybird.co/docs/forward/commands'
|
|
5
5
|
__author__ = 'Tinybird'
|
|
6
6
|
__author_email__ = 'support@tinybird.co'
|
|
7
|
-
__version__ = '0.0.1.
|
|
8
|
-
__revision__ = '
|
|
7
|
+
__version__ = '0.0.1.dev244'
|
|
8
|
+
__revision__ = '434c7ff'
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import sys
|
|
2
|
+
import uuid
|
|
2
3
|
from datetime import datetime
|
|
4
|
+
from functools import partial
|
|
5
|
+
from typing import Any
|
|
3
6
|
|
|
4
7
|
import click
|
|
5
8
|
from prompt_toolkit import prompt
|
|
@@ -26,20 +29,29 @@ from tinybird.tb.modules.agent.animations import ThinkingAnimation
|
|
|
26
29
|
from tinybird.tb.modules.agent.banner import display_banner
|
|
27
30
|
from tinybird.tb.modules.agent.memory import clear_history, load_history
|
|
28
31
|
from tinybird.tb.modules.agent.models import create_model
|
|
29
|
-
from tinybird.tb.modules.agent.prompts import
|
|
32
|
+
from tinybird.tb.modules.agent.prompts import (
|
|
33
|
+
datafile_instructions,
|
|
34
|
+
plan_instructions,
|
|
35
|
+
resources_prompt,
|
|
36
|
+
sql_instructions,
|
|
37
|
+
)
|
|
30
38
|
from tinybird.tb.modules.agent.tools.create_datafile import create_datafile
|
|
31
39
|
from tinybird.tb.modules.agent.tools.explore import explore_data
|
|
32
40
|
from tinybird.tb.modules.agent.tools.plan import plan
|
|
33
41
|
from tinybird.tb.modules.agent.tools.preview_datafile import preview_datafile
|
|
34
42
|
from tinybird.tb.modules.agent.utils import TinybirdAgentContext
|
|
43
|
+
from tinybird.tb.modules.build_common import process as build_process
|
|
44
|
+
from tinybird.tb.modules.exceptions import CLIBuildException
|
|
35
45
|
from tinybird.tb.modules.feedback_manager import FeedbackManager
|
|
46
|
+
from tinybird.tb.modules.local_common import get_tinybird_local_client
|
|
47
|
+
from tinybird.tb.modules.project import Project
|
|
36
48
|
|
|
37
49
|
|
|
38
50
|
class TinybirdAgent:
|
|
39
|
-
def __init__(self, token: str, host: str,
|
|
51
|
+
def __init__(self, token: str, host: str, project: Project):
|
|
40
52
|
self.token = token
|
|
41
53
|
self.host = host
|
|
42
|
-
self.
|
|
54
|
+
self.project = project
|
|
43
55
|
self.messages: list[ModelMessage] = []
|
|
44
56
|
self.agent = Agent(
|
|
45
57
|
model=create_model(token, host),
|
|
@@ -83,9 +95,10 @@ You have access to the following tools:
|
|
|
83
95
|
4. Without asking, use the `create_datafile` tool to create the datafile, because it will ask for confirmation before creating the file.
|
|
84
96
|
5. Check the result of the `create_datafile` tool to see if the datafile was created successfully.
|
|
85
97
|
6. If the datafile was created successfully, report the result to the user.
|
|
86
|
-
7. If the datafile was not created
|
|
98
|
+
7. If the datafile was not created, finish the process and just wait for a new user prompt.
|
|
99
|
+
8. If the datafile was created successfully, but the built failed, try to fix the error and repeat the process.
|
|
87
100
|
|
|
88
|
-
IMPORTANT: If the user cancels some of the steps or there is an error, DO NOT continue with the plan. Stop the process and wait for the user before using any other tool.
|
|
101
|
+
IMPORTANT: If the user cancels some of the steps or there is an error in file creation, DO NOT continue with the plan. Stop the process and wait for the user before using any other tool.
|
|
89
102
|
|
|
90
103
|
# When planning the creation or update of resources:
|
|
91
104
|
{plan_instructions}
|
|
@@ -134,9 +147,10 @@ Today is {datetime.now().strftime("%Y-%m-%d")}
|
|
|
134
147
|
"""Keep only the last 5 messages to manage token usage."""
|
|
135
148
|
return self.messages[-5:] if len(self.messages) > 5 else self.messages
|
|
136
149
|
|
|
137
|
-
def run(self, user_prompt: str) -> None:
|
|
150
|
+
def run(self, user_prompt: str, project: Project) -> None:
|
|
151
|
+
user_prompt = f"{user_prompt}\n\n# Existing resources in the project:\n{resources_prompt(project)}"
|
|
138
152
|
client = TinyB(token=self.token, host=self.host)
|
|
139
|
-
|
|
153
|
+
folder = self.project.folder
|
|
140
154
|
thinking_animation = ThinkingAnimation(message="Chirping", delay=0.15)
|
|
141
155
|
thinking_animation.start()
|
|
142
156
|
|
|
@@ -145,7 +159,9 @@ Today is {datetime.now().strftime("%Y-%m-%d")}
|
|
|
145
159
|
deps=TinybirdAgentContext(
|
|
146
160
|
# context does not support the whole client, so we need to pass only the functions we need
|
|
147
161
|
explore_data=client.explore_data,
|
|
148
|
-
folder=
|
|
162
|
+
build_project=partial(build_project, folder=folder),
|
|
163
|
+
get_project_files=project.get_project_files,
|
|
164
|
+
folder=folder,
|
|
149
165
|
thinking_animation=thinking_animation,
|
|
150
166
|
),
|
|
151
167
|
message_history=self.messages,
|
|
@@ -158,11 +174,13 @@ Today is {datetime.now().strftime("%Y-%m-%d")}
|
|
|
158
174
|
click.echo("\n")
|
|
159
175
|
|
|
160
176
|
|
|
161
|
-
def run_agent(
|
|
177
|
+
def run_agent(config: dict[str, Any], project: Project):
|
|
162
178
|
display_banner()
|
|
163
179
|
|
|
164
180
|
try:
|
|
165
|
-
|
|
181
|
+
token = config["token"]
|
|
182
|
+
host = config["host"]
|
|
183
|
+
agent = TinybirdAgent(token, host, project)
|
|
166
184
|
click.echo()
|
|
167
185
|
click.echo(FeedbackManager.success(message="Welcome to Tinybird Code"))
|
|
168
186
|
click.echo(FeedbackManager.info(message="Describe what you want to create and I'll help you build it"))
|
|
@@ -207,7 +225,7 @@ def run_agent(token: str, host: str, folder: str):
|
|
|
207
225
|
elif user_input.strip() == "":
|
|
208
226
|
continue
|
|
209
227
|
else:
|
|
210
|
-
agent.run(user_input)
|
|
228
|
+
agent.run(user_input, project)
|
|
211
229
|
|
|
212
230
|
except KeyboardInterrupt:
|
|
213
231
|
click.echo(FeedbackManager.info(message="Goodbye!"))
|
|
@@ -219,3 +237,12 @@ def run_agent(token: str, host: str, folder: str):
|
|
|
219
237
|
except Exception as e:
|
|
220
238
|
click.echo(FeedbackManager.error(message=f"Error: {e}"))
|
|
221
239
|
sys.exit(1)
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def build_project(folder: str) -> None:
|
|
243
|
+
workspace_name = f"tmp_workspace_{uuid.uuid4()}"
|
|
244
|
+
project = Project(folder, workspace_name=workspace_name)
|
|
245
|
+
local_client = get_tinybird_local_client({"path": folder, "name": workspace_name}, test=True, silent=True)
|
|
246
|
+
build_error = build_process(project=project, tb_client=local_client, watch=False, silent=True, exit_on_error=False)
|
|
247
|
+
if build_error:
|
|
248
|
+
raise CLIBuildException(build_error)
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from tinybird.tb.modules.project import Project
|
|
4
|
+
|
|
1
5
|
plan_instructions = """
|
|
2
6
|
When asked to create a plan, you MUST respond with this EXACT format and NOTHING ELSE:
|
|
3
7
|
|
|
@@ -81,3 +85,35 @@ datafile_instructions = """
|
|
|
81
85
|
- Datasource files will be created under the `/datasources` folder.
|
|
82
86
|
</datafile_instructions>
|
|
83
87
|
"""
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def resources_prompt(project: Project) -> str:
|
|
91
|
+
files = project.get_project_files()
|
|
92
|
+
|
|
93
|
+
if not files:
|
|
94
|
+
return "No resources found"
|
|
95
|
+
|
|
96
|
+
paths = [Path(file_path) for file_path in files]
|
|
97
|
+
|
|
98
|
+
def get_resource_type(path: Path) -> str:
|
|
99
|
+
if path.suffix.lower() == ".pipe":
|
|
100
|
+
return Project.get_pipe_type(str(path))
|
|
101
|
+
elif path.suffix.lower() == ".datasource":
|
|
102
|
+
return "datasource"
|
|
103
|
+
elif path.suffix.lower() == ".connection":
|
|
104
|
+
return "connection"
|
|
105
|
+
return "unknown"
|
|
106
|
+
|
|
107
|
+
return "\n".join(
|
|
108
|
+
[
|
|
109
|
+
f"""
|
|
110
|
+
<resource>
|
|
111
|
+
<path>{file_path.relative_to(project.folder)}</path>
|
|
112
|
+
<type>{get_resource_type(file_path)}</type>
|
|
113
|
+
<name>{file_path.stem}</name>
|
|
114
|
+
<content>{file_path.read_text()}</content>
|
|
115
|
+
</resource>
|
|
116
|
+
"""
|
|
117
|
+
for file_path in paths
|
|
118
|
+
]
|
|
119
|
+
)
|
{tinybird-0.0.1.dev242 → tinybird-0.0.1.dev244}/tinybird/tb/modules/agent/tools/create_datafile.py
RENAMED
|
@@ -4,13 +4,16 @@ import click
|
|
|
4
4
|
from pydantic_ai import RunContext
|
|
5
5
|
|
|
6
6
|
from tinybird.tb.modules.agent.utils import Datafile, TinybirdAgentContext, show_options
|
|
7
|
+
from tinybird.tb.modules.exceptions import CLIBuildException
|
|
8
|
+
from tinybird.tb.modules.feedback_manager import FeedbackManager
|
|
7
9
|
|
|
8
10
|
|
|
9
|
-
def get_resource_confirmation(resource: Datafile) -> bool:
|
|
11
|
+
def get_resource_confirmation(resource: Datafile, exists: bool) -> bool:
|
|
10
12
|
"""Get user confirmation for creating a resource"""
|
|
11
13
|
while True:
|
|
14
|
+
action = "create" if not exists else "update"
|
|
12
15
|
result = show_options(
|
|
13
|
-
options=[f"Yes,
|
|
16
|
+
options=[f"Yes, {action} {resource.type} '{resource.name}'", "No, and tell Tinybird Code what to do"],
|
|
14
17
|
title=f"What would you like to do with {resource.type} '{resource.name}'?",
|
|
15
18
|
)
|
|
16
19
|
|
|
@@ -36,29 +39,28 @@ def create_datafile(ctx: RunContext[TinybirdAgentContext], resource: Datafile) -
|
|
|
36
39
|
"""
|
|
37
40
|
try:
|
|
38
41
|
ctx.deps.thinking_animation.stop()
|
|
39
|
-
click.echo()
|
|
40
42
|
click.echo(resource.content)
|
|
41
|
-
|
|
43
|
+
resource.pathname = resource.pathname.removeprefix("/")
|
|
44
|
+
path = Path(ctx.deps.folder) / resource.pathname
|
|
45
|
+
exists = str(path) in ctx.deps.get_project_files()
|
|
46
|
+
confirmation = get_resource_confirmation(resource, exists)
|
|
42
47
|
ctx.deps.thinking_animation.start()
|
|
43
48
|
|
|
44
49
|
if not confirmation:
|
|
45
50
|
return f"Resource {resource.pathname} was not created. User cancelled creation."
|
|
46
51
|
|
|
47
|
-
resource.pathname = resource.pathname.removeprefix("/")
|
|
48
|
-
|
|
49
|
-
path = Path(ctx.deps.folder) / resource.pathname
|
|
50
|
-
|
|
51
52
|
folder_path = path.parent
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
folder_path.mkdir()
|
|
55
|
-
|
|
56
|
-
if not path.exists():
|
|
57
|
-
path.touch()
|
|
53
|
+
folder_path.mkdir(parents=True, exist_ok=True)
|
|
54
|
+
path.touch(exist_ok=True)
|
|
58
55
|
|
|
59
56
|
path.write_text(resource.content)
|
|
60
|
-
|
|
57
|
+
ctx.deps.build_project()
|
|
61
58
|
return f"Created {resource.pathname}"
|
|
62
59
|
|
|
60
|
+
except CLIBuildException as e:
|
|
61
|
+
ctx.deps.thinking_animation.stop()
|
|
62
|
+
click.echo(FeedbackManager.error(message=e))
|
|
63
|
+
ctx.deps.thinking_animation.start()
|
|
64
|
+
return f"Error building project: {e}"
|
|
63
65
|
except Exception as e:
|
|
64
66
|
return f"Error creating {resource.pathname}: {e}"
|
|
@@ -20,7 +20,9 @@ from pydantic import BaseModel, Field
|
|
|
20
20
|
class TinybirdAgentContext(BaseModel):
|
|
21
21
|
explore_data: Callable[[str], str]
|
|
22
22
|
folder: str
|
|
23
|
+
build_project: Callable[[], None]
|
|
23
24
|
thinking_animation: Any
|
|
25
|
+
get_project_files: Callable[[], List[str]]
|
|
24
26
|
|
|
25
27
|
|
|
26
28
|
default_style = Style.from_dict(
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import threading
|
|
2
|
+
import time
|
|
3
|
+
from copy import deepcopy
|
|
4
|
+
from functools import partial
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Callable, List
|
|
7
|
+
from urllib.parse import urlencode
|
|
8
|
+
|
|
9
|
+
import click
|
|
10
|
+
|
|
11
|
+
import tinybird.context as context
|
|
12
|
+
from tinybird.datafile.exceptions import ParseException
|
|
13
|
+
from tinybird.datafile.parse_datasource import parse_datasource
|
|
14
|
+
from tinybird.datafile.parse_pipe import parse_pipe
|
|
15
|
+
from tinybird.tb.client import TinyB
|
|
16
|
+
from tinybird.tb.modules.build_common import process
|
|
17
|
+
from tinybird.tb.modules.cli import cli
|
|
18
|
+
from tinybird.tb.modules.config import CLIConfig
|
|
19
|
+
from tinybird.tb.modules.datafile.playground import folder_playground
|
|
20
|
+
from tinybird.tb.modules.dev_server import BuildStatus, start_server
|
|
21
|
+
from tinybird.tb.modules.feedback_manager import FeedbackManager
|
|
22
|
+
from tinybird.tb.modules.project import Project
|
|
23
|
+
from tinybird.tb.modules.secret_common import load_secrets
|
|
24
|
+
from tinybird.tb.modules.shell import Shell, print_table_formatted
|
|
25
|
+
from tinybird.tb.modules.watch import watch_files, watch_project
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@cli.command()
|
|
29
|
+
@click.option("--watch", is_flag=True, default=False, help="Watch for changes and rebuild automatically")
|
|
30
|
+
@click.pass_context
|
|
31
|
+
def build(ctx: click.Context, watch: bool) -> None:
|
|
32
|
+
"""
|
|
33
|
+
Validate and build the project server side.
|
|
34
|
+
"""
|
|
35
|
+
project: Project = ctx.ensure_object(dict)["project"]
|
|
36
|
+
tb_client: TinyB = ctx.ensure_object(dict)["client"]
|
|
37
|
+
|
|
38
|
+
if project.has_deeper_level():
|
|
39
|
+
click.echo(
|
|
40
|
+
FeedbackManager.warning(
|
|
41
|
+
message="Your project contains directories nested deeper than the default scan depth (max_depth=3). "
|
|
42
|
+
"Files in these deeper directories will not be processed. "
|
|
43
|
+
"To include all nested directories, run `tb --max-depth <depth> <cmd>` with a higher depth value."
|
|
44
|
+
)
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
load_secrets(project, tb_client)
|
|
48
|
+
click.echo(FeedbackManager.highlight_building_project())
|
|
49
|
+
process(project=project, tb_client=tb_client, watch=False)
|
|
50
|
+
if watch:
|
|
51
|
+
run_watch(
|
|
52
|
+
project=project,
|
|
53
|
+
tb_client=tb_client,
|
|
54
|
+
process=partial(process, project=project, tb_client=tb_client, watch=True),
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@cli.command("dev", help="Build the project server side and watch for changes.")
|
|
59
|
+
@click.option("--data-origin", type=str, default="", help="Data origin: local or cloud")
|
|
60
|
+
@click.option("--ui", is_flag=True, default=False, help="Connect your local project to Tinybird UI")
|
|
61
|
+
@click.pass_context
|
|
62
|
+
def dev(ctx: click.Context, data_origin: str, ui: bool) -> None:
|
|
63
|
+
if data_origin == "cloud":
|
|
64
|
+
return dev_cloud(ctx)
|
|
65
|
+
project: Project = ctx.ensure_object(dict)["project"]
|
|
66
|
+
tb_client: TinyB = ctx.ensure_object(dict)["client"]
|
|
67
|
+
build_status = BuildStatus()
|
|
68
|
+
if ui:
|
|
69
|
+
server_thread = threading.Thread(
|
|
70
|
+
target=start_server, args=(project, tb_client, process, build_status), daemon=True
|
|
71
|
+
)
|
|
72
|
+
server_thread.start()
|
|
73
|
+
# Wait for the server to start
|
|
74
|
+
time.sleep(0.5)
|
|
75
|
+
|
|
76
|
+
load_secrets(project, tb_client)
|
|
77
|
+
click.echo(FeedbackManager.highlight_building_project())
|
|
78
|
+
process(project=project, tb_client=tb_client, watch=True, build_status=build_status)
|
|
79
|
+
run_watch(
|
|
80
|
+
project=project,
|
|
81
|
+
tb_client=tb_client,
|
|
82
|
+
process=partial(process, project=project, tb_client=tb_client, build_status=build_status),
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def run_watch(project: Project, tb_client: TinyB, process: Callable) -> None:
|
|
87
|
+
shell = Shell(project=project, tb_client=tb_client, playground=False)
|
|
88
|
+
click.echo(FeedbackManager.gray(message="\nWatching for changes..."))
|
|
89
|
+
watcher_thread = threading.Thread(
|
|
90
|
+
target=watch_project,
|
|
91
|
+
args=(shell, process, project),
|
|
92
|
+
daemon=True,
|
|
93
|
+
)
|
|
94
|
+
watcher_thread.start()
|
|
95
|
+
shell.run()
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def is_vendor(f: Path) -> bool:
|
|
99
|
+
return f.parts[0] == "vendor"
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def get_vendor_workspace(f: Path) -> str:
|
|
103
|
+
return f.parts[1]
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def is_endpoint(f: Path) -> bool:
|
|
107
|
+
return f.suffix == ".pipe" and not is_vendor(f) and f.parts[0] == "endpoints"
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def is_pipe(f: Path) -> bool:
|
|
111
|
+
return f.suffix == ".pipe" and not is_vendor(f)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def check_filenames(filenames: List[str]):
|
|
115
|
+
parser_matrix = {".pipe": parse_pipe, ".datasource": parse_datasource}
|
|
116
|
+
incl_suffix = ".incl"
|
|
117
|
+
|
|
118
|
+
for filename in filenames:
|
|
119
|
+
file_suffix = Path(filename).suffix
|
|
120
|
+
if file_suffix == incl_suffix:
|
|
121
|
+
continue
|
|
122
|
+
|
|
123
|
+
parser = parser_matrix.get(file_suffix)
|
|
124
|
+
if not parser:
|
|
125
|
+
raise ParseException(FeedbackManager.error_unsupported_datafile(extension=file_suffix))
|
|
126
|
+
|
|
127
|
+
parser(filename)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def dev_cloud(
|
|
131
|
+
ctx: click.Context,
|
|
132
|
+
) -> None:
|
|
133
|
+
project: Project = ctx.ensure_object(dict)["project"]
|
|
134
|
+
config = CLIConfig.get_project_config()
|
|
135
|
+
tb_client: TinyB = config.get_client()
|
|
136
|
+
context.disable_template_security_validation.set(True)
|
|
137
|
+
|
|
138
|
+
def process(filenames: List[str], watch: bool = False):
|
|
139
|
+
datafiles = [f for f in filenames if f.endswith(".datasource") or f.endswith(".pipe")]
|
|
140
|
+
if len(datafiles) > 0:
|
|
141
|
+
check_filenames(filenames=datafiles)
|
|
142
|
+
folder_playground(
|
|
143
|
+
project, config, tb_client, filenames=datafiles, is_internal=False, current_ws=None, local_ws=None
|
|
144
|
+
)
|
|
145
|
+
if len(filenames) > 0 and watch:
|
|
146
|
+
filename = filenames[0]
|
|
147
|
+
build_and_print_resource(config, tb_client, filename)
|
|
148
|
+
|
|
149
|
+
datafiles = project.get_project_files()
|
|
150
|
+
filenames = datafiles
|
|
151
|
+
|
|
152
|
+
def build_once(filenames: List[str]):
|
|
153
|
+
ok = False
|
|
154
|
+
try:
|
|
155
|
+
click.echo(FeedbackManager.highlight(message="» Building project...\n"))
|
|
156
|
+
time_start = time.time()
|
|
157
|
+
process(filenames=filenames, watch=False)
|
|
158
|
+
time_end = time.time()
|
|
159
|
+
elapsed_time = time_end - time_start
|
|
160
|
+
|
|
161
|
+
click.echo(FeedbackManager.success(message=f"\n✓ Build completed in {elapsed_time:.1f}s"))
|
|
162
|
+
ok = True
|
|
163
|
+
except Exception as e:
|
|
164
|
+
error_path = Path(".tb_error.txt")
|
|
165
|
+
if error_path.exists():
|
|
166
|
+
content = error_path.read_text()
|
|
167
|
+
content += f"\n\n{str(e)}"
|
|
168
|
+
error_path.write_text(content)
|
|
169
|
+
else:
|
|
170
|
+
error_path.write_text(str(e))
|
|
171
|
+
click.echo(FeedbackManager.error_exception(error=e))
|
|
172
|
+
ok = False
|
|
173
|
+
return ok
|
|
174
|
+
|
|
175
|
+
build_ok = build_once(filenames)
|
|
176
|
+
|
|
177
|
+
shell = Shell(project=project, tb_client=tb_client, playground=True)
|
|
178
|
+
click.echo(FeedbackManager.gray(message="\nWatching for changes..."))
|
|
179
|
+
watcher_thread = threading.Thread(
|
|
180
|
+
target=watch_files, args=(filenames, process, shell, project, build_ok), daemon=True
|
|
181
|
+
)
|
|
182
|
+
watcher_thread.start()
|
|
183
|
+
shell.run()
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def build_and_print_resource(config: CLIConfig, tb_client: TinyB, filename: str):
|
|
187
|
+
resource_path = Path(filename)
|
|
188
|
+
name = resource_path.stem
|
|
189
|
+
playground_name = name if filename.endswith(".pipe") else None
|
|
190
|
+
user_client = deepcopy(tb_client)
|
|
191
|
+
user_client.token = config.get_user_token() or ""
|
|
192
|
+
cli_params = {}
|
|
193
|
+
cli_params["workspace_id"] = config.get("id", None)
|
|
194
|
+
data = user_client._req(f"/v0/playgrounds?{urlencode(cli_params)}")
|
|
195
|
+
playgrounds = data["playgrounds"]
|
|
196
|
+
playground = next((p for p in playgrounds if p["name"] == (f"{playground_name}" + "__tb__playground")), None)
|
|
197
|
+
if not playground:
|
|
198
|
+
return
|
|
199
|
+
playground_id = playground["id"]
|
|
200
|
+
last_node = playground["nodes"][-1]
|
|
201
|
+
if not last_node:
|
|
202
|
+
return
|
|
203
|
+
node_sql = last_node["sql"]
|
|
204
|
+
res = tb_client.query(f"{node_sql} FORMAT JSON", playground=playground_id)
|
|
205
|
+
print_table_formatted(res, name)
|