Skip to content

Commit c8e5260

Browse files
lzwjavaclaude
andcommitted
feat: add /export command and improve tool calling
- Add /export command to save full conversation history with tool logs - Track tool execution logs (web_search, exec, edit) with timestamps - Add tool_choice: auto to encourage models to use tools - Export includes messages, tool logs, and timestamp Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 415f4eb commit c8e5260

3 files changed

Lines changed: 60 additions & 0 deletions

File tree

iclaw/commands/export.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import json
2+
from datetime import datetime
3+
4+
5+
def handle_export_command(messages, tool_logs):
6+
if not messages:
7+
print("No conversation history to export.")
8+
return
9+
10+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
11+
filename = f"iclaw_session_{timestamp}.json"
12+
13+
export_data = {
14+
"exported_at": datetime.now().isoformat(),
15+
"messages": messages,
16+
"tool_logs": tool_logs,
17+
}
18+
19+
with open(filename, "w") as f:
20+
json.dump(export_data, f, indent=2)
21+
22+
print(
23+
f"Exported {len(messages)} messages and {len(tool_logs)} tool logs to {filename}"
24+
)

iclaw/github_api.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ def chat(messages, copilot_token, model="gpt-4o", tools=None):
5151
payload = {"model": model, "messages": messages, "stream": False}
5252
if tools:
5353
payload["tools"] = tools
54+
payload["tool_choice"] = "auto"
5455

5556
resp = http.get_session().post(
5657
f"{COPILOT_API_BASE}/chat/completions",

iclaw/main.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from iclaw import log
1111
from iclaw.at_mention import resolve_at_mentions
1212
from iclaw.commands.compact import handle_compact_command
13+
from iclaw.commands.export import handle_export_command
1314
from iclaw.commands.log import handle_log_command
1415
from iclaw.commands.model import handle_model_command, handle_model_provider_command
1516
from iclaw.commands.proxy import handle_ca_bundle_command, handle_proxy_command
@@ -40,6 +41,7 @@
4041
("/copy", "Copy last Copilot response to clipboard"),
4142
("/clear", "Clear conversation history"),
4243
("/compact", "Compact conversation history using LLM"),
44+
("/export", "Export full conversation history to JSON file"),
4345
("/status", "Show current settings"),
4446
("/help", "Show available commands"),
4547
(".exit", "Quit"),
@@ -74,6 +76,7 @@ def main():
7476
log.log_info("No token found. Type /provider_model to authenticate.\n")
7577

7678
messages = []
79+
tool_logs = []
7780
log.log_info("iclaw CLI ready. Available commands:")
7881
for cmd, desc in COMMANDS_HELP:
7982
log.log_info(f" {cmd:<20} {desc}")
@@ -225,6 +228,7 @@ def main():
225228
continue
226229
if user_input == "/clear":
227230
messages.clear()
231+
tool_logs.clear()
228232
last_reply = None
229233
print("Conversation history cleared.")
230234
continue
@@ -233,6 +237,9 @@ def main():
233237
messages, chat, copilot_token, current_model
234238
)
235239
continue
240+
if user_input == "/export":
241+
handle_export_command(messages, tool_logs)
242+
continue
236243

237244
if not copilot_token:
238245
print("Not authenticated. Type /provider_model first.", file=sys.stderr)
@@ -263,6 +270,16 @@ def main():
263270
num_results=function_args.get("num_results", 20),
264271
provider=search_provider,
265272
)
273+
tool_logs.append(
274+
{
275+
"timestamp": time.time(),
276+
"function": function_name,
277+
"args": function_args,
278+
"result": search_context[:500] + "..."
279+
if len(search_context) > 500
280+
else search_context,
281+
}
282+
)
266283
messages.append(
267284
{
268285
"tool_call_id": tool_call["id"],
@@ -275,6 +292,16 @@ def main():
275292

276293
if function_name == "exec":
277294
output = exec(function_args.get("command"))
295+
tool_logs.append(
296+
{
297+
"timestamp": time.time(),
298+
"function": function_name,
299+
"args": function_args,
300+
"result": output[:500] + "..."
301+
if len(output) > 500
302+
else output,
303+
}
304+
)
278305
messages.append(
279306
{
280307
"tool_call_id": tool_call["id"],
@@ -292,6 +319,14 @@ def main():
292319
)
293320
with open(file_path, "w") as f:
294321
f.write(result)
322+
tool_logs.append(
323+
{
324+
"timestamp": time.time(),
325+
"function": function_name,
326+
"args": function_args,
327+
"result": f"Successfully edited {file_path}",
328+
}
329+
)
295330
messages.append(
296331
{
297332
"tool_call_id": tool_call["id"],

0 commit comments

Comments
 (0)