restructure cli (#656)

This commit is contained in:
Adil Hafeez 2025-12-25 14:55:29 -08:00 committed by GitHub
parent a56bb9d190
commit 88d14a205b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
45 changed files with 153 additions and 115 deletions

View file

@ -9,7 +9,7 @@ on:
- main
jobs:
# Build ARM64 image on native ARM64 runner
# Build ARM64 image on native ARM64 runner.
build-arm64:
runs-on: [linux-arm64]
steps:
@ -34,7 +34,7 @@ jobs:
uses: docker/build-push-action@v5
with:
context: .
file: ./arch/Dockerfile
file: ./Dockerfile
platforms: linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}-arm64
@ -64,7 +64,7 @@ jobs:
uses: docker/build-push-action@v5
with:
context: .
file: ./arch/Dockerfile
file: ./Dockerfile
platforms: linux/amd64
push: true
tags: ${{ steps.meta.outputs.tags }}-amd64

View file

@ -33,7 +33,7 @@ jobs:
uses: docker/build-push-action@v5
with:
context: .
file: ./arch/Dockerfile
file: ./Dockerfile
platforms: linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}-arm64
@ -63,7 +63,7 @@ jobs:
uses: docker/build-push-action@v5
with:
context: .
file: ./arch/Dockerfile
file: ./Dockerfile
platforms: linux/amd64
push: true
tags: ${{ steps.meta.outputs.tags }}-amd64

View file

@ -30,7 +30,7 @@ jobs:
- name: build arch docker image
run: |
cd ../../ && docker build -f arch/Dockerfile . -t katanemo/plano -t katanemo/plano:0.4.0 -t katanemo/plano:latest
cd ../../ && docker build -f Dockerfile . -t katanemo/plano -t katanemo/plano:0.4.0 -t katanemo/plano:latest
- name: start plano
env:

View file

@ -24,7 +24,7 @@ jobs:
- name: build plano docker image
run: |
docker build -f arch/Dockerfile . -t katanemo/plano -t katanemo/plano:0.4.0
docker build -f Dockerfile . -t katanemo/plano -t katanemo/plano:0.4.0
- name: install poetry
run: |
@ -43,8 +43,8 @@ jobs:
- name: install arch gateway and test dependencies
run: |
source venv/bin/activate
cd arch/tools && echo "installing plano cli" && poetry install
cd ../../demos/shared/test_runner && echo "installing test dependencies" && poetry install
cd cli && echo "installing plano cli" && poetry install
cd ../demos/shared/test_runner && echo "installing test dependencies" && poetry install
- name: run demo tests
env:

View file

@ -24,7 +24,7 @@ jobs:
- name: build arch docker image
run: |
docker build -f arch/Dockerfile . -t katanemo/plano -t katanemo/plano:0.4.0
docker build -f Dockerfile . -t katanemo/plano -t katanemo/plano:0.4.0
- name: install poetry
run: |
@ -43,8 +43,8 @@ jobs:
- name: install arch gateway and test dependencies
run: |
source venv/bin/activate
cd arch/tools && echo "installing plano cli" && poetry install
cd ../../demos/shared/test_runner && echo "installing test dependencies" && poetry install
cd cli && echo "installing plano cli" && poetry install
cd ../demos/shared/test_runner && echo "installing test dependencies" && poetry install
- name: run demo tests
env:

View file

@ -30,7 +30,7 @@ jobs:
uses: docker/build-push-action@v5
with:
context: .
file: ./arch/Dockerfile
file: ./Dockerfile
platforms: linux/arm64
push: true
# produce ghcr.io/<owner>/plano:latest-arm64
@ -58,7 +58,7 @@ jobs:
uses: docker/build-push-action@v5
with:
context: .
file: ./arch/Dockerfile
file: ./Dockerfile
platforms: linux/amd64
push: true
tags: ${{ steps.meta.outputs.tags }}-amd64

View file

@ -30,7 +30,7 @@ jobs:
uses: docker/build-push-action@v5
with:
context: .
file: ./arch/Dockerfile
file: ./Dockerfile
platforms: linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}-arm64
@ -57,7 +57,7 @@ jobs:
uses: docker/build-push-action@v5
with:
context: .
file: ./arch/Dockerfile
file: ./Dockerfile
platforms: linux/amd64
push: true
tags: ${{ steps.meta.outputs.tags }}-amd64

View file

@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest-m
defaults:
run:
working-directory: ./arch/tools
working-directory: ./cli
steps:
- name: Checkout code

View file

@ -24,8 +24,8 @@ jobs:
- name: build arch docker image
run: |
docker build -f arch/Dockerfile . -t katanemo/plano -t katanemo/plano:0.4.0
docker build -f Dockerfile . -t katanemo/plano -t katanemo/plano:0.4.0
- name: validate arch config
run: |
bash arch/validate_plano_config.sh
bash config/validate_plano_config.sh

4
.gitignore vendored
View file

@ -108,8 +108,8 @@ venv.bak/
# =========================================
# Arch
arch/tools/config
arch/tools/build
cli/config
cli/build
# Archgw - Docs
docs/build/

View file

@ -3,7 +3,7 @@ repos:
rev: v4.6.0
hooks:
- id: check-yaml
exclude: arch/envoy.template*
exclude: config/envoy.template*
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: local

View file

@ -30,12 +30,12 @@ COPY --from=builder /arch/target/release/brightstaff /app/brightstaff
COPY --from=envoy /usr/local/bin/envoy /usr/local/bin/envoy
WORKDIR /app
COPY arch/requirements.txt .
COPY config/requirements.txt .
RUN pip install -r requirements.txt
COPY arch/tools .
COPY arch/envoy.template.yaml .
COPY arch/arch_config_schema.yaml .
COPY arch/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY cli .
COPY config/envoy.template.yaml .
COPY config/arch_config_schema.yaml .
COPY config/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
RUN pip install requests
RUN mkdir -p /var/log/supervisor && touch /var/log/envoy.log /var/log/supervisor/supervisord.log

View file

@ -233,10 +233,10 @@ endpoints:
```sh
$ planoai up plano_config.yaml
2024-12-05 16:56:27,979 - cli.main - INFO - Starting plano cli version: 0.4.0
2024-12-05 16:56:28,485 - cli.utils - INFO - Schema validation successful!
2024-12-05 16:56:28,485 - cli.main - INFO - Starting plano model server and plano gateway
2024-12-05 16:56:51,647 - cli.core - INFO - Container is healthy!
2024-12-05 16:56:27,979 - planoai.main - INFO - Starting plano cli version: 0.4.0
2024-12-05 16:56:28,485 - planoai.utils - INFO - Schema validation successful!
2024-12-05 16:56:28,485 - planoai.main - INFO - Starting plano model server and plano gateway
2024-12-05 16:56:51,647 - planoai.core - INFO - Container is healthy!
```
Once the gateway is up you can start interacting with it at port `10000` using the OpenAI chat completion API.

View file

@ -10,7 +10,7 @@
},
{
"name": "archgw_cli",
"path": "arch/tools"
"path": "cli"
},
{
"name": "tests_e2e",

View file

@ -1 +1 @@
docker build -f arch/Dockerfile . -t katanemo/plano -t katanemo/plano:0.4.0
docker build -f Dockerfile . -t katanemo/plano -t katanemo/plano:0.4.0

View file

@ -1,6 +1,6 @@
import json
import os
from cli.utils import convert_legacy_listeners
from planoai.utils import convert_legacy_listeners
from jinja2 import Environment, FileSystemLoader
import yaml
from jsonschema import validate

View file

@ -5,13 +5,13 @@ import time
import sys
import yaml
from cli.utils import convert_legacy_listeners, getLogger
from cli.consts import (
from planoai.utils import convert_legacy_listeners, getLogger
from planoai.consts import (
PLANO_DOCKER_IMAGE,
PLANO_DOCKER_NAME,
)
import subprocess
from cli.docker_cli import (
from planoai.docker_cli import (
docker_container_status,
docker_remove_container,
docker_start_plano_detached,

View file

@ -3,11 +3,11 @@ import json
import sys
import requests
from cli.consts import (
from planoai.consts import (
PLANO_DOCKER_IMAGE,
PLANO_DOCKER_NAME,
)
from cli.utils import getLogger
from planoai.utils import getLogger
log = getLogger(__name__)
@ -127,7 +127,7 @@ def docker_validate_plano_schema(arch_config_file):
"python",
PLANO_DOCKER_IMAGE,
"-m",
"cli.config_generator",
"planoai.config_generator",
],
capture_output=True,
text=True,

View file

@ -5,26 +5,27 @@ import subprocess
import multiprocessing
import importlib.metadata
import json
from cli import targets
from cli.docker_cli import (
from planoai import targets
from planoai.docker_cli import (
docker_validate_plano_schema,
stream_gateway_logs,
docker_container_status,
)
from cli.utils import (
from planoai.utils import (
getLogger,
get_llm_provider_access_keys,
has_ingress_listener,
load_env_file_to_dict,
stream_access_logs,
find_config_file,
find_repo_root,
)
from cli.core import (
from planoai.core import (
start_arch,
stop_docker_container,
start_cli_agent,
)
from cli.consts import (
from planoai.consts import (
PLANO_DOCKER_IMAGE,
PLANO_DOCKER_NAME,
SERVICE_NAME_ARCHGW,
@ -44,12 +45,12 @@ ______ _
"""
# Command to build plano Docker images
ARCHGW_DOCKERFILE = "./arch/Dockerfile"
ARCHGW_DOCKERFILE = "./Dockerfile"
def get_version():
try:
version = importlib.metadata.version("plano")
version = importlib.metadata.version("planoai")
return version
except importlib.metadata.PackageNotFoundError:
return "version not found"
@ -73,35 +74,41 @@ def main(ctx, version):
@click.command()
def build():
"""Build Arch from source. Must be in root of cloned repo."""
"""Build Arch from source. Works from any directory within the repo."""
# Check if /arch/Dockerfile exists
if os.path.exists(ARCHGW_DOCKERFILE):
if os.path.exists(ARCHGW_DOCKERFILE):
click.echo("Building plano image...")
try:
subprocess.run(
[
"docker",
"build",
"-f",
ARCHGW_DOCKERFILE,
"-t",
f"{PLANO_DOCKER_IMAGE}",
".",
"--add-host=host.docker.internal:host-gateway",
],
check=True,
)
click.echo("archgw image built successfully.")
except subprocess.CalledProcessError as e:
click.echo(f"Error building plano image: {e}")
sys.exit(1)
else:
click.echo("Error: Dockerfile not found in /arch")
sys.exit(1)
# Find the repo root
repo_root = find_repo_root()
if not repo_root:
click.echo(
"Error: Could not find repository root. Make sure you're inside the plano repository."
)
sys.exit(1)
click.echo("archgw image built successfully.")
dockerfile_path = os.path.join(repo_root, "Dockerfile")
if not os.path.exists(dockerfile_path):
click.echo(f"Error: Dockerfile not found at {dockerfile_path}")
sys.exit(1)
click.echo(f"Building plano image from {repo_root}...")
try:
subprocess.run(
[
"docker",
"build",
"-f",
dockerfile_path,
"-t",
f"{PLANO_DOCKER_IMAGE}",
repo_root,
"--add-host=host.docker.internal:host-gateway",
],
check=True,
)
click.echo("archgw image built successfully.")
except subprocess.CalledProcessError as e:
click.echo(f"Error building plano image: {e}")
sys.exit(1)
@click.command()

View file

@ -4,6 +4,7 @@ import subprocess
import sys
import yaml
import logging
from planoai.consts import PLANO_DOCKER_NAME
logging.basicConfig(
@ -21,6 +22,33 @@ def getLogger(name="cli"):
log = getLogger(__name__)
def find_repo_root(start_path=None):
"""Find the repository root by looking for Dockerfile or .git directory."""
if start_path is None:
start_path = os.getcwd()
current = os.path.abspath(start_path)
while current != os.path.dirname(current): # Stop at filesystem root
# Check for markers that indicate repo root
if (
os.path.exists(os.path.join(current, "Dockerfile"))
and os.path.exists(os.path.join(current, "crates"))
and os.path.exists(os.path.join(current, "config"))
):
return current
# Also check for .git as fallback
if os.path.exists(os.path.join(current, ".git")):
# Verify it's the right repo by checking for expected structure
if os.path.exists(os.path.join(current, "crates")):
return current
current = os.path.dirname(current)
return None
def has_ingress_listener(arch_config_file):
"""Check if the arch config file has ingress_traffic listener configured."""
try:
@ -221,7 +249,7 @@ def stream_access_logs(follow):
stream_command = [
"docker",
"exec",
"archgw",
PLANO_DOCKER_NAME,
"sh",
"-c",
f"tail {follow_arg} /var/log/access_*.log",

View file

@ -4,7 +4,7 @@ version = "0.4.0"
description = "Python-based CLI tool to manage Plano."
authors = ["Katanemo Labs, Inc."]
readme = "README.md"
packages = [{ include = "cli" }]
packages = [{ include = "planoai" }]
[tool.poetry.dependencies]
python = ">=3.10"
@ -18,7 +18,7 @@ requests = ">=2.31.0,<3.0.0"
pytest = ">=8.4.1,<9.0.0"
[tool.poetry.scripts]
planoai = "cli.main:main"
planoai = "planoai.main:main"
[build-system]
requires = ["poetry-core>=2.0.0"]

View file

@ -2,7 +2,7 @@ import json
import pytest
from unittest import mock
import sys
from cli.config_generator import validate_and_render_schema
from planoai.config_generator import validate_and_render_schema
# Patch sys.path to allow import from cli/
import os
@ -59,13 +59,13 @@ tracing:
random_sampling: 100
"""
arch_config_schema = ""
with open("../arch_config_schema.yaml", "r") as file:
with open("../config/arch_config_schema.yaml", "r") as file:
arch_config_schema = file.read()
m_open = mock.mock_open()
# Provide enough file handles for all open() calls in validate_and_render_schema
m_open.side_effect = [
mock.mock_open(read_data="").return_value,
# Removed empty read - was causing validation failures
mock.mock_open(read_data=arch_config).return_value, # ARCH_CONFIG_FILE
mock.mock_open(
read_data=arch_config_schema
@ -78,7 +78,7 @@ tracing:
mock.mock_open().return_value, # ARCH_CONFIG_FILE_RENDERED (write)
]
with mock.patch("builtins.open", m_open):
with mock.patch("config_generator.Environment"):
with mock.patch("planoai.config_generator.Environment"):
validate_and_render_schema()
@ -108,7 +108,7 @@ agents:
listeners:
- name: tmobile
type: agent
router: arch_agent_v2
router: plano_orchestrator_v1
agents:
- name: simple_tmobile_rag_agent
description: t-mobile virtual assistant for device contracts.
@ -132,13 +132,13 @@ listeners:
model: openai/gpt-4o
"""
arch_config_schema = ""
with open("../arch_config_schema.yaml", "r") as file:
with open("../config/arch_config_schema.yaml", "r") as file:
arch_config_schema = file.read()
m_open = mock.mock_open()
# Provide enough file handles for all open() calls in validate_and_render_schema
m_open.side_effect = [
mock.mock_open(read_data="").return_value,
# Removed empty read - was causing validation failures
mock.mock_open(read_data=arch_config).return_value, # ARCH_CONFIG_FILE
mock.mock_open(
read_data=arch_config_schema
@ -151,7 +151,7 @@ listeners:
mock.mock_open().return_value, # ARCH_CONFIG_FILE_RENDERED (write)
]
with mock.patch("builtins.open", m_open):
with mock.patch("cli.config_generator.Environment"):
with mock.patch("planoai.config_generator.Environment"):
validate_and_render_schema()
@ -319,26 +319,29 @@ def test_validate_and_render_schema_tests(monkeypatch, arch_config_test_case):
expected_error = arch_config_test_case.get("expected_error")
arch_config_schema = ""
with open("../arch_config_schema.yaml", "r") as file:
with open("../config/arch_config_schema.yaml", "r") as file:
arch_config_schema = file.read()
m_open = mock.mock_open()
# Provide enough file handles for all open() calls in validate_and_render_schema
m_open.side_effect = [
mock.mock_open(read_data="").return_value,
mock.mock_open(read_data=arch_config).return_value, # ARCH_CONFIG_FILE
mock.mock_open(
read_data=arch_config
).return_value, # validate_prompt_config: ARCH_CONFIG_FILE
mock.mock_open(
read_data=arch_config_schema
).return_value, # ARCH_CONFIG_SCHEMA_FILE
mock.mock_open(read_data=arch_config).return_value, # ARCH_CONFIG_FILE
).return_value, # validate_prompt_config: ARCH_CONFIG_SCHEMA_FILE
mock.mock_open(
read_data=arch_config
).return_value, # validate_and_render_schema: ARCH_CONFIG_FILE
mock.mock_open(
read_data=arch_config_schema
).return_value, # ARCH_CONFIG_SCHEMA_FILE
).return_value, # validate_and_render_schema: ARCH_CONFIG_SCHEMA_FILE
mock.mock_open().return_value, # ENVOY_CONFIG_FILE_RENDERED (write)
mock.mock_open().return_value, # ARCH_CONFIG_FILE_RENDERED (write)
]
with mock.patch("builtins.open", m_open):
with mock.patch("config_generator.Environment"):
with mock.patch("planoai.config_generator.Environment"):
if expected_error:
# Test expects an error
with pytest.raises(Exception) as excinfo:
@ -350,7 +353,7 @@ def test_validate_and_render_schema_tests(monkeypatch, arch_config_test_case):
def test_convert_legacy_llm_providers():
from cli.utils import convert_legacy_listeners
from planoai.utils import convert_legacy_listeners
listeners = {
"ingress_traffic": {
@ -420,7 +423,7 @@ def test_convert_legacy_llm_providers():
def test_convert_legacy_llm_providers_no_prompt_gateway():
from cli.utils import convert_legacy_listeners
from planoai.utils import convert_legacy_listeners
listeners = {
"egress_traffic": {

View file

View file

@ -12,7 +12,7 @@ services:
- /etc/ssl/cert.pem:/etc/ssl/cert.pem
- ./envoy.template.yaml:/app/envoy.template.yaml
- ./arch_config_schema.yaml:/app/arch_config_schema.yaml
- ./tools/cli/config_generator.py:/app/config_generator.py
- ../cli/planoai/config_generator.py:/app/planoai/config_generator.py
- ../crates/target/wasm32-wasip1/release/llm_gateway.wasm:/etc/envoy/proxy-wasm-plugins/llm_gateway.wasm
- ../crates/target/wasm32-wasip1/release/prompt_gateway.wasm:/etc/envoy/proxy-wasm-plugins/prompt_gateway.wasm
- ~/archgw_logs:/var/log/

View file

@ -9,7 +9,7 @@ stdout_logfile_maxbytes=0
stderr_logfile_maxbytes=0
[program:envoy]
command=/bin/sh -c "python -m cli.config_generator && envsubst < /etc/envoy/envoy.yaml > /etc/envoy.env_sub.yaml && envoy -c /etc/envoy.env_sub.yaml --component-log-level wasm:info --log-format '[%%Y-%%m-%%d %%T.%%e][%%l] %%v' 2>&1 | tee /var/log/envoy.log | while IFS= read -r line; do echo '[archgw_logs]' \"$line\"; done"
command=/bin/sh -c "python -m planoai.config_generator && envsubst < /etc/envoy/envoy.yaml > /etc/envoy.env_sub.yaml && envoy -c /etc/envoy.env_sub.yaml --component-log-level wasm:info --log-format '[%%Y-%%m-%%d %%T.%%e][%%l] %%v' 2>&1 | tee /var/log/envoy.log | while IFS= read -r line; do echo '[archgw_logs]' \"$line\"; done"
stdout_logfile=/dev/stdout
redirect_stderr=true
stdout_logfile_maxbytes=0

View file

@ -2,10 +2,10 @@
failed_files=()
for file in $(find . -name arch_config.yaml -o -name arch_config_full_reference.yaml); do
for file in $(find . -name config.yaml -o -name arch_config_full_reference.yaml); do
echo "Validating ${file}..."
touch $(pwd)/${file}_rendered
if ! docker run --rm -v "$(pwd)/${file}:/app/arch_config.yaml:ro" -v "$(pwd)/${file}_rendered:/app/arch_config_rendered.yaml:rw" --entrypoint /bin/sh katanemo/plano:0.4.0 -c "python -m cli.config_generator" 2>&1 > /dev/null ; then
if ! docker run --rm -v "$(pwd)/${file}:/app/arch_config.yaml:ro" -v "$(pwd)/${file}_rendered:/app/arch_config_rendered.yaml:rw" --entrypoint /bin/sh katanemo/plano:0.4.0 -c "python -m planoai.config_generator" 2>&1 > /dev/null ; then
echo "Validation failed for $file"
failed_files+=("$file")
fi

View file

@ -29,11 +29,11 @@ Start arch gateway,
```
$ planoai up config.yaml
2024-12-05 11:24:51,288 - cli.main - INFO - Starting plano cli version: 0.4.0
2024-12-05 11:24:51,825 - cli.utils - INFO - Schema validation successful!
2024-12-05 11:24:51,825 - cli.main - INFO - Starting arch model server and arch gateway
2024-12-05 11:24:51,288 - planoai.main - INFO - Starting plano cli version: 0.4.0
2024-12-05 11:24:51,825 - planoai.utils - INFO - Schema validation successful!
2024-12-05 11:24:51,825 - planoai.main - INFO - Starting arch model server and arch gateway
...
2024-12-05 11:25:16,131 - cli.core - INFO - Container is healthy!
2024-12-05 11:25:16,131 - planoai.core - INFO - Container is healthy!
```
### Step 3: Interact with LLM

View file

@ -14,7 +14,7 @@ services:
plano:
build:
context: ../../../
dockerfile: arch/Dockerfile
dockerfile: Dockerfile
ports:
- "12000:12000"
- "8001:8001"

View file

@ -14,8 +14,8 @@ Make sure your machine is up to date with [latest version of plano]([url](https:
2. start plano in the foreground
```bash
(venv) $ planoai up --service plano --foreground
2025-05-30 18:00:09,953 - cli.main - INFO - Starting plano cli version: 0.4.0
2025-05-30 18:00:09,953 - cli.main - INFO - Validating /Users/adilhafeez/src/intelligent-prompt-gateway/demos/use_cases/preference_based_routing/config.yaml
2025-05-30 18:00:09,953 - planoai.main - INFO - Starting plano cli version: 0.4.0
2025-05-30 18:00:09,953 - planoai.main - INFO - Validating /Users/adilhafeez/src/intelligent-prompt-gateway/demos/use_cases/preference_based_routing/config.yaml
2025-05-30 18:00:10,422 - cli.core - INFO - Starting arch gateway, image name: plano, tag: katanemo/plano:0.4.0
2025-05-30 18:00:10,662 - cli.core - INFO - plano status: running, health status: starting
2025-05-30 18:00:11,712 - cli.core - INFO - plano status: running, health status: starting

View file

@ -3,7 +3,7 @@ services:
plano:
build:
context: ../../../
dockerfile: arch/Dockerfile
dockerfile: Dockerfile
ports:
- "12000:12000"
- "8001:8001"

View file

@ -177,12 +177,12 @@ Step 2. Start plano with currency conversion config
.. code-block:: sh
$ planoai up plano_config.yaml
2024-12-05 16:56:27,979 - cli.main - INFO - Starting plano cli version: 0.1.5
2024-12-05 16:56:27,979 - planoai.main - INFO - Starting plano cli version: 0.1.5
...
2024-12-05 16:56:28,485 - cli.utils - INFO - Schema validation successful!
2024-12-05 16:56:28,485 - cli.main - INFO - Starting plano model server and plano gateway
2024-12-05 16:56:28,485 - planoai.utils - INFO - Schema validation successful!
2024-12-05 16:56:28,485 - planoai.main - INFO - Starting plano model server and plano gateway
...
2024-12-05 16:56:51,647 - cli.core - INFO - Container is healthy!
2024-12-05 16:56:51,647 - planoai.core - INFO - Container is healthy!
Once the gateway is up, you can start interacting with it at port 10000 using the OpenAI chat completion API.
@ -253,11 +253,11 @@ Start Plano:
.. code-block:: console
$ planoai up plano_config.yaml
2024-12-05 11:24:51,288 - cli.main - INFO - Starting plano cli version: 0.4.0
2024-12-05 11:24:51,825 - cli.utils - INFO - Schema validation successful!
2024-12-05 11:24:51,825 - cli.main - INFO - Starting plano
2024-12-05 11:24:51,288 - planoai.main - INFO - Starting plano cli version: 0.4.0
2024-12-05 11:24:51,825 - planoai.utils - INFO - Schema validation successful!
2024-12-05 11:24:51,825 - planoai.main - INFO - Starting plano
...
2024-12-05 11:25:16,131 - cli.core - INFO - Container is healthy!
2024-12-05 11:25:16,131 - planoai.core - INFO - Container is healthy!
Step 3: Interact with LLM
~~~~~~~~~~~~~~~~~~~~~~~~~

View file

@ -29,7 +29,7 @@ cd -
log building and installing plano cli
log ==================================
cd ../../arch/tools
cd ../../cli
poetry install
cd -