gibson-cli 0.8.8__py3-none-any.whl → 0.8.10__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
gibson/api/ProjectApi.py CHANGED
@@ -1,3 +1,5 @@
1
+ from typing import List
2
+
1
3
  from gibson.api.BaseApi import BaseApi
2
4
  from gibson.core.Configuration import Configuration
3
5
 
@@ -20,8 +22,13 @@ class ProjectApi(BaseApi):
20
22
  def lookup(self, uuid: str):
21
23
  return self.get(f"{uuid}")
22
24
 
23
- def deploy(self, uuid: str):
24
- return self.post(f"{uuid}/deploy")
25
+ def deploy(self, uuid: str, environments: List[str] | None = None):
26
+ return self.post(
27
+ f"{uuid}/deploy", {"environments": environments} if environments else None
28
+ )
29
+
30
+ def diff(self, uuid: str):
31
+ return self.get(f"{uuid}/diff")
25
32
 
26
33
  def mcp(self, uuid: str):
27
34
  return self.get(f"{uuid}/mcp")
@@ -10,7 +10,7 @@ class BaseCommand:
10
10
  self.memory = Memory(self.configuration)
11
11
 
12
12
  def customization_management_is_enabled(self):
13
- return self.__enable_customization_management == True
13
+ return self.__enable_customization_management
14
14
 
15
15
  def disable_customization_management(self):
16
16
  self.__enable_customization_management = False
gibson/command/Build.py CHANGED
@@ -15,7 +15,7 @@ class Build(BaseCommand):
15
15
 
16
16
  db = create_engine(self.configuration.project.datastore.uri)
17
17
  session = sessionmaker(autocommit=False, autoflush=False, bind=db)()
18
- table_exceptions = TableExceptions().universal()
18
+ TableExceptions().universal()
19
19
 
20
20
  self.conversation.type("Connected to datastore...\n")
21
21
 
@@ -52,7 +52,7 @@ class Build(BaseCommand):
52
52
  self.conversation.type(" foreign key checks have been enabled\n")
53
53
 
54
54
  def __build_postgresql(self, session):
55
- table_exceptions = TableExceptions().postgresql()
55
+ TableExceptions().postgresql()
56
56
 
57
57
  schema = list(session.execute("select current_schema()"))[0][0]
58
58
  self.conversation.type(f" current schema is {schema}\n")
@@ -83,12 +83,11 @@ class Build(BaseCommand):
83
83
  while tables != {}:
84
84
  remove = []
85
85
  for name, definition in tables.items():
86
-
87
86
  try:
88
87
  session.execute(definition)
89
88
  session.commit()
90
89
 
91
- self.conversation.type(f' {name.split(".")[-1]}\n')
90
+ self.conversation.type(f" {name.split('.')[-1]}\n")
92
91
 
93
92
  remove.append(name)
94
93
  except sqlalchemy.exc.ProgrammingError:
@@ -0,0 +1,52 @@
1
+ from rich.prompt import Confirm
2
+
3
+ from gibson.api.ProjectApi import ProjectApi
4
+ from gibson.command.BaseCommand import BaseCommand
5
+ from gibson.core.Select import MultiSelect
6
+ from gibson.core.Spinner import Spinner
7
+
8
+
9
+ class Deploy(BaseCommand):
10
+ def execute(self):
11
+ self.configuration.require_login()
12
+ project_id = self.configuration.require_project_id()
13
+ project = ProjectApi(self.configuration).lookup(project_id)
14
+ databases = [database["environment"] for database in project["databases"]]
15
+
16
+ selected = MultiSelect(
17
+ title="Select the database(s) to deploy",
18
+ options=databases,
19
+ ).prompt()
20
+
21
+ if not selected:
22
+ self.conversation.type("No database selected\n")
23
+ exit(1)
24
+
25
+ for database in selected:
26
+ diff = ProjectApi(self.configuration).diff(project_id)
27
+ if diff:
28
+ self.conversation.type(f"\nDiff for {database} database:\n\n")
29
+ self.conversation.type(diff)
30
+ self.conversation.newline()
31
+
32
+ if Confirm.ask(
33
+ f"After reviewing the diff, are you sure you want to deploy the {database} database?"
34
+ ):
35
+ self.conversation.newline()
36
+ with Spinner(
37
+ start_text=f"Deploying {database} database...",
38
+ success_text=f"Deployed {database} database",
39
+ fail_text=f"Deployment failed for {database} database",
40
+ ):
41
+ ProjectApi(self.configuration).deploy(
42
+ project_id, environments=[database]
43
+ )
44
+
45
+ else:
46
+ self.conversation.type(
47
+ f"\nSkipping deployment for {database} database\n",
48
+ )
49
+ else:
50
+ self.conversation.type(
51
+ f"\nNo changes to deploy for {database} database\n",
52
+ )
gibson/command/Forget.py CHANGED
@@ -14,11 +14,11 @@ class Forget(BaseCommand):
14
14
 
15
15
  if sys.argv[2] in ["all", "last"]:
16
16
  self.memory.forget_last()
17
- self.conversation.type(f"last memory is forgotten.\n")
17
+ self.conversation.type("last memory is forgotten.\n")
18
18
 
19
19
  if sys.argv[2] in ["all", "stored"]:
20
20
  self.memory.forget_entities()
21
- self.conversation.type(f"stored memory is forgotten.\n")
21
+ self.conversation.type("stored memory is forgotten.\n")
22
22
 
23
23
  self.conversation.newline()
24
24
 
gibson/command/Help.py CHANGED
@@ -47,6 +47,11 @@ class Help(BaseCommand):
47
47
  "subcommands": ["last", "stored"],
48
48
  "memory": "based on user selection",
49
49
  },
50
+ "deploy": {
51
+ "description": "deploy the project database(s) with the current schema",
52
+ "subcommands": None,
53
+ "memory": None,
54
+ },
50
55
  "dev": {
51
56
  "description": Text.assemble(
52
57
  "gibson will automatically write code for you",
@@ -111,6 +116,11 @@ class Help(BaseCommand):
111
116
  "subcommands": None,
112
117
  "memory": "last > stored",
113
118
  },
119
+ "studio": {
120
+ "description": "connect to your database and launch the SQL studio",
121
+ "subcommands": None,
122
+ "memory": None,
123
+ },
114
124
  "tree": {
115
125
  "description": "illustrate the project layout in a tree view",
116
126
  "subcommands": None,
@@ -0,0 +1,58 @@
1
+ from urllib.parse import urlparse
2
+
3
+ from harlequin.app import Harlequin
4
+ from harlequin.plugins import load_adapter_plugins
5
+
6
+ from gibson.api.ProjectApi import ProjectApi
7
+ from gibson.command.BaseCommand import BaseCommand
8
+ from gibson.core.Select import Select
9
+ from gibson.core.Spinner import DisappearingSpinner
10
+
11
+
12
+ class Studio(BaseCommand):
13
+ def execute(self):
14
+ self.configuration.require_login()
15
+ project_id = self.configuration.require_project_id()
16
+
17
+ project = ProjectApi(self.configuration).lookup(project_id)
18
+
19
+ choices = [database["environment"] for database in project["databases"]]
20
+
21
+ selected = Select(
22
+ title="Select a database",
23
+ options=choices,
24
+ ).prompt()
25
+
26
+ if not selected:
27
+ self.conversation.type("No database selected\n")
28
+ exit(1)
29
+
30
+ database = next(
31
+ (db for db in project["databases"] if db["environment"] == selected), None
32
+ )
33
+
34
+ with DisappearingSpinner(
35
+ start_text=f"Connecting to {database['environment']} database...",
36
+ success_text=f"Connected to {database['environment']} database",
37
+ fail_text=f"Failed to connect to {database['environment']} database",
38
+ ):
39
+ plugins = load_adapter_plugins()
40
+ adapter = plugins[database["datastore_type"]]
41
+
42
+ if database["datastore_type"] == "mysql":
43
+ connection = urlparse(database["connection_string"])
44
+ adapter = adapter(
45
+ conn_str=None,
46
+ host=connection.hostname,
47
+ port=connection.port,
48
+ user=connection.username,
49
+ password=connection.password,
50
+ database=connection.path.lstrip("/"),
51
+ )
52
+ else:
53
+ raise ValueError(
54
+ f"Unsupported database type: {database['datastore_type']}"
55
+ )
56
+
57
+ app = Harlequin(adapter=adapter)
58
+ app.run()
@@ -1,6 +1,4 @@
1
- from gibson.api.BaseApi import BaseApi
2
1
  from gibson.command.BaseCommand import BaseCommand
3
- from gibson.services.auth.Server import Server as AuthServer
4
2
 
5
3
 
6
4
  class Login(BaseCommand):
@@ -32,14 +32,14 @@ class Module(BaseCommand):
32
32
  print(entity["definition"])
33
33
 
34
34
  self.conversation.newline()
35
- self.conversation.type(f"If you want to persist these new entities run:\n")
35
+ self.conversation.type("If you want to persist these new entities run:\n")
36
36
  self.conversation.type(
37
37
  f"{Colors.command(self.configuration.command, 'merge')}\n"
38
38
  )
39
39
 
40
40
  self.conversation.newline()
41
41
  self.conversation.type(
42
- f"Afterwards, you can modify any of these entities by running:\n"
42
+ "Afterwards, you can modify any of these entities by running:\n"
43
43
  )
44
44
  self.conversation.type(
45
45
  f"{Colors.command(self.configuration.command, 'modify', inputs=['[entity name]', '[instructions]'])}\n"
gibson/conf/Dev.py CHANGED
@@ -1,5 +1,3 @@
1
- import os
2
-
3
1
  from gibson.conf.dev.Api import Api
4
2
  from gibson.conf.dev.Base import Base
5
3
  from gibson.conf.dev.Model import Model
@@ -3,3 +3,9 @@ from gibson.conf.Dependencies import Dependencies
3
3
 
4
4
  def test_compute():
5
5
  dependencies = Dependencies().compute()
6
+
7
+ assert dependencies.api == "fastapi==0.85"
8
+ assert dependencies.model == "sqlalchemy==1.4"
9
+ assert dependencies.revision == "alembic==1.12"
10
+ assert dependencies.schema == "pydantic==2.6"
11
+ assert dependencies.test == "pytest==7.1"
@@ -5,6 +5,7 @@ from gibson.command.Build import Build
5
5
  from gibson.command.code.Code import Code
6
6
  from gibson.command.Conf import Conf
7
7
  from gibson.command.Count import Count
8
+ from gibson.command.Deploy import Deploy
8
9
  from gibson.command.Dev import Dev
9
10
  from gibson.command.Forget import Forget
10
11
  from gibson.command.Help import Help
@@ -19,6 +20,7 @@ from gibson.command.Remove import Remove
19
20
  from gibson.command.rename.Rename import Rename
20
21
  from gibson.command.rewrite.Rewrite import Rewrite
21
22
  from gibson.command.Show import Show
23
+ from gibson.command.Studio import Studio
22
24
  from gibson.command.Tree import Tree
23
25
  from gibson.command.Version import Version
24
26
  from gibson.core.Configuration import Configuration
@@ -52,6 +54,8 @@ class CommandRouter:
52
54
  command = Conf(self.configuration)
53
55
  elif sys.argv[1] == "count":
54
56
  command = Count(self.configuration)
57
+ elif sys.argv[1] == "deploy":
58
+ command = Deploy(self.configuration)
55
59
  elif sys.argv[1] == "dev":
56
60
  command = Dev(self.configuration)
57
61
  elif sys.argv[1] == "forget":
@@ -78,6 +82,8 @@ class CommandRouter:
78
82
  command = Rewrite(self.configuration, with_header=True)
79
83
  elif sys.argv[1] == "show":
80
84
  command = Show(self.configuration)
85
+ elif sys.argv[1] == "studio":
86
+ command = Studio(self.configuration)
81
87
  elif sys.argv[1] == "tree":
82
88
  command = Tree(self.configuration)
83
89
  elif sys.argv[1] in ["q"]:
@@ -127,7 +127,7 @@ class Configuration:
127
127
  test_file = f"{os.path.expandvars(path)}/gibsonai-test-file"
128
128
 
129
129
  try:
130
- with open(test_file, "w") as f:
130
+ with open(test_file, "w"):
131
131
  pass
132
132
 
133
133
  os.remove(test_file)
@@ -237,6 +237,10 @@ class Configuration:
237
237
  return self.settings[self.project.name]
238
238
 
239
239
  def get_project_id(self):
240
+ project_id = os.getenv("GIBSONAI_PROJECT_ID")
241
+ if project_id:
242
+ return project_id
243
+
240
244
  self.require_project()
241
245
  return self.project.id
242
246
 
gibson/core/PythonPath.py CHANGED
@@ -24,7 +24,7 @@ class PythonPath:
24
24
  try:
25
25
  with open(f"{self.user_home}/{self.gibson_config}/config", "r") as f:
26
26
  config = json.loads(f.read())
27
- except:
27
+ except Exception:
28
28
  return self
29
29
 
30
30
  project_paths = filter(
gibson/core/Select.py ADDED
@@ -0,0 +1,270 @@
1
+ from typing import Any, List, Optional
2
+
3
+ import click
4
+ from rich.align import Align
5
+ from rich.console import Group
6
+ from rich.live import Live
7
+ from rich.panel import Panel
8
+ from rich.text import Text
9
+
10
+
11
+ class BaseSelect:
12
+ """Base class for select components with shared functionality."""
13
+
14
+ def __init__(
15
+ self,
16
+ options: List[str] = [],
17
+ title: str = "",
18
+ color: str = "bold magenta",
19
+ align: str = "left",
20
+ selection: str = "→",
21
+ highlight: str = "green",
22
+ ):
23
+ self.options = options
24
+ self.index = 0
25
+ self.title = title
26
+ self.color = color
27
+ self.align = align
28
+ self.selection = selection
29
+ self.highlight = highlight
30
+
31
+ def _get_click(self) -> Optional[str]:
32
+ match click.getchar():
33
+ case "\r":
34
+ return "enter"
35
+ case "\x1b[B" | "s" | "S" | "àP":
36
+ return "down"
37
+ case "\x1b[A" | "w" | "W" | "àH":
38
+ return "up"
39
+ case "\x1b[D" | "a" | "A" | "àK":
40
+ return "left"
41
+ case "\x1b[C" | "d" | "D" | "àM":
42
+ return "right"
43
+ case "\x1b":
44
+ return "exit"
45
+ case _:
46
+ return None
47
+
48
+ def _set_index(self, key: str) -> None:
49
+ if key == "down":
50
+ self.index += 1
51
+ elif key == "up":
52
+ self.index -= 1
53
+
54
+ if self.index > len(self.options) - 1:
55
+ self.index = 0
56
+ elif self.index < 0:
57
+ self.index = len(self.options) - 1
58
+
59
+ def _clear(self) -> None:
60
+ for _ in range(len(self.options) + 5):
61
+ print("\x1b[A\x1b[K", end="")
62
+
63
+ @property
64
+ def _usage_info(self) -> Text:
65
+ """Return usage information text for the select menu."""
66
+ return Text("Use ↑/↓ to navigate, ENTER to submit", "dim")
67
+
68
+ @property
69
+ def _layout(self) -> Group:
70
+ """Generate the display group for the menu.
71
+ This method should be overridden by subclasses.
72
+ """
73
+ raise NotImplementedError("Subclasses must implement _layout")
74
+
75
+ @property
76
+ def _panel_width(self) -> int:
77
+ """Return the width of the panel."""
78
+ # Calculate minimum width needed for the usage text
79
+ usage_width = len(self._usage_info.plain) + 2
80
+ # Get the max width of options
81
+ options_width = (
82
+ max((len(option) for option in self.options), default=0) + 5
83
+ ) # +5 for marker and spacing
84
+ # Use the larger of the two widths, plus some padding
85
+ return max(usage_width, options_width) + 4
86
+
87
+ def prompt(self) -> Any:
88
+ """Display the menu and handle user input.
89
+ This method should be overridden by subclasses.
90
+ """
91
+ raise NotImplementedError("Subclasses must implement prompt")
92
+
93
+
94
+ class Select(BaseSelect):
95
+ def __init__(
96
+ self,
97
+ options: List[str] = [],
98
+ start_index: int = 0,
99
+ title: str = "",
100
+ color: str = "bold magenta",
101
+ align: str = "left",
102
+ selection: str = "→",
103
+ highlight: str = "green",
104
+ ):
105
+ super().__init__(
106
+ options=options,
107
+ title=title,
108
+ color=color,
109
+ align=align,
110
+ selection=selection,
111
+ highlight=highlight,
112
+ )
113
+ self.index = start_index
114
+
115
+ @property
116
+ def _layout(self) -> Group:
117
+ menu = Text(justify="left")
118
+
119
+ selected = Text(self.selection + " ", self.highlight)
120
+ not_selected = Text(" " * (len(self.selection) + 1))
121
+
122
+ for idx, option in enumerate(self.options):
123
+ if idx == self.index:
124
+ menu.append(
125
+ Text.assemble(selected, Text(option + "\n", self.highlight))
126
+ )
127
+ else:
128
+ menu.append(Text.assemble(not_selected, option + "\n"))
129
+
130
+ menu.rstrip()
131
+
132
+ menu = Panel(menu, padding=1, width=self._panel_width)
133
+ menu.title = Text(self.title, self.color)
134
+ menu.subtitle = self._usage_info
135
+
136
+ return Group(Align(menu, self.align))
137
+
138
+ def prompt(self) -> str:
139
+ with Live(self._layout, auto_refresh=False, screen=False) as live:
140
+ live.update(self._layout, refresh=True)
141
+ while True:
142
+ try:
143
+ key = self._get_click()
144
+ if key == "enter":
145
+ break
146
+ elif key == "exit":
147
+ exit()
148
+
149
+ self._set_index(key)
150
+ live.update(self._layout, refresh=True)
151
+ except (KeyboardInterrupt, EOFError):
152
+ exit()
153
+
154
+ self._clear()
155
+
156
+ return self.options[self.index]
157
+
158
+
159
+ class MultiSelect(BaseSelect):
160
+ def __init__(
161
+ self,
162
+ options: List[str] = [],
163
+ start_indices: Optional[List[int]] = None,
164
+ title: str = "",
165
+ color: str = "bold magenta",
166
+ align: str = "left",
167
+ selection: str = "→",
168
+ highlight: str = "green",
169
+ selected_marker: str = "●",
170
+ unselected_marker: str = "○",
171
+ ):
172
+ super().__init__(
173
+ options=options,
174
+ title=title,
175
+ color=color,
176
+ align=align,
177
+ selection=selection,
178
+ highlight=highlight,
179
+ )
180
+ self.selected_indices = start_indices or []
181
+ self.selected_marker = selected_marker
182
+ self.unselected_marker = unselected_marker
183
+
184
+ def _get_click(self) -> Optional[str]:
185
+ # Override to add space key handling
186
+ match click.getchar():
187
+ case "\r":
188
+ return "enter"
189
+ case "\x1b[B" | "s" | "S" | "àP":
190
+ return "down"
191
+ case "\x1b[A" | "w" | "W" | "àH":
192
+ return "up"
193
+ case "\x1b[D" | "a" | "A" | "àK":
194
+ return "left"
195
+ case "\x1b[C" | "d" | "D" | "àM":
196
+ return "right"
197
+ case " ":
198
+ return "space"
199
+ case "\x1b":
200
+ return "exit"
201
+ case _:
202
+ return None
203
+
204
+ def _toggle_selection(self) -> None:
205
+ if self.index in self.selected_indices:
206
+ self.selected_indices.remove(self.index)
207
+ else:
208
+ self.selected_indices.append(self.index)
209
+
210
+ @property
211
+ def _usage_info(self) -> Text:
212
+ """Return usage information text for the multi-select menu."""
213
+ return Text("Use ↑/↓ to navigate, SPACE to toggle, ENTER to submit", "dim")
214
+
215
+ @property
216
+ def _layout(self) -> Group:
217
+ menu = Text(justify="left")
218
+
219
+ cursor_selected = Text(self.selection + " ", self.highlight)
220
+ cursor_not_selected = Text(" " * (len(self.selection) + 1))
221
+
222
+ for idx, option in enumerate(self.options):
223
+ # Determine if this option is selected
224
+ marker = (
225
+ self.selected_marker
226
+ if idx in self.selected_indices
227
+ else self.unselected_marker
228
+ )
229
+
230
+ # Determine if cursor is on this item
231
+ if idx == self.index:
232
+ menu.append(
233
+ Text.assemble(
234
+ cursor_selected, Text(f"{marker} {option}\n", self.highlight)
235
+ )
236
+ )
237
+ else:
238
+ menu.append(Text.assemble(cursor_not_selected, f"{marker} {option}\n"))
239
+
240
+ menu.rstrip()
241
+
242
+ menu = Panel(menu, padding=1, width=self._panel_width)
243
+ menu.title = Text(self.title, self.color)
244
+ menu.subtitle = self._usage_info
245
+
246
+ return Group(Align(menu, self.align))
247
+
248
+ def prompt(self) -> List[str]:
249
+ with Live(self._layout, auto_refresh=False, screen=False) as live:
250
+ live.update(self._layout, refresh=True)
251
+ while True:
252
+ try:
253
+ key = self._get_click()
254
+ if key == "enter":
255
+ break
256
+ elif key == "exit":
257
+ exit()
258
+ elif key == "space":
259
+ self._toggle_selection()
260
+ live.update(self._layout, refresh=True)
261
+ else:
262
+ self._set_index(key)
263
+ live.update(self._layout, refresh=True)
264
+ except (KeyboardInterrupt, EOFError):
265
+ exit()
266
+
267
+ self._clear()
268
+
269
+ # Return the selected options
270
+ return [self.options[i] for i in self.selected_indices]
@@ -1,5 +1,3 @@
1
- import pytest
2
-
3
1
  from gibson.structure.postgresql.References import References
4
2
  from gibson.structure.postgresql.table.ForeignKey import ForeignKey
5
3
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gibson-cli
3
- Version: 0.8.8
3
+ Version: 0.8.10
4
4
  Summary: Gibson Command Line Interface
5
5
  Author-email: GibsonAI <noc@gibsonai.com>
6
6
  Project-URL: Homepage, https://gibsonai.com/
@@ -27,6 +27,8 @@ Requires-Dist: faker-sqlalchemy==0.10.2208140
27
27
  Requires-Dist: fastapi==0.115.12
28
28
  Requires-Dist: fastapi-cli==0.0.2
29
29
  Requires-Dist: h11==0.14.0
30
+ Requires-Dist: harlequin==2.1.2
31
+ Requires-Dist: harlequin-mysql==1.1.0
30
32
  Requires-Dist: httpcore==1.0.5
31
33
  Requires-Dist: httptools==0.6.4
32
34
  Requires-Dist: httpx==0.27.0
@@ -38,7 +40,7 @@ Requires-Dist: markdown-it-py==3.0.0
38
40
  Requires-Dist: markupsafe==2.1.5
39
41
  Requires-Dist: mcp==1.6.0
40
42
  Requires-Dist: mdurl==0.1.2
41
- Requires-Dist: orjson==3.10.3
43
+ Requires-Dist: orjson==3.10.18
42
44
  Requires-Dist: packaging==24.2
43
45
  Requires-Dist: pluggy==1.4.0
44
46
  Requires-Dist: pydantic==2.11.0
@@ -60,7 +62,7 @@ Requires-Dist: sniffio==1.3.1
60
62
  Requires-Dist: sqlalchemy==1.4.41
61
63
  Requires-Dist: sse-starlette==2.2.1
62
64
  Requires-Dist: starlette==0.46.1
63
- Requires-Dist: textual==0.83.0
65
+ Requires-Dist: textual==0.89.1
64
66
  Requires-Dist: tomli==2.0.1
65
67
  Requires-Dist: typer==0.12.3
66
68
  Requires-Dist: typing-extensions==4.13.0
@@ -68,7 +70,7 @@ Requires-Dist: typing-inspection==0.4.0
68
70
  Requires-Dist: ujson==5.9.0
69
71
  Requires-Dist: urllib3==1.26.6
70
72
  Requires-Dist: uvicorn==0.29.0
71
- Requires-Dist: watchfiles==0.21.0
73
+ Requires-Dist: watchfiles==1.0.5
72
74
  Requires-Dist: websockets==12.0
73
75
  Requires-Dist: yaspin==3.1.0
74
76
 
@@ -76,9 +78,9 @@ Requires-Dist: yaspin==3.1.0
76
78
 
77
79
  # Gibson CLI
78
80
 
79
- [![PyPI - Version](https://img.shields.io/pypi/v/gibson-cli)](https://pypi.org/project/gibson-cli/)
80
- ![Python 3.10+](https://img.shields.io/badge/Python-3.10%2B-blue)
81
- [![Docs](https://img.shields.io/badge/Docs-https://docs.gibsonai.com-green)](https://docs.gibsonai.com)
81
+ [![PyPI - Version](https://img.shields.io/pypi/v/gibson-cli?label=📦)](https://pypi.org/project/gibson-cli/)
82
+ ![Python 3.10+](https://img.shields.io/badge/🐍-Python%203.10%2B-blue)
83
+ [![Docs](https://img.shields.io/badge/📚-docs.gibsonai.com-green)](https://docs.gibsonai.com)
82
84
 
83
85
  ## Prerequisites
84
86
 
@@ -178,7 +180,7 @@ All of Gibson's configuration files and caches are stored in `$HOME/.gibson`. Us
178
180
 
179
181
  ### For Windows Users
180
182
 
181
- - Make sure that you have an environment variable called HOME set. Gibson will store its configuration files and caches in this directory. We recommend you keep this directory outside of any repository to which you might be committing.
183
+ - Make sure that you have an environment variable called `HOME` set. Gibson will store its configuration files and caches in this directory. We recommend you keep this directory outside of any repository to which you might be committing.
182
184
  - To execute the `gibson` command, follow these instructions:
183
185
  - Assuming the gibson executable is in `c:\Users\\[me]\projects\gibson\bin`
184
186
  - Run `python c:\Users\\[me]\projects\gibson\bin\gibson`
@@ -4,24 +4,26 @@ bin/release.sh,sha256=6pnY_GctbwF-3sZB67b0nzUlTsxlhY1hqJQoqRutXuw,137
4
4
  gibson/api/BaseApi.py,sha256=Wza4yuLHhFjkPxt2dhtUtM_r9b5IGd72V80VDl7v3Gw,3510
5
5
  gibson/api/Cli.py,sha256=Qcm5NIQ4x1Wn6KfkrAzwvZeWyt-cKF_xD7_lTWL4Lbw,8071
6
6
  gibson/api/DataApi.py,sha256=JZN6q7bO2O87xBCsU9w96NgINOJJZx3d7jOiHoVH1Wo,542
7
- gibson/api/ProjectApi.py,sha256=1_gRAAgaqblV0I0D-R-wwgSQArQ4fSCxTDfTO3zDQzY,1212
7
+ gibson/api/ProjectApi.py,sha256=IY3njspfanpaAIGnkrraQvqFmgQde7kzdg0ZNA2N1Vs,1428
8
8
  gibson/bin/gibson.py,sha256=ybtdrqLfmTb-gG2U7kWSHWSZDvc864omYR9vres38ZU,458
9
- gibson/command/BaseCommand.py,sha256=mmWUO0FxjMCbv3cHWnnasfAWnU_hTuGHUsRVJ4hUcqM,777
10
- gibson/command/Build.py,sha256=6lMdTa3HZvcbskoX8iJZJnekiJmyNVSbgGmgvh1v-BM,4421
9
+ gibson/command/BaseCommand.py,sha256=0LdxshtNj8sySMSaDFIPooDbdZx0mNMyhCuyqcF4JsU,769
10
+ gibson/command/Build.py,sha256=nFwYhO5lpq7cM6oSH6nBA2ubW8wW7aJFsXIwjE1F2EY,4382
11
11
  gibson/command/Conf.py,sha256=yuAGL6M8MUURG4hW3MAW043c-h_ALw3FHWbyCOR8YTQ,2375
12
12
  gibson/command/Count.py,sha256=QOagwCwDxUHYPivFntr-RWUmlKWKDHgDIGZBfju6VpY,1040
13
+ gibson/command/Deploy.py,sha256=-SqM3w7feTJmYNrZ70EKzuwlNBSZgaB_d_MQaR8zRwc,2006
13
14
  gibson/command/Dev.py,sha256=zbZjsgAKAHlNUflEr_Lj2QmRBXNbIGIHrPJ3t5DcFC8,4213
14
- gibson/command/Forget.py,sha256=Fm1mUyZkK3HS5fIVgNaC3d97vcWWQVysdDkg4ciE8Bk,1018
15
- gibson/command/Help.py,sha256=Gih3JVZ3SLXrdZPInZccb-NtlzvSUTbTwW2NztKnrbo,6456
15
+ gibson/command/Forget.py,sha256=rpUmnHISvQlMgsFwa0p2nndaygy9UvDph3mlOmwlugo,1016
16
+ gibson/command/Help.py,sha256=DVce2KCeNTjhxJ3v6nHub9vVJ-Vi0FNFFcA9dU0KToQ,6846
16
17
  gibson/command/Merge.py,sha256=R5ybMC1tUR5_T8YyUfXutzFa_V9j1_flv0s7KTJRq0M,1061
17
18
  gibson/command/Modify.py,sha256=XgTM6EodL7sVhWrnWuTCDx2PNJw3xo-aKI80HCmSpV8,1171
18
19
  gibson/command/Question.py,sha256=g8SwopbzeG14WWP0bc-fXIDVqOOicMzjC9YXoGd-NxY,3830
19
20
  gibson/command/Remove.py,sha256=Ar8-vSNwmCaBupCLY_rcvyU_kWIILU_qVX5njV-tZVw,2478
20
21
  gibson/command/Show.py,sha256=qkkprY2JhA4qOOhYOwAECDnFZwTdqcsKsG4cwB_b-84,1409
22
+ gibson/command/Studio.py,sha256=ZOcXGzrkGGFYtsrxP0qTeComKfUcpTAZWJ9Njd7JfR4,2019
21
23
  gibson/command/Tree.py,sha256=BeJ_13xrrRCK5FP2rQHWpDKrshVzte-_D1pNG1GXPIw,3056
22
24
  gibson/command/Version.py,sha256=jxkRdbQiyTdto18RpbL-5vudcbvLLX9kcl8vmkt7USw,1187
23
25
  gibson/command/auth/Auth.py,sha256=DAvnKq3Ks77QJwuGJCWA9Iv3c0Qq5pHFIpEA-gy6CxM,1086
24
- gibson/command/auth/Login.py,sha256=b43OfV76i6aGdOwj1NK64ZOdYlNyc08g3lZGQ_37KDw,437
26
+ gibson/command/auth/Login.py,sha256=4iv3lm-6QNTgtIaszpphyye4eeYOvjU6Ol6ZLmZQZ1I,337
25
27
  gibson/command/auth/Logout.py,sha256=QwW9pCNi61Ak0-1B-3spd_YlsmLYBxzV4uwyO0RYzxg,252
26
28
  gibson/command/code/Api.py,sha256=sSvAqEJXdgQjYcu0uiM6ndHE3GnfkfVL6eqP2Otkbww,1002
27
29
  gibson/command/code/Base.py,sha256=YJ2a5Hl0f9NXHUBBPvlt-dUIqEPWQz5vH6-1EHmbFbA,640
@@ -39,7 +41,7 @@ gibson/command/list/Entities.py,sha256=o5Wemlq_EpeObNwJHbCqkUT4nccfu_OOZ_gYWzJ05
39
41
  gibson/command/list/List.py,sha256=IA9VYuOiFdweg-6HIBZ5hECnMyNxsoU2dKd-gzRNtio,1107
40
42
  gibson/command/list/Projects.py,sha256=ju82kC3cuvAMGg4YJl1yn0l8t11fa1T5Zvgkl_p9m9U,1194
41
43
  gibson/command/mcp/McpServer.py,sha256=LiKPGtxpdGHJQP280tmqhnUOvdJboF6UtoQggKQHVJg,881
42
- gibson/command/new/Module.py,sha256=PCTt6k54XFzgNjNgwY0FKQFzk0YFoaN_KPZF2sfN_V0,1535
44
+ gibson/command/new/Module.py,sha256=nyVsxW9XTMIizwMwM7ahPlPAzQMUTk7dDFikzZ9UprI,1533
43
45
  gibson/command/new/New.py,sha256=cwsBpZAZH-9se26ywAUFyvrc9L9ezwoERIrRLlDkrzU,1519
44
46
  gibson/command/new/Project.py,sha256=Cw1Z6TvPIGhTi7GiQZ2VFjv6hXdpGKQdX9HuAd5gric,759
45
47
  gibson/command/rename/Entity.py,sha256=SaAiN1bYsTOsqjyVzxghK8-N3sAKITThTzS5LEYgppY,1801
@@ -52,7 +54,7 @@ gibson/conf/Code.py,sha256=3Bd5kxCbgWaUOyYLRejOO_SqM9spGk1dYAf2hYzuDSw,199
52
54
  gibson/conf/Custom.py,sha256=7S5v3bQK3UKuGUMTrAJeubWqszDtMlJI19-yOXk1TFs,101
53
55
  gibson/conf/Datastore.py,sha256=PVAnysrk4wH1oCWxTUaakH2_x83Zpm4vzD1ELhfMDSw,90
54
56
  gibson/conf/Dependencies.py,sha256=DZxyFtDR_3QpmsZbHApJFSeA7uYrMX1Bdx4lZKJ49Uo,891
55
- gibson/conf/Dev.py,sha256=nMjKmRrJbNIsMqQRFo8f68Lx-hSU-lihvLvhj0Safzg,344
57
+ gibson/conf/Dev.py,sha256=0gVwBbnUTgbCxvvz-h50Y68fSsaAR-KJlzwaqGQVQpw,333
56
58
  gibson/conf/Frameworks.py,sha256=Dv5iqeVe0JmNCKX5a-6S_dCrx7WZyI3qkTAFX6JWfDU,173
57
59
  gibson/conf/Modeler.py,sha256=RayW3VFD_2nCFXZepfEcCXTUX2tWd7WtOjHULNVCai8,67
58
60
  gibson/conf/Paths.py,sha256=FB8_w-8oCnzuqGIMVUahvZfl0p8i_ERnVzVPjuXTk3Y,243
@@ -63,17 +65,18 @@ gibson/conf/dev/Api.py,sha256=EKZwy-3h7NxLdP6AYtwyTpJhD1kdQN6gVLuWw4_2KC8,158
63
65
  gibson/conf/dev/Base.py,sha256=HisA87syPa5sJFjfjyxWRkLIKuVM5CtAkwW3f2zJx5Y,72
64
66
  gibson/conf/dev/Model.py,sha256=HbHRX3VDxR7hXlzuxkKw4Bf7FH6XMfQ96k9BeIUoBf4,73
65
67
  gibson/conf/dev/Schema.py,sha256=kOSlX1jEyVb82xd8TO8jEAimLcaefIFJr6d2JYvyTqg,74
66
- gibson/conf/tests/test_conf_Dependencies.py,sha256=LITeeYiqXM5rKkyWFBqcnMvUR5pzDRuHVAngH372jWc,116
68
+ gibson/conf/tests/test_conf_Dependencies.py,sha256=-MAS3SzB1euHFwFhd0dpyIHYNMYgxEaN2LTeZ1pqc6w,363
67
69
  gibson/conf/tests/test_conf_Platform.py,sha256=Zc53IsZmV-hT9VRrZEPNrsuehSdWnJXWKGMmOhEqWHo,138
68
70
  gibson/core/Colors.py,sha256=sllEmJAb2AAUH0e-ZLP1_C8pfz5U_w0fo5kubSH5g1o,3426
69
- gibson/core/CommandRouter.py,sha256=V7awLSPjOx2GQqJNoHQSFsiA2uFkrxtpysyTDbyPloA,3442
71
+ gibson/core/CommandRouter.py,sha256=WiTQJ2HwIoWOcoT0yL_7wXClOWqPSdWP5eoOd1f1tWw,3698
70
72
  gibson/core/Completions.py,sha256=a26WRh40UpnTT5HGTPT8TCcL8h80HvvZiTJXZofDjx8,1207
71
- gibson/core/Configuration.py,sha256=5nO4hY1MvVQapt37RbwrJpc9zwUx6u86n1BRRbIgjUQ,16586
73
+ gibson/core/Configuration.py,sha256=eBGBoCe4rrBxlAUg0-UhKwrQSnyxFoey5jC_FeaGlCI,16689
72
74
  gibson/core/Conversation.py,sha256=KF7YPXijhhz6HOkife__ycHox4WeRKNHIpv3juDPhq0,10237
73
75
  gibson/core/Diff.py,sha256=onUJ5_0_S1vKAY_oFgX4vmwQo4byrnXLV4w7QSNA8fY,1071
74
76
  gibson/core/Env.py,sha256=08dZRHzzR0ahrbM4S0bXC7V1xhYQkT8Zefs00qUHf0U,498
75
77
  gibson/core/Memory.py,sha256=3ItGef4RCfBplbjxhNyid8eiPVKHmW-DKAMFeYujqN0,4063
76
- gibson/core/PythonPath.py,sha256=p1q7n_5KnPvA8XbxJyvqC2vrIdEdTiMr6vRU9yj77Cs,1567
78
+ gibson/core/PythonPath.py,sha256=0Pj9VUmN-lbv_jGJjjI9UreU4JCdHPdRHSpxQDBrKQw,1577
79
+ gibson/core/Select.py,sha256=8Ax8-rpK3BNrSAlSSSKpv1_uqQuwfy_4kNz7IJoZkjc,8510
77
80
  gibson/core/Spinner.py,sha256=_BO26dOa3h0ZCNaPgMvwOh7K6DUiDv8LgP7QMR3EvNw,1225
78
81
  gibson/core/TimeKeeper.py,sha256=dSeIgGOQJOi0ULlFGAigroGTBfAZXrvP9a1Op_jIsZ0,300
79
82
  gibson/core/utils.py,sha256=KTnPvA3sUYnLFTZG7Tke5YEdls8Da0rNbeaOm8hapiU,408
@@ -122,15 +125,15 @@ gibson/structure/postgresql/Entity.py,sha256=eBHsHlvOLZXiU8uxwhfF66GdCz-Fou0kShs
122
125
  gibson/structure/postgresql/References.py,sha256=ILNs88AriVGYJuYOfwS7d5aZeFe5TNuHNqI6lb4kOos,1771
123
126
  gibson/structure/postgresql/testing.py,sha256=znghwbXOGZdzp7JF1YBNvZDAqg8GevXr-ZxX_ZaS1m8,6091
124
127
  gibson/structure/postgresql/table/ForeignKey.py,sha256=HKu4JwwKmeAZJaYTWK5sSoJMEPr0XS017WXux55O0a8,704
125
- gibson/structure/postgresql/table/tests/test_structure_postgresql_table_ForeignKey.py,sha256=ALaJt7S1K575xJw-5aH_mupYd4nKtUXVqYI1bLH6S-Q,1367
128
+ gibson/structure/postgresql/table/tests/test_structure_postgresql_table_ForeignKey.py,sha256=ArSGydHlHBQnylMsGWx1h8AGsE9_cqcn6lF-F9uilmM,1352
126
129
  gibson/structure/postgresql/tests/test_structure_postgresql_Entity.py,sha256=PzQwOHJg7q4awmOawlViJi2RDyDX5iKaG6o7H-SMbNE,2622
127
130
  gibson/structure/tests/test_structure_Entity.py,sha256=askl8w0p1uqET6HKBogJlRcPPwKEVa9HjeYlMk3ah8E,635
128
131
  gibson/tests/test_Env.py,sha256=DPWmP0-aEelducq9bAwv7rKoY2NjWXUeCrzfJDQkn2M,369
129
132
  gibson/tests/test_Memory.py,sha256=YP7owToABAk_-s7fD5UG0HTc4lamDjdA39JUlLnk3Fg,2574
130
133
  gibson/tests/test_utils.py,sha256=r_y-EG05YTCNtL8MWiAK1KmPsmeoMgypKsQC_lVgOtM,559
131
134
  venv/bin/activate_this.py,sha256=E1T7r3559tBsyqFpdcQW0HbY7gDvNiIv5Pc6HQ4bpoA,2383
132
- gibson_cli-0.8.8.dist-info/METADATA,sha256=DORMMl7yzYRQWEnQn1Tnnv2i5AEcWfgyn_DTVxBCyGw,14562
133
- gibson_cli-0.8.8.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
134
- gibson_cli-0.8.8.dist-info/entry_points.txt,sha256=j5VUvq3AzL21xPvVC24zMoXFt-I5lUWulr66nL3OAPM,50
135
- gibson_cli-0.8.8.dist-info/top_level.txt,sha256=fSV3vegbdbSDwiB6n5z3FCeYwkIonzFrx4ek3F_OSdI,16
136
- gibson_cli-0.8.8.dist-info/RECORD,,
135
+ gibson_cli-0.8.10.dist-info/METADATA,sha256=5Rz6qup5c7MX09nxiEi3xKUgEnChRIsVHqy-pLU45WM,14645
136
+ gibson_cli-0.8.10.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
137
+ gibson_cli-0.8.10.dist-info/entry_points.txt,sha256=j5VUvq3AzL21xPvVC24zMoXFt-I5lUWulr66nL3OAPM,50
138
+ gibson_cli-0.8.10.dist-info/top_level.txt,sha256=fSV3vegbdbSDwiB6n5z3FCeYwkIonzFrx4ek3F_OSdI,16
139
+ gibson_cli-0.8.10.dist-info/RECORD,,