nanocode-cli 0.7.0__tar.gz → 0.7.1__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.
- {nanocode_cli-0.7.0/nanocode_cli.egg-info → nanocode_cli-0.7.1}/PKG-INFO +1 -1
- {nanocode_cli-0.7.0 → nanocode_cli-0.7.1}/nanocode.py +109 -45
- {nanocode_cli-0.7.0 → nanocode_cli-0.7.1/nanocode_cli.egg-info}/PKG-INFO +1 -1
- {nanocode_cli-0.7.0 → nanocode_cli-0.7.1}/pyproject.toml +1 -1
- {nanocode_cli-0.7.0 → nanocode_cli-0.7.1}/LICENSE +0 -0
- {nanocode_cli-0.7.0 → nanocode_cli-0.7.1}/MANIFEST.in +0 -0
- {nanocode_cli-0.7.0 → nanocode_cli-0.7.1}/README.md +0 -0
- {nanocode_cli-0.7.0 → nanocode_cli-0.7.1}/README.zh-CN.md +0 -0
- {nanocode_cli-0.7.0 → nanocode_cli-0.7.1}/nanocode_cli.egg-info/SOURCES.txt +0 -0
- {nanocode_cli-0.7.0 → nanocode_cli-0.7.1}/nanocode_cli.egg-info/dependency_links.txt +0 -0
- {nanocode_cli-0.7.0 → nanocode_cli-0.7.1}/nanocode_cli.egg-info/entry_points.txt +0 -0
- {nanocode_cli-0.7.0 → nanocode_cli-0.7.1}/nanocode_cli.egg-info/requires.txt +0 -0
- {nanocode_cli-0.7.0 → nanocode_cli-0.7.1}/nanocode_cli.egg-info/top_level.txt +0 -0
- {nanocode_cli-0.7.0 → nanocode_cli-0.7.1}/setup.cfg +0 -0
|
@@ -60,7 +60,7 @@ from rich.console import Console
|
|
|
60
60
|
from rich.markdown import Markdown
|
|
61
61
|
from rich.rule import Rule
|
|
62
62
|
|
|
63
|
-
__version__ = "0.7.
|
|
63
|
+
__version__ = "0.7.1"
|
|
64
64
|
|
|
65
65
|
Json = dict[str, Any]
|
|
66
66
|
HTTP_USER_AGENT = "nanocode/" + __version__
|
|
@@ -490,6 +490,7 @@ class AgentState:
|
|
|
490
490
|
code_index_error: str = ""
|
|
491
491
|
code_index_notice: str = ""
|
|
492
492
|
code_index_refreshing: bool = False
|
|
493
|
+
code_index_checking: bool = False
|
|
493
494
|
context_percent: int = 0
|
|
494
495
|
turn_step: int = 0
|
|
495
496
|
turn_tool_calls: int = 0
|
|
@@ -528,7 +529,9 @@ class AgentState:
|
|
|
528
529
|
|
|
529
530
|
def format(self) -> str:
|
|
530
531
|
known = ["- " + item for item in self.known] or ["- (empty)"]
|
|
531
|
-
return "\n".join(
|
|
532
|
+
return "\n".join(
|
|
533
|
+
["Goal: " + (self.goal or "(empty)"), "Plan:", *self.plan_rows_for(self.plan), "Known:", *known, "Check: " + (self.check or "(empty)")]
|
|
534
|
+
)
|
|
532
535
|
|
|
533
536
|
|
|
534
537
|
@dataclass
|
|
@@ -915,16 +918,12 @@ class SessionSnapshotCodec:
|
|
|
915
918
|
@staticmethod
|
|
916
919
|
def tool_records(data: list[Json]) -> list[ToolResultRecord]:
|
|
917
920
|
return [
|
|
918
|
-
ToolResultRecord(key=rec["key"], name=rec["name"], args=rec.get("args", []), output=rec.get("output", ""), note=rec.get("note", ""))
|
|
919
|
-
for rec in data
|
|
921
|
+
ToolResultRecord(key=rec["key"], name=rec["name"], args=rec.get("args", []), output=rec.get("output", ""), note=rec.get("note", "")) for rec in data
|
|
920
922
|
]
|
|
921
923
|
|
|
922
924
|
@staticmethod
|
|
923
925
|
def tool_errors(data: list[Json]) -> list[ToolErrorRecord]:
|
|
924
|
-
return [
|
|
925
|
-
ToolErrorRecord(key=err["key"], name=err["name"], args=err.get("args", []), error=err.get("error", ""))
|
|
926
|
-
for err in data
|
|
927
|
-
]
|
|
926
|
+
return [ToolErrorRecord(key=err["key"], name=err["name"], args=err.get("args", []), error=err.get("error", "")) for err in data]
|
|
928
927
|
|
|
929
928
|
|
|
930
929
|
class SessionSnapshotStore:
|
|
@@ -2001,6 +2000,25 @@ class CodeIndex:
|
|
|
2001
2000
|
return ""
|
|
2002
2001
|
return self.update([self.session.resolve_path(path) for path in files])
|
|
2003
2002
|
|
|
2003
|
+
def update_pending_async(self) -> None:
|
|
2004
|
+
"""Run the working-tree check (and any auto-update) off the UI critical path.
|
|
2005
|
+
|
|
2006
|
+
``update_pending`` does a ``check=True`` scan that walks/hashes the tree — slow on
|
|
2007
|
+
large repos. Running it inline blocks answer emission and /status, so spawn it in a
|
|
2008
|
+
daemon thread. Guarded so only one scan/update runs at a time.
|
|
2009
|
+
"""
|
|
2010
|
+
if self.session.state.code_index_checking or self.session.state.code_index_refreshing:
|
|
2011
|
+
return
|
|
2012
|
+
self.session.state.code_index_checking = True
|
|
2013
|
+
|
|
2014
|
+
def run() -> None:
|
|
2015
|
+
try:
|
|
2016
|
+
self.update_pending()
|
|
2017
|
+
finally:
|
|
2018
|
+
self.session.state.code_index_checking = False
|
|
2019
|
+
|
|
2020
|
+
threading.Thread(target=run, daemon=True).start()
|
|
2021
|
+
|
|
2004
2022
|
def refresh_existing_async(self) -> bool:
|
|
2005
2023
|
if self.session.state.code_index_refreshing:
|
|
2006
2024
|
return False
|
|
@@ -2565,7 +2583,9 @@ class BashTool(Tool):
|
|
|
2565
2583
|
|
|
2566
2584
|
class GitTool(Tool):
|
|
2567
2585
|
NAME = "Git"
|
|
2568
|
-
DESCRIPTION =
|
|
2586
|
+
DESCRIPTION = (
|
|
2587
|
+
"Run git with explicit argv (default: cwd from Environment; use cwd= for other directories). For add, pass explicit file paths; broad add is rejected."
|
|
2588
|
+
)
|
|
2569
2589
|
SIGNATURE = "Git(argv=[command,...], cwd?)"
|
|
2570
2590
|
EXAMPLE = (
|
|
2571
2591
|
'Status. Example: {"argv":["status","--short"]}',
|
|
@@ -2589,11 +2609,7 @@ class GitTool(Tool):
|
|
|
2589
2609
|
def payload_args(cls, payload: Json) -> list[Any]:
|
|
2590
2610
|
argv = payload.get("argv")
|
|
2591
2611
|
if not isinstance(argv, list) or not argv:
|
|
2592
|
-
raise ToolError(
|
|
2593
|
-
"Git requires a non-empty 'argv' list. "
|
|
2594
|
-
'Signature: Git(argv=[command,...], cwd?) '
|
|
2595
|
-
'Example: {"argv":["status","--short"]}'
|
|
2596
|
-
)
|
|
2612
|
+
raise ToolError('Git requires a non-empty \'argv\' list. Signature: Git(argv=[command,...], cwd?) Example: {"argv":["status","--short"]}')
|
|
2597
2613
|
argv = [str(a) for a in argv]
|
|
2598
2614
|
return [("cwd=" + str(payload["cwd"])), *argv] if payload.get("cwd") else argv
|
|
2599
2615
|
|
|
@@ -2785,7 +2801,13 @@ class NoteTool(Tool):
|
|
|
2785
2801
|
}
|
|
2786
2802
|
return {
|
|
2787
2803
|
"type": "object",
|
|
2788
|
-
"properties": {
|
|
2804
|
+
"properties": {
|
|
2805
|
+
"set_goal": {"type": "string"},
|
|
2806
|
+
"replace_plan": {"type": "array", "items": plan_item},
|
|
2807
|
+
"append_known": strings,
|
|
2808
|
+
"replace_known": strings,
|
|
2809
|
+
"set_check": {"type": "string"},
|
|
2810
|
+
},
|
|
2789
2811
|
"additionalProperties": False,
|
|
2790
2812
|
}
|
|
2791
2813
|
|
|
@@ -2872,7 +2894,7 @@ class QuestionSpec:
|
|
|
2872
2894
|
class QuestionTool(Tool):
|
|
2873
2895
|
NAME = "Question"
|
|
2874
2896
|
DESCRIPTION = "Ask the user one or more questions (asked in sequence) and wait for their answers. Use when intent is genuinely ambiguous, a choice affects the codebase's external shape (module layout, public API, naming), or you need prioritization; prefer offering choices with previews, and optionally a recommended index when one option is clearly best. Do NOT ask about trivial internal details or anything determinable from context (Read/InspectCode/Bash) or already specified; if a reasonable default exists, proceed."
|
|
2875
|
-
SIGNATURE =
|
|
2897
|
+
SIGNATURE = "Question(questions=[{question, choices?, previews?, recommended?}, ...])"
|
|
2876
2898
|
EXAMPLE = (
|
|
2877
2899
|
'One question, recommending a choice. Example: {"questions":[{"question":"Which approach?","choices":["Refactor","Rewrite"],"previews":["Extract module +87 -12","Rewrite from scratch"],"recommended":0}]}',
|
|
2878
2900
|
'Batch related questions. Example: {"questions":[{"question":"Target runtime?","choices":["Node","Deno"]},{"question":"Name the module?"}]}',
|
|
@@ -2971,6 +2993,7 @@ class QuestionTool(Tool):
|
|
|
2971
2993
|
label = Tool.compact(first, 80)
|
|
2972
2994
|
return [label + (f" (+{len(questions) - 1} more)" if len(questions) > 1 else "")]
|
|
2973
2995
|
|
|
2996
|
+
|
|
2974
2997
|
class MCPTool(Tool):
|
|
2975
2998
|
NAME = "MCP"
|
|
2976
2999
|
DESCRIPTION = "Call/describe external MCP server tools, and list/read MCP resources"
|
|
@@ -3085,9 +3108,10 @@ class MCPTool(Tool):
|
|
|
3085
3108
|
return mcp.read_resource(server, str(payload.get("uri") or ""))
|
|
3086
3109
|
raise ToolError(
|
|
3087
3110
|
f"unknown MCP action {action!r}. Valid actions: {', '.join(self.ACTIONS)}. "
|
|
3088
|
-
f
|
|
3111
|
+
f'To invoke a remote tool named {action!r}, use action="call", tool={action!r}.'
|
|
3089
3112
|
)
|
|
3090
3113
|
|
|
3114
|
+
|
|
3091
3115
|
TOOLS: tuple[type[Tool], ...] = (
|
|
3092
3116
|
MCPTool,
|
|
3093
3117
|
ReadTool,
|
|
@@ -3121,8 +3145,7 @@ class ContextManager:
|
|
|
3121
3145
|
COMPACT_RECENT_MESSAGES: ClassVar[int] = 8
|
|
3122
3146
|
MCP_DESCRIBE_BLOCK: ClassVar[re.Pattern] = re.compile(r"<MCPDescribe server=(\".*?\") tool=(\".*?\")>.*?</MCPDescribe>", re.DOTALL)
|
|
3123
3147
|
CODE_EXTENSIONS: ClassVar[set[str]] = set(
|
|
3124
|
-
".c .cc .cpp .cxx .css .go .h .hpp .html .java .js .json .jsx .kt .lua .php .py .rb .rs .scss .sh .sql "
|
|
3125
|
-
".swift .toml .ts .tsx .vue .yaml .yml".split()
|
|
3148
|
+
".c .cc .cpp .cxx .css .go .h .hpp .html .java .js .json .jsx .kt .lua .php .py .rb .rs .scss .sh .sql .swift .toml .ts .tsx .vue .yaml .yml".split()
|
|
3126
3149
|
)
|
|
3127
3150
|
CODE_FILENAMES: ClassVar[set[str]] = {"CMakeLists.txt", "Dockerfile", "Makefile", "go.mod", "package.json", "pyproject.toml"}
|
|
3128
3151
|
|
|
@@ -4185,7 +4208,9 @@ class MCPManager:
|
|
|
4185
4208
|
|
|
4186
4209
|
try:
|
|
4187
4210
|
result = self.run_async(
|
|
4188
|
-
self._call_oauth_tool(config, headers, tool_name, arguments)
|
|
4211
|
+
self._call_oauth_tool(config, headers, tool_name, arguments)
|
|
4212
|
+
if config.auth == "oauth"
|
|
4213
|
+
else self._call_tool(config, headers, tool_name, arguments)
|
|
4189
4214
|
)
|
|
4190
4215
|
except Exception as e:
|
|
4191
4216
|
raise ToolError("MCP call failed: " + self.error_text(e))
|
|
@@ -4226,9 +4251,7 @@ class MCPManager:
|
|
|
4226
4251
|
raise ToolError("MCP read_resource requires a uri")
|
|
4227
4252
|
config, headers = self._resource_preamble(server)
|
|
4228
4253
|
try:
|
|
4229
|
-
result = self.run_async(
|
|
4230
|
-
self._read_oauth_resource(config, headers, uri) if config.auth == "oauth" else self._read_resource(config, headers, uri)
|
|
4231
|
-
)
|
|
4254
|
+
result = self.run_async(self._read_oauth_resource(config, headers, uri) if config.auth == "oauth" else self._read_resource(config, headers, uri))
|
|
4232
4255
|
except Exception as e:
|
|
4233
4256
|
raise ToolError("MCP resource read failed: " + self.error_text(e))
|
|
4234
4257
|
text = self.normalize_resource(result)
|
|
@@ -4346,7 +4369,9 @@ class MCPManager:
|
|
|
4346
4369
|
from fastmcp.client.transports import StreamableHttpTransport
|
|
4347
4370
|
|
|
4348
4371
|
timeout = self.discovery_timeout()
|
|
4349
|
-
async with Client(
|
|
4372
|
+
async with Client(
|
|
4373
|
+
StreamableHttpTransport(config.url, headers=headers), auth=self.oauth_client(config), timeout=timeout, init_timeout=timeout
|
|
4374
|
+
) as client:
|
|
4350
4375
|
return await asyncio.wait_for(client.list_resources(), timeout=timeout)
|
|
4351
4376
|
|
|
4352
4377
|
async def _read_resource(self, config: MCPServerConfig, headers: dict[str, str], uri: str) -> Any:
|
|
@@ -4361,7 +4386,9 @@ class MCPManager:
|
|
|
4361
4386
|
from fastmcp.client.transports import StreamableHttpTransport
|
|
4362
4387
|
|
|
4363
4388
|
timeout = self.call_timeout()
|
|
4364
|
-
async with Client(
|
|
4389
|
+
async with Client(
|
|
4390
|
+
StreamableHttpTransport(config.url, headers=headers), auth=self.oauth_client(config), timeout=timeout, init_timeout=timeout
|
|
4391
|
+
) as client:
|
|
4365
4392
|
return await asyncio.wait_for(client.read_resource(uri), timeout=timeout)
|
|
4366
4393
|
|
|
4367
4394
|
async def _call_oauth_tool(self, config: MCPServerConfig, headers: dict[str, str], name: str, arguments: Json) -> Any:
|
|
@@ -4369,7 +4396,9 @@ class MCPManager:
|
|
|
4369
4396
|
from fastmcp.client.transports import StreamableHttpTransport
|
|
4370
4397
|
|
|
4371
4398
|
timeout = self.call_timeout()
|
|
4372
|
-
async with Client(
|
|
4399
|
+
async with Client(
|
|
4400
|
+
StreamableHttpTransport(config.url, headers=headers), auth=self.oauth_client(config), timeout=timeout, init_timeout=timeout
|
|
4401
|
+
) as client:
|
|
4373
4402
|
return await asyncio.wait_for(client.call_tool(name, arguments), timeout=timeout)
|
|
4374
4403
|
|
|
4375
4404
|
def login_server(self, name: str, notify: Callable[[str], None] | None = None) -> str:
|
|
@@ -4553,7 +4582,7 @@ class MCPManager:
|
|
|
4553
4582
|
if line:
|
|
4554
4583
|
lines.append(line)
|
|
4555
4584
|
if resources:
|
|
4556
|
-
lines.append(f
|
|
4585
|
+
lines.append(f'resources ({len(resources)}) — read with MCP(action="read_resource", server={json.dumps(config.name)}, uri=...):')
|
|
4557
4586
|
lines.extend(self._format_resource_line(res) for res in resources)
|
|
4558
4587
|
lines.append("")
|
|
4559
4588
|
|
|
@@ -4633,7 +4662,7 @@ class MCPManager:
|
|
|
4633
4662
|
lines.append(line)
|
|
4634
4663
|
resources = self.resources.get(server, [])
|
|
4635
4664
|
if resources:
|
|
4636
|
-
lines.append(f
|
|
4665
|
+
lines.append(f'resources ({len(resources)}) — read with MCP(action="read_resource", server={json.dumps(server)}, uri=...):')
|
|
4637
4666
|
lines.extend(self._format_resource_line(res) for res in resources)
|
|
4638
4667
|
return "\n".join(lines)
|
|
4639
4668
|
|
|
@@ -4651,7 +4680,7 @@ class MCPManager:
|
|
|
4651
4680
|
# truncated above, so surface any resource-like URIs it mentions explicitly.
|
|
4652
4681
|
uris = self._extract_uris(info.description)
|
|
4653
4682
|
if uris:
|
|
4654
|
-
line +=
|
|
4683
|
+
line += '\n refs (read with MCP action="read_resource"): ' + ", ".join(uris)
|
|
4655
4684
|
if include_schema:
|
|
4656
4685
|
schema = self._schema_json(info.input_schema, self.INDEX_SCHEMA_LIMIT)
|
|
4657
4686
|
if schema:
|
|
@@ -4760,13 +4789,24 @@ class MCPManager:
|
|
|
4760
4789
|
if config.env_http_headers:
|
|
4761
4790
|
for header_name in config.env_http_headers:
|
|
4762
4791
|
auth.append("env_header(" + header_name + ")")
|
|
4763
|
-
lines.append(
|
|
4792
|
+
lines.append(
|
|
4793
|
+
"| `"
|
|
4794
|
+
+ self.markdown_cell(config.name)
|
|
4795
|
+
+ "` | "
|
|
4796
|
+
+ self.markdown_cell(status)
|
|
4797
|
+
+ " | "
|
|
4798
|
+
+ self.markdown_cell(tools or "-")
|
|
4799
|
+
+ " | "
|
|
4800
|
+
+ self.markdown_cell(", ".join(auth) or "-")
|
|
4801
|
+
+ " |"
|
|
4802
|
+
)
|
|
4764
4803
|
return "\n".join(lines) if len(lines) > 2 else "(no MCP servers configured)"
|
|
4765
4804
|
|
|
4766
4805
|
@staticmethod
|
|
4767
4806
|
def markdown_cell(text: str) -> str:
|
|
4768
4807
|
return Text.clean(str(text)).replace("\n", " ").replace("|", "\\|")
|
|
4769
4808
|
|
|
4809
|
+
|
|
4770
4810
|
class ToolRunner:
|
|
4771
4811
|
def __init__(self, session: Session, context: ContextManager, input_fn=input, output_fn=print):
|
|
4772
4812
|
self.session = session
|
|
@@ -4991,7 +5031,9 @@ class ToolRunner:
|
|
|
4991
5031
|
self.session.record_tool_error(key or "-", call.name, call.args, output)
|
|
4992
5032
|
elif key:
|
|
4993
5033
|
self.update_code_index(call, output)
|
|
4994
|
-
self.output_fn(
|
|
5034
|
+
self.output_fn(
|
|
5035
|
+
self.finish_display(call, key, output, failed=failed, approved=approved, auto=auto, display=display, batch_suffix=batch_suffix, elapsed=elapsed)
|
|
5036
|
+
)
|
|
4995
5037
|
return self.tool_message(call, key, output, failed=failed, display=display)
|
|
4996
5038
|
|
|
4997
5039
|
def tool_message(self, call: ToolCall, key: str, output: str, *, failed: bool = False, display: str | None = None) -> str:
|
|
@@ -5067,7 +5109,17 @@ class ToolRunner:
|
|
|
5067
5109
|
return "\n".join([" preview", *(" " + line for line in lines)])
|
|
5068
5110
|
|
|
5069
5111
|
def finish_display(
|
|
5070
|
-
self,
|
|
5112
|
+
self,
|
|
5113
|
+
call: ToolCall,
|
|
5114
|
+
key: str,
|
|
5115
|
+
output: str,
|
|
5116
|
+
*,
|
|
5117
|
+
failed: bool,
|
|
5118
|
+
approved: bool = False,
|
|
5119
|
+
auto: bool = False,
|
|
5120
|
+
display: str | None = None,
|
|
5121
|
+
batch_suffix: str = "",
|
|
5122
|
+
elapsed: float | None = None,
|
|
5071
5123
|
) -> str:
|
|
5072
5124
|
if call.name == "Note" and not failed and display:
|
|
5073
5125
|
return self.with_batch_suffix(display.removeprefix("Note ").strip(), batch_suffix)
|
|
@@ -5949,6 +6001,7 @@ class UiPrinter:
|
|
|
5949
6001
|
at_start = part.endswith("\n")
|
|
5950
6002
|
return indented
|
|
5951
6003
|
|
|
6004
|
+
|
|
5952
6005
|
class BashLivePreview:
|
|
5953
6006
|
HEIGHT: ClassVar[int] = 6
|
|
5954
6007
|
MAX_CHARS: ClassVar[int] = 8000
|
|
@@ -6484,7 +6537,6 @@ Tools:
|
|
|
6484
6537
|
while self.queue_input_active.is_set() and time.monotonic() < deadline:
|
|
6485
6538
|
time.sleep(0.01)
|
|
6486
6539
|
|
|
6487
|
-
|
|
6488
6540
|
def drain_queued_input(self) -> str:
|
|
6489
6541
|
"""Return queued user input, or empty string if nothing queued."""
|
|
6490
6542
|
texts = []
|
|
@@ -6495,6 +6547,7 @@ Tools:
|
|
|
6495
6547
|
texts.append(self.queue_input_text)
|
|
6496
6548
|
self.queue_input_text = ""
|
|
6497
6549
|
return "\n".join(texts)
|
|
6550
|
+
|
|
6498
6551
|
def run(self) -> int:
|
|
6499
6552
|
self.emit(f"nanocode {__version__}. /help for commands.")
|
|
6500
6553
|
self.session.clean_expired_snapshots()
|
|
@@ -6546,7 +6599,7 @@ Tools:
|
|
|
6546
6599
|
watcher.join(timeout=1.0)
|
|
6547
6600
|
self.queue_input_paused.clear()
|
|
6548
6601
|
self.session.state.manual_model_retry_requested = False
|
|
6549
|
-
CodeIndex(self.session).
|
|
6602
|
+
CodeIndex(self.session).update_pending_async()
|
|
6550
6603
|
self.status_bar.stop()
|
|
6551
6604
|
elapsed = time.monotonic() - started
|
|
6552
6605
|
self.ui.emit_answer(answer)
|
|
@@ -6639,14 +6692,12 @@ Tools:
|
|
|
6639
6692
|
# the index is too large to fit even as name-only (some tools are hidden from the model).
|
|
6640
6693
|
self.session.mcp.render_tools_index()
|
|
6641
6694
|
if self.session.mcp.index_truncated:
|
|
6642
|
-
self.emit(
|
|
6695
|
+
self.emit(
|
|
6696
|
+
"mcp: tools index exceeds the size budget; some tools are hidden from the model. Reduce enabled servers or run /mcp tools to see the full list."
|
|
6697
|
+
)
|
|
6643
6698
|
|
|
6644
6699
|
def mcp_error_notice(self) -> str:
|
|
6645
|
-
errors = [
|
|
6646
|
-
(name, error)
|
|
6647
|
-
for name, error in sorted(self.session.mcp.server_errors.items())
|
|
6648
|
-
if error and not error.startswith("oauth login required")
|
|
6649
|
-
]
|
|
6700
|
+
errors = [(name, error) for name, error in sorted(self.session.mcp.server_errors.items()) if error and not error.startswith("oauth login required")]
|
|
6650
6701
|
if not errors:
|
|
6651
6702
|
return ""
|
|
6652
6703
|
shown = errors if self.session.settings.debug else errors[:3]
|
|
@@ -7239,7 +7290,11 @@ Tools:
|
|
|
7239
7290
|
previews = spec.previews
|
|
7240
7291
|
preview_map = {c: previews[i] for i, c in enumerate(choices) if previews and i < len(previews) and previews[i]}
|
|
7241
7292
|
result = self.choice_application(
|
|
7242
|
-
"Select:",
|
|
7293
|
+
"Select:",
|
|
7294
|
+
tuple(choices),
|
|
7295
|
+
labels,
|
|
7296
|
+
current,
|
|
7297
|
+
set(),
|
|
7243
7298
|
preview_fn=lambda choice: preview_map.get(choice, ""),
|
|
7244
7299
|
free_text=True,
|
|
7245
7300
|
)
|
|
@@ -7270,7 +7325,9 @@ Tools:
|
|
|
7270
7325
|
usage = self.session.usage
|
|
7271
7326
|
provider = self.session.config.provider
|
|
7272
7327
|
self.agent.context.update_percent(self.agent.context.model_messages(self.agent.SYSTEM_PROMPT))
|
|
7273
|
-
|
|
7328
|
+
index = CodeIndex(self.session)
|
|
7329
|
+
index_status, index_message = index.status(check=False)
|
|
7330
|
+
index.update_pending_async()
|
|
7274
7331
|
if self.session.state.code_index_refreshing:
|
|
7275
7332
|
index_status, index_message = self.session.state.code_index_notice or "syncing", ""
|
|
7276
7333
|
elif self.session.state.code_index_error:
|
|
@@ -7316,7 +7373,15 @@ Tools:
|
|
|
7316
7373
|
state = self.session.state
|
|
7317
7374
|
known = ["- " + item for item in state.known] or ["- (empty)"]
|
|
7318
7375
|
return "\n".join(
|
|
7319
|
-
[
|
|
7376
|
+
[
|
|
7377
|
+
"goal: " + (state.goal or "(empty)"),
|
|
7378
|
+
"summary:",
|
|
7379
|
+
state.summary or "(empty)",
|
|
7380
|
+
"plan:",
|
|
7381
|
+
*AgentState.plan_rows_for(state.plan, status=True, style="symbol"),
|
|
7382
|
+
"known:",
|
|
7383
|
+
*known,
|
|
7384
|
+
]
|
|
7320
7385
|
)
|
|
7321
7386
|
|
|
7322
7387
|
def config(self, args: str) -> str:
|
|
@@ -7568,8 +7633,7 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
7568
7633
|
parser.add_argument("--yolo", action="store_true", help="Skip confirmations for mutating tools")
|
|
7569
7634
|
parser.add_argument("--debug", action="store_true", help="Enable debug mode")
|
|
7570
7635
|
parser.add_argument("--mcp", default="", help='Filter MCP servers, e.g. "orion*,!orionEval", "all", or "none"')
|
|
7571
|
-
parser.add_argument("--resume", default="", nargs="?", const="latest",
|
|
7572
|
-
help='Resume a session by UID, or "latest"/"last" for most recent')
|
|
7636
|
+
parser.add_argument("--resume", default="", nargs="?", const="latest", help='Resume a session by UID, or "latest"/"last" for most recent')
|
|
7573
7637
|
parser.add_argument("-v", "--version", action="store_true", help="Show version")
|
|
7574
7638
|
args = parser.parse_args(argv)
|
|
7575
7639
|
if args.version:
|
|
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
|