codebind 0.1.2__tar.gz → 0.1.4__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codebind
3
- Version: 0.1.2
3
+ Version: 0.1.4
4
4
  Summary: A minimal model loop over a persistent IPython session.
5
5
  Keywords: ai,ipython,llm,repl,agents
6
6
  Author: Giovanni Gravili
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "codebind"
3
- version = "0.1.2"
3
+ version = "0.1.4"
4
4
  description = "A minimal model loop over a persistent IPython session."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "codebind"
3
- version = "0.1.2"
3
+ version = "0.1.4"
4
4
  description = "A minimal model loop over a persistent IPython session."
5
5
  readme = "README.md"
6
6
  authors = [
@@ -8,9 +8,6 @@ from typing import Any
8
8
  from IPython.core.interactiveshell import InteractiveShell
9
9
  from IPython.utils.capture import capture_output
10
10
 
11
- from .prompts import CellPrompts
12
-
13
-
14
11
  @dataclass(frozen=True, slots=True)
15
12
  class ExecutionReport:
16
13
  """The model-facing result of one IPython cell."""
@@ -33,24 +30,19 @@ class IPythonExecutor:
33
30
  def __init__(self, shell: InteractiveShell) -> None:
34
31
  self.shell = shell
35
32
 
36
- def execute(self, cell: str, *, prompts: CellPrompts | None = None) -> ExecutionReport:
33
+ def execute(self, cell: str) -> ExecutionReport:
37
34
  """Execute a cell, replay its visible output, and capture a structured result."""
38
35
  if not isinstance(cell, str) or not cell.strip():
39
36
  raise ValueError("cell must be a non-empty string")
40
37
 
41
- original_prompts = getattr(self.shell, "prompts", None)
42
38
  displayhook = self.shell.displayhook
43
39
  original_output_prompt = displayhook.write_output_prompt
44
- if prompts is not None and original_prompts is not None:
45
- self.shell.prompts = prompts
46
- displayhook.write_output_prompt = lambda: None
40
+ displayhook.write_output_prompt = lambda: None
47
41
  try:
48
42
  with capture_output() as captured:
49
- result = self.shell.run_cell(cell, store_history=False)
43
+ result = self.shell.run_cell(cell, store_history=True)
50
44
  finally:
51
- if prompts is not None and original_prompts is not None:
52
- self.shell.prompts = original_prompts
53
- displayhook.write_output_prompt = original_output_prompt
45
+ displayhook.write_output_prompt = original_output_prompt
54
46
 
55
47
  displays: list[str] = []
56
48
  for output in captured.outputs:
@@ -4,49 +4,19 @@ from __future__ import annotations
4
4
 
5
5
  import sys
6
6
 
7
- from IPython.terminal.prompts import Prompts
8
7
  from IPython.terminal.ptutils import IPythonPTLexer
9
8
  from prompt_toolkit.document import Document
10
9
  from prompt_toolkit.formatted_text import FormattedText, PygmentsTokens
11
10
  from prompt_toolkit.shortcuts import print_formatted_text
12
- from pygments.token import Token
13
11
 
14
12
 
15
- class CellPrompts(Prompts):
16
- """IPython prompts for one numbered model-authored cell."""
17
-
18
- def __init__(self, shell: object, number: int) -> None:
19
- super().__init__(shell)
20
- self.number = number
21
-
22
- def in_prompt_tokens(self):
23
- return [
24
- (Token.Prompt, "Python ["),
25
- (Token.PromptNum, str(self.number)),
26
- (Token.Prompt, "]: "),
27
- ]
28
-
29
- def continuation_prompt_tokens(self, width: int | None = None, **_: object):
30
- width = self._width() if width is None else width
31
- return [
32
- (Token.Prompt.Continuation, (" " * (width - 5)) + "...:"),
33
- (Token.Prompt.Padding, " "),
34
- ]
35
-
36
- def out_prompt_tokens(self):
37
- return [
38
- (Token.OutPrompt, "Shell ["),
39
- (Token.OutPromptNum, str(self.number)),
40
- (Token.OutPrompt, "]: "),
41
- ]
42
-
43
-
44
- def render_cell(shell: object, cell: str, prompts: CellPrompts) -> None:
13
+ def render_cell(shell: object, cell: str) -> None:
45
14
  """Render a cell with IPython's lexer, prompt tokens, and terminal style."""
46
15
  lexer = IPythonPTLexer().lex_document(Document(cell))
47
16
  pt_app = getattr(shell, "pt_app", None)
48
17
  style = pt_app.app.style if pt_app is not None else None
49
18
  sys.stdout.write(getattr(shell, "separate_in", "\n"))
19
+ prompts = shell.prompts
50
20
 
51
21
  for index, _line in enumerate(cell.split("\n")):
52
22
  prompt_tokens = (
@@ -58,8 +28,9 @@ def render_cell(shell: object, cell: str, prompts: CellPrompts) -> None:
58
28
  print_formatted_text(FormattedText(lexer(index)), style=style)
59
29
 
60
30
 
61
- def render_output_prompt(shell: object, prompts: CellPrompts) -> None:
31
+ def render_output_prompt(shell: object) -> None:
62
32
  """Render an output prompt with IPython's terminal style."""
63
33
  pt_app = getattr(shell, "pt_app", None)
64
34
  style = pt_app.app.style if pt_app is not None else None
65
- print_formatted_text(PygmentsTokens(prompts.out_prompt_tokens()), style=style, end="")
35
+ sys.stdout.write(getattr(shell, "separate_out", "") or "\n")
36
+ print_formatted_text(PygmentsTokens(shell.prompts.out_prompt_tokens()), style=style, end="")
@@ -2,18 +2,12 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from itertools import chain
6
-
7
5
  from rich.console import Console
8
6
  from rich.markdown import Markdown
9
- from rich.segment import Segments
10
7
  from rich.text import Text
11
8
 
12
9
  from .execution import ExecutionReport
13
- from .prompts import CellPrompts, render_output_prompt
14
-
15
-
16
- _MAXIMUM_OUTPUT_LINES = 10
10
+ from .prompts import render_output_prompt
17
11
 
18
12
 
19
13
  def _visible_output(report: ExecutionReport) -> str:
@@ -28,28 +22,20 @@ def _visible_output(report: ExecutionReport) -> str:
28
22
 
29
23
 
30
24
  class TerminalRenderer:
31
- """Render concise tool previews and Markdown answers to the active terminal."""
25
+ """Render tool output and Markdown answers to the active terminal."""
32
26
 
33
27
  def __init__(self) -> None:
34
28
  self.console = Console()
35
29
 
36
- def tool_output(self, report: ExecutionReport, shell: object, prompts: CellPrompts) -> None:
37
- """Show a bounded preview while leaving the report itself intact for the model."""
30
+ def tool_output(self, report: ExecutionReport, shell: object) -> None:
31
+ """Show the complete tool output."""
38
32
  visible = _visible_output(report)
39
33
  if not visible:
40
34
  return
41
35
  output = Text.from_ansi(visible)
42
- options = self.console.options
43
- complete = self.console.render_lines(output, options, pad=False, new_lines=True)
44
- preview = complete[:_MAXIMUM_OUTPUT_LINES]
45
36
  if report.ok:
46
- render_output_prompt(shell, prompts)
47
- self.console.print(Segments(chain.from_iterable(preview)), end="")
48
- if len(complete) > len(preview):
49
- self.console.print(
50
- f"[dim]{len(preview)} of {len(complete)} lines shown; "
51
- "the complete result was returned to the model.[/dim]"
52
- )
37
+ render_output_prompt(shell)
38
+ self.console.print(output)
53
39
 
54
40
  def assistant(self, text: str) -> None:
55
41
  """Render the final model response as terminal Markdown."""
@@ -13,7 +13,7 @@ from langchain_core.messages import AIMessage, BaseMessage, HumanMessage, System
13
13
  from langchain_core.runnables import Runnable
14
14
 
15
15
  from .execution import ExecutionReport, IPythonExecutor
16
- from .prompts import CellPrompts, render_cell
16
+ from .prompts import render_cell
17
17
  from .rendering import TerminalRenderer
18
18
 
19
19
 
@@ -134,11 +134,10 @@ class Session:
134
134
  return _tool_error("InvalidArguments", "ipython requires a string cell argument")
135
135
 
136
136
  cell = arguments["cell"]
137
- prompts = CellPrompts(self.shell, self.shell.execution_count - 1)
138
- render_cell(self.shell, cell, prompts)
137
+ render_cell(self.shell, cell)
139
138
  try:
140
- report = self.executor.execute(cell, prompts=prompts)
139
+ report = self.executor.execute(cell)
141
140
  except Exception as error: # The failure must be returned to the model, not end the session.
142
141
  report = _tool_error(type(error).__name__, str(error))
143
- self.renderer.tool_output(report, self.shell, prompts)
142
+ self.renderer.tool_output(report, self.shell)
144
143
  return report
File without changes
File without changes
File without changes
File without changes