@clawnet/template-minimal 0.0.1
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.
- package/.agents/skills/claude-agent-sdk/.claude-plugin/plugin.json +13 -0
- package/.agents/skills/claude-agent-sdk/SKILL.md +954 -0
- package/.agents/skills/claude-agent-sdk/references/mcp-servers-guide.md +387 -0
- package/.agents/skills/claude-agent-sdk/references/permissions-guide.md +429 -0
- package/.agents/skills/claude-agent-sdk/references/query-api-reference.md +437 -0
- package/.agents/skills/claude-agent-sdk/references/session-management.md +419 -0
- package/.agents/skills/claude-agent-sdk/references/subagents-patterns.md +464 -0
- package/.agents/skills/claude-agent-sdk/references/top-errors.md +503 -0
- package/.agents/skills/claude-agent-sdk/rules/claude-agent-sdk.md +96 -0
- package/.agents/skills/claude-agent-sdk/scripts/check-versions.sh +55 -0
- package/.agents/skills/claude-agent-sdk/templates/basic-query.ts +55 -0
- package/.agents/skills/claude-agent-sdk/templates/custom-mcp-server.ts +161 -0
- package/.agents/skills/claude-agent-sdk/templates/error-handling.ts +283 -0
- package/.agents/skills/claude-agent-sdk/templates/filesystem-settings.ts +211 -0
- package/.agents/skills/claude-agent-sdk/templates/multi-agent-workflow.ts +318 -0
- package/.agents/skills/claude-agent-sdk/templates/package.json +30 -0
- package/.agents/skills/claude-agent-sdk/templates/permission-control.ts +211 -0
- package/.agents/skills/claude-agent-sdk/templates/query-with-tools.ts +54 -0
- package/.agents/skills/claude-agent-sdk/templates/session-management.ts +151 -0
- package/.agents/skills/claude-agent-sdk/templates/subagents-orchestration.ts +166 -0
- package/.agents/skills/claude-agent-sdk/templates/tsconfig.json +22 -0
- package/.claude/settings.local.json +70 -0
- package/.claude/skills/moltbook-example/SKILL.md +79 -0
- package/.claude/skills/post/SKILL.md +130 -0
- package/.env.example +4 -0
- package/.vercel/README.txt +11 -0
- package/.vercel/project.json +1 -0
- package/AGENTS.md +114 -0
- package/CLAUDE.md +532 -0
- package/README.md +44 -0
- package/api/index.ts +3 -0
- package/biome.json +14 -0
- package/clark_avatar.jpeg +0 -0
- package/package.json +21 -0
- package/scripts/wake.ts +38 -0
- package/skills/clawbook/HEARTBEAT.md +142 -0
- package/skills/clawbook/SKILL.md +219 -0
- package/skills/moltbook-example/SKILL.md +79 -0
- package/skills/moltbook-example/bot/index.ts +61 -0
- package/src/agent/prompts.ts +98 -0
- package/src/agent/runner.ts +526 -0
- package/src/agent/tool-definitions.ts +1151 -0
- package/src/agent-options.ts +14 -0
- package/src/bot-identity.ts +41 -0
- package/src/constants.ts +15 -0
- package/src/handlers/heartbeat.ts +21 -0
- package/src/handlers/openai-compat.ts +95 -0
- package/src/handlers/post.ts +21 -0
- package/src/identity.ts +83 -0
- package/src/index.ts +30 -0
- package/src/middleware/cron-auth.ts +53 -0
- package/src/middleware/sigma-auth.ts +147 -0
- package/src/runs.ts +49 -0
- package/tests/agent/prompts.test.ts +172 -0
- package/tests/agent/runner.test.ts +353 -0
- package/tests/agent/tool-definitions.test.ts +171 -0
- package/tests/constants.test.ts +24 -0
- package/tests/handlers/openai-compat.test.ts +128 -0
- package/tests/handlers.test.ts +133 -0
- package/tests/identity.test.ts +66 -0
- package/tests/index.test.ts +108 -0
- package/tests/middleware/cron-auth.test.ts +99 -0
- package/tests/middleware/sigma-auth.test.ts +198 -0
- package/tests/runs.test.ts +56 -0
- package/tests/skill.test.ts +71 -0
- package/tsconfig.json +14 -0
- package/vercel.json +9 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { query, createSdkMcpServer, tool } from "@anthropic-ai/claude-agent-sdk";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Custom MCP Server Template
|
|
6
|
+
*
|
|
7
|
+
* Demonstrates:
|
|
8
|
+
* - Creating in-process MCP server
|
|
9
|
+
* - Defining tools with Zod schemas
|
|
10
|
+
* - Multiple tools in one server
|
|
11
|
+
* - Error handling in tools
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
// Define a custom MCP server with multiple tools
|
|
15
|
+
const weatherServer = createSdkMcpServer({
|
|
16
|
+
name: "weather-service",
|
|
17
|
+
version: "1.0.0",
|
|
18
|
+
tools: [
|
|
19
|
+
tool(
|
|
20
|
+
"get_weather",
|
|
21
|
+
"Get current weather for a location",
|
|
22
|
+
{
|
|
23
|
+
location: z.string().describe("City name or coordinates"),
|
|
24
|
+
units: z.enum(["celsius", "fahrenheit"]).default("celsius")
|
|
25
|
+
},
|
|
26
|
+
async (args) => {
|
|
27
|
+
try {
|
|
28
|
+
// Simulate API call
|
|
29
|
+
const response = await fetch(
|
|
30
|
+
`https://api.weather.com/v1/current?location=${args.location}&units=${args.units}`
|
|
31
|
+
);
|
|
32
|
+
const data = await response.json();
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
content: [{
|
|
36
|
+
type: "text",
|
|
37
|
+
text: `Temperature: ${data.temp}° ${args.units}\nConditions: ${data.conditions}\nHumidity: ${data.humidity}%`
|
|
38
|
+
}]
|
|
39
|
+
};
|
|
40
|
+
} catch (error) {
|
|
41
|
+
return {
|
|
42
|
+
content: [{
|
|
43
|
+
type: "text",
|
|
44
|
+
text: `Error fetching weather: ${error.message}`
|
|
45
|
+
}],
|
|
46
|
+
isError: true
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
),
|
|
51
|
+
tool(
|
|
52
|
+
"get_forecast",
|
|
53
|
+
"Get weather forecast for next 7 days",
|
|
54
|
+
{
|
|
55
|
+
location: z.string(),
|
|
56
|
+
days: z.number().min(1).max(7).default(7)
|
|
57
|
+
},
|
|
58
|
+
async (args) => {
|
|
59
|
+
// Simulated forecast data
|
|
60
|
+
return {
|
|
61
|
+
content: [{
|
|
62
|
+
type: "text",
|
|
63
|
+
text: `7-day forecast for ${args.location}: Mostly sunny with temperatures ranging from 15-25°C`
|
|
64
|
+
}]
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
)
|
|
68
|
+
]
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Database tools server
|
|
72
|
+
const databaseServer = createSdkMcpServer({
|
|
73
|
+
name: "database",
|
|
74
|
+
version: "1.0.0",
|
|
75
|
+
tools: [
|
|
76
|
+
tool(
|
|
77
|
+
"query_users",
|
|
78
|
+
"Query user records from the database",
|
|
79
|
+
{
|
|
80
|
+
email: z.string().email().optional(),
|
|
81
|
+
limit: z.number().min(1).max(100).default(10),
|
|
82
|
+
offset: z.number().min(0).default(0)
|
|
83
|
+
},
|
|
84
|
+
async (args) => {
|
|
85
|
+
// Simulated database query
|
|
86
|
+
const results = [
|
|
87
|
+
{ id: 1, email: "user1@example.com", name: "User 1" },
|
|
88
|
+
{ id: 2, email: "user2@example.com", name: "User 2" }
|
|
89
|
+
];
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
content: [{
|
|
93
|
+
type: "text",
|
|
94
|
+
text: JSON.stringify(results, null, 2)
|
|
95
|
+
}]
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
),
|
|
99
|
+
tool(
|
|
100
|
+
"calculate",
|
|
101
|
+
"Perform mathematical calculations",
|
|
102
|
+
{
|
|
103
|
+
expression: z.string().describe("Mathematical expression to evaluate"),
|
|
104
|
+
precision: z.number().min(0).max(10).default(2)
|
|
105
|
+
},
|
|
106
|
+
async (args) => {
|
|
107
|
+
try {
|
|
108
|
+
// In production, use a proper math parser (e.g., mathjs)
|
|
109
|
+
const result = eval(args.expression);
|
|
110
|
+
const rounded = Number(result.toFixed(args.precision));
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
content: [{
|
|
114
|
+
type: "text",
|
|
115
|
+
text: `Result: ${rounded}`
|
|
116
|
+
}]
|
|
117
|
+
};
|
|
118
|
+
} catch (error) {
|
|
119
|
+
return {
|
|
120
|
+
content: [{
|
|
121
|
+
type: "text",
|
|
122
|
+
text: `Invalid expression: ${error.message}`
|
|
123
|
+
}],
|
|
124
|
+
isError: true
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
)
|
|
129
|
+
]
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// Use custom tools in query
|
|
133
|
+
async function useCustomTools() {
|
|
134
|
+
const response = query({
|
|
135
|
+
prompt: "What's the weather in San Francisco? Also query users with gmail addresses and calculate 15% tip on $85.50",
|
|
136
|
+
options: {
|
|
137
|
+
model: "claude-sonnet-4-5",
|
|
138
|
+
mcpServers: {
|
|
139
|
+
"weather-service": weatherServer,
|
|
140
|
+
"database": databaseServer
|
|
141
|
+
},
|
|
142
|
+
allowedTools: [
|
|
143
|
+
"mcp__weather-service__get_weather",
|
|
144
|
+
"mcp__weather-service__get_forecast",
|
|
145
|
+
"mcp__database__query_users",
|
|
146
|
+
"mcp__database__calculate"
|
|
147
|
+
]
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
for await (const message of response) {
|
|
152
|
+
if (message.type === 'assistant') {
|
|
153
|
+
console.log('Assistant:', message.content);
|
|
154
|
+
} else if (message.type === 'tool_call') {
|
|
155
|
+
console.log(`\n🔧 ${message.tool_name}:`, message.input);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Run
|
|
161
|
+
useCustomTools().catch(console.error);
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Error Handling Template
|
|
5
|
+
*
|
|
6
|
+
* Demonstrates:
|
|
7
|
+
* - SDK error handling
|
|
8
|
+
* - Message-level error handling
|
|
9
|
+
* - Retry strategies
|
|
10
|
+
* - Graceful degradation
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// Example 1: Basic Error Handling
|
|
14
|
+
async function basicErrorHandling() {
|
|
15
|
+
try {
|
|
16
|
+
const response = query({
|
|
17
|
+
prompt: "Analyze and refactor code",
|
|
18
|
+
options: {
|
|
19
|
+
model: "claude-sonnet-4-5",
|
|
20
|
+
workingDirectory: "/path/to/project"
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
for await (const message of response) {
|
|
25
|
+
switch (message.type) {
|
|
26
|
+
case 'assistant':
|
|
27
|
+
console.log('Assistant:', message.content);
|
|
28
|
+
break;
|
|
29
|
+
|
|
30
|
+
case 'error':
|
|
31
|
+
console.error('Agent error:', message.error.message);
|
|
32
|
+
if (message.error.type === 'permission_denied') {
|
|
33
|
+
console.log('Permission denied for:', message.error.tool);
|
|
34
|
+
// Handle permission errors gracefully
|
|
35
|
+
}
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
} catch (error) {
|
|
40
|
+
console.error('Fatal error:', error);
|
|
41
|
+
|
|
42
|
+
// Handle specific error codes
|
|
43
|
+
if (error.code === 'CLI_NOT_FOUND') {
|
|
44
|
+
console.error('Claude Code CLI not installed');
|
|
45
|
+
console.error('Install: npm install -g @anthropic-ai/claude-code');
|
|
46
|
+
} else if (error.code === 'AUTHENTICATION_FAILED') {
|
|
47
|
+
console.error('Invalid API key. Check ANTHROPIC_API_KEY');
|
|
48
|
+
} else if (error.code === 'RATE_LIMIT_EXCEEDED') {
|
|
49
|
+
console.error('Rate limit exceeded. Retry after delay.');
|
|
50
|
+
} else if (error.code === 'CONTEXT_LENGTH_EXCEEDED') {
|
|
51
|
+
console.error('Context too large. Use session compaction.');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Example 2: Retry with Exponential Backoff
|
|
57
|
+
async function retryWithBackoff(
|
|
58
|
+
prompt: string,
|
|
59
|
+
maxRetries = 3,
|
|
60
|
+
baseDelay = 1000
|
|
61
|
+
): Promise<void> {
|
|
62
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
63
|
+
try {
|
|
64
|
+
const response = query({
|
|
65
|
+
prompt,
|
|
66
|
+
options: {
|
|
67
|
+
model: "claude-sonnet-4-5"
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
for await (const message of response) {
|
|
72
|
+
if (message.type === 'assistant') {
|
|
73
|
+
console.log(message.content);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return; // Success, exit
|
|
78
|
+
} catch (error) {
|
|
79
|
+
if (error.code === 'RATE_LIMIT_EXCEEDED' && attempt < maxRetries - 1) {
|
|
80
|
+
const delay = baseDelay * Math.pow(2, attempt);
|
|
81
|
+
console.log(`Rate limited. Retrying in ${delay}ms...`);
|
|
82
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
83
|
+
} else {
|
|
84
|
+
throw error; // Re-throw if not rate limit or final attempt
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Example 3: Graceful Degradation
|
|
91
|
+
async function gracefulDegradation(prompt: string) {
|
|
92
|
+
// Try with full capabilities first
|
|
93
|
+
try {
|
|
94
|
+
console.log('Attempting with Sonnet model...');
|
|
95
|
+
const response = query({
|
|
96
|
+
prompt,
|
|
97
|
+
options: {
|
|
98
|
+
model: "claude-sonnet-4-5",
|
|
99
|
+
allowedTools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"]
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
for await (const message of response) {
|
|
104
|
+
if (message.type === 'assistant') {
|
|
105
|
+
console.log(message.content);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
} catch (error) {
|
|
109
|
+
console.warn('Sonnet failed, falling back to Haiku...');
|
|
110
|
+
|
|
111
|
+
// Fallback to faster/cheaper model with limited tools
|
|
112
|
+
try {
|
|
113
|
+
const response = query({
|
|
114
|
+
prompt,
|
|
115
|
+
options: {
|
|
116
|
+
model: "haiku",
|
|
117
|
+
allowedTools: ["Read", "Grep", "Glob"] // Read-only
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
for await (const message of response) {
|
|
122
|
+
if (message.type === 'assistant') {
|
|
123
|
+
console.log(message.content);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
} catch (fallbackError) {
|
|
127
|
+
console.error('All attempts failed:', fallbackError);
|
|
128
|
+
throw fallbackError;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Example 4: Comprehensive Error Handler
|
|
134
|
+
async function comprehensiveErrorHandling() {
|
|
135
|
+
const errors: Array<{ type: string; message: string; timestamp: Date }> = [];
|
|
136
|
+
|
|
137
|
+
try {
|
|
138
|
+
const response = query({
|
|
139
|
+
prompt: "Complex multi-step task",
|
|
140
|
+
options: {
|
|
141
|
+
model: "claude-sonnet-4-5",
|
|
142
|
+
permissionMode: "default"
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
for await (const message of response) {
|
|
147
|
+
switch (message.type) {
|
|
148
|
+
case 'assistant':
|
|
149
|
+
console.log('✅ Assistant:', message.content);
|
|
150
|
+
break;
|
|
151
|
+
|
|
152
|
+
case 'tool_call':
|
|
153
|
+
console.log(`🔧 Executing: ${message.tool_name}`);
|
|
154
|
+
break;
|
|
155
|
+
|
|
156
|
+
case 'tool_result':
|
|
157
|
+
console.log(`✅ ${message.tool_name} completed`);
|
|
158
|
+
break;
|
|
159
|
+
|
|
160
|
+
case 'error':
|
|
161
|
+
console.error('❌ Error:', message.error.message);
|
|
162
|
+
errors.push({
|
|
163
|
+
type: message.error.type,
|
|
164
|
+
message: message.error.message,
|
|
165
|
+
timestamp: new Date()
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// Handle different error types
|
|
169
|
+
if (message.error.type === 'permission_denied') {
|
|
170
|
+
console.log('→ Permission was denied, continuing with limited access');
|
|
171
|
+
} else if (message.error.type === 'tool_execution_failed') {
|
|
172
|
+
console.log('→ Tool failed, attempting alternative approach');
|
|
173
|
+
}
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
} catch (error) {
|
|
178
|
+
console.error('💥 Fatal error:', error);
|
|
179
|
+
|
|
180
|
+
// Log error details
|
|
181
|
+
errors.push({
|
|
182
|
+
type: error.code || 'UNKNOWN',
|
|
183
|
+
message: error.message,
|
|
184
|
+
timestamp: new Date()
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// Specific handlers
|
|
188
|
+
if (error.code === 'AUTHENTICATION_FAILED') {
|
|
189
|
+
console.error('→ Check your ANTHROPIC_API_KEY environment variable');
|
|
190
|
+
console.error('→ Visit https://console.anthropic.com/ for API keys');
|
|
191
|
+
} else if (error.code === 'RATE_LIMIT_EXCEEDED') {
|
|
192
|
+
console.error('→ Rate limit exceeded');
|
|
193
|
+
console.error('→ Implement exponential backoff or reduce request frequency');
|
|
194
|
+
} else if (error.code === 'CONTEXT_LENGTH_EXCEEDED') {
|
|
195
|
+
console.error('→ Context too large');
|
|
196
|
+
console.error('→ Consider using session management or reducing prompt size');
|
|
197
|
+
} else if (error.code === 'CLI_NOT_FOUND') {
|
|
198
|
+
console.error('→ Claude Code CLI not found');
|
|
199
|
+
console.error('→ Install: npm install -g @anthropic-ai/claude-code');
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
throw error;
|
|
203
|
+
} finally {
|
|
204
|
+
// Always log error summary
|
|
205
|
+
if (errors.length > 0) {
|
|
206
|
+
console.log('\n\n=== Error Summary ===');
|
|
207
|
+
errors.forEach(err => {
|
|
208
|
+
console.log(`${err.timestamp.toISOString()} - ${err.type}: ${err.message}`);
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Example 5: Circuit Breaker Pattern
|
|
215
|
+
class CircuitBreaker {
|
|
216
|
+
private failures = 0;
|
|
217
|
+
private lastFailureTime?: Date;
|
|
218
|
+
private readonly threshold = 3;
|
|
219
|
+
private readonly resetTimeout = 60000; // 1 minute
|
|
220
|
+
|
|
221
|
+
async execute(fn: () => Promise<void>): Promise<void> {
|
|
222
|
+
// Check if circuit is open
|
|
223
|
+
if (this.isOpen()) {
|
|
224
|
+
throw new Error('Circuit breaker is OPEN. Too many failures.');
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
try {
|
|
228
|
+
await fn();
|
|
229
|
+
this.onSuccess();
|
|
230
|
+
} catch (error) {
|
|
231
|
+
this.onFailure();
|
|
232
|
+
throw error;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
private isOpen(): boolean {
|
|
237
|
+
if (this.failures >= this.threshold) {
|
|
238
|
+
const now = new Date();
|
|
239
|
+
if (this.lastFailureTime &&
|
|
240
|
+
now.getTime() - this.lastFailureTime.getTime() < this.resetTimeout) {
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
// Reset after timeout
|
|
244
|
+
this.failures = 0;
|
|
245
|
+
}
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
private onSuccess() {
|
|
250
|
+
this.failures = 0;
|
|
251
|
+
this.lastFailureTime = undefined;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
private onFailure() {
|
|
255
|
+
this.failures++;
|
|
256
|
+
this.lastFailureTime = new Date();
|
|
257
|
+
console.warn(`Circuit breaker: ${this.failures}/${this.threshold} failures`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
async function useCircuitBreaker() {
|
|
262
|
+
const breaker = new CircuitBreaker();
|
|
263
|
+
|
|
264
|
+
try {
|
|
265
|
+
await breaker.execute(async () => {
|
|
266
|
+
const response = query({
|
|
267
|
+
prompt: "Perform task",
|
|
268
|
+
options: { model: "sonnet" }
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
for await (const message of response) {
|
|
272
|
+
if (message.type === 'assistant') {
|
|
273
|
+
console.log(message.content);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
} catch (error) {
|
|
278
|
+
console.error('Circuit breaker prevented execution or task failed:', error);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Run
|
|
283
|
+
comprehensiveErrorHandling().catch(console.error);
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Filesystem Settings Template
|
|
5
|
+
*
|
|
6
|
+
* Demonstrates:
|
|
7
|
+
* - Loading settings from user, project, local
|
|
8
|
+
* - Settings priority and merging
|
|
9
|
+
* - Isolated vs configured execution
|
|
10
|
+
* - Loading CLAUDE.md project instructions
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// Example 1: Load All Settings (Legacy Behavior)
|
|
14
|
+
async function loadAllSettings() {
|
|
15
|
+
const response = query({
|
|
16
|
+
prompt: "Build a new feature following project conventions",
|
|
17
|
+
options: {
|
|
18
|
+
model: "claude-sonnet-4-5",
|
|
19
|
+
settingSources: ["user", "project", "local"]
|
|
20
|
+
// Loads:
|
|
21
|
+
// 1. ~/.claude/settings.json (user)
|
|
22
|
+
// 2. .claude/settings.json (project)
|
|
23
|
+
// 3. .claude/settings.local.json (local overrides)
|
|
24
|
+
//
|
|
25
|
+
// Priority (highest first):
|
|
26
|
+
// 1. Programmatic options (this config)
|
|
27
|
+
// 2. Local settings
|
|
28
|
+
// 3. Project settings
|
|
29
|
+
// 4. User settings
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
for await (const message of response) {
|
|
34
|
+
if (message.type === 'assistant') {
|
|
35
|
+
console.log(message.content);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Example 2: Project Settings Only (CI/CD Pattern)
|
|
41
|
+
async function projectSettingsOnly() {
|
|
42
|
+
const response = query({
|
|
43
|
+
prompt: "Run automated code review",
|
|
44
|
+
options: {
|
|
45
|
+
model: "claude-sonnet-4-5",
|
|
46
|
+
settingSources: ["project"]
|
|
47
|
+
// Only .claude/settings.json
|
|
48
|
+
// Ignores user and local settings
|
|
49
|
+
// Ensures consistent behavior in CI/CD
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
for await (const message of response) {
|
|
54
|
+
if (message.type === 'assistant') {
|
|
55
|
+
console.log(message.content);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Example 3: No Filesystem Settings (Fully Isolated)
|
|
61
|
+
async function isolatedExecution() {
|
|
62
|
+
const response = query({
|
|
63
|
+
prompt: "Analyze this code snippet",
|
|
64
|
+
options: {
|
|
65
|
+
model: "claude-sonnet-4-5",
|
|
66
|
+
settingSources: [], // Empty = no filesystem settings
|
|
67
|
+
workingDirectory: "/tmp/sandbox",
|
|
68
|
+
allowedTools: ["Read", "Grep", "Glob"],
|
|
69
|
+
systemPrompt: "You are a code analyzer."
|
|
70
|
+
// Fully isolated, no filesystem dependencies
|
|
71
|
+
// Perfect for sandboxed/containerized environments
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
for await (const message of response) {
|
|
76
|
+
if (message.type === 'assistant') {
|
|
77
|
+
console.log(message.content);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Example 4: Hybrid Approach (Project + Programmatic)
|
|
83
|
+
async function hybridConfiguration() {
|
|
84
|
+
const response = query({
|
|
85
|
+
prompt: "Implement user authentication system",
|
|
86
|
+
options: {
|
|
87
|
+
model: "claude-sonnet-4-5",
|
|
88
|
+
settingSources: ["project"], // Load CLAUDE.md and project settings
|
|
89
|
+
systemPrompt: "Follow security best practices and company coding standards.",
|
|
90
|
+
agents: {
|
|
91
|
+
"security-checker": {
|
|
92
|
+
description: "Security validation specialist",
|
|
93
|
+
prompt: "Validate all security implementations against OWASP guidelines.",
|
|
94
|
+
tools: ["Read", "Grep"],
|
|
95
|
+
model: "sonnet"
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
allowedTools: ["Read", "Write", "Edit", "Grep", "Glob"]
|
|
99
|
+
// Project settings + programmatic overrides
|
|
100
|
+
// Programmatic settings always win
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
for await (const message of response) {
|
|
105
|
+
if (message.type === 'assistant') {
|
|
106
|
+
console.log(message.content);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Example 5: Loading CLAUDE.md Project Instructions
|
|
112
|
+
async function loadProjectInstructions() {
|
|
113
|
+
const response = query({
|
|
114
|
+
prompt: "Implement new feature according to project guidelines",
|
|
115
|
+
options: {
|
|
116
|
+
model: "claude-sonnet-4-5",
|
|
117
|
+
systemPrompt: {
|
|
118
|
+
type: 'preset',
|
|
119
|
+
preset: 'claude_code' // Required to use CLAUDE.md
|
|
120
|
+
},
|
|
121
|
+
settingSources: ["project"], // Reads CLAUDE.md from project directory
|
|
122
|
+
workingDirectory: process.cwd()
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
for await (const message of response) {
|
|
127
|
+
if (message.type === 'assistant') {
|
|
128
|
+
console.log(message.content);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Example 6: Environment-Specific Settings
|
|
134
|
+
async function environmentSpecificSettings(
|
|
135
|
+
environment: 'development' | 'staging' | 'production'
|
|
136
|
+
) {
|
|
137
|
+
let settingSources: Array<'user' | 'project' | 'local'>;
|
|
138
|
+
let permissionMode: 'default' | 'acceptEdits' | 'bypassPermissions';
|
|
139
|
+
|
|
140
|
+
switch (environment) {
|
|
141
|
+
case 'development':
|
|
142
|
+
settingSources = ["user", "project", "local"];
|
|
143
|
+
permissionMode = "acceptEdits";
|
|
144
|
+
break;
|
|
145
|
+
|
|
146
|
+
case 'staging':
|
|
147
|
+
settingSources = ["project"];
|
|
148
|
+
permissionMode = "default";
|
|
149
|
+
break;
|
|
150
|
+
|
|
151
|
+
case 'production':
|
|
152
|
+
settingSources = ["project"];
|
|
153
|
+
permissionMode = "default";
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const response = query({
|
|
158
|
+
prompt: "Deploy application",
|
|
159
|
+
options: {
|
|
160
|
+
model: "claude-sonnet-4-5",
|
|
161
|
+
settingSources,
|
|
162
|
+
permissionMode,
|
|
163
|
+
workingDirectory: process.cwd()
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
for await (const message of response) {
|
|
168
|
+
if (message.type === 'assistant') {
|
|
169
|
+
console.log(message.content);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Settings File Examples:
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* ~/.claude/settings.json (User Settings)
|
|
178
|
+
* {
|
|
179
|
+
* "model": "claude-sonnet-4-5",
|
|
180
|
+
* "allowedTools": ["Read", "Write", "Edit", "Bash", "Grep", "Glob"],
|
|
181
|
+
* "permissionMode": "default"
|
|
182
|
+
* }
|
|
183
|
+
*/
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* .claude/settings.json (Project Settings - version controlled)
|
|
187
|
+
* {
|
|
188
|
+
* "model": "claude-sonnet-4-5",
|
|
189
|
+
* "allowedTools": ["Read", "Write", "Edit", "Grep", "Glob"],
|
|
190
|
+
* "disallowedTools": ["Bash"],
|
|
191
|
+
* "agents": {
|
|
192
|
+
* "code-reviewer": {
|
|
193
|
+
* "description": "Review code for quality",
|
|
194
|
+
* "prompt": "You review code for best practices.",
|
|
195
|
+
* "tools": ["Read", "Grep"],
|
|
196
|
+
* "model": "haiku"
|
|
197
|
+
* }
|
|
198
|
+
* }
|
|
199
|
+
* }
|
|
200
|
+
*/
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* .claude/settings.local.json (Local Overrides - gitignored)
|
|
204
|
+
* {
|
|
205
|
+
* "permissionMode": "acceptEdits",
|
|
206
|
+
* "allowedTools": ["Read", "Write", "Edit", "Bash", "Grep", "Glob"]
|
|
207
|
+
* }
|
|
208
|
+
*/
|
|
209
|
+
|
|
210
|
+
// Run
|
|
211
|
+
hybridConfiguration().catch(console.error);
|