Skip to content

Commit 10854b5

Browse files
committed
feat: migrate to Claude Sonnet 4.5 with SDK v0.67.0
- Upgraded @anthropic-ai/sdk from v0.59.0 to v0.67.0 - Migrated model from claude-sonnet-4-20250514 to claude-sonnet-4-5 - Updated text editor tool from text_editor_20250429 to text_editor_20250728 - Extended StopReason type to include refusal and model_context_window_exceeded - Enhanced title generation with 1.5s timeout and automatic fallback
1 parent 91095c3 commit 10854b5

File tree

7 files changed

+88
-26
lines changed

7 files changed

+88
-26
lines changed

RELEASE_NOTES.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ Pocket Server — Release Notes
33

44
Highlights
55
----------
6+
- **Claude Sonnet 4.5 migration** with updated SDK (v0.67.0) and latest text editor tool
7+
- Enhanced title generation with timeout protection and graceful fallback
8+
- Extended stop reason types for better error handling (refusal, context window exceeded)
69
- Remote pairing mode protected by one-time tokens and capped retry attempts
710
- Session asset storage for user image uploads (disk-backed with token-gated retrieval)
811
- Turn lifecycle telemetry (`agent:turn`) unified across Anthropic and OpenAI providers
@@ -11,6 +14,12 @@ Highlights
1114

1215
New
1316
---
17+
- **Claude Sonnet 4.5 migration**
18+
- Upgraded `@anthropic-ai/sdk` from v0.59.0 to v0.67.0
19+
- Migrated model from `claude-sonnet-4-20250514` to `claude-sonnet-4-5` across all chat endpoints
20+
- Updated text editor tool from `text_editor_20250429` to `text_editor_20250728`
21+
- Extended `StopReason` type to include `refusal` and `model_context_window_exceeded`
22+
- Enhanced title generation with 1.5s timeout and automatic fallback to heuristic on errors
1423
- Remote pairing flow
1524
- `pocket-server pair --remote` opens a remote pairing window with PIN + one-time token
1625
- `/auth/pair` accepts `{ deviceId, pin, pairToken }` during remote windows and rejects other origins

package-lock.json

Lines changed: 43 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"node": ">=22.18.0"
1616
},
1717
"dependencies": {
18-
"@anthropic-ai/sdk": "^0.59.0",
18+
"@anthropic-ai/sdk": "^0.67.0",
1919
"@hono/node-server": "^1.18.1",
2020
"@hono/node-ws": "^1.0.4",
2121
"@xterm/headless": "^5.5.0",

src/agent/anthropic/anthropic.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export class AnthropicService {
7777
updatedAt: now,
7878
messages: [],
7979
metadata: {
80-
model: 'claude-sonnet-4-20250514',
80+
model: 'claude-sonnet-4-5',
8181
totalTokens: 0
8282
},
8383
settings: {
@@ -271,7 +271,7 @@ export class AnthropicService {
271271

272272
const anthropic = this.initClient(apiKey);
273273
const streamConfig = {
274-
model: 'claude-sonnet-4-20250514',
274+
model: 'claude-sonnet-4-5',
275275
max_tokens: 4096,
276276
system: systemPrompt,
277277
messages: await this.materializeMessagesWithBase64(sessionId, session.conversation.messages),
@@ -717,7 +717,7 @@ export class AnthropicService {
717717
session.currentStreamController = new AbortController();
718718

719719
const streamConfig = {
720-
model: 'claude-sonnet-4-20250514',
720+
model: 'claude-sonnet-4-5',
721721
max_tokens: 4096,
722722
system: systemPrompt,
723723
messages: await this.materializeMessagesWithBase64(session.id, session.conversation.messages),

src/agent/anthropic/tools/editor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import type { CreateCommand, InsertCommand, StrReplaceCommand, TextEditorCommand
1212
* Text editor tool definition for Anthropic API
1313
*/
1414
export const editorToolDefinition: TextEditorTool = {
15-
type: 'text_editor_20250429',
15+
type: 'text_editor_20250728',
1616
name: 'str_replace_based_edit_tool'
1717
};
1818

src/agent/anthropic/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export interface Message {
2121
usage: Usage;
2222
}
2323

24-
export type StopReason = 'end_turn' | 'max_tokens' | 'stop_sequence' | 'tool_use' | 'pause_turn';
24+
export type StopReason = 'end_turn' | 'max_tokens' | 'stop_sequence' | 'tool_use' | 'pause_turn' | 'refusal' | 'model_context_window_exceeded';
2525

2626
export interface Usage {
2727
input_tokens: number;
@@ -261,7 +261,7 @@ export interface UserLocation {
261261

262262
// Text Editor Tool
263263
export interface TextEditorTool extends SpecialTool {
264-
type: 'text_editor_20250429' | 'text_editor_20250124' | 'text_editor_20241022';
264+
type: 'text_editor_20250728' | 'text_editor_20250429' | 'text_editor_20250124' | 'text_editor_20241022';
265265
name: 'str_replace_based_edit_tool';
266266
}
267267

src/agent/core/title.ts

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,40 @@
77
import Anthropic from '@anthropic-ai/sdk';
88

99
export async function generateConversationTitle(userMessage: string, anthropicApiKey?: string): Promise<string> {
10-
// Try Anthropic if a key is available
10+
// Try Anthropic if a key is available (prefer mobile key, fallback to server env)
1111
const key = anthropicApiKey || process.env.ANTHROPIC_API_KEY;
1212
if (key) {
1313
try {
14-
const anthropic = new Anthropic({ apiKey: key });
15-
const response = await anthropic.messages.create({
16-
model: 'claude-sonnet-4-20250514',
17-
max_tokens: 20,
18-
temperature: 0.7,
19-
messages: [{
20-
role: 'user',
21-
content: `Generate a short title (max 3 words) for a conversation that starts with: "${userMessage}". Return only the title, no quotes or punctuation.`
22-
}]
23-
});
24-
const content = response.content[0];
25-
if (content?.type === 'text') {
26-
const title = content.text.trim();
27-
const words = title.split(' ').filter(Boolean);
28-
return words.length > 3 ? words.slice(0, 3).join(' ') : (title || 'New Chat');
14+
// Create abort controller for timeout
15+
const abortController = new AbortController();
16+
const timeoutId = setTimeout(() => abortController.abort(), 1500);
17+
18+
try {
19+
const anthropic = new Anthropic({ apiKey: key });
20+
const response = await anthropic.messages.create({
21+
model: 'claude-sonnet-4-5',
22+
max_tokens: 20,
23+
temperature: 0.7,
24+
messages: [{
25+
role: 'user',
26+
content: `Generate a short title (max 3 words) for a conversation that starts with: "${userMessage}". Return only the title, no quotes or punctuation.`
27+
}]
28+
}, {
29+
signal: abortController.signal
30+
});
31+
clearTimeout(timeoutId);
32+
33+
const content = response.content[0];
34+
if (content?.type === 'text') {
35+
const title = content.text.trim();
36+
const words = title.split(' ').filter(Boolean);
37+
return words.length > 3 ? words.slice(0, 3).join(' ') : (title || 'New Chat');
38+
}
39+
} finally {
40+
clearTimeout(timeoutId);
2941
}
3042
} catch (err) {
31-
// Fall through to heuristic
43+
// Silently fall through to heuristic (includes timeout, auth errors, etc.)
3244
}
3345
}
3446
return generateFallbackTitle(userMessage);

0 commit comments

Comments
 (0)