pi-repl-py 0.6.6 → 0.6.7

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-repl-py",
3
- "version": "0.6.6",
3
+ "version": "0.6.7",
4
4
  "type": "module",
5
5
  "description": "A pi extension with a single tool: execute, running a TypeScript host with a persistent Python (ipykernel) evaluator and a user-configurable toolbox of functions.",
6
6
  "keywords": [
@@ -20,12 +20,12 @@ function resolvePythonPath(_cwd: string | undefined): string {
20
20
  return process.env.PYTHON ?? "python3";
21
21
  }
22
22
 
23
- const DEFAULT_MAX_OUTPUT_CHARS = 65536;
23
+ const DEFAULT_MAX_OUTPUT_CHARS = 46080;
24
24
  /** Per-line cap: one genuinely oversized line must not own the channel budget, while legitimately long
25
25
  * REPL output (JSON, reprs, errors) still fits under the cap in one piece. Generous enough that only
26
26
  * pathological giant lines are trimmed, unlike pi's grep where the line cap keeps matches terse. */
27
27
  export const MAX_OUTPUT_LINE_CHARS = 4096;
28
- const ABORT_GRACE_MS = 500;
28
+ const ABORT_GRACE_MS = 20_000;
29
29
  const DEFAULT_SNAPSHOT_DEBOUNCE_MS = 1500;
30
30
 
31
31
  interface EngineExecuteError {
@@ -50,7 +50,7 @@ export interface ExecuteOptions {
50
50
  /** Aborting cancels the cell via kernel interrupt; the namespace is preserved. */
51
51
  signal?: AbortSignal;
52
52
  onStream?: (chunk: string, name: "stdout" | "stderr") => void;
53
- /** Cap stdout / stderr / result at this many characters. Default 65536. */
53
+ /** Cap stdout / stderr / result at this many characters. Default 45K. */
54
54
  maxOutputChars?: number;
55
55
  }
56
56
 
@@ -38,9 +38,10 @@ function loadHelperEntries(dir?: string): HelperEntry[] {
38
38
 
39
39
  /** The prompt-facing list, one bullet per loaded file (verbatim description, or an introspection pointer). */
40
40
  export function buildHelpersMap(dir?: string): string[] {
41
+ // pi renders each prompt guideline as "- <line>"; these lines are bare, no bullet prefix.
41
42
  return loadHelperEntries(dir).map((t) =>
42
43
  t.description
43
- ? `- ${t.description.replace(/\n/g, "\n ")}`
44
- : `- ${t.name} (no description, inspect it with print(${t.name}.__doc__))`,
44
+ ? t.description.replace(/\n/g, "\n ")
45
+ : `${t.name} (no description, inspect it with print(${t.name}.__doc__))`,
45
46
  );
46
47
  }
@@ -1,52 +1,23 @@
1
- // --- execute tool: the model-facing contract + workspace doctrine (pure, no pi/helper dep) ---
1
+ // --- execute tool: the model-facing contract, shaped exactly like pi's built-in tools ---
2
+ // description = rich short behavior; promptSnippet = one-liner; guidelines = flat bullets.
2
3
 
3
4
  export const executeToolDescription =
4
- "Execute Python cells in a persistent ipython kernel; state survives across cells and turns, replacing " +
5
- "the default read, bash, edit, write, and search tools. Let a cell's returned value prove the work, " +
6
- "not prose restating it.";
5
+ "Execute Python cells in a persistent Python shell that is your entire workspace: it is where you read, " +
6
+ "write, run, and move, all in one instrument. The state you build, files, and subprocesses survive " +
7
+ "from one call to the next. Returns stdout, stderr, and the value of the last expression. Output is " +
8
+ "truncated to 45K with a marker.";
7
9
 
8
- export const executePromptSnippet =
9
- "Execute Python cells in a persistent ipython kernel (replaces read, bash, edit, write, and search; state survives across cells and turns)";
10
+ export const executePromptSnippet = "Execute Python in a persistent shell (read, write, run, search, and more)";
10
11
 
11
- // --- the workspace doctrine riding the execute tool ---
12
+ // --- the model-facing guidelines, flat bullets like pi's own tool contributions ---
12
13
  export function buildPromptGuidelines(preloaded: string[]): string[] {
13
14
  return [
14
- "## Your only workspace",
15
- "You are an engineer in a persistent Python REPL. `execute` is the only callable surface, it replaces read, bash, edit, write, and search. What you define (variables, functions, imports) survives across cells and turns, so define any function once and call it in later cells. The work is proven by the result each cell returns, and by nothing else.",
16
- "",
17
- "## Reason, then say, then stop",
18
- "Reason inside the cell, not the transcript: do the thinking in variables and filters, return only the outcome. End on an assignment, a bare expression auto-prints. Keep the reasoning you need, drop the rest, the returned result is the evidence of the work, not the words around it.",
19
- "",
20
- "## The environment answers you",
21
- "The cell's output is the ground truth, what actually ran, what errored, what came back. Trust it over any narrative: if a cell already proved it, point at that. When you're unsure what a fetch contains, read a slice, don't guess and don't dump it whole to 'check'.",
22
- "",
23
- "## Gather, slice, decide",
24
- "Fetch into a variable, never into the transcript. Search results, reads, command output, file contents, assign. A bare expression prints, so end those cells on the assignment. Then advance on a bounded slice: print only the fragment that decides the next step, hold the rest in the variable, peel into the pieces you need without re-fetching, and when the reasoning lands, print the conclusion.",
25
- "",
26
- "Reading whole is fine when the task needs all of it, hold it and reason on it; the point isn't to never read fully, it's to not re-fetch the same big thing twice.",
27
- "",
28
- "## Output format",
29
- "In reply text: the conclusion and the handful of results that prove it, the slice you acted on, the returned value, a one-line takeaway. Do not transcribe the run, restate every variable, or narrate what the cell already showed.",
30
- "",
31
- "## Edits and repo discipline",
32
- "Surgical old-text/new-text: read the region, fix an exact unique anchor that appears once, replace, verify. Many small edits over one big rewrite, a parse error can strand an anchor; after an error, read the file back from disk first. Make the smallest valid change, preserve conventions, never invent files, APIs, conventions, or test results. Prune generated dirs when walking trees. Pass a `timeout` to any `subprocess.run(...)`, a silent cell must die, not hang.",
33
- "",
34
- "## Print is expensive",
35
- "Every token you print is spent from the context you need for the turns to come, and it never comes back. Treat printing as debt, not reward. Print only the exact fragment the next decision consumes and hold the whole in a variable. Every other print is waste, it buys nothing and closes the room you have left to think. Ask before you print: does this decide the next step, or is it just noise? When it is noise, cut it. When in doubt, cut it. A tight transcript is the sign you actually worked; a bloated one is the sign you did not.",
36
- "",
37
- ...(preloaded.length
38
- ? [
39
- "## Helpers",
40
- "These helpers are already defined in the workspace namespace. Use them by name as you would any other loaded function, class, or variable. Their code already executed at kernel boot. Descriptions appear below.",
41
- "",
42
- ...preloaded,
43
- "",
44
- ]
45
- : []),
46
- "## Environment & rescue",
47
- "The evaluator runs in a project-local venv, not the system Python. Do not install a project's dependencies into the evaluator; run external projects through their own interface. If output begins with `<repl_engine_reset>`, the kernel rebuilt, re-verify a revived variable before reusing it.",
48
- "",
49
- "## These rules are the surface",
50
- "The rules above are the surface of how this workspace works, not the whole of it. Internalize their intent, apply it to cases they don't mention, and follow them diligently.",
15
+ "State persists across cells, so define a function once and keep building on it.",
16
+ "Find, filter, fetch, read: narrow the output in Python, then print the exact slice you need.",
17
+ "Keep the result in a variable and reuse it, instead of re-fetching the same thing.",
18
+ "Make surgical, precise changes over rewrites or whole-file dumps: a small unique anchor, replace, verify, read the file back before trusting it.",
19
+ "The evaluator runs in a project-local venv. Do not install a project's dependencies into it; run external projects through their own interface. If output begins with <repl_engine_reset>, the kernel rebuilt; re-verify a revived variable.",
20
+ ...(preloaded.length ? ["Preloaded helpers, use them as any loaded function or variable:", ...preloaded] : []),
21
+ "Be concise.",
51
22
  ];
52
23
  }