Skip to content

Commit e7638a9

Browse files
committed
upgrade claude.ai client
1 parent 643d5fe commit e7638a9

File tree

3 files changed

+87
-65
lines changed

3 files changed

+87
-65
lines changed

src/services/apis/claude-web.mjs

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { pushRecord } from './shared.mjs'
1+
import { pushRecord, setAbortController } from './shared.mjs'
22
import Claude from '../clients/claude'
33
import { Models } from '../../config/index.mjs'
44

@@ -18,6 +18,7 @@ export async function generateAnswersWithClaudeWebApi(
1818
) {
1919
const bot = new Claude({ sessionKey })
2020
await bot.init()
21+
const { controller, cleanController } = setAbortController(port)
2122

2223
let answer = ''
2324
const progressFunc = ({ completion }) => {
@@ -31,22 +32,34 @@ export async function generateAnswersWithClaudeWebApi(
3132
port.postMessage({ answer: answer, done: true, session: session })
3233
}
3334

35+
const params = {
36+
progress: progressFunc,
37+
done: doneFunc,
38+
model: Models[modelName].value,
39+
signal: controller.signal,
40+
}
41+
3442
if (!session.claude_conversation)
3543
await bot
36-
.startConversation(question, {
37-
progress: progressFunc,
38-
done: doneFunc,
39-
model: Models[modelName].value,
40-
})
44+
.startConversation(question, params)
4145
.then((conversation) => {
4246
session.claude_conversation = conversation
4347
port.postMessage({ answer: answer, done: true, session: session })
48+
cleanController()
49+
})
50+
.catch((err) => {
51+
cleanController()
52+
throw err
4453
})
4554
else
46-
await bot.sendMessage(question, {
47-
conversation: session.claude_conversation,
48-
progress: progressFunc,
49-
done: doneFunc,
50-
model: Models[modelName].value,
51-
})
55+
await bot
56+
.sendMessage(question, {
57+
conversation: session.claude_conversation,
58+
...params,
59+
})
60+
.then(cleanController)
61+
.catch((err) => {
62+
cleanController()
63+
throw err
64+
})
5265
}

src/services/apis/shared.mjs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,12 @@ export function setAbortController(port, onStop, onDisconnect) {
3636
}
3737
port.onDisconnect.addListener(disconnectListener)
3838

39-
return { controller, messageListener, disconnectListener }
39+
const cleanController = () => {
40+
port.onMessage.removeListener(messageListener)
41+
port.onDisconnect.removeListener(disconnectListener)
42+
}
43+
44+
return { controller, cleanController, messageListener, disconnectListener }
4045
}
4146

4247
export function pushRecord(session, question, answer) {

src/services/clients/claude/index.mjs

Lines changed: 56 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
// https://github.com/Explosion-Scratch/claude-unofficial-api
22
/* eslint-disable */
33

4+
import { fetchSSE } from '../../../utils/index.mjs'
5+
import { isEmpty } from 'lodash-es'
6+
47
/**
58
* The main Claude API client class.
69
* @typedef Claude
@@ -267,6 +270,7 @@ export class Claude {
267270
cookie: `sessionKey=${this.sessionKey}`,
268271
},
269272
method: 'POST',
273+
signal: params.signal,
270274
body: JSON.stringify({
271275
name: '',
272276
uuid: uuid(),
@@ -555,6 +559,7 @@ export class Conversation {
555559
done = () => {},
556560
progress = () => {},
557561
rawResponse = () => {},
562+
signal = null,
558563
} = {},
559564
) {
560565
if (model === 'default') {
@@ -565,67 +570,66 @@ export class Conversation {
565570
attachments,
566571
timezone,
567572
}
568-
const response = await this.request(
569-
`/api/organizations/${this.claude.organizationId}/chat_conversations/${this.conversationId}/${
570-
retry ? 'retry_completion' : 'completion'
571-
}`,
573+
let resolve, reject
574+
let returnPromise = new Promise((r, j) => {
575+
resolve = r
576+
reject = j
577+
})
578+
let fullResponse = ''
579+
await fetchSSE(
580+
`https://claude.ai/api/organizations/${this.claude.organizationId}/chat_conversations/${
581+
this.conversationId
582+
}/${retry ? 'retry_completion' : 'completion'}`,
572583
{
573584
method: 'POST',
574585
headers: {
575586
accept: 'text/event-stream,text/event-stream',
576587
'content-type': 'application/json',
577588
cookie: `sessionKey=${this.claude.sessionKey}`,
578589
},
590+
signal: signal,
579591
body: JSON.stringify(body),
592+
onMessage(message) {
593+
console.debug('sse message', message)
594+
let parsed
595+
try {
596+
parsed = JSON.parse(message)
597+
} catch (error) {
598+
console.debug('json error', error)
599+
return
600+
}
601+
if (parsed.completion) fullResponse += parsed.completion
602+
const PROGRESS_OBJECT = {
603+
...parsed,
604+
completion: fullResponse,
605+
delta: parsed.completion || '',
606+
}
607+
progress(PROGRESS_OBJECT)
608+
if (parsed.stop_reason === 'stop_sequence') {
609+
done(PROGRESS_OBJECT)
610+
resolve(PROGRESS_OBJECT)
611+
}
612+
},
613+
async onStart() {},
614+
async onEnd() {
615+
resolve({
616+
completion: fullResponse,
617+
})
618+
},
619+
async onError(resp) {
620+
if (resp instanceof Error) {
621+
reject(resp)
622+
return
623+
}
624+
const error = await resp.json().catch(() => ({}))
625+
reject(
626+
new Error(
627+
!isEmpty(error) ? JSON.stringify(error) : `${resp.status} ${resp.statusText}`,
628+
),
629+
)
630+
},
580631
},
581632
)
582-
let resolve
583-
let returnPromise = new Promise((r) => (resolve = r))
584-
let parsed
585-
readStream(response, (a, fullResponse) => {
586-
rawResponse(a, fullResponse)
587-
if (!a.toString().startsWith('data:')) {
588-
return
589-
}
590-
try {
591-
parsed = JSON.parse(
592-
a
593-
.toString()
594-
.replace(/^data\:/, '')
595-
.split('\n\ndata:')[0]
596-
?.trim() || '{}',
597-
)
598-
} catch (e) {
599-
return
600-
}
601-
const PROGRESS_OBJECT = {
602-
...parsed,
603-
completion: fullResponse
604-
.split('\n\n')
605-
.filter((i) => i.startsWith('data:'))
606-
.map((i) => {
607-
try {
608-
return JSON.parse(
609-
i
610-
.toString()
611-
.replace(/^data\: */, '')
612-
.split('\n\ndata:')[0]
613-
?.trim() || '{}',
614-
)
615-
} catch (e) {
616-
return {}
617-
}
618-
})
619-
.map((i) => i.completion)
620-
.join(''),
621-
delta: parsed.completion,
622-
}
623-
progress(PROGRESS_OBJECT)
624-
if (parsed.stop_reason === 'stop_sequence') {
625-
done(PROGRESS_OBJECT)
626-
resolve(PROGRESS_OBJECT)
627-
}
628-
})
629633
return returnPromise
630634
}
631635
/**
@@ -815,7 +819,7 @@ function errorHandle(msg) {
815819
return (e) => {
816820
console.error(`Error at: ${msg}`)
817821
console.error(e)
818-
process.exit(0)
822+
// process.exit(0)
819823
}
820824
}
821825

0 commit comments

Comments
 (0)