code-puppy 0.0.49__py3-none-any.whl → 0.0.51__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.
- code_puppy/command_line/meta_command_handler.py +45 -1
- code_puppy/command_line/prompt_toolkit_completion.py +39 -1
- code_puppy/config.py +49 -2
- code_puppy/tools/command_runner.py +2 -1
- {code_puppy-0.0.49.dist-info → code_puppy-0.0.51.dist-info}/METADATA +1 -1
- {code_puppy-0.0.49.dist-info → code_puppy-0.0.51.dist-info}/RECORD +10 -10
- {code_puppy-0.0.49.data → code_puppy-0.0.51.data}/data/code_puppy/models.json +0 -0
- {code_puppy-0.0.49.dist-info → code_puppy-0.0.51.dist-info}/WHEEL +0 -0
- {code_puppy-0.0.49.dist-info → code_puppy-0.0.51.dist-info}/entry_points.txt +0 -0
- {code_puppy-0.0.49.dist-info → code_puppy-0.0.51.dist-info}/licenses/LICENSE +0 -0
|
@@ -44,6 +44,50 @@ def handle_meta_command(command: str, console: Console) -> bool:
|
|
|
44
44
|
console.print(f'[red]Not a directory:[/red] [bold]{dirname}[/bold]')
|
|
45
45
|
return True
|
|
46
46
|
|
|
47
|
+
if command.strip().startswith("~show"):
|
|
48
|
+
from code_puppy.config import get_puppy_name, get_owner_name
|
|
49
|
+
from code_puppy.command_line.model_picker_completion import get_active_model
|
|
50
|
+
puppy_name = get_puppy_name()
|
|
51
|
+
owner_name = get_owner_name()
|
|
52
|
+
model = get_active_model()
|
|
53
|
+
from code_puppy.config import get_yolo_mode
|
|
54
|
+
yolo_mode = get_yolo_mode()
|
|
55
|
+
console.print(f'''[bold magenta]🐶 Puppy Status[/bold magenta]
|
|
56
|
+
\n[bold]puppy_name:[/bold] [cyan]{puppy_name}[/cyan]
|
|
57
|
+
[bold]owner_name:[/bold] [cyan]{owner_name}[/cyan]
|
|
58
|
+
[bold]model:[/bold] [green]{model}[/green]
|
|
59
|
+
[bold]YOLO_MODE:[/bold] {'[red]ON[/red]' if yolo_mode else '[yellow]off[/yellow]'}
|
|
60
|
+
''')
|
|
61
|
+
return True
|
|
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
|
+
|
|
47
91
|
if command.startswith("~m"):
|
|
48
92
|
# Try setting model and show confirmation
|
|
49
93
|
new_input = update_model_in_input(command)
|
|
@@ -59,7 +103,7 @@ def handle_meta_command(command: str, console: Console) -> bool:
|
|
|
59
103
|
console.print(f"[yellow]Usage:[/yellow] ~m <model_name>")
|
|
60
104
|
return True
|
|
61
105
|
if command in ("~help", "~h"):
|
|
62
|
-
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!)")
|
|
63
107
|
return True
|
|
64
108
|
if command.startswith("~"):
|
|
65
109
|
name = command[1:].split()[0] if len(command)>1 else ""
|
|
@@ -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()
|
code_puppy/config.py
CHANGED
|
@@ -7,7 +7,6 @@ CONFIG_FILE = os.path.join(CONFIG_DIR, "puppy.cfg")
|
|
|
7
7
|
DEFAULT_SECTION = "puppy"
|
|
8
8
|
REQUIRED_KEYS = ["puppy_name", "owner_name"]
|
|
9
9
|
|
|
10
|
-
|
|
11
10
|
def ensure_config_exists():
|
|
12
11
|
"""
|
|
13
12
|
Ensure that the .code_puppy dir and puppy.cfg exist, prompting if needed.
|
|
@@ -45,13 +44,37 @@ def get_value(key: str):
|
|
|
45
44
|
val = config.get(DEFAULT_SECTION, key, fallback=None)
|
|
46
45
|
return val
|
|
47
46
|
|
|
48
|
-
|
|
49
47
|
def get_puppy_name():
|
|
50
48
|
return get_value("puppy_name") or "Puppy"
|
|
51
49
|
|
|
52
50
|
def get_owner_name():
|
|
53
51
|
return get_value("owner_name") or "Master"
|
|
54
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
|
+
|
|
55
78
|
# --- MODEL STICKY EXTENSION STARTS HERE ---
|
|
56
79
|
def get_model_name():
|
|
57
80
|
"""Returns the last used model name stored in config, or None if unset."""
|
|
@@ -66,3 +89,27 @@ def set_model_name(model: str):
|
|
|
66
89
|
config[DEFAULT_SECTION]["model"] = model or ""
|
|
67
90
|
with open(CONFIG_FILE, "w") as f:
|
|
68
91
|
config.write(f)
|
|
92
|
+
|
|
93
|
+
def get_yolo_mode():
|
|
94
|
+
"""
|
|
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
|
+
"""
|
|
102
|
+
true_vals = {'1', 'true', 'yes', 'on'}
|
|
103
|
+
cfg_val = get_value('yolo_mode')
|
|
104
|
+
if cfg_val is not None:
|
|
105
|
+
if str(cfg_val).strip().lower() in true_vals:
|
|
106
|
+
return True
|
|
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
|
|
115
|
+
return False
|
|
@@ -19,7 +19,8 @@ def register_command_runner_tools(agent):
|
|
|
19
19
|
if cwd:
|
|
20
20
|
console.print(f"[dim]Working directory: {cwd}[/dim]")
|
|
21
21
|
console.print("[dim]" + "-" * 60 + "[/dim]")
|
|
22
|
-
|
|
22
|
+
from code_puppy.config import get_yolo_mode
|
|
23
|
+
yolo_mode = get_yolo_mode()
|
|
23
24
|
if not yolo_mode:
|
|
24
25
|
user_input = input("Are you sure you want to run this command? (yes/no): ")
|
|
25
26
|
if user_input.strip().lower() not in {"yes", "y"}:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
code_puppy/__init__.py,sha256=orgffM-uGp8g1XCqXGKWaFB4tCCz8TVgsLMPKCOGNx0,81
|
|
2
2
|
code_puppy/agent.py,sha256=avoOEorAYUyQYnYVVCezLz1QKDm0Qgx3i_C-BqgDiQQ,3198
|
|
3
3
|
code_puppy/agent_prompts.py,sha256=A6ADydqbHozIAtwOy_UY-fYZ2XDE9_5oV3oxOMtVCFA,6782
|
|
4
|
-
code_puppy/config.py,sha256=
|
|
4
|
+
code_puppy/config.py,sha256=jsPnwDjz_H69Oww5JyEg3eud3rYMKp3ah2WrnablRak,3894
|
|
5
5
|
code_puppy/main.py,sha256=bc27bk6rFge95H2BumTTzRLtOx43z5FnsmjIjQx_RpU,10052
|
|
6
6
|
code_puppy/model_factory.py,sha256=vDlEoEKkOoikExCqi5oxb_PuTF8STUMABXAbPHV_p34,11639
|
|
7
7
|
code_puppy/models.json,sha256=7H-y97YK9BXhag5wJU19rtg24JtZWYx60RsBLBW3WiI,2162
|
|
@@ -9,20 +9,20 @@ code_puppy/session_memory.py,sha256=vuLSw1Pfa-MXD4lD8hj2qt65OR_aL2WdoMuF6Jwnc1k,
|
|
|
9
9
|
code_puppy/version_checker.py,sha256=cK-eU7Y_yYjn7feIONqzzZUdiedozL0iiKXlGKjfq68,395
|
|
10
10
|
code_puppy/command_line/__init__.py,sha256=y7WeRemfYppk8KVbCGeAIiTuiOszIURCDjOMZv_YRmU,45
|
|
11
11
|
code_puppy/command_line/file_path_completion.py,sha256=HAlOu9XVYgJ7FbjdrhKBL0rFmCVFxSGGewdcfKTUsPw,2865
|
|
12
|
-
code_puppy/command_line/meta_command_handler.py,sha256=
|
|
12
|
+
code_puppy/command_line/meta_command_handler.py,sha256=lavg91Qak68v0S7nxZfcIObHfd-hQiJJaeOGAR1BGzo,5290
|
|
13
13
|
code_puppy/command_line/model_picker_completion.py,sha256=5VEa6OE9shsF0EafJXzBLpFXhFIkqevJi9RRD-eUvZA,3718
|
|
14
|
-
code_puppy/command_line/prompt_toolkit_completion.py,sha256=
|
|
14
|
+
code_puppy/command_line/prompt_toolkit_completion.py,sha256=R-ykRmhVTieE4zIQnn7H1GDKk32yvalot0rZpFizLAQ,7358
|
|
15
15
|
code_puppy/command_line/utils.py,sha256=L1PnV9tNupEW1zeziyb5aGAq8DYP8sMiuQbFYLO5Nus,1236
|
|
16
16
|
code_puppy/tools/__init__.py,sha256=48BVpMt0HAMtz8G_z9SQhX6LnRqR83_AVfMQMf7bY0g,557
|
|
17
17
|
code_puppy/tools/code_map.py,sha256=BghDHaebhGDfDGvA34gwO_5r92Py4O0Q3J4RV-WtnWs,3155
|
|
18
|
-
code_puppy/tools/command_runner.py,sha256=
|
|
18
|
+
code_puppy/tools/command_runner.py,sha256=eg7pOIMkuHtNYVqVE1pPsNYSR2D6XXnkwFaBKd-Ejc8,4773
|
|
19
19
|
code_puppy/tools/common.py,sha256=dbmyZTrTBQh_0WWpaYN6jEync62W2mMrzNS8UFK0co4,146
|
|
20
20
|
code_puppy/tools/file_modifications.py,sha256=nT87uAoY14RTAapnFCgkLTmW9g9P9bymxts2MpSpoo0,19297
|
|
21
21
|
code_puppy/tools/file_operations.py,sha256=LJU_1b3WCXTAHa2B5VAbckrn1VVWb-HhcI3TF3BxYWs,11625
|
|
22
22
|
code_puppy/tools/web_search.py,sha256=HhcwX0MMvMDPFO8gr8gzgesD5wPXOypjkxyLZeNwL5g,589
|
|
23
|
-
code_puppy-0.0.
|
|
24
|
-
code_puppy-0.0.
|
|
25
|
-
code_puppy-0.0.
|
|
26
|
-
code_puppy-0.0.
|
|
27
|
-
code_puppy-0.0.
|
|
28
|
-
code_puppy-0.0.
|
|
23
|
+
code_puppy-0.0.51.data/data/code_puppy/models.json,sha256=7H-y97YK9BXhag5wJU19rtg24JtZWYx60RsBLBW3WiI,2162
|
|
24
|
+
code_puppy-0.0.51.dist-info/METADATA,sha256=sobI_laF57EIXLW_rLfU-E3ibYWAKLsRukigD5I6yMM,4716
|
|
25
|
+
code_puppy-0.0.51.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
26
|
+
code_puppy-0.0.51.dist-info/entry_points.txt,sha256=d8YkBvIUxF-dHNJAj-x4fPEqizbY5d_TwvYpc01U5kw,58
|
|
27
|
+
code_puppy-0.0.51.dist-info/licenses/LICENSE,sha256=31u8x0SPgdOq3izJX41kgFazWsM43zPEF9eskzqbJMY,1075
|
|
28
|
+
code_puppy-0.0.51.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|