code-puppy 0.0.50__tar.gz → 0.0.51__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.
- {code_puppy-0.0.50 → code_puppy-0.0.51}/PKG-INFO +1 -1
- {code_puppy-0.0.50 → code_puppy-0.0.51}/code_puppy/command_line/meta_command_handler.py +29 -2
- {code_puppy-0.0.50 → code_puppy-0.0.51}/code_puppy/command_line/prompt_toolkit_completion.py +39 -1
- {code_puppy-0.0.50 → code_puppy-0.0.51}/code_puppy/config.py +39 -9
- {code_puppy-0.0.50 → code_puppy-0.0.51}/pyproject.toml +1 -1
- {code_puppy-0.0.50 → code_puppy-0.0.51}/.gitignore +0 -0
- {code_puppy-0.0.50 → code_puppy-0.0.51}/LICENSE +0 -0
- {code_puppy-0.0.50 → code_puppy-0.0.51}/README.md +0 -0
- {code_puppy-0.0.50 → code_puppy-0.0.51}/code_puppy/__init__.py +0 -0
- {code_puppy-0.0.50 → code_puppy-0.0.51}/code_puppy/agent.py +0 -0
- {code_puppy-0.0.50 → code_puppy-0.0.51}/code_puppy/agent_prompts.py +0 -0
- {code_puppy-0.0.50 → code_puppy-0.0.51}/code_puppy/command_line/__init__.py +0 -0
- {code_puppy-0.0.50 → code_puppy-0.0.51}/code_puppy/command_line/file_path_completion.py +0 -0
- {code_puppy-0.0.50 → code_puppy-0.0.51}/code_puppy/command_line/model_picker_completion.py +0 -0
- {code_puppy-0.0.50 → code_puppy-0.0.51}/code_puppy/command_line/utils.py +0 -0
- {code_puppy-0.0.50 → code_puppy-0.0.51}/code_puppy/main.py +0 -0
- {code_puppy-0.0.50 → code_puppy-0.0.51}/code_puppy/model_factory.py +0 -0
- {code_puppy-0.0.50 → code_puppy-0.0.51}/code_puppy/models.json +0 -0
- {code_puppy-0.0.50 → code_puppy-0.0.51}/code_puppy/session_memory.py +0 -0
- {code_puppy-0.0.50 → code_puppy-0.0.51}/code_puppy/tools/__init__.py +0 -0
- {code_puppy-0.0.50 → code_puppy-0.0.51}/code_puppy/tools/code_map.py +0 -0
- {code_puppy-0.0.50 → code_puppy-0.0.51}/code_puppy/tools/command_runner.py +0 -0
- {code_puppy-0.0.50 → code_puppy-0.0.51}/code_puppy/tools/common.py +0 -0
- {code_puppy-0.0.50 → code_puppy-0.0.51}/code_puppy/tools/file_modifications.py +0 -0
- {code_puppy-0.0.50 → code_puppy-0.0.51}/code_puppy/tools/file_operations.py +0 -0
- {code_puppy-0.0.50 → code_puppy-0.0.51}/code_puppy/tools/web_search.py +0 -0
- {code_puppy-0.0.50 → code_puppy-0.0.51}/code_puppy/version_checker.py +0 -0
|
@@ -47,7 +47,6 @@ def handle_meta_command(command: str, console: Console) -> bool:
|
|
|
47
47
|
if command.strip().startswith("~show"):
|
|
48
48
|
from code_puppy.config import get_puppy_name, get_owner_name
|
|
49
49
|
from code_puppy.command_line.model_picker_completion import get_active_model
|
|
50
|
-
import os
|
|
51
50
|
puppy_name = get_puppy_name()
|
|
52
51
|
owner_name = get_owner_name()
|
|
53
52
|
model = get_active_model()
|
|
@@ -61,6 +60,34 @@ def handle_meta_command(command: str, console: Console) -> bool:
|
|
|
61
60
|
''')
|
|
62
61
|
return True
|
|
63
62
|
|
|
63
|
+
if command.startswith("~set"):
|
|
64
|
+
# Syntax: ~set KEY=VALUE or ~set KEY VALUE
|
|
65
|
+
from code_puppy.config import set_config_value, get_config_keys
|
|
66
|
+
tokens = command.split(None, 2)
|
|
67
|
+
argstr = command[len('~set'):].strip()
|
|
68
|
+
key = None
|
|
69
|
+
value = None
|
|
70
|
+
if '=' in argstr:
|
|
71
|
+
key, value = argstr.split('=', 1)
|
|
72
|
+
key = key.strip()
|
|
73
|
+
value = value.strip()
|
|
74
|
+
elif len(tokens) >= 3:
|
|
75
|
+
key = tokens[1]
|
|
76
|
+
value = tokens[2]
|
|
77
|
+
elif len(tokens) == 2:
|
|
78
|
+
key = tokens[1]
|
|
79
|
+
value = ''
|
|
80
|
+
else:
|
|
81
|
+
console.print('[yellow]Usage:[/yellow] ~set KEY=VALUE or ~set KEY VALUE')
|
|
82
|
+
console.print('Config keys: ' + ', '.join(get_config_keys()))
|
|
83
|
+
return True
|
|
84
|
+
if key:
|
|
85
|
+
set_config_value(key, value)
|
|
86
|
+
console.print(f'[green]🌶 Set[/green] [cyan]{key}[/cyan] = "{value}" in puppy.cfg!')
|
|
87
|
+
else:
|
|
88
|
+
console.print('[red]You must supply a key.[/red]')
|
|
89
|
+
return True
|
|
90
|
+
|
|
64
91
|
if command.startswith("~m"):
|
|
65
92
|
# Try setting model and show confirmation
|
|
66
93
|
new_input = update_model_in_input(command)
|
|
@@ -76,7 +103,7 @@ def handle_meta_command(command: str, console: Console) -> bool:
|
|
|
76
103
|
console.print(f"[yellow]Usage:[/yellow] ~m <model_name>")
|
|
77
104
|
return True
|
|
78
105
|
if command in ("~help", "~h"):
|
|
79
|
-
console.print("[bold magenta]Meta commands available:[/bold magenta]\n ~m <model>: Pick a model from your list!\n ~cd [dir]: Change directories\n ~codemap [dir]: Visualize project code structure\n ~help: Show this help\n (More soon. Woof!)")
|
|
106
|
+
console.print("[bold magenta]Meta commands available:[/bold magenta]\n ~m <model>: Pick a model from your list!\n ~cd [dir]: Change directories\n ~codemap [dir]: Visualize project code structure\n ~set KEY=VALUE: Set a puppy.cfg setting!\n ~help: Show this help\n (More soon. Woof!)")
|
|
80
107
|
return True
|
|
81
108
|
if command.startswith("~"):
|
|
82
109
|
name = command[1:].split()[0] if len(command)>1 else ""
|
{code_puppy-0.0.50 → code_puppy-0.0.51}/code_puppy/command_line/prompt_toolkit_completion.py
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import os
|
|
2
2
|
from code_puppy.command_line.utils import list_directory
|
|
3
|
-
from code_puppy.config import get_puppy_name, get_owner_name
|
|
3
|
+
from code_puppy.config import get_puppy_name, get_owner_name, get_config_keys, get_value
|
|
4
4
|
# ANSI color codes are no longer necessary because prompt_toolkit handles
|
|
5
5
|
# styling via the `Style` class. We keep them here commented-out in case
|
|
6
6
|
# someone needs raw ANSI later, but they are unused in the current code.
|
|
@@ -27,6 +27,43 @@ from code_puppy.command_line.file_path_completion import FilePathCompleter
|
|
|
27
27
|
|
|
28
28
|
from prompt_toolkit.completion import Completer, Completion
|
|
29
29
|
|
|
30
|
+
class SetCompleter(Completer):
|
|
31
|
+
def __init__(self, trigger: str = '~set'):
|
|
32
|
+
self.trigger = trigger
|
|
33
|
+
def get_completions(self, document, complete_event):
|
|
34
|
+
text = document.text_before_cursor
|
|
35
|
+
if not text.strip().startswith(self.trigger):
|
|
36
|
+
return
|
|
37
|
+
# If the only thing typed is exactly '~set', suggest space
|
|
38
|
+
if text.strip() == self.trigger:
|
|
39
|
+
yield Completion(self.trigger + ' ', start_position=-len(self.trigger), display=f'{self.trigger} ', display_meta='set config')
|
|
40
|
+
tokens = text.strip().split()
|
|
41
|
+
# completion for the first arg after ~set
|
|
42
|
+
if len(tokens) == 1:
|
|
43
|
+
# user just typed ~set <-- suggest config keys
|
|
44
|
+
base = ''
|
|
45
|
+
else:
|
|
46
|
+
base = tokens[1]
|
|
47
|
+
# --- SPECIAL HANDLING FOR 'model' KEY ---
|
|
48
|
+
if base == 'model':
|
|
49
|
+
# Don't return any completions -- let ModelNameCompleter handle it
|
|
50
|
+
return
|
|
51
|
+
for key in get_config_keys():
|
|
52
|
+
if key == 'model':
|
|
53
|
+
continue # exclude 'model' from regular ~set completions
|
|
54
|
+
if key.startswith(base):
|
|
55
|
+
prev_value = get_value(key)
|
|
56
|
+
# Ensure there's a space after '~set' if it's the only thing typed
|
|
57
|
+
if text.strip() == self.trigger or text.strip() == self.trigger + '':
|
|
58
|
+
prefix = self.trigger + ' ' # Always enforce a space
|
|
59
|
+
insert_text = f'{prefix}{key} = {prev_value}' if prev_value is not None else f'{prefix}{key} = '
|
|
60
|
+
sp = -len(text)
|
|
61
|
+
else:
|
|
62
|
+
insert_text = f'{key} = {prev_value}' if prev_value is not None else f'{key} = '
|
|
63
|
+
sp = -len(base)
|
|
64
|
+
# Make it obvious the value part is from before
|
|
65
|
+
yield Completion(insert_text, start_position=sp, display_meta=f'puppy.cfg key (was: {prev_value})' if prev_value is not None else 'puppy.cfg key')
|
|
66
|
+
|
|
30
67
|
class CDCompleter(Completer):
|
|
31
68
|
def __init__(self, trigger: str = '~cd'):
|
|
32
69
|
self.trigger = trigger
|
|
@@ -84,6 +121,7 @@ async def get_input_with_combined_completion(prompt_str = '>>> ', history_file:
|
|
|
84
121
|
FilePathCompleter(symbol='@'),
|
|
85
122
|
ModelNameCompleter(trigger='~m'),
|
|
86
123
|
CDCompleter(trigger='~cd'),
|
|
124
|
+
SetCompleter(trigger='~set'),
|
|
87
125
|
])
|
|
88
126
|
# Add custom key bindings for Alt+M to insert a new line without submitting
|
|
89
127
|
bindings = KeyBindings()
|
|
@@ -50,6 +50,31 @@ def get_puppy_name():
|
|
|
50
50
|
def get_owner_name():
|
|
51
51
|
return get_value("owner_name") or "Master"
|
|
52
52
|
|
|
53
|
+
# --- CONFIG SETTER STARTS HERE ---
|
|
54
|
+
def get_config_keys():
|
|
55
|
+
'''
|
|
56
|
+
Returns the list of all config keys currently in puppy.cfg,
|
|
57
|
+
plus certain preset expected keys (e.g. "yolo_mode", "model").
|
|
58
|
+
'''
|
|
59
|
+
default_keys = ['yolo_mode', 'model']
|
|
60
|
+
config = configparser.ConfigParser()
|
|
61
|
+
config.read(CONFIG_FILE)
|
|
62
|
+
keys = set(config[DEFAULT_SECTION].keys()) if DEFAULT_SECTION in config else set()
|
|
63
|
+
keys.update(default_keys)
|
|
64
|
+
return sorted(keys)
|
|
65
|
+
|
|
66
|
+
def set_config_value(key: str, value: str):
|
|
67
|
+
'''
|
|
68
|
+
Sets a config value in the persistent config file.
|
|
69
|
+
'''
|
|
70
|
+
config = configparser.ConfigParser()
|
|
71
|
+
config.read(CONFIG_FILE)
|
|
72
|
+
if DEFAULT_SECTION not in config:
|
|
73
|
+
config[DEFAULT_SECTION] = {}
|
|
74
|
+
config[DEFAULT_SECTION][key] = value
|
|
75
|
+
with open(CONFIG_FILE, 'w') as f:
|
|
76
|
+
config.write(f)
|
|
77
|
+
|
|
53
78
|
# --- MODEL STICKY EXTENSION STARTS HERE ---
|
|
54
79
|
def get_model_name():
|
|
55
80
|
"""Returns the last used model name stored in config, or None if unset."""
|
|
@@ -66,20 +91,25 @@ def set_model_name(model: str):
|
|
|
66
91
|
config.write(f)
|
|
67
92
|
|
|
68
93
|
def get_yolo_mode():
|
|
69
|
-
"""Checks env var CODE_PUPPY_YOLO or puppy.cfg for 'yolo_mode'.
|
|
70
|
-
Returns True if either is explicitly truthy, else False by default.
|
|
71
|
-
Env var wins if both are set.
|
|
72
|
-
Allowed env/cfg values: 1, '1', 'true', 'yes', 'on' (case-insensitive).
|
|
73
94
|
"""
|
|
74
|
-
|
|
95
|
+
Checks puppy.cfg for 'yolo_mode' (case-insensitive in value only).
|
|
96
|
+
If not set, checks YOLO_MODE env var:
|
|
97
|
+
- If found in env, saves that value to puppy.cfg for future use.
|
|
98
|
+
- If neither present, defaults to False.
|
|
99
|
+
Allowed values for ON: 1, '1', 'true', 'yes', 'on' (all case-insensitive for value).
|
|
100
|
+
Always prioritizes the config once set!
|
|
101
|
+
"""
|
|
75
102
|
true_vals = {'1', 'true', 'yes', 'on'}
|
|
76
|
-
if env_val is not None:
|
|
77
|
-
if str(env_val).strip().lower() in true_vals:
|
|
78
|
-
return True
|
|
79
|
-
return False
|
|
80
103
|
cfg_val = get_value('yolo_mode')
|
|
81
104
|
if cfg_val is not None:
|
|
82
105
|
if str(cfg_val).strip().lower() in true_vals:
|
|
83
106
|
return True
|
|
84
107
|
return False
|
|
108
|
+
env_val = os.getenv('YOLO_MODE')
|
|
109
|
+
if env_val is not None:
|
|
110
|
+
# Persist the env value now
|
|
111
|
+
set_config_value('yolo_mode', env_val)
|
|
112
|
+
if str(env_val).strip().lower() in true_vals:
|
|
113
|
+
return True
|
|
114
|
+
return False
|
|
85
115
|
return False
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|