abstractcode 0.3.4__py3-none-any.whl → 0.3.5__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.
abstractcode/cli.py CHANGED
@@ -43,68 +43,21 @@ def _default_max_tokens() -> Optional[int]:
43
43
  return -1 # Auto (use model capabilities)
44
44
 
45
45
 
46
- def _env_flag(name: str, *, default: bool = False) -> bool:
47
- raw = os.getenv(name)
48
- if raw is None:
49
- return bool(default)
50
- val = str(raw).strip().lower()
51
- if val in {"1", "true", "yes", "y", "on"}:
52
- return True
53
- if val in {"0", "false", "no", "n", "off"}:
54
- return False
55
- return bool(default)
56
-
57
-
58
46
  def _configure_abstractcode_logging(argv_list: Sequence[str]) -> None:
59
- """Silence Python/Structured logs for the interactive TUI (default).
47
+ """Initialize framework logging early (default: ERROR-only).
60
48
 
61
- Rationale: log lines from providers (httpx, AbstractCore providers, etc) break the
62
- terminal UI and are noisy. AbstractCode should surface errors in its own UI instead.
63
-
64
- Override:
65
- - Set `ABSTRACTCODE_SILENCE_LOGS=0` to keep standard logging.
49
+ AbstractCode should rely on the shared framework defaults rather than maintaining
50
+ a TUI-specific “silence logs” mode. Operators can still raise verbosity by setting
51
+ AbstractCore logging config/env vars.
66
52
  """
67
- if any(arg in {"-h", "--help"} for arg in argv_list):
68
- # Help should be fast and quiet.
69
- try:
70
- import logging
71
-
72
- logging.disable(logging.CRITICAL)
73
- except Exception:
74
- pass
75
- return
76
-
77
- if not _env_flag("ABSTRACTCODE_SILENCE_LOGS", default=True):
78
- return
79
-
80
53
  try:
81
- import logging
82
- from abstractcore.utils import structured_logging
83
-
84
- defaults = structured_logging._get_config_defaults()
85
- log_dir = defaults.get("log_dir")
86
- file_level = defaults.get("file_level") if log_dir else None
87
-
88
- structured_logging.configure_logging(
89
- console_level=None,
90
- file_level=file_level,
91
- log_dir=log_dir,
92
- verbatim_enabled=bool(defaults.get("verbatim_enabled", True)),
93
- console_json=bool(defaults.get("console_json", False)),
94
- file_json=bool(defaults.get("file_json", True)),
95
- )
96
-
97
- # Defensive: if libraries attach their own handlers, keep them quiet.
98
- for name in ("httpx", "httpcore", "asyncio", "urllib3"):
99
- logging.getLogger(name).setLevel(logging.WARNING)
54
+ # Import triggers AbstractCore structured logging initialization.
55
+ from abstractcore.utils import structured_logging as _structured_logging # noqa: F401
100
56
  except Exception:
101
- # Best-effort: suppress any remaining logging noise.
102
- try:
103
- import logging
57
+ # Fallback: ensure Python logging stays quiet by default.
58
+ import logging
104
59
 
105
- logging.disable(logging.CRITICAL)
106
- except Exception:
107
- pass
60
+ logging.basicConfig(level=logging.ERROR)
108
61
 
109
62
 
110
63
  def build_agent_parser() -> argparse.ArgumentParser:
@@ -14,18 +14,17 @@ _MOUNT_NAME_RE = re.compile(r"^[a-zA-Z0-9_-]{1,32}$")
14
14
  def default_workspace_root(*, cwd: Path | None = None) -> Path:
15
15
  """Return the workspace root used by AbstractCode for `@file` mentions.
16
16
 
17
- Preference order:
18
- - `ABSTRACTCODE_WORKSPACE_DIR`
19
- - `ABSTRACTGATEWAY_WORKSPACE_DIR` (common shared convention)
20
- - `cwd` (or `Path.cwd()`)
17
+ Always uses the current working directory (or the provided `cwd`).
21
18
  """
22
- raw = os.environ.get("ABSTRACTCODE_WORKSPACE_DIR") or os.environ.get("ABSTRACTGATEWAY_WORKSPACE_DIR")
23
- if isinstance(raw, str) and raw.strip():
24
- return Path(raw).expanduser().resolve()
25
19
  base = cwd if isinstance(cwd, Path) else Path.cwd()
26
20
  return base.resolve()
27
21
 
28
22
 
23
+ def workspace_root_from_env() -> Path | None:
24
+ """Deprecated: env-based workspace root overrides are not supported."""
25
+ return None
26
+
27
+
29
28
  def extract_at_file_mentions(text: str) -> Tuple[str, List[str]]:
30
29
  """Extract `@file` mentions from a text prompt.
31
30
 
@@ -460,6 +460,7 @@ class ReactShell:
460
460
 
461
461
  # Workspace root for `@file` mentions / attachments.
462
462
  self._workspace_root: Path = default_workspace_root()
463
+ self._workspace_root_source: str = "cwd"
463
464
  self._workspace_mounts: Dict[str, Path] = default_workspace_mounts()
464
465
  self._workspace_mount_ignores: Dict[str, Any] = {}
465
466
  self._workspace_blocked_paths: List[Path] = []
@@ -8020,8 +8021,9 @@ class ReactShell:
8020
8021
  # - Mount roots are expressed as `workspace_allowed_paths` (absolute paths).
8021
8022
  # - Blacklist uses `workspace_ignored_paths` (absolute paths) and always has priority.
8022
8023
  try:
8023
- if "workspace_root" not in state.vars:
8024
- state.vars["workspace_root"] = str(self._workspace_root)
8024
+ # Always sync workspace_root so it reflects the current session's root.
8025
+ state.vars["workspace_root"] = str(self._workspace_root)
8026
+ state.vars["workspace_root_source"] = self._workspace_root_source
8025
8027
 
8026
8028
  allowed_paths = [str(p) for p in (self._workspace_mounts or {}).values() if isinstance(p, Path)]
8027
8029
  ignored_paths = [str(p) for p in (self._workspace_blocked_paths or []) if isinstance(p, Path)]
@@ -8239,6 +8241,27 @@ class ReactShell:
8239
8241
  self._print(_style("State load failed:", _C.YELLOW, enabled=self._color) + f" {e}")
8240
8242
  return
8241
8243
  if state is not None:
8244
+ prev_root: Optional[Path] = None
8245
+ try:
8246
+ if isinstance(getattr(state, "vars", None), dict):
8247
+ raw_prev = state.vars.get("workspace_root")
8248
+ if isinstance(raw_prev, str) and raw_prev.strip():
8249
+ prev_root = Path(raw_prev).expanduser().resolve()
8250
+ except Exception:
8251
+ prev_root = None
8252
+ try:
8253
+ current_root = self._workspace_root.resolve()
8254
+ except Exception:
8255
+ current_root = self._workspace_root
8256
+ if prev_root is not None and prev_root != current_root:
8257
+ self._print(
8258
+ _style(
8259
+ f"Workspace root changed ({prev_root} -> {current_root}). Previous history not loaded. Use '/resume' to continue.",
8260
+ _C.YELLOW,
8261
+ enabled=self._color,
8262
+ )
8263
+ )
8264
+ return
8242
8265
  messages: Optional[List[Dict[str, Any]]] = None
8243
8266
  loaded = self._messages_from_state(state)
8244
8267
  if loaded:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: abstractcode
3
- Version: 0.3.4
3
+ Version: 0.3.5
4
4
  Summary: A clean terminal CLI for multi-agent agentic coding
5
5
  Author-email: Laurent-Philippe Albou <contact@abstractcore.ai>
6
6
  Maintainer-email: Laurent-Philippe Albou <contact@abstractcore.ai>
@@ -1,22 +1,22 @@
1
1
  abstractcode/__init__.py,sha256=O-DbZctdBATghwjZUCeHBYwe84a5wuRK6cd4z3kkyzg,658
2
2
  abstractcode/__main__.py,sha256=fCPR9aX40LUKCK-Ke57j7u3aAO6mO4QVQydA1F2YER8,134
3
- abstractcode/cli.py,sha256=sDpKTREeRGWcXyFwnVEZLBuLQcpD4WuOnGU9nTx6SMU,44440
4
- abstractcode/file_mentions.py,sha256=KFtFX_Ofjk_9r9Nirt1IXKLWr1VsSrXimHnRYxxvRYs,8664
3
+ abstractcode/cli.py,sha256=yawpX8gD2LAqLOflPXWA2I6-blF_GULRlr5KTarsIiQ,43033
4
+ abstractcode/file_mentions.py,sha256=Bc6Z6DZHl4tnki2rw4Bxvc6sOV9TV0WvQhgElSXTJ0I,8524
5
5
  abstractcode/flow_cli.py,sha256=CQq1g4rFylSW7y8ZZeQYmfroAXG1dDtmuOF8tc1BF2Y,49235
6
6
  abstractcode/fullscreen_ui.py,sha256=rcYETwA5nMFNE1cNgIDTF3zUFLlqtJoveQ2W6feR7Ao,117536
7
7
  abstractcode/gateway_cli.py,sha256=ajAYI0IUK3FBAVx5HdDh_zThyU7-tABre8meAUuO_cU,25251
8
8
  abstractcode/input_handler.py,sha256=W2ImW4Yr3HMMD5SNPZOZJendVL-CRdYR5idXTWroxAY,2240
9
9
  abstractcode/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
10
- abstractcode/react_shell.py,sha256=lgydDok2ZgNwVDForvAYT9MxVYk7SiVmuUFMnYEOpvg,387224
10
+ abstractcode/react_shell.py,sha256=RnMZwZN-E1Qa09E0JNTwL0o9Kvcrmd18tMY6cqAJlzQ,388350
11
11
  abstractcode/recall.py,sha256=xu-xz8-kvkmAW6pKoAIcwox5jHWMBfBKExsA8fgwg_A,13040
12
12
  abstractcode/remember.py,sha256=cmJlw-nR0OvK7tkN5B0sZSMaYlECl_tAyO34c-IL0Uo,6158
13
13
  abstractcode/terminal_markdown.py,sha256=mL3YdBZt25DoJec23EXgve2zH4OMDJLxBnQfWvsSSh0,21465
14
14
  abstractcode/theme.py,sha256=WWlMsbqIj4Z-jylOTnmV_zTirf87tdbrlrRsIaTBfQE,6689
15
15
  abstractcode/workflow_agent.py,sha256=J8pw7r79lJZ58aqMXsRTabbgxEJzIlJHb8__oUPg_08,56744
16
16
  abstractcode/workflow_cli.py,sha256=gabA7RzPe9-qkI3MSaRCrxErWeCl1faRa-oTGULxp_w,8936
17
- abstractcode-0.3.4.dist-info/licenses/LICENSE,sha256=f8z-PbFM_xH0eqLsha8_nEg1jbm1eVtC2NNjtXhtuCo,1080
18
- abstractcode-0.3.4.dist-info/METADATA,sha256=BpEuVke3yxeDfIEl2bSQkoggrIPafvvLowWWx32hwd0,4657
19
- abstractcode-0.3.4.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
20
- abstractcode-0.3.4.dist-info/entry_points.txt,sha256=M4AOKb4h2vKWy5OMg-czeJE2aXunVKlljUPN8BUtwoE,51
21
- abstractcode-0.3.4.dist-info/top_level.txt,sha256=n9Hfv6cnmL55HoxXsA3V1YLbQxYAr58-UMLbdr-FCNw,13
22
- abstractcode-0.3.4.dist-info/RECORD,,
17
+ abstractcode-0.3.5.dist-info/licenses/LICENSE,sha256=f8z-PbFM_xH0eqLsha8_nEg1jbm1eVtC2NNjtXhtuCo,1080
18
+ abstractcode-0.3.5.dist-info/METADATA,sha256=_aGCVB_TaCXtkYUaL_dhXMgXTxSFGod4Eo5aoQ8UNsk,4657
19
+ abstractcode-0.3.5.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
20
+ abstractcode-0.3.5.dist-info/entry_points.txt,sha256=M4AOKb4h2vKWy5OMg-czeJE2aXunVKlljUPN8BUtwoE,51
21
+ abstractcode-0.3.5.dist-info/top_level.txt,sha256=n9Hfv6cnmL55HoxXsA3V1YLbQxYAr58-UMLbdr-FCNw,13
22
+ abstractcode-0.3.5.dist-info/RECORD,,