anthropics / anthropics/claude-agent-sdk-typescript
Non-interactive unsupported slash commands return non-resumable session_id
- 主要语言
- Shell
- 星标
- 1.8k
- 派生
- 226
- PR 合并指标
- 30 天内没有已合并 PR
描述
## Summary
When running Claude Agent SDK / Claude Code in non-interactive mode, an unsupported built-in slash command such as `/status` emits a `system/init` message with a `session_id`, then returns a successful synthetic result:
```text
/status isn't available in this environment.
```
However, no transcript JSONL file is created for that `session_id`. If a client stores the emitted `session_id` and later tries to resume it, resume fails with:
```text
No conversation found with session ID:
```
This is surprising for SDK consumers because `system/init.session_id` and `result.session_id` look like a valid resumable session.
## Environment
- `@anthropic-ai/claude-agent-sdk`: observed with `0.2.31`
- Claude Code executable: `2.1.119`
- Platform: macOS arm64
- Mode: non-interactive / `--print --output-format stream-json`
- `CLAUDE_CONFIG_DIR`: temporary directory for reproduction
## Minimal reproduction
This can be reproduced without any external wrapper:
```bash
tmp="$(mktemp -d)"
workdir="/tmp/claude-sdk-session-repro"
mkdir -p "$workdir"
cd "$workdir"
CLAUDE_CONFIG_DIR="$tmp" \
AGENTRIX_CLAUDE_HOME="$tmp" \
claude --print --verbose --output-format stream-json "/status" \
> "$tmp/first.jsonl" 2> "$tmp/first.err"
session_id="$(node -e '
const fs = require("fs");
const first = fs.readFileSync(process.argv[1], "utf8").trim().split(/\n/)[0];
console.log(JSON.parse(first).session_id);
' "$tmp/first.jsonl")"
echo "session_id=$session_id"
find "$tmp/projects" -name "${session_id}.jsonl" -print 2>/dev/null
CLAUDE_CONFIG_DIR="$tmp" \
AGENTRIX_CLAUDE_HOME="$tmp" \
claude --print --verbose --output-format stream-json --resume "$session_id" "hello" \
> "$tmp/resume.jsonl" 2> "$tmp/resume.err"
cat "$tmp/resume.jsonl"
cat "$tmp/resume.err"
```
## Actual behavior
The first command emits a valid-looking session id:
```json
{"type":"system","subtype":"init","session_id":"1f692c5e-512f-40af-8739-7e7e0eea722f", "...":"..."}
{"type":"assistant","message":{"model":"","content":[{"type":"text","text":"/status isn't available in this environment."}]},"session_id":"1f692c5e-512f-40af-8739-7e7e0eea722f", "...":"..."}
{"type":"result","subtype":"success","is_error":false,"result":"/status isn't available in this environment.","session_id":"1f692c5e-512f-40af-8739-7e7e0eea722f", "...":"..."}
```
But no transcript file exists for that session id under `CLAUDE_CONFIG_DIR/projects/**`.
A later resume fails:
```json
{
"type": "result",
"subtype": "error_during_execution",
"is_error": true,
"errors": [
"No conversation found with session ID: 1f692c5e-512f-40af-8739-7e7e0eea722f"
]
}
```
stderr also prints:
```text
No conversation found with session ID: 1f692c5e-512f-40af-8739-7e7e0eea722f
```
## Expected behavior
One of the following would be much easier for SDK consumers to handle:
1. Do not emit a resumable `session_id` for synthetic unsupported slash-command results that are not persisted; or
2. Persist a minimal transcript for the emitted `session_id`, so `--resume ` succeeds; or
3. Mark the result/init metadata to indicate the session is not resumable.
## Why this matters
SDK clients commonly treat `system/init.session_id` or `result.session_id` as the authoritative id to store for future resumes. In this case, the SDK/CLI reports success and provides a session id, but the id cannot be resumed.
This can happen in real integrations when the first user message is a built-in slash command that is filtered out of headless mode, e.g. `/status` or similar commands. The client stores the session id from `system/init`, the process exits normally, and the next user message fails immediately on resume.
## Additional notes
The emitted response appears to be synthetic:
- assistant `message.model` is `""`
- token usage is all zero
- `duration_api_ms` is zero
- result text is `/ isn't available in this environment.`
That suggests this path returns before a normal model turn and before a transcript is materialized, while still exposing a `session_id` through the SDK stream.
贡献指南
这个仓库没有索引到贡献指南
评估
这个 Issue 还没有评估数据。