python-agent-harness 1.5.5.6__tar.gz → 1.5.5.7__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.
- {python_agent_harness-1.5.5.6/python_agent_harness.egg-info → python_agent_harness-1.5.5.7}/PKG-INFO +1 -1
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/pyproject.toml +1 -1
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/__init__.py +1 -1
- python_agent_harness-1.5.5.7/python_agent_harness/tools/lsp.py +273 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7/python_agent_harness.egg-info}/PKG-INFO +1 -1
- python_agent_harness-1.5.5.6/python_agent_harness/tools/lsp.py +0 -243
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/LICENSE +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/README.md +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/__main__.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/agent.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/cli.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/client.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/commands.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/config.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/context_manager.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/diffrender.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/lsp/__init__.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/lsp/client.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/lsp/config.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/lsp/manager.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/mcp/__init__.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/mcp/client.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/mcp/config.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/mcp/manager.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/models.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/persistence.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/planmode.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/prompts/agent.md +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/prompts/agents/reviewer.md +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/prompts/build-switch.md +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/prompts/commands/explain.md +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/prompts/compact.md +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/prompts/initialize.md +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/prompts/plan-mode.md +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/prompts/plan.md +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/prompts/review.md +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/prompts/subagent.md +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/prompts/summary.md +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/prompts/task-completion-rules.md +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/prompts/title.md +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/prompts.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/session.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/subagent.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/token_estimator.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tool_runner.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/__init__.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/agent_tool.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/base.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/bash.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/bash_win.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/diffapply.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/edit.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/edit_mac.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/edit_win.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/filesystem.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/glob.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/glob_mac.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/glob_win.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/grep.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/grep_mac.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/grep_win.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/insert.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/mcp.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/mkdir.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/planexit.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/question.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/read.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/skill.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/todo.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/write.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tui/__init__.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tui/commands.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tui/core.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tui/input.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tui/render.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness.egg-info/SOURCES.txt +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness.egg-info/dependency_links.txt +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness.egg-info/entry_points.txt +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness.egg-info/requires.txt +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness.egg-info/top_level.txt +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/setup.cfg +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/tests/test_agents_md.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/tests/test_cli.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/tests/test_client.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/tests/test_commands.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/tests/test_concurrent_subagents.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/tests/test_config.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/tests/test_context_rules.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/tests/test_custom_agents.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/tests/test_diffrender.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/tests/test_filesystem.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/tests/test_invariants.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/tests/test_lsp.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/tests/test_mcp.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/tests/test_models.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/tests/test_persistence.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/tests/test_planmode.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/tests/test_prompts.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/tests/test_scenarios.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/tests/test_session.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/tests/test_subagent.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/tests/test_subagent_isolation.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/tests/test_todos_scope.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/tests/test_token_estimator.py +0 -0
- {python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/tests/test_tools_misc.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "python-agent-harness"
|
|
7
|
-
version = "1.5.5.
|
|
7
|
+
version = "1.5.5.7"
|
|
8
8
|
description = "A lightweight, hackable mini-OpenCode written in Python."
|
|
9
9
|
authors = [
|
|
10
10
|
{name = "Huming Chen", email = "chenhuming@gmail.com"}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
"""Agent-facing LSP code-intelligence tool.
|
|
2
|
+
|
|
3
|
+
A small OpenCode-style surface over the built-in LSP client. The model sees
|
|
4
|
+
1-based file/line/character coordinates; the client translates them to LSP's
|
|
5
|
+
0-based representation.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import contextlib
|
|
11
|
+
import json
|
|
12
|
+
import os
|
|
13
|
+
from collections.abc import Callable
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import Any
|
|
16
|
+
from urllib.parse import unquote, urlparse
|
|
17
|
+
|
|
18
|
+
from ..lsp import LSPError, get_client
|
|
19
|
+
from .base import Tool, ToolContext
|
|
20
|
+
|
|
21
|
+
OPERATIONS = (
|
|
22
|
+
"goToDefinition",
|
|
23
|
+
"findReferences",
|
|
24
|
+
"hover",
|
|
25
|
+
"documentSymbol",
|
|
26
|
+
"workspaceSymbol",
|
|
27
|
+
"goToImplementation",
|
|
28
|
+
"prepareCallHierarchy",
|
|
29
|
+
"incomingCalls",
|
|
30
|
+
"outgoingCalls",
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
DESCRIPTION = """Interact with Language Server Protocol (LSP) servers to get code intelligence features.
|
|
34
|
+
|
|
35
|
+
Supported operations:
|
|
36
|
+
- goToDefinition: Find where a symbol is defined
|
|
37
|
+
- findReferences: Find all references to a symbol
|
|
38
|
+
- hover: Get hover information (documentation, type info) for a symbol
|
|
39
|
+
- documentSymbol: Get all symbols (functions, classes, variables) in a document
|
|
40
|
+
- workspaceSymbol: List project-wide symbols matching a query string
|
|
41
|
+
- goToImplementation: Find implementations of an interface or abstract method
|
|
42
|
+
- prepareCallHierarchy: Get call hierarchy item at a position (functions/methods)
|
|
43
|
+
- incomingCalls: Find all functions/methods that call the function at a position
|
|
44
|
+
- outgoingCalls: Find all functions/methods called by the function at a position
|
|
45
|
+
|
|
46
|
+
All position-based operations use 1-based line and character numbers, as shown in editors.
|
|
47
|
+
workspaceSymbol uses file_path only to select the workspace/LSP server and query is optional.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
PARAMETERS = {
|
|
51
|
+
"type": "object",
|
|
52
|
+
"properties": {
|
|
53
|
+
"operation": {
|
|
54
|
+
"type": "string",
|
|
55
|
+
"enum": list(OPERATIONS),
|
|
56
|
+
"description": "The LSP operation to perform",
|
|
57
|
+
},
|
|
58
|
+
"file_path": {
|
|
59
|
+
"type": "string",
|
|
60
|
+
"description": "The absolute or relative path to the file",
|
|
61
|
+
},
|
|
62
|
+
"line": {
|
|
63
|
+
"type": "integer",
|
|
64
|
+
"minimum": 1,
|
|
65
|
+
"description": (
|
|
66
|
+
"The line number (1-based, as shown in editors). "
|
|
67
|
+
"Required for all operations except workspaceSymbol."
|
|
68
|
+
),
|
|
69
|
+
},
|
|
70
|
+
"character": {
|
|
71
|
+
"type": "integer",
|
|
72
|
+
"minimum": 1,
|
|
73
|
+
"description": (
|
|
74
|
+
"The character offset (1-based, as shown in editors). "
|
|
75
|
+
"Required for all operations except workspaceSymbol."
|
|
76
|
+
),
|
|
77
|
+
},
|
|
78
|
+
"query": {
|
|
79
|
+
"type": "string",
|
|
80
|
+
"description": "Search query for workspaceSymbol. Empty string requests all symbols.",
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
"required": ["operation", "file_path"],
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
# Operations that require a position (line/character).
|
|
87
|
+
_POSITION_OPS = frozenset(o for o in OPERATIONS if o != "workspaceSymbol")
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def _uri_to_path(uri: str) -> str:
|
|
91
|
+
parsed = urlparse(uri)
|
|
92
|
+
if parsed.scheme == "file":
|
|
93
|
+
path = unquote(parsed.path)
|
|
94
|
+
if os.name == "nt" and path.startswith("/") and len(path) >= 3 and path[2] == ":":
|
|
95
|
+
path = path[1:]
|
|
96
|
+
return os.path.normpath(path)
|
|
97
|
+
return uri
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _jsonable(value: Any) -> Any:
|
|
101
|
+
if isinstance(value, list):
|
|
102
|
+
return [_jsonable(v) for v in value]
|
|
103
|
+
if isinstance(value, dict):
|
|
104
|
+
return {k: _jsonable(v) for k, v in value.items()}
|
|
105
|
+
return value
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _resolve_path(raw_path: str, cwd: str) -> str:
|
|
109
|
+
if not os.path.isabs(raw_path):
|
|
110
|
+
return os.path.realpath(os.path.abspath(os.path.join(cwd, raw_path)))
|
|
111
|
+
return os.path.realpath(raw_path)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _to_lsp_position(lines: list[str], line: int, character: int, encoding: str) -> dict[str, int]:
|
|
115
|
+
source_line = lines[line - 1].rstrip("\r\n")
|
|
116
|
+
py_index = min(character - 1, len(source_line))
|
|
117
|
+
if encoding == "utf-8":
|
|
118
|
+
lsp_character = len(source_line[:py_index].encode("utf-8"))
|
|
119
|
+
elif encoding == "utf-32":
|
|
120
|
+
lsp_character = py_index
|
|
121
|
+
else:
|
|
122
|
+
lsp_character = len(source_line[:py_index].encode("utf-16-le")) // 2
|
|
123
|
+
return {"line": line - 1, "character": lsp_character}
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def _format_result(result: Any, operation: str) -> str:
|
|
127
|
+
if result is None:
|
|
128
|
+
result = []
|
|
129
|
+
if isinstance(result, (dict, list)) and not result:
|
|
130
|
+
return f"No results found for {operation}"
|
|
131
|
+
return json.dumps(_jsonable(result), ensure_ascii=False, indent=2)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
# --- Operation handlers -------------------------------------------------
|
|
135
|
+
# Each handler receives (client, uri, position, args) and returns the raw
|
|
136
|
+
# LSP response (or a str error message for early-exit cases like empty
|
|
137
|
+
# call-hierarchy preparation).
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def _op_definition(client, uri, position, args) -> Any:
|
|
141
|
+
return client.request(
|
|
142
|
+
"textDocument/definition",
|
|
143
|
+
{"textDocument": {"uri": uri}, "position": position},
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def _op_references(client, uri, position, args) -> Any:
|
|
148
|
+
return client.request(
|
|
149
|
+
"textDocument/references",
|
|
150
|
+
{
|
|
151
|
+
"textDocument": {"uri": uri},
|
|
152
|
+
"position": position,
|
|
153
|
+
"context": {"includeDeclaration": True},
|
|
154
|
+
},
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def _op_hover(client, uri, position, args) -> Any:
|
|
159
|
+
return client.request(
|
|
160
|
+
"textDocument/hover", {"textDocument": {"uri": uri}, "position": position}
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def _op_document_symbol(client, uri, position, args) -> Any:
|
|
165
|
+
return client.request("textDocument/documentSymbol", {"textDocument": {"uri": uri}})
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def _op_workspace_symbol(client, uri, position, args) -> Any:
|
|
169
|
+
return client.request("workspace/symbol", {"query": str(args.get("query", ""))})
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def _op_implementation(client, uri, position, args) -> Any:
|
|
173
|
+
return client.request(
|
|
174
|
+
"textDocument/implementation",
|
|
175
|
+
{"textDocument": {"uri": uri}, "position": position},
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def _op_prepare_call_hierarchy(client, uri, position, args) -> Any:
|
|
180
|
+
return client.request(
|
|
181
|
+
"textDocument/prepareCallHierarchy",
|
|
182
|
+
{"textDocument": {"uri": uri}, "position": position},
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def _op_call_hierarchy(direction: str) -> Callable[..., Any]:
|
|
187
|
+
def handler(client, uri, position, args) -> Any:
|
|
188
|
+
prepared = client.request(
|
|
189
|
+
"textDocument/prepareCallHierarchy",
|
|
190
|
+
{"textDocument": {"uri": uri}, "position": position},
|
|
191
|
+
)
|
|
192
|
+
if not isinstance(prepared, list) or not prepared:
|
|
193
|
+
return "No call hierarchy item found at this position"
|
|
194
|
+
item = prepared[0]
|
|
195
|
+
method = (
|
|
196
|
+
"callHierarchy/incomingCalls"
|
|
197
|
+
if direction == "incoming"
|
|
198
|
+
else "callHierarchy/outgoingCalls"
|
|
199
|
+
)
|
|
200
|
+
return client.request(method, {"item": item})
|
|
201
|
+
|
|
202
|
+
return handler
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
_DISPATCH: dict[str, Callable[..., Any]] = {
|
|
206
|
+
"goToDefinition": _op_definition,
|
|
207
|
+
"findReferences": _op_references,
|
|
208
|
+
"hover": _op_hover,
|
|
209
|
+
"documentSymbol": _op_document_symbol,
|
|
210
|
+
"workspaceSymbol": _op_workspace_symbol,
|
|
211
|
+
"goToImplementation": _op_implementation,
|
|
212
|
+
"prepareCallHierarchy": _op_prepare_call_hierarchy,
|
|
213
|
+
"incomingCalls": _op_call_hierarchy("incoming"),
|
|
214
|
+
"outgoingCalls": _op_call_hierarchy("outgoing"),
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
class LSP(Tool):
|
|
219
|
+
name = "LSP"
|
|
220
|
+
description = DESCRIPTION
|
|
221
|
+
parameters = PARAMETERS
|
|
222
|
+
is_readonly = True
|
|
223
|
+
|
|
224
|
+
def run(self, args: dict, ctx: ToolContext) -> str:
|
|
225
|
+
operation = args.get("operation")
|
|
226
|
+
if operation not in OPERATIONS:
|
|
227
|
+
return f"Error: unsupported LSP operation {operation!r}"
|
|
228
|
+
|
|
229
|
+
raw_path = str(args.get("file_path", ""))
|
|
230
|
+
if not raw_path:
|
|
231
|
+
return "Error: file_path must not be empty"
|
|
232
|
+
path = _resolve_path(raw_path, ctx.cwd)
|
|
233
|
+
if not os.path.isfile(path):
|
|
234
|
+
return f"Error: File not found: {raw_path}"
|
|
235
|
+
|
|
236
|
+
needs_position = operation in _POSITION_OPS
|
|
237
|
+
|
|
238
|
+
try:
|
|
239
|
+
line = int(args.get("line", 1))
|
|
240
|
+
character = int(args.get("character", 1))
|
|
241
|
+
except (TypeError, ValueError):
|
|
242
|
+
return "Error: line and character must be integers"
|
|
243
|
+
if needs_position and (line < 1 or character < 1):
|
|
244
|
+
return "Error: line and character must be >= 1"
|
|
245
|
+
|
|
246
|
+
try:
|
|
247
|
+
text = Path(path).read_text(encoding="utf-8", errors="replace")
|
|
248
|
+
except (OSError, UnicodeError) as e:
|
|
249
|
+
return f"Error: failed to read {raw_path}: {e}"
|
|
250
|
+
lines = text.splitlines(keepends=True)
|
|
251
|
+
if needs_position and line > len(lines):
|
|
252
|
+
return f"Error: line {line} is beyond end of file ({len(lines)} lines)"
|
|
253
|
+
|
|
254
|
+
try:
|
|
255
|
+
client, _ = get_client(path, ctx.cwd, ctx.config_path)
|
|
256
|
+
uri = Path(path).as_uri()
|
|
257
|
+
client.open_document(uri, text)
|
|
258
|
+
try:
|
|
259
|
+
position: dict[str, int] | None = None
|
|
260
|
+
if needs_position:
|
|
261
|
+
position = _to_lsp_position(lines, line, character, client.position_encoding)
|
|
262
|
+
|
|
263
|
+
handler = _DISPATCH[operation]
|
|
264
|
+
result = handler(client, uri, position, args)
|
|
265
|
+
finally:
|
|
266
|
+
with contextlib.suppress(Exception):
|
|
267
|
+
client.close_document(uri)
|
|
268
|
+
except (LSPError, ValueError) as e:
|
|
269
|
+
return f"Error: {e}"
|
|
270
|
+
|
|
271
|
+
if isinstance(result, str):
|
|
272
|
+
return result
|
|
273
|
+
return _format_result(result, operation)
|
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
"""Agent-facing LSP code-intelligence tool.
|
|
2
|
-
|
|
3
|
-
A small OpenCode-style surface over the built-in LSP client. The model sees
|
|
4
|
-
1-based file/line/character coordinates; the client translates them to LSP's
|
|
5
|
-
0-based representation.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from __future__ import annotations
|
|
9
|
-
|
|
10
|
-
import contextlib
|
|
11
|
-
import json
|
|
12
|
-
import os
|
|
13
|
-
from pathlib import Path
|
|
14
|
-
from typing import Any
|
|
15
|
-
from urllib.parse import unquote, urlparse
|
|
16
|
-
|
|
17
|
-
from ..lsp import LSPError, get_client
|
|
18
|
-
from .base import Tool, ToolContext
|
|
19
|
-
|
|
20
|
-
OPERATIONS = (
|
|
21
|
-
"goToDefinition",
|
|
22
|
-
"findReferences",
|
|
23
|
-
"hover",
|
|
24
|
-
"documentSymbol",
|
|
25
|
-
"workspaceSymbol",
|
|
26
|
-
"goToImplementation",
|
|
27
|
-
"prepareCallHierarchy",
|
|
28
|
-
"incomingCalls",
|
|
29
|
-
"outgoingCalls",
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
DESCRIPTION = """Interact with Language Server Protocol (LSP) servers to get code intelligence features.
|
|
33
|
-
|
|
34
|
-
Supported operations:
|
|
35
|
-
- goToDefinition: Find where a symbol is defined
|
|
36
|
-
- findReferences: Find all references to a symbol
|
|
37
|
-
- hover: Get hover information (documentation, type info) for a symbol
|
|
38
|
-
- documentSymbol: Get all symbols (functions, classes, variables) in a document
|
|
39
|
-
- workspaceSymbol: List project-wide symbols matching a query string
|
|
40
|
-
- goToImplementation: Find implementations of an interface or abstract method
|
|
41
|
-
- prepareCallHierarchy: Get call hierarchy item at a position (functions/methods)
|
|
42
|
-
- incomingCalls: Find all functions/methods that call the function at a position
|
|
43
|
-
- outgoingCalls: Find all functions/methods called by the function at a position
|
|
44
|
-
|
|
45
|
-
All position-based operations use 1-based line and character numbers, as shown in editors.
|
|
46
|
-
workspaceSymbol uses file_path only to select the workspace/LSP server and query is optional.
|
|
47
|
-
"""
|
|
48
|
-
|
|
49
|
-
PARAMETERS = {
|
|
50
|
-
"type": "object",
|
|
51
|
-
"properties": {
|
|
52
|
-
"operation": {
|
|
53
|
-
"type": "string",
|
|
54
|
-
"enum": list(OPERATIONS),
|
|
55
|
-
"description": "The LSP operation to perform",
|
|
56
|
-
},
|
|
57
|
-
"file_path": {
|
|
58
|
-
"type": "string",
|
|
59
|
-
"description": "The absolute or relative path to the file",
|
|
60
|
-
},
|
|
61
|
-
"line": {
|
|
62
|
-
"type": "integer",
|
|
63
|
-
"minimum": 1,
|
|
64
|
-
"description": (
|
|
65
|
-
"The line number (1-based, as shown in editors). "
|
|
66
|
-
"Required for all operations except workspaceSymbol."
|
|
67
|
-
),
|
|
68
|
-
},
|
|
69
|
-
"character": {
|
|
70
|
-
"type": "integer",
|
|
71
|
-
"minimum": 1,
|
|
72
|
-
"description": (
|
|
73
|
-
"The character offset (1-based, as shown in editors). "
|
|
74
|
-
"Required for all operations except workspaceSymbol."
|
|
75
|
-
),
|
|
76
|
-
},
|
|
77
|
-
"query": {
|
|
78
|
-
"type": "string",
|
|
79
|
-
"description": "Search query for workspaceSymbol. Empty string requests all symbols.",
|
|
80
|
-
},
|
|
81
|
-
},
|
|
82
|
-
"required": ["operation", "file_path"],
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
def _uri_to_path(uri: str) -> str:
|
|
87
|
-
parsed = urlparse(uri)
|
|
88
|
-
if parsed.scheme == "file":
|
|
89
|
-
path = unquote(parsed.path)
|
|
90
|
-
if os.name == "nt" and path.startswith("/") and len(path) >= 3 and path[2] == ":":
|
|
91
|
-
path = path[1:]
|
|
92
|
-
return os.path.normpath(path)
|
|
93
|
-
return uri
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
def _jsonable(value: Any) -> Any:
|
|
97
|
-
if isinstance(value, list):
|
|
98
|
-
return [_jsonable(v) for v in value]
|
|
99
|
-
if isinstance(value, dict):
|
|
100
|
-
return {k: _jsonable(v) for k, v in value.items()}
|
|
101
|
-
return value
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
class LSP(Tool):
|
|
105
|
-
name = "LSP"
|
|
106
|
-
description = DESCRIPTION
|
|
107
|
-
parameters = PARAMETERS
|
|
108
|
-
is_readonly = True
|
|
109
|
-
|
|
110
|
-
def run(self, args: dict, ctx: ToolContext) -> str:
|
|
111
|
-
operation = args.get("operation")
|
|
112
|
-
if operation not in OPERATIONS:
|
|
113
|
-
return f"Error: unsupported LSP operation {operation!r}"
|
|
114
|
-
|
|
115
|
-
raw_path = str(args.get("file_path", ""))
|
|
116
|
-
if not raw_path:
|
|
117
|
-
return "Error: file_path must not be empty"
|
|
118
|
-
path = (
|
|
119
|
-
os.path.realpath(os.path.abspath(os.path.join(ctx.cwd, raw_path)))
|
|
120
|
-
if not os.path.isabs(raw_path)
|
|
121
|
-
else os.path.realpath(raw_path)
|
|
122
|
-
)
|
|
123
|
-
if not os.path.isfile(path):
|
|
124
|
-
return f"Error: File not found: {raw_path}"
|
|
125
|
-
|
|
126
|
-
# workspaceSymbol is project-wide: it uses file_path only to select
|
|
127
|
-
# the workspace/server and ignores line/character, so it skips all
|
|
128
|
-
# position validation and coordinate conversion below.
|
|
129
|
-
needs_position = operation != "workspaceSymbol"
|
|
130
|
-
|
|
131
|
-
# Keep the agent-facing contract 1-based, while the LSP protocol is 0-based.
|
|
132
|
-
try:
|
|
133
|
-
line = int(args.get("line", 1))
|
|
134
|
-
character = int(args.get("character", 1))
|
|
135
|
-
except (TypeError, ValueError):
|
|
136
|
-
return "Error: line and character must be integers"
|
|
137
|
-
if needs_position and (line < 1 or character < 1):
|
|
138
|
-
return "Error: line and character must be >= 1"
|
|
139
|
-
|
|
140
|
-
# Validate the requested line before spinning up a server so a bad
|
|
141
|
-
# position fails fast even when no LSP binary is installed.
|
|
142
|
-
try:
|
|
143
|
-
text = Path(path).read_text(encoding="utf-8", errors="replace")
|
|
144
|
-
except (OSError, UnicodeError) as e:
|
|
145
|
-
return f"Error: failed to read {raw_path}: {e}"
|
|
146
|
-
lines = text.splitlines(keepends=True)
|
|
147
|
-
if needs_position and line > len(lines):
|
|
148
|
-
return f"Error: line {line} is beyond end of file ({len(lines)} lines)"
|
|
149
|
-
|
|
150
|
-
try:
|
|
151
|
-
client, _ = get_client(path, ctx.cwd, ctx.config_path)
|
|
152
|
-
uri = Path(path).as_uri()
|
|
153
|
-
client.open_document(uri, text)
|
|
154
|
-
try:
|
|
155
|
-
# LSP positions are 0-based. Character conversion to the
|
|
156
|
-
# negotiated encoding is done here using the source line.
|
|
157
|
-
# Skipped entirely for workspaceSymbol, which sends no position.
|
|
158
|
-
position: dict[str, int] | None = None
|
|
159
|
-
if needs_position:
|
|
160
|
-
source_line = lines[line - 1].rstrip("\r\n")
|
|
161
|
-
py_index = min(character - 1, len(source_line))
|
|
162
|
-
if client.position_encoding == "utf-8":
|
|
163
|
-
lsp_character = len(source_line[:py_index].encode("utf-8"))
|
|
164
|
-
elif client.position_encoding == "utf-32":
|
|
165
|
-
lsp_character = py_index
|
|
166
|
-
else:
|
|
167
|
-
lsp_character = len(source_line[:py_index].encode("utf-16-le")) // 2
|
|
168
|
-
position = {"line": line - 1, "character": lsp_character}
|
|
169
|
-
|
|
170
|
-
if operation == "goToDefinition":
|
|
171
|
-
result = client.request(
|
|
172
|
-
"textDocument/definition",
|
|
173
|
-
{"textDocument": {"uri": uri}, "position": position},
|
|
174
|
-
)
|
|
175
|
-
elif operation == "findReferences":
|
|
176
|
-
result = client.request(
|
|
177
|
-
"textDocument/references",
|
|
178
|
-
{
|
|
179
|
-
"textDocument": {"uri": uri},
|
|
180
|
-
"position": position,
|
|
181
|
-
"context": {"includeDeclaration": True},
|
|
182
|
-
},
|
|
183
|
-
)
|
|
184
|
-
elif operation == "hover":
|
|
185
|
-
result = client.request(
|
|
186
|
-
"textDocument/hover", {"textDocument": {"uri": uri}, "position": position}
|
|
187
|
-
)
|
|
188
|
-
elif operation == "documentSymbol":
|
|
189
|
-
result = client.request(
|
|
190
|
-
"textDocument/documentSymbol", {"textDocument": {"uri": uri}}
|
|
191
|
-
)
|
|
192
|
-
elif operation == "workspaceSymbol":
|
|
193
|
-
result = client.request(
|
|
194
|
-
"workspace/symbol", {"query": str(args.get("query", ""))}
|
|
195
|
-
)
|
|
196
|
-
elif operation == "goToImplementation":
|
|
197
|
-
result = client.request(
|
|
198
|
-
"textDocument/implementation",
|
|
199
|
-
{"textDocument": {"uri": uri}, "position": position},
|
|
200
|
-
)
|
|
201
|
-
elif operation == "prepareCallHierarchy":
|
|
202
|
-
result = client.request(
|
|
203
|
-
"textDocument/prepareCallHierarchy",
|
|
204
|
-
{"textDocument": {"uri": uri}, "position": position},
|
|
205
|
-
)
|
|
206
|
-
else:
|
|
207
|
-
prepared = client.request(
|
|
208
|
-
"textDocument/prepareCallHierarchy",
|
|
209
|
-
{"textDocument": {"uri": uri}, "position": position},
|
|
210
|
-
)
|
|
211
|
-
# A spec-compliant server returns a list or null; guard
|
|
212
|
-
# against a non-list (truthy but unsubscriptable) reply so
|
|
213
|
-
# a misbehaving server cannot raise past the LSPError guard.
|
|
214
|
-
if not isinstance(prepared, list) or not prepared:
|
|
215
|
-
return "No call hierarchy item found at this position"
|
|
216
|
-
item = prepared[0]
|
|
217
|
-
method = (
|
|
218
|
-
"callHierarchy/incomingCalls"
|
|
219
|
-
if operation == "incomingCalls"
|
|
220
|
-
else "callHierarchy/outgoingCalls"
|
|
221
|
-
)
|
|
222
|
-
result = client.request(method, {"item": item})
|
|
223
|
-
finally:
|
|
224
|
-
# Close-after-use: keeping every inspected file open would grow
|
|
225
|
-
# the (long-lived, cached) server's document set unbounded over a
|
|
226
|
-
# session. Best-effort — a failed close must not mask a result
|
|
227
|
-
# or a raised LSPError.
|
|
228
|
-
with contextlib.suppress(Exception):
|
|
229
|
-
client.close_document(uri)
|
|
230
|
-
except (LSPError, ValueError) as e:
|
|
231
|
-
# LSPError: no server / server failure. ValueError: a malformed
|
|
232
|
-
# lsp.servers entry surfacing on this lazy get_client call (it is
|
|
233
|
-
# also validated eagerly at session start, but a Session built
|
|
234
|
-
# outside make_session may reach here first).
|
|
235
|
-
return f"Error: {e}"
|
|
236
|
-
|
|
237
|
-
if result is None:
|
|
238
|
-
result = []
|
|
239
|
-
if isinstance(result, dict) and not result:
|
|
240
|
-
return f"No results found for {operation}"
|
|
241
|
-
if isinstance(result, list) and not result:
|
|
242
|
-
return f"No results found for {operation}"
|
|
243
|
-
return json.dumps(_jsonable(result), ensure_ascii=False, indent=2)
|
|
File without changes
|
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/__main__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/client.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/commands.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/config.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/diffrender.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/lsp/__init__.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/lsp/client.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/lsp/config.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/lsp/manager.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/mcp/__init__.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/mcp/client.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/mcp/config.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/mcp/manager.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/models.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/persistence.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/planmode.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/prompts/agent.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/prompts/plan.md
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/prompts/review.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/prompts/title.md
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/prompts.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/session.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/subagent.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tool_runner.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/base.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/bash.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/bash_win.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/edit.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/edit_mac.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/edit_win.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/glob.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/glob_mac.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/glob_win.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/grep.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/grep_mac.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/grep_win.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/insert.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/mcp.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/mkdir.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/planexit.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/question.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/read.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/skill.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/todo.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tools/write.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tui/__init__.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tui/commands.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tui/core.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tui/input.py
RENAMED
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/python_agent_harness/tui/render.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/tests/test_concurrent_subagents.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_agent_harness-1.5.5.6 → python_agent_harness-1.5.5.7}/tests/test_subagent_isolation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|