Skip to content

Commit 4f4fd55

Browse files
shahariaazamVibeXP Botclaude
authored
Close feature gaps vs official SDKs (#6)
## Summary - Add 8 missing hook event constants, 13 new message types, and supporting structs (`ToolProgressMessage`, `TaskMessage`) - Add per-model usage breakdown (`ModelUsage`, `ModelUsages`) and `WebSearchRequests` to `Usage` - Add `RewindFiles`, query/introspection methods (`SupportedModels`, `SupportedCommands`, `SupportedAgents`, `AccountInfo`), `StopTask`, and runtime MCP management (`ReconnectMcpServer`, `ToggleMcpServer`, `SetMcpServers`) to `Stream` and `Session` - Add `NewTool[In, Out]` generic helper, `ToolServer`, and `WithTools` convenience option for easy MCP tool definition - Add `ListSessions` and `GetSessionMessages` top-level functions for session history - Add `ResumeSessionAt`, `PromptSuggestions`, and `ElicitationHandler` options with elicitation handling in the control request loop - Add `Transport` interface as a preparatory abstraction for future alternative transports - Fix `WithCWD` to set `PWD` env var matching Python SDK behaviour (closes #5) - Bump SDK version to 0.3.0 ## Test plan - [x] `go build ./...` compiles cleanly - [x] `go vet ./...` passes with no issues - [ ] Verify new `WithXxx` options follow existing patterns - [ ] Verify new `Stream` methods follow `sendControlRequest` pattern - [ ] Verify all new `Session` methods delegate to `Stream` - [ ] Test `NewTool` compiles with MCP SDK's `mcp.AddTool` generic signature Closes #4, closes #5 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: VibeXP Bot <bot@vibexp.io> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent ef14df2 commit 4f4fd55

19 files changed

Lines changed: 1677 additions & 44 deletions

.github/workflows/ci.yml

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
lint:
14+
name: Lint
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: actions/checkout@v4
18+
19+
- uses: actions/setup-go@v5
20+
with:
21+
go-version: "1.24"
22+
23+
- name: Check go fmt
24+
run: |
25+
output=$(gofmt -l .)
26+
if [ -n "$output" ]; then
27+
echo "Files not formatted:"
28+
echo "$output"
29+
exit 1
30+
fi
31+
32+
- name: Run go vet
33+
run: go vet ./...
34+
35+
- name: Check go mod tidy
36+
run: |
37+
go mod tidy
38+
git diff --exit-code go.mod go.sum
39+
40+
test:
41+
name: Test (Go ${{ matrix.go-version }})
42+
runs-on: ubuntu-latest
43+
strategy:
44+
matrix:
45+
go-version: ["1.24"]
46+
steps:
47+
- uses: actions/checkout@v4
48+
49+
- uses: actions/setup-go@v5
50+
with:
51+
go-version: ${{ matrix.go-version }}
52+
53+
- name: Run tests
54+
run: go test -v -race -count=1 ./...
55+
56+
build:
57+
name: Build
58+
runs-on: ubuntu-latest
59+
steps:
60+
- uses: actions/checkout@v4
61+
62+
- uses: actions/setup-go@v5
63+
with:
64+
go-version: "1.24"
65+
66+
- name: Build
67+
run: go build ./...

CONTRIBUTING.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# Contributing to Claude Agent SDK Go
2+
3+
Thank you for your interest in contributing to Claude Agent SDK Go! We welcome contributions from everyone — whether you are a human developer or an AI agent.
4+
5+
Regardless of the source, all contributions go through the same review process and must meet the same quality standards. We maintain strict coding standards, automated checks, and thorough reviews to keep the codebase clean, reliable, and maintainable.
6+
7+
## Ways to Contribute
8+
9+
- **Report bugs** — Open a GitHub issue describing the problem, steps to reproduce, and expected behavior.
10+
- **Request features** — Open a GitHub issue describing the feature, the motivation behind it, and any ideas for implementation.
11+
- **Propose ideas** — Start a discussion via a GitHub issue to gather community feedback before diving into code.
12+
- **Submit pull requests** — Fix bugs, implement features, improve documentation, or refactor code.
13+
14+
## Issues Before Pull Requests
15+
16+
**Every pull request must be linked to a GitHub issue.**
17+
18+
Opening an issue first gives the community the opportunity to discuss the problem or feature, provide feedback on the approach, and ensure visibility into the work being planned. Pull requests created without a corresponding issue may be closed.
19+
20+
1. Search existing issues to avoid duplicates.
21+
2. Open a new issue if none exists.
22+
3. Wait for acknowledgment or feedback before starting significant work.
23+
4. Reference the issue in your pull request (e.g., `Fixes #42` or `Closes #42`).
24+
25+
## Development Setup
26+
27+
### Prerequisites
28+
29+
- Go 1.24+
30+
31+
### Running Tests
32+
33+
```bash
34+
go test ./...
35+
```
36+
37+
### Running Linters
38+
39+
```bash
40+
golangci-lint run ./...
41+
```
42+
43+
## Pull Request Guidelines
44+
45+
### Before Submitting
46+
47+
- [ ] Your PR is linked to a GitHub issue.
48+
- [ ] All tests pass (`go test ./...`).
49+
- [ ] Go linting passes.
50+
- [ ] You have checked whether your changes require a documentation update — if so, include the documentation changes in the same PR.
51+
52+
### Code Quality Standards
53+
54+
- Write clean, readable code that follows existing patterns in the codebase.
55+
- Keep changes focused — one issue per pull request.
56+
- Add tests for new functionality and bug fixes.
57+
- Do not introduce security vulnerabilities (see OWASP top 10).
58+
- Avoid over-engineering — solve the problem at hand without unnecessary abstractions.
59+
60+
### Documentation
61+
62+
Check whether your changes require documentation updates. This includes:
63+
64+
- Changes to API behavior
65+
- New features or configuration options
66+
- Changes to the development setup or build process
67+
- Architecture changes
68+
69+
Include documentation updates in the same pull request as the code changes.
70+
71+
### Commit Messages
72+
73+
Write clear, descriptive commit messages. Use the imperative mood (e.g., "Add streaming support" not "Added streaming").
74+
75+
## For AI Agent Contributors
76+
77+
AI-generated contributions are welcome and go through the same process as human contributions:
78+
79+
1. An issue must exist before a pull request is created.
80+
2. All automated checks (linting, tests) must pass.
81+
3. Code must meet the same quality and security standards.
82+
4. Pull requests are reviewed with the same rigor.
83+
84+
## License
85+
86+
By contributing to Claude Agent SDK Go, you agree that your contributions will be licensed under the [MIT License](LICENSE).

SECURITY.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Security Policy
2+
3+
## Reporting a Vulnerability
4+
5+
We take security seriously and appreciate your help in keeping Claude Agent SDK Go safe for everyone.
6+
7+
### GitHub Issues
8+
9+
For most security concerns, please open a GitHub issue describing the vulnerability, its potential impact, and steps to reproduce if possible.
10+
11+
### Private Disclosure for Critical Vulnerabilities
12+
13+
If you discover a zero-day vulnerability or a critical issue that could be actively exploited, please report it privately by email:
14+
15+
**hello@shaharialab.com**
16+
17+
Use email when:
18+
19+
- The vulnerability is a zero-day or has no known fix.
20+
- Public disclosure could put users at immediate risk.
21+
- The issue involves sensitive data exposure or remote code execution.
22+
- You believe the vulnerability is being actively exploited.
23+
24+
In your email, please include:
25+
26+
- A description of the vulnerability.
27+
- Steps to reproduce or a proof of concept.
28+
- The potential impact and affected components.
29+
- Any suggested fixes, if you have them.
30+
31+
We will acknowledge your report within 48 hours and work with you to understand the scope and coordinate a fix before any public disclosure.
32+
33+
## Supported Versions
34+
35+
Security fixes are applied to the latest release. We recommend always running the most recent version of Claude Agent SDK Go.

claude/client.go

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package claude
22

33
import (
44
"context"
5+
"encoding/json"
56
"fmt"
67
"strings"
78
"sync"
@@ -77,10 +78,66 @@ func (s *Stream) SendUserMessage(msg string) error {
7778
return s.write(userMsg(msg))
7879
}
7980

80-
// sendControlRequest writes a control_request with the given subtype and extra
81-
// fields, then blocks until a matching control_response arrives or the ctx
82-
// is cancelled.
83-
func (s *Stream) sendControlRequest(subtype string, extras map[string]any) error {
81+
// RewindFiles asks the CLI to rewind files to the state at the given user message ID.
82+
func (s *Stream) RewindFiles(userMessageID string) error {
83+
return s.sendControlRequest("rewind_files", map[string]any{
84+
"user_message_id": userMessageID,
85+
})
86+
}
87+
88+
// ReconnectMcpServer asks the CLI to reconnect a named MCP server.
89+
func (s *Stream) ReconnectMcpServer(serverName string) error {
90+
return s.sendControlRequest("reconnect_mcp_server", map[string]any{
91+
"server_name": serverName,
92+
})
93+
}
94+
95+
// ToggleMcpServer asks the CLI to enable or disable a named MCP server.
96+
func (s *Stream) ToggleMcpServer(serverName string, enabled bool) error {
97+
return s.sendControlRequest("toggle_mcp_server", map[string]any{
98+
"server_name": serverName,
99+
"enabled": enabled,
100+
})
101+
}
102+
103+
// SetMcpServers asks the CLI to replace the current MCP server configuration.
104+
func (s *Stream) SetMcpServers(servers map[string]any) error {
105+
return s.sendControlRequest("set_mcp_servers", map[string]any{
106+
"mcp_servers": servers,
107+
})
108+
}
109+
110+
// SupportedModels queries the CLI for the list of supported models.
111+
// Returns the raw JSON response body.
112+
func (s *Stream) SupportedModels() (json.RawMessage, error) {
113+
return s.sendControlRequestWithResponse("supported_models", nil)
114+
}
115+
116+
// SupportedCommands queries the CLI for the list of supported commands.
117+
func (s *Stream) SupportedCommands() (json.RawMessage, error) {
118+
return s.sendControlRequestWithResponse("supported_commands", nil)
119+
}
120+
121+
// SupportedAgents queries the CLI for the list of supported agents.
122+
func (s *Stream) SupportedAgents() (json.RawMessage, error) {
123+
return s.sendControlRequestWithResponse("supported_agents", nil)
124+
}
125+
126+
// AccountInfo queries the CLI for the current account information.
127+
func (s *Stream) AccountInfo() (json.RawMessage, error) {
128+
return s.sendControlRequestWithResponse("account_info", nil)
129+
}
130+
131+
// StopTask asks the CLI to stop a running background task.
132+
func (s *Stream) StopTask(taskID string) error {
133+
return s.sendControlRequest("stop_task", map[string]any{
134+
"task_id": taskID,
135+
})
136+
}
137+
138+
// sendControlRequestWithResponse is like sendControlRequest but returns the raw
139+
// JSON response body on success.
140+
func (s *Stream) sendControlRequestWithResponse(subtype string, extras map[string]any) (json.RawMessage, error) {
84141
reqID := newUUID()
85142
respCh := make(chan controlResponse, 1)
86143

@@ -102,23 +159,31 @@ func (s *Stream) sendControlRequest(subtype string, extras map[string]any) error
102159
s.pendingMu.Lock()
103160
delete(s.pending, reqID)
104161
s.pendingMu.Unlock()
105-
return fmt.Errorf("claude: %s: %w", subtype, err)
162+
return nil, fmt.Errorf("claude: %s: %w", subtype, err)
106163
}
107164

108165
select {
109166
case resp := <-respCh:
110167
if !resp.Success {
111-
return fmt.Errorf("claude: %s: %s", subtype, resp.Error)
168+
return nil, fmt.Errorf("claude: %s: %s", subtype, resp.Error)
112169
}
113-
return nil
170+
return resp.Body, nil
114171
case <-s.ctx.Done():
115172
s.pendingMu.Lock()
116173
delete(s.pending, reqID)
117174
s.pendingMu.Unlock()
118-
return s.ctx.Err()
175+
return nil, s.ctx.Err()
119176
}
120177
}
121178

179+
// sendControlRequest writes a control_request with the given subtype and extra
180+
// fields, then blocks until a matching control_response arrives or the ctx
181+
// is cancelled.
182+
func (s *Stream) sendControlRequest(subtype string, extras map[string]any) error {
183+
_, err := s.sendControlRequestWithResponse(subtype, extras)
184+
return err
185+
}
186+
122187
// Query runs the claude agent with the given prompt and returns a *Stream for
123188
// real-time event processing.
124189
//

claude/hooks.go

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ import "encoding/json"
66
type HookEvent string
77

88
const (
9-
HookEventPreToolUse HookEvent = "PreToolUse"
10-
HookEventPostToolUse HookEvent = "PostToolUse"
9+
HookEventPreToolUse HookEvent = "PreToolUse"
10+
HookEventPostToolUse HookEvent = "PostToolUse"
1111
// HookEventPostToolUseFailure fires after a tool call fails.
1212
HookEventPostToolUseFailure HookEvent = "PostToolUseFailure"
13-
HookEventNotification HookEvent = "Notification"
14-
HookEventStop HookEvent = "Stop"
15-
HookEventSubagentStop HookEvent = "SubagentStop"
13+
HookEventNotification HookEvent = "Notification"
14+
HookEventStop HookEvent = "Stop"
15+
HookEventSubagentStop HookEvent = "SubagentStop"
1616
// HookEventSubagentStart fires when a sub-agent is started.
1717
HookEventSubagentStart HookEvent = "SubagentStart"
1818
HookEventPreCompact HookEvent = "PreCompact"
@@ -25,6 +25,22 @@ const (
2525
HookEventSetup HookEvent = "Setup"
2626
// HookEventPermissionRequest fires when Claude requests permission to use a tool.
2727
HookEventPermissionRequest HookEvent = "PermissionRequest"
28+
// HookEventSessionEnd fires when a session ends.
29+
HookEventSessionEnd HookEvent = "SessionEnd"
30+
// HookEventTeammateIdle fires when a teammate agent becomes idle.
31+
HookEventTeammateIdle HookEvent = "TeammateIdle"
32+
// HookEventTaskCompleted fires when a task completes.
33+
HookEventTaskCompleted HookEvent = "TaskCompleted"
34+
// HookEventElicitation fires when claude requests user elicitation.
35+
HookEventElicitation HookEvent = "Elicitation"
36+
// HookEventElicitationResult fires after an elicitation is resolved.
37+
HookEventElicitationResult HookEvent = "ElicitationResult"
38+
// HookEventConfigChange fires when configuration changes mid-session.
39+
HookEventConfigChange HookEvent = "ConfigChange"
40+
// HookEventWorktreeCreate fires when a git worktree is created.
41+
HookEventWorktreeCreate HookEvent = "WorktreeCreate"
42+
// HookEventWorktreeRemove fires when a git worktree is removed.
43+
HookEventWorktreeRemove HookEvent = "WorktreeRemove"
2844
)
2945

3046
// HookOutput is the return value of a HookFunc. All fields are optional.

0 commit comments

Comments
 (0)