code-puppy 0.0.50__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.
@@ -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 ""
@@ -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
@@ -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
- env_val = os.getenv('YOLO_MODE')
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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-puppy
3
- Version: 0.0.50
3
+ Version: 0.0.51
4
4
  Summary: Code generation agent
5
5
  Author: Michael Pfaffenberger
6
6
  License: MIT
@@ -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=eVUWtcRHuD7cwHuBOgypTV7qINjT7Z5sBmXprKrOjEs,2869
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,9 +9,9 @@ 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=C14QL_MMNnKQh1rKQ7KdQkHCJRl5oRTKd9NYSe8OCqk,4220
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=QtXqqEzc6C8ODHTfvIDD1sY0fLaX40S7Sfbol43A9i8,5338
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
@@ -20,9 +20,9 @@ code_puppy/tools/common.py,sha256=dbmyZTrTBQh_0WWpaYN6jEync62W2mMrzNS8UFK0co4,14
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.50.data/data/code_puppy/models.json,sha256=7H-y97YK9BXhag5wJU19rtg24JtZWYx60RsBLBW3WiI,2162
24
- code_puppy-0.0.50.dist-info/METADATA,sha256=LRlwtx444fmT-6hL6p99vIYRKb8zIL30CaHG5k3lSRw,4716
25
- code_puppy-0.0.50.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
26
- code_puppy-0.0.50.dist-info/entry_points.txt,sha256=d8YkBvIUxF-dHNJAj-x4fPEqizbY5d_TwvYpc01U5kw,58
27
- code_puppy-0.0.50.dist-info/licenses/LICENSE,sha256=31u8x0SPgdOq3izJX41kgFazWsM43zPEF9eskzqbJMY,1075
28
- code_puppy-0.0.50.dist-info/RECORD,,
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,,