bindai-cli 0.1.8__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of bindai-cli might be problematic. Click here for more details.

Files changed (73) hide show
  1. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/PKG-INFO +4 -11
  2. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/README.md +1 -9
  3. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/pyproject.toml +4 -3
  4. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/app.py +15 -4
  5. bindai_cli-0.2.0/src/bindai_cli/commands/config.py +204 -0
  6. bindai_cli-0.2.0/src/bindai_cli/commands/connections.py +144 -0
  7. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/commands/doctor.py +53 -0
  8. bindai_cli-0.2.0/src/bindai_cli/commands/new.py +116 -0
  9. bindai_cli-0.2.0/src/bindai_cli/scaffolds/basic/requirements.txt +1 -0
  10. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli.egg-info/PKG-INFO +4 -11
  11. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli.egg-info/SOURCES.txt +4 -0
  12. bindai_cli-0.2.0/src/bindai_cli.egg-info/requires.txt +5 -0
  13. bindai_cli-0.2.0/tests/test_config.py +461 -0
  14. bindai_cli-0.2.0/tests/test_connections.py +416 -0
  15. bindai_cli-0.2.0/tests/test_doctor.py +170 -0
  16. bindai_cli-0.2.0/tests/test_new.py +208 -0
  17. bindai_cli-0.1.8/src/bindai_cli/commands/new.py +0 -80
  18. bindai_cli-0.1.8/src/bindai_cli/scaffolds/basic/requirements.txt +0 -1
  19. bindai_cli-0.1.8/src/bindai_cli.egg-info/requires.txt +0 -4
  20. bindai_cli-0.1.8/tests/test_doctor.py +0 -60
  21. bindai_cli-0.1.8/tests/test_new.py +0 -64
  22. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/setup.cfg +0 -0
  23. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/__init__.py +0 -0
  24. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/__main__.py +0 -0
  25. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/commands/__init__.py +0 -0
  26. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/commands/add.py +0 -0
  27. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/commands/inspect.py +0 -0
  28. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/commands/run.py +0 -0
  29. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/commands/template.py +0 -0
  30. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/commands/version.py +0 -0
  31. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/commands/workflow.py +0 -0
  32. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/generators/__init__.py +0 -0
  33. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/generators/agent.py +0 -0
  34. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/generators/directories.py +0 -0
  35. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/generators/knowledge.py +0 -0
  36. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/generators/memory.py +0 -0
  37. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/generators/pyproject.py +0 -0
  38. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/generators/tool.py +0 -0
  39. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/generators/workflow.py +0 -0
  40. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/inspectors/project.py +0 -0
  41. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/scaffolds/basic/.env.example +0 -0
  42. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/scaffolds/basic/.gitignore +0 -0
  43. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/scaffolds/basic/LICENSE +0 -0
  44. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/scaffolds/basic/README.md +0 -0
  45. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/scaffolds/basic/__pycache__/main.cpython-314.pyc +0 -0
  46. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/scaffolds/basic/agents/__pycache__/assistant.cpython-314.pyc +0 -0
  47. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/scaffolds/basic/agents/assistant.py +0 -0
  48. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/scaffolds/basic/bindai.toml +0 -0
  49. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/scaffolds/basic/knowledge/.gitkeep +0 -0
  50. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/scaffolds/basic/main.py +0 -0
  51. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/scaffolds/basic/memory/.gitkeep +0 -0
  52. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/scaffolds/basic/templates/.gitkeep +0 -0
  53. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/scaffolds/basic/tests/.gitkeep +0 -0
  54. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/scaffolds/basic/tools/.gitkeep +0 -0
  55. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/scaffolds/basic/tools/__pycache__/echo.cpython-314.pyc +0 -0
  56. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/scaffolds/basic/tools/echo.py +0 -0
  57. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/scaffolds/basic/workflows/.gitkeep +0 -0
  58. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/templates/installer.py +0 -0
  59. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/templates/models.py +0 -0
  60. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/templates/registry.py +0 -0
  61. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/templates/validator.py +0 -0
  62. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/templates/workflow-basic/template.json +0 -0
  63. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/utils/config.py +0 -0
  64. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/utils/providers.py +0 -0
  65. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/utils/scaffold.py +0 -0
  66. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/workflows/graph.py +0 -0
  67. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli/workflows/validator.py +0 -0
  68. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli.egg-info/dependency_links.txt +0 -0
  69. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli.egg-info/entry_points.txt +0 -0
  70. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/src/bindai_cli.egg-info/top_level.txt +0 -0
  71. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/tests/test_app.py +0 -0
  72. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/tests/test_run.py +0 -0
  73. {bindai_cli-0.1.8 → bindai_cli-0.2.0}/tests/test_templates.py +0 -0
@@ -1,13 +1,14 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bindai-cli
3
- Version: 0.1.8
3
+ Version: 0.2.0
4
4
  Summary: BindAI Command Line Interface
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
7
7
  Requires-Dist: typer>=0.16
8
8
  Requires-Dist: rich>=14.0
9
9
  Requires-Dist: python-dotenv>=1.0
10
- Requires-Dist: bindai-config>=0.1.2
10
+ Requires-Dist: bindai-config>=0.2.0
11
+ Requires-Dist: bindai-connections[credentials]>=0.2.0
11
12
 
12
13
  # BindAI CLI
13
14
 
@@ -19,7 +20,7 @@ The CLI is designed to provide a convenient developer workflow around the BindAI
19
20
 
20
21
  The BindAI CLI provides commands for common development tasks, including:
21
22
 
22
- * Project initialization
23
+ * Project creation
23
24
  * Project scaffolding
24
25
  * BindAI environment inspection
25
26
  * Framework diagnostics
@@ -63,14 +64,6 @@ Inspect the current BindAI environment or project:
63
64
  bindai inspect
64
65
  ```
65
66
 
66
- ### Initialize
67
-
68
- Initialize a BindAI project:
69
-
70
- ```bash
71
- bindai init
72
- ```
73
-
74
67
  ### Create a Project
75
68
 
76
69
  Create a new BindAI project:
@@ -8,7 +8,7 @@ The CLI is designed to provide a convenient developer workflow around the BindAI
8
8
 
9
9
  The BindAI CLI provides commands for common development tasks, including:
10
10
 
11
- * Project initialization
11
+ * Project creation
12
12
  * Project scaffolding
13
13
  * BindAI environment inspection
14
14
  * Framework diagnostics
@@ -52,14 +52,6 @@ Inspect the current BindAI environment or project:
52
52
  bindai inspect
53
53
  ```
54
54
 
55
- ### Initialize
56
-
57
- Initialize a BindAI project:
58
-
59
- ```bash
60
- bindai init
61
- ```
62
-
63
55
  ### Create a Project
64
56
 
65
57
  Create a new BindAI project:
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "bindai-cli"
3
- version = "0.1.8"
3
+ version = "0.2.0"
4
4
  description = "BindAI Command Line Interface"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -9,7 +9,8 @@ dependencies = [
9
9
  "typer>=0.16",
10
10
  "rich>=14.0",
11
11
  "python-dotenv>=1.0",
12
- "bindai-config>=0.1.2",
12
+ "bindai-config>=0.2.0",
13
+ "bindai-connections[credentials]>=0.2.0",
13
14
  ]
14
15
 
15
16
  [project.scripts]
@@ -27,4 +28,4 @@ bindai_cli = [
27
28
  "templates/*/template.json",
28
29
  "scaffolds/**/*",
29
30
  "scaffolds/**/.*",
30
- ]
31
+ ]
@@ -1,8 +1,10 @@
1
1
  import typer
2
2
 
3
+ from bindai_cli.commands.config import app as config_app
4
+ from bindai_cli.commands.connections import app as connections_app
3
5
  from bindai_cli.commands.doctor import app as doctor_app
4
6
  from bindai_cli.commands.inspect import app as inspect_app
5
- from bindai_cli.commands.new import app as new_app
7
+ from bindai_cli.commands.new import new
6
8
  from bindai_cli.commands.run import app as run_app
7
9
  from bindai_cli.commands.template import app as template_app
8
10
  from bindai_cli.commands.version import app as version_app
@@ -23,10 +25,9 @@ app.add_typer(
23
25
  name="doctor",
24
26
  )
25
27
 
26
- app.add_typer(
27
- new_app,
28
+ app.command(
28
29
  name="new",
29
- )
30
+ )(new)
30
31
 
31
32
  app.add_typer(
32
33
  run_app,
@@ -47,3 +48,13 @@ app.add_typer(
47
48
  inspect_app,
48
49
  name="inspect",
49
50
  )
51
+
52
+ app.add_typer(
53
+ config_app,
54
+ name="config",
55
+ )
56
+
57
+ app.add_typer(
58
+ connections_app,
59
+ name="connections",
60
+ )
@@ -0,0 +1,204 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import fields
4
+ from pathlib import Path
5
+ from typing import Any, get_args, get_type_hints
6
+
7
+ import typer
8
+ from bindai_config import ProjectConfig, ProjectRuntime, TomlWriter
9
+ from rich.console import Console
10
+ from rich.table import Table
11
+
12
+ app = typer.Typer(
13
+ help="Inspect and modify BindAI project configuration.",
14
+ no_args_is_help=True,
15
+ )
16
+
17
+ console = Console()
18
+
19
+
20
+ @app.command(name="list")
21
+ def list_config() -> None:
22
+ """
23
+ List effective project configuration and its source.
24
+ """
25
+ runtime = ProjectRuntime(Path.cwd())
26
+ values = runtime.resolver.all()
27
+
28
+ table = Table(title="Configuration")
29
+ table.add_column("Name", style="cyan")
30
+ table.add_column("Value")
31
+ table.add_column("Source")
32
+
33
+ for name, config_value in values.items():
34
+ table.add_row(
35
+ name,
36
+ str(config_value.value),
37
+ config_value.source,
38
+ )
39
+
40
+ console.print(table)
41
+
42
+
43
+ @app.command(name="get")
44
+ def get_config(
45
+ name: str = typer.Argument(
46
+ ...,
47
+ help="Configuration field to inspect.",
48
+ ),
49
+ ) -> None:
50
+ """
51
+ Show one effective configuration value and its source.
52
+ """
53
+ runtime = ProjectRuntime(Path.cwd())
54
+
55
+ try:
56
+ config_value = runtime.resolver.resolve(name)
57
+ except KeyError as exc:
58
+ raise typer.BadParameter(
59
+ f'Unknown configuration field "{name}".',
60
+ ) from exc
61
+
62
+ console.print(f"{name} = {config_value.value}")
63
+ console.print(f"source = {config_value.source}")
64
+
65
+
66
+ @app.command(name="set")
67
+ def set_config(
68
+ name: str = typer.Argument(
69
+ ...,
70
+ help="Configuration field to update.",
71
+ ),
72
+ value: str = typer.Argument(
73
+ ...,
74
+ help="Value to persist in bindai.toml.",
75
+ ),
76
+ ) -> None:
77
+ """
78
+ Set one project configuration value in bindai.toml.
79
+ """
80
+ config_path = Path.cwd() / "bindai.toml"
81
+
82
+ if not config_path.exists():
83
+ raise typer.BadParameter(
84
+ f'No bindai.toml found in "{Path.cwd()}".',
85
+ )
86
+
87
+ try:
88
+ expected_type = _field_type(name)
89
+ converted_value = _convert_value(
90
+ name,
91
+ value,
92
+ expected_type,
93
+ )
94
+ except KeyError as exc:
95
+ raise typer.BadParameter(str(exc).strip("'")) from exc
96
+ except ValueError as exc:
97
+ raise typer.BadParameter(str(exc)) from exc
98
+
99
+ try:
100
+ TomlWriter().set(
101
+ config_path,
102
+ name,
103
+ converted_value,
104
+ )
105
+ except (TypeError, ValueError) as exc:
106
+ raise typer.BadParameter(str(exc)) from exc
107
+
108
+ console.print(
109
+ f'Set {name} = {converted_value!r} in {config_path.name}.',
110
+ )
111
+
112
+
113
+ @app.command(name="path")
114
+ def config_path() -> None:
115
+ """
116
+ Show the path to the active bindai.toml file.
117
+ """
118
+ config_path = Path.cwd() / "bindai.toml"
119
+
120
+ if not config_path.exists():
121
+ raise typer.BadParameter(
122
+ f'No bindai.toml found in "{Path.cwd()}".',
123
+ )
124
+
125
+ console.print(config_path.resolve())
126
+
127
+
128
+ def _field_type(name: str) -> Any:
129
+ config_fields = {
130
+ field.name: field
131
+ for field in fields(ProjectConfig)
132
+ }
133
+
134
+ if name not in config_fields:
135
+ raise KeyError(
136
+ f'Unknown configuration field "{name}".'
137
+ )
138
+
139
+ return get_type_hints(ProjectConfig)[name]
140
+
141
+
142
+ def _convert_value(
143
+ name: str,
144
+ value: str,
145
+ expected_type: Any,
146
+ ) -> Any:
147
+ expected_types = get_args(expected_type)
148
+
149
+ if expected_types:
150
+ non_none_types = tuple(
151
+ item
152
+ for item in expected_types
153
+ if item is not type(None)
154
+ )
155
+
156
+ if len(non_none_types) == 1:
157
+ return _convert_value(
158
+ name,
159
+ value,
160
+ non_none_types[0],
161
+ )
162
+
163
+ raise ValueError(
164
+ f'Unsupported configuration type for "{name}".',
165
+ )
166
+
167
+ if expected_type is str:
168
+ return value
169
+
170
+ if expected_type is int:
171
+ try:
172
+ return int(value)
173
+ except ValueError as exc:
174
+ raise ValueError(
175
+ f'Invalid value for "{name}": '
176
+ f'expected an integer, got "{value}".',
177
+ ) from exc
178
+
179
+ if expected_type is float:
180
+ try:
181
+ return float(value)
182
+ except ValueError as exc:
183
+ raise ValueError(
184
+ f'Invalid value for "{name}": '
185
+ f'expected a number, got "{value}".',
186
+ ) from exc
187
+
188
+ if expected_type is bool:
189
+ normalized = value.strip().lower()
190
+
191
+ if normalized in {"1", "true", "yes", "on"}:
192
+ return True
193
+
194
+ if normalized in {"0", "false", "no", "off"}:
195
+ return False
196
+
197
+ raise ValueError(
198
+ f'Invalid value for "{name}": '
199
+ f'expected a boolean, got "{value}".',
200
+ )
201
+
202
+ raise ValueError(
203
+ f'Unsupported configuration type for "{name}".',
204
+ )
@@ -0,0 +1,144 @@
1
+ from __future__ import annotations
2
+
3
+ from pathlib import Path
4
+
5
+ import typer
6
+ from bindai_config import get_provider_connection
7
+ from bindai_connections import (
8
+ ConnectionManifest,
9
+ KeyringProviderCredentialStore,
10
+ )
11
+ from rich.console import Console
12
+ from rich.table import Table
13
+
14
+ app = typer.Typer(
15
+ help="Manage provider connections.",
16
+ no_args_is_help=True,
17
+ )
18
+
19
+ console = Console()
20
+
21
+
22
+ @app.command(name="add")
23
+ def add_connection(
24
+ provider: str = typer.Argument(
25
+ ...,
26
+ help="Provider to connect.",
27
+ ),
28
+ name: str | None = typer.Option(
29
+ None,
30
+ "--name",
31
+ help="Connection name. Defaults to the provider name.",
32
+ ),
33
+ ) -> None:
34
+ """
35
+ Store a connection credential and register its non-secret metadata.
36
+ """
37
+ provider_name = provider.strip().lower()
38
+
39
+ try:
40
+ get_provider_connection(provider_name)
41
+ except KeyError as exc:
42
+ raise typer.BadParameter(
43
+ str(exc).strip("'"),
44
+ ) from exc
45
+
46
+ connection_name = (
47
+ name.strip().lower()
48
+ if name is not None
49
+ else provider_name
50
+ )
51
+
52
+ if not connection_name:
53
+ raise typer.BadParameter(
54
+ "Connection name cannot be empty.",
55
+ )
56
+
57
+ credential = typer.prompt(
58
+ "Credential",
59
+ hide_input=True,
60
+ )
61
+
62
+ store = KeyringProviderCredentialStore()
63
+ manifest = ConnectionManifest(
64
+ Path.cwd() / ".bindai" / "connections.toml",
65
+ )
66
+
67
+ store.set(
68
+ connection_name,
69
+ credential,
70
+ )
71
+
72
+ manifest.add(
73
+ connection_name,
74
+ provider_name,
75
+ )
76
+
77
+ console.print(
78
+ f'Connection "{connection_name}" added for provider '
79
+ f'"{provider_name}".',
80
+ )
81
+
82
+
83
+ @app.command(name="list")
84
+ def list_connections() -> None:
85
+ """
86
+ List configured provider connections and credential status.
87
+ """
88
+ manifest = ConnectionManifest(
89
+ Path.cwd() / ".bindai" / "connections.toml",
90
+ )
91
+ store = KeyringProviderCredentialStore()
92
+
93
+ connections = manifest.list()
94
+
95
+ table = Table(title="BindAI Connections")
96
+
97
+ table.add_column("Name", style="cyan")
98
+ table.add_column("Provider")
99
+ table.add_column("Credential")
100
+
101
+ for connection in connections:
102
+ credential_status = (
103
+ "Configured"
104
+ if store.exists(connection.name)
105
+ else "Missing"
106
+ )
107
+
108
+ table.add_row(
109
+ connection.name,
110
+ connection.provider,
111
+ credential_status,
112
+ )
113
+
114
+ console.print(table)
115
+
116
+
117
+ @app.command(name="remove")
118
+ def remove_connection(
119
+ name: str = typer.Argument(
120
+ ...,
121
+ help="Connection name to remove.",
122
+ ),
123
+ ) -> None:
124
+ """
125
+ Remove a named provider connection and its stored credential.
126
+ """
127
+ manifest = ConnectionManifest(
128
+ Path.cwd() / ".bindai" / "connections.toml",
129
+ )
130
+ store = KeyringProviderCredentialStore()
131
+
132
+ connection = manifest.get(name)
133
+
134
+ if connection is None:
135
+ raise typer.BadParameter(
136
+ f'Connection "{name}" not found.',
137
+ )
138
+
139
+ store.delete(connection.name)
140
+ manifest.remove(connection.name)
141
+
142
+ console.print(
143
+ f'Connection "{connection.name}" removed.',
144
+ )
@@ -3,8 +3,13 @@ from __future__ import annotations
3
3
  import os
4
4
  import platform
5
5
  import sys
6
+ from pathlib import Path
6
7
 
7
8
  import typer
9
+ from bindai_connections import (
10
+ ConnectionManifest,
11
+ KeyringProviderCredentialStore,
12
+ )
8
13
  from dotenv import load_dotenv
9
14
  from rich.console import Console
10
15
  from rich.table import Table
@@ -64,6 +69,11 @@ def doctor() -> None:
64
69
  table.add_row("Default Provider", config.provider)
65
70
 
66
71
  table.add_row("Default Model", config.model)
72
+
73
+ _add_connection_checks(
74
+ table,
75
+ config.connection,
76
+ )
67
77
  else:
68
78
  table.add_row(
69
79
  "Configuration",
@@ -120,3 +130,46 @@ def doctor() -> None:
120
130
  )
121
131
 
122
132
  console.print(table)
133
+
134
+
135
+ def _add_connection_checks(
136
+ table: Table,
137
+ connection_name: str | None,
138
+ ) -> None:
139
+ if connection_name is None:
140
+ table.add_row(
141
+ "Connection",
142
+ "Not configured",
143
+ )
144
+ return
145
+
146
+ table.add_row(
147
+ "Connection",
148
+ connection_name,
149
+ )
150
+
151
+ manifest = ConnectionManifest(
152
+ Path.cwd() / ".bindai" / "connections.toml",
153
+ )
154
+
155
+ connection = manifest.get(connection_name)
156
+
157
+ if connection is None:
158
+ table.add_row(
159
+ "Connection Credential",
160
+ "Connection not configured",
161
+ )
162
+ return
163
+
164
+ store = KeyringProviderCredentialStore()
165
+
166
+ if store.exists(connection.name):
167
+ table.add_row(
168
+ "Connection Credential",
169
+ "Configured",
170
+ )
171
+ else:
172
+ table.add_row(
173
+ "Connection Credential",
174
+ "Missing",
175
+ )
@@ -0,0 +1,116 @@
1
+ import os
2
+ import subprocess
3
+ import sys
4
+ from pathlib import Path
5
+
6
+ import typer
7
+ from rich.console import Console
8
+
9
+ from bindai_cli.utils.scaffold import copy_scaffold
10
+
11
+ console = Console()
12
+
13
+
14
+ def _venv_python(root: Path) -> Path:
15
+ bin_dir = "Scripts" if os.name == "nt" else "bin"
16
+ return root / ".venv" / bin_dir / "python"
17
+
18
+
19
+ def _activation_command() -> str:
20
+ if os.name == "nt":
21
+ return ".venv\\Scripts\\activate"
22
+ return "source .venv/bin/activate"
23
+
24
+
25
+ def new(
26
+ name: str,
27
+ install: bool = typer.Option(
28
+ False,
29
+ "--install",
30
+ help="Install dependencies.",
31
+ ),
32
+ ) -> None:
33
+ """
34
+ Create a new BindAI project.
35
+ """
36
+
37
+ root = Path(name)
38
+
39
+ if root.exists():
40
+ console.print(f"[red]Project '{name}' already exists.[/red]")
41
+ raise typer.Exit(1)
42
+
43
+ scaffold = Path(__file__).parent.parent / "scaffolds" / "basic"
44
+
45
+ copy_scaffold(
46
+ scaffold,
47
+ root,
48
+ )
49
+
50
+ console.print("[cyan]Creating virtual environment...[/cyan]")
51
+
52
+ try:
53
+ subprocess.run(
54
+ [
55
+ sys.executable,
56
+ "-m",
57
+ "venv",
58
+ str(root / ".venv"),
59
+ ],
60
+ check=True,
61
+ )
62
+ except subprocess.CalledProcessError as exc:
63
+ console.print(
64
+ "[red]Failed to create the virtual environment.[/red]"
65
+ )
66
+ console.print(
67
+ f"Project '{name}' was created, but setup is incomplete."
68
+ )
69
+ console.print(f"Command exited with status {exc.returncode}.")
70
+ raise typer.Exit(1) from exc
71
+
72
+ print()
73
+
74
+ if install:
75
+ console.print("[cyan]Installing dependencies...[/cyan]")
76
+
77
+ try:
78
+ subprocess.run(
79
+ [
80
+ str(_venv_python(root)),
81
+ "-m",
82
+ "pip",
83
+ "install",
84
+ "-r",
85
+ str(root / "requirements.txt"),
86
+ ],
87
+ check=True,
88
+ )
89
+ except subprocess.CalledProcessError as exc:
90
+ console.print(
91
+ "[red]Failed to install project dependencies.[/red]"
92
+ )
93
+ console.print(
94
+ f"Project '{name}' was created, but setup is incomplete."
95
+ )
96
+ console.print(f"Command exited with status {exc.returncode}.")
97
+ raise typer.Exit(1) from exc
98
+
99
+ print()
100
+
101
+ console.print(
102
+ f"[green]✓ Project '{name}' created successfully.[/green]"
103
+ )
104
+
105
+ print()
106
+
107
+ console.print("[bold]Next steps:[/bold]")
108
+
109
+ console.print(f" cd {name}")
110
+ console.print(f" {_activation_command()}")
111
+
112
+ if not install:
113
+ console.print(" pip install -r requirements.txt")
114
+
115
+ console.print(" bindai doctor")
116
+ console.print(" python main.py")
@@ -0,0 +1 @@
1
+ bindai[openai]>=0.1.6
@@ -1,13 +1,14 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bindai-cli
3
- Version: 0.1.8
3
+ Version: 0.2.0
4
4
  Summary: BindAI Command Line Interface
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
7
7
  Requires-Dist: typer>=0.16
8
8
  Requires-Dist: rich>=14.0
9
9
  Requires-Dist: python-dotenv>=1.0
10
- Requires-Dist: bindai-config>=0.1.2
10
+ Requires-Dist: bindai-config>=0.2.0
11
+ Requires-Dist: bindai-connections[credentials]>=0.2.0
11
12
 
12
13
  # BindAI CLI
13
14
 
@@ -19,7 +20,7 @@ The CLI is designed to provide a convenient developer workflow around the BindAI
19
20
 
20
21
  The BindAI CLI provides commands for common development tasks, including:
21
22
 
22
- * Project initialization
23
+ * Project creation
23
24
  * Project scaffolding
24
25
  * BindAI environment inspection
25
26
  * Framework diagnostics
@@ -63,14 +64,6 @@ Inspect the current BindAI environment or project:
63
64
  bindai inspect
64
65
  ```
65
66
 
66
- ### Initialize
67
-
68
- Initialize a BindAI project:
69
-
70
- ```bash
71
- bindai init
72
- ```
73
-
74
67
  ### Create a Project
75
68
 
76
69
  Create a new BindAI project: