thincoder 0.12.62 → 0.12.63
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/CHANGELOG.md +9 -0
- package/README.md +13 -12
- package/bin/thincoder.mjs +53 -27
- package/package.json +6 -5
- package/src/acp/bridge.mjs +35 -15
- package/src/acp/client-caps.mjs +86 -0
- package/src/acp/ext.mjs +86 -0
- package/src/acp/handlers-session.mjs +240 -0
- package/src/acp/handlers-slots.mjs +196 -0
- package/src/acp/login.mjs +48 -0
- package/src/acp/session.mjs +6 -4
- package/src/acp.mjs +67 -379
- package/src/cli/distill-command.mjs +3 -3
- package/src/cli/make-agent.mjs +59 -17
- package/src/cli/memory-command.mjs +3 -3
- package/src/cli/permission.mjs +4 -48
- package/src/cli/setup-wizard.mjs +1 -1
- package/src/completions.mjs +3 -1
- package/src/crash-reports.mjs +1 -1
- package/src/distill.mjs +4 -4
- package/src/heap-watch.mjs +1 -1
- package/src/prompt-injections.mjs +20 -0
- package/src/tui/agent-turn.mjs +40 -9
- package/src/tui/cmd-advisor.mjs +5 -5
- package/src/tui/cmd-config.mjs +8 -8
- package/src/tui/cmd-eng.mjs +25 -9
- package/src/tui/cmd-mcp.mjs +9 -8
- package/src/tui/cmd-model.mjs +1 -1
- package/src/tui/cmd-new.mjs +6 -5
- package/src/tui/cmd-reindex.mjs +1 -1
- package/src/tui/cmd-restore.mjs +2 -2
- package/src/tui/cmd-session.mjs +24 -1
- package/src/tui/cmd-skills.mjs +1 -1
- package/src/tui/cmd-think.mjs +22 -9
- package/src/tui/config-helpers.mjs +1 -1
- package/src/tui/display-budget.mjs +33 -11
- package/src/tui/index.mjs +9 -9
- package/src/tui/interaction.mjs +16 -7
- package/src/tui/key-modes.mjs +9 -4
- package/src/tui/ledger-surface.mjs +26 -10
- package/src/tui/model-catalog.mjs +4 -4
- package/src/tui/model-picker.mjs +8 -7
- package/src/tui/mouse.mjs +11 -6
- package/src/tui/pickers.mjs +15 -2
- package/src/tui/render-conversation.mjs +1 -1
- package/src/tui/render-frame.mjs +10 -5
- package/src/tui/render-loop.mjs +1 -1
- package/src/tui/render-segments.mjs +3 -1
- package/src/tui/slash-commands.mjs +1 -1
- package/src/tui/startup.mjs +14 -14
- package/src/tui/subagent-blocks.mjs +20 -3
- package/src/tui/subagent-freeze.mjs +73 -2
- package/src/tui/suspension-drive.mjs +46 -22
- package/src/tui/tool-events.mjs +11 -8
- package/src/tui/wizard.mjs +3 -3
- package/src/abort-provenance.mjs +0 -116
- package/src/advisor/citations.mjs +0 -139
- package/src/advisor/compaction.mjs +0 -174
- package/src/advisor/convergence.mjs +0 -80
- package/src/advisor/history.mjs +0 -77
- package/src/advisor/loop.mjs +0 -293
- package/src/advisor/messages.mjs +0 -299
- package/src/advisor/project-context.mjs +0 -194
- package/src/advisor/repos.mjs +0 -150
- package/src/advisor/run.mjs +0 -293
- package/src/advisor/truncate.mjs +0 -57
- package/src/advisor.mjs +0 -290
- package/src/agent/completion.mjs +0 -146
- package/src/agent/dispatch.mjs +0 -489
- package/src/agent/helpers.mjs +0 -384
- package/src/agent/post-turn.mjs +0 -70
- package/src/agent/record-results.mjs +0 -174
- package/src/agent/relay-prefix.mjs +0 -39
- package/src/agent/run-stages.mjs +0 -244
- package/src/agent/setup-reminders.mjs +0 -69
- package/src/agent/setup.mjs +0 -354
- package/src/agent/spawn-child.mjs +0 -243
- package/src/agent-tools/advisor-async.mjs +0 -346
- package/src/agent-tools/advisor-settle.mjs +0 -231
- package/src/agent-tools/advisor.mjs +0 -260
- package/src/agent-tools/async-settle.mjs +0 -204
- package/src/agent-tools/batch-segment.mjs +0 -195
- package/src/agent-tools/consult.mjs +0 -473
- package/src/agent-tools/design-token.mjs +0 -117
- package/src/agent-tools/digest-budget.mjs +0 -76
- package/src/agent-tools/eng.mjs +0 -67
- package/src/agent-tools/escalate-async.mjs +0 -295
- package/src/agent-tools/goal.mjs +0 -119
- package/src/agent-tools/plan.mjs +0 -81
- package/src/agent-tools/read-history.mjs +0 -309
- package/src/agent-tools/recent-changes.mjs +0 -24
- package/src/agent-tools/review-streak.mjs +0 -93
- package/src/agent-tools/settings.mjs +0 -265
- package/src/agent-tools/skill.mjs +0 -47
- package/src/agent-tools/subagent-actions.mjs +0 -482
- package/src/agent-tools/subagent-async.mjs +0 -434
- package/src/agent-tools/subagent-panel.mjs +0 -160
- package/src/agent-tools/subagent-run.mjs +0 -205
- package/src/agent-tools/subagent-scheduler.mjs +0 -392
- package/src/agent-tools/subagent-spawn.mjs +0 -459
- package/src/agent-tools/subagent.mjs +0 -404
- package/src/agent-tools/task.mjs +0 -87
- package/src/agent-tools/timer.mjs +0 -46
- package/src/agent-tools/verify.mjs +0 -271
- package/src/agent-tools.mjs +0 -17
- package/src/agent.mjs +0 -417
- package/src/auto-think.mjs +0 -115
- package/src/config-migrate.mjs +0 -70
- package/src/config.mjs +0 -496
- package/src/context.mjs +0 -392
- package/src/conventions.mjs +0 -223
- package/src/embedding.mjs +0 -120
- package/src/escape.mjs +0 -152
- package/src/expand-home.mjs +0 -16
- package/src/explore-distill.mjs +0 -155
- package/src/generate-title.mjs +0 -88
- package/src/git/checkpoint.mjs +0 -448
- package/src/git/gitmem.mjs +0 -100
- package/src/hooks.mjs +0 -97
- package/src/ledger.mjs +0 -227
- package/src/log.mjs +0 -195
- package/src/markdown.mjs +0 -106
- package/src/mcp/helpers.mjs +0 -51
- package/src/mcp/transport-http.mjs +0 -248
- package/src/mcp/transport-stdio.mjs +0 -140
- package/src/mcp/transport-ws.mjs +0 -122
- package/src/mcp.mjs +0 -295
- package/src/memory/code-index.mjs +0 -219
- package/src/memory/code-sync.mjs +0 -415
- package/src/memory/core.mjs +0 -299
- package/src/memory/delete.mjs +0 -236
- package/src/memory/docs.mjs +0 -419
- package/src/memory/file-walk.mjs +0 -109
- package/src/memory/scan.mjs +0 -95
- package/src/memory/schema.mjs +0 -452
- package/src/memory.mjs +0 -21
- package/src/model-ref.mjs +0 -66
- package/src/model-specs.mjs +0 -179
- package/src/peer-domains.mjs +0 -265
- package/src/peer-instances.mjs +0 -231
- package/src/prompt-overlays.mjs +0 -82
- package/src/prompts/advisor-design.md +0 -41
- package/src/prompts/advisor-round1.md +0 -41
- package/src/prompts/advisor-round2.md +0 -46
- package/src/prompts/advisor-round3.md +0 -42
- package/src/prompts/common.md +0 -115
- package/src/prompts/consult-base.md +0 -19
- package/src/prompts/discipline-engineering.md +0 -258
- package/src/prompts/discipline-normal.md +0 -185
- package/src/prompts/persona-coder.md +0 -21
- package/src/prompts/persona-eng-coder.md +0 -37
- package/src/prompts/persona-eng-designer.md +0 -60
- package/src/prompts/persona-engineering.md +0 -55
- package/src/prompts/persona-explore.md +0 -15
- package/src/prompts/persona-normal.md +0 -27
- package/src/prompts/persona-plan.md +0 -26
- package/src/provider/anthropic.mjs +0 -225
- package/src/provider/core.mjs +0 -476
- package/src/provider/errors.mjs +0 -101
- package/src/provider/google.mjs +0 -257
- package/src/provider/index.mjs +0 -7
- package/src/provider/list-models.mjs +0 -93
- package/src/provider/normalize.mjs +0 -81
- package/src/provider/rate.mjs +0 -108
- package/src/provider/responses.mjs +0 -495
- package/src/provider/retry.mjs +0 -88
- package/src/provider/sse.mjs +0 -264
- package/src/proxy.mjs +0 -261
- package/src/rules.mjs +0 -53
- package/src/session-gc.mjs +0 -221
- package/src/session-guard.mjs +0 -59
- package/src/session-migrate.mjs +0 -48
- package/src/session-rename.mjs +0 -38
- package/src/session-segments.mjs +0 -100
- package/src/session-slots.mjs +0 -492
- package/src/session-store.mjs +0 -441
- package/src/session.mjs +0 -492
- package/src/skills.mjs +0 -153
- package/src/text-budget.mjs +0 -46
- package/src/token-ttl.mjs +0 -274
- package/src/tools/apply_patch.md +0 -15
- package/src/tools/bash.md +0 -37
- package/src/tools/bash.mjs +0 -268
- package/src/tools/checklist-sync.mjs +0 -181
- package/src/tools/checklist.md +0 -13
- package/src/tools/checklist.mjs +0 -299
- package/src/tools/delete.md +0 -13
- package/src/tools/edit-batch.mjs +0 -191
- package/src/tools/edit-diff.mjs +0 -348
- package/src/tools/edit.md +0 -30
- package/src/tools/execute.md +0 -21
- package/src/tools/execute.mjs +0 -228
- package/src/tools/fetch.md +0 -12
- package/src/tools/file.mjs +0 -469
- package/src/tools/file_ops.md +0 -17
- package/src/tools/get_current_time.md +0 -8
- package/src/tools/git-checkpoint.mjs +0 -143
- package/src/tools/git-ext.mjs +0 -173
- package/src/tools/git.md +0 -54
- package/src/tools/git.mjs +0 -356
- package/src/tools/glob-dialect.mjs +0 -130
- package/src/tools/glob.md +0 -11
- package/src/tools/grep.md +0 -19
- package/src/tools/hashline_edit.md +0 -14
- package/src/tools/index.mjs +0 -36
- package/src/tools/insert_after.md +0 -15
- package/src/tools/lint.md +0 -10
- package/src/tools/linter.mjs +0 -128
- package/src/tools/ls.md +0 -12
- package/src/tools/lsp.md +0 -10
- package/src/tools/lsp.mjs +0 -316
- package/src/tools/ops.mjs +0 -299
- package/src/tools/patch.mjs +0 -282
- package/src/tools/process.md +0 -10
- package/src/tools/question.md +0 -16
- package/src/tools/question.mjs +0 -26
- package/src/tools/read.md +0 -20
- package/src/tools/read_image.md +0 -8
- package/src/tools/repomap.mjs +0 -314
- package/src/tools/search.mjs +0 -236
- package/src/tools/shared.mjs +0 -446
- package/src/tools/tree.md +0 -14
- package/src/tools/tree.mjs +0 -66
- package/src/tools/wait_for.md +0 -22
- package/src/tools/web.mjs +0 -224
- package/src/tools/websearch.md +0 -16
- package/src/tools/write.md +0 -11
- package/src/traces/trace-store.mjs +0 -355
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* provider/anthropic.mjs — Anthropic Messages API (Claude)
|
|
3
|
-
* Endpoint: POST https://api.anthropic.com/v1/messages
|
|
4
|
-
* Docs: https://docs.anthropic.com/en/api/messages
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { specForModel } from "../config.mjs"
|
|
8
|
-
import { proxyFetch } from "../proxy.mjs"
|
|
9
|
-
import { requestWithRetry } from "./retry.mjs"
|
|
10
|
-
import { effectiveFetchTimeoutMs } from "./core.mjs"
|
|
11
|
-
import { abortError } from "../abort-provenance.mjs"
|
|
12
|
-
|
|
13
|
-
const ANTHROPIC_VERSION = "2023-06-01"
|
|
14
|
-
|
|
15
|
-
/** OpenAI 语义 tool_choice → Anthropic tool_choice(2026-08-31 能力层)。
|
|
16
|
-
* 传入值形态:undefined | "auto" | "required" | "none" | {type:"function",function:{name}} */
|
|
17
|
-
function mapToolChoice(choice) {
|
|
18
|
-
if (choice === "auto") return { type: "auto" }
|
|
19
|
-
if (choice === "required") return { type: "any" }
|
|
20
|
-
if (choice === "none") return { type: "none" }
|
|
21
|
-
if (choice && typeof choice === "object" && choice.function?.name) return { type: "tool", name: choice.function.name }
|
|
22
|
-
throw new Error(`Invalid tool_choice for Anthropic format: ${JSON.stringify(choice).slice(0, 120)}`)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
/** Convert OpenAI-format tools to Anthropic format */
|
|
27
|
-
export function normalizeTools(tools) {
|
|
28
|
-
return (tools || []).map((t) => ({
|
|
29
|
-
name: t.function.name,
|
|
30
|
-
description: t.function.description || "",
|
|
31
|
-
input_schema: t.function.parameters || { type: "object", properties: {} },
|
|
32
|
-
}))
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/** Build and send an Anthropic chat request. Returns the same shape as core.mjs chat.
|
|
36
|
-
* 2026-08-31 会诊 #6:接入 rateGate/recordRate + 429 Retry-After 单次重试
|
|
37
|
-
* (原实现完全绕过 TPM/RPM 闸门与记账——用户配了 tpm 以为受控实际不受控)。
|
|
38
|
-
* 注:5xx/网络退避重试未与 OpenAI 格式对齐(三 transport 共用那步工作量大,见报告)。 */
|
|
39
|
-
export async function chat(provider, { messages, tools, onToken, onReasoning, onWait, signal, toolChoice, parallelToolCalls }) {
|
|
40
|
-
// Extract system message(s) — Anthropic uses top-level `system` field
|
|
41
|
-
const systemMessages = []
|
|
42
|
-
const chatMessages = []
|
|
43
|
-
for (const m of messages) {
|
|
44
|
-
if (m.role === "system") {
|
|
45
|
-
systemMessages.push(typeof m.content === "string" ? m.content : JSON.stringify(m.content))
|
|
46
|
-
} else {
|
|
47
|
-
chatMessages.push(m)
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const spec = specForModel(provider.model)
|
|
52
|
-
const body = {
|
|
53
|
-
model: provider.model,
|
|
54
|
-
messages: chatMessages,
|
|
55
|
-
stream: true,
|
|
56
|
-
max_tokens: provider.maxTokens || (spec.maxOutput || 8192),
|
|
57
|
-
}
|
|
58
|
-
if (systemMessages.length > 0) body.system = systemMessages.join("\n\n")
|
|
59
|
-
if (tools?.length) body.tools = tools
|
|
60
|
-
// 2026-08-31:tool_choice 能力层——OpenAI 语义映射到 Anthropic tool_choice
|
|
61
|
-
// (auto→{type:"auto"} / required→{type:"any"} / none→{type:"none"} / 具体函数→{type:"tool",name})
|
|
62
|
-
if (toolChoice !== undefined) body.tool_choice = mapToolChoice(toolChoice)
|
|
63
|
-
if (provider.temperature != null) {
|
|
64
|
-
let t = provider.temperature
|
|
65
|
-
// Anthropic API hard limit is 0-1; models without a declared tempRange still get clamped
|
|
66
|
-
const [tMin, tMax] = spec.tempRange ?? [0, 1]
|
|
67
|
-
t = Math.min(tMax, Math.max(tMin, t))
|
|
68
|
-
t = Math.round(t * 100) / 100
|
|
69
|
-
body.temperature = t
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// 2026-09-01:FETCH_TIMEOUT_MS 常量退役(绝对墙钟废除)——anthropic/responses 经 core.mjs 的
|
|
73
|
-
// effectiveFetchTimeoutMs 共用;响应头阶段 600s 默认,body 阶段 idle 超时。
|
|
74
|
-
const headers = {
|
|
75
|
-
...(provider.headers ?? {}), // 定制头展开(PROVIDER.md §21):定制头在前、内置头在后——同名内置头胜出
|
|
76
|
-
"Content-Type": "application/json",
|
|
77
|
-
"x-api-key": provider.apiKey,
|
|
78
|
-
"anthropic-version": ANTHROPIC_VERSION,
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Active signal check
|
|
82
|
-
if (signal?.aborted) throw abortError(signal, "provider", "transport-anthropic")
|
|
83
|
-
|
|
84
|
-
// 会诊 #6:TPM/RPM 闸门 + 记账(rate.mjs 与 OpenAI 格式共用同一窗口)
|
|
85
|
-
const { rateGate, recordRate } = await import("./rate.mjs")
|
|
86
|
-
const estimated = await (async () => {
|
|
87
|
-
const { estimateRequestTokens } = await import("./rate.mjs")
|
|
88
|
-
return estimateRequestTokens(body)
|
|
89
|
-
})()
|
|
90
|
-
await rateGate(provider, estimated, onWait, signal)
|
|
91
|
-
|
|
92
|
-
// 2026-08-31:4xx/5xx/网络与 OpenAI 格式统一退避重试链(原仅 429 Retry-After 单次重试,
|
|
93
|
-
// 5xx 直接抛——DeepSeek/Claude 排队 503 时其他格式可自动恢复,这里语义割裂)
|
|
94
|
-
const response = await requestWithRetry(
|
|
95
|
-
() => proxyFetch(`${provider.baseURL}/messages`, {
|
|
96
|
-
method: "POST",
|
|
97
|
-
headers,
|
|
98
|
-
body: JSON.stringify(body),
|
|
99
|
-
// 2026-09-01:同 core.mjs——绝对墙钟废除(长生成被 10min 腰斩),signal 只保留用户取消链;
|
|
100
|
-
// 响应头阶段仍用 fetchTimeoutMs(600s 默认),body 阶段由 parseAnthropicStream 读侧 idle 管
|
|
101
|
-
signal,
|
|
102
|
-
_headerTimeoutMs: effectiveFetchTimeoutMs(provider),
|
|
103
|
-
_bodyIdleMs: 120_000,
|
|
104
|
-
}, provider.proxyUri),
|
|
105
|
-
{ signal, onWait, buildMessage: (status, text) => `Anthropic API error ${status}: ${text}` },
|
|
106
|
-
)
|
|
107
|
-
|
|
108
|
-
const result = await parseAnthropicStream(response, { onToken, onReasoning, signal })
|
|
109
|
-
recordRate(provider, estimated, result.usage)
|
|
110
|
-
return finishAnthropic(result)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/** Convert the parsed stream to the core.mjs result shape (usage → OpenAI-compatible). */
|
|
114
|
-
function finishAnthropic(result) {
|
|
115
|
-
const usage = result.usage
|
|
116
|
-
if (usage) {
|
|
117
|
-
return {
|
|
118
|
-
content: result.content,
|
|
119
|
-
reasoning: result.reasoning,
|
|
120
|
-
usage: {
|
|
121
|
-
prompt_tokens: usage.input_tokens ?? 0,
|
|
122
|
-
completion_tokens: usage.output_tokens ?? 0,
|
|
123
|
-
total_tokens: (usage.input_tokens ?? 0) + (usage.output_tokens ?? 0),
|
|
124
|
-
prompt_cache_hit_tokens: usage.cache_read_input_tokens ?? 0,
|
|
125
|
-
prompt_cache_miss_tokens: usage.cache_creation_input_tokens ?? 0,
|
|
126
|
-
},
|
|
127
|
-
toolCalls: result.toolCalls,
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
return { content: result.content, reasoning: result.reasoning, toolCalls: result.toolCalls }
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Parse Anthropic SSE stream.
|
|
135
|
-
* Events: message_start, content_block_start, content_block_delta, content_block_stop, message_delta, message_stop
|
|
136
|
-
*/
|
|
137
|
-
async function parseAnthropicStream(response, { onToken, onReasoning, signal }) {
|
|
138
|
-
const result = { content: "", reasoning: "", toolCalls: [], usage: null }
|
|
139
|
-
const decoder = new TextDecoder()
|
|
140
|
-
let buffer = ""
|
|
141
|
-
const toolBlocks = new Map()
|
|
142
|
-
|
|
143
|
-
const processEvent = (eventType, data) => {
|
|
144
|
-
if (!data) return
|
|
145
|
-
let json
|
|
146
|
-
try { json = JSON.parse(data) } catch { return }
|
|
147
|
-
|
|
148
|
-
switch (eventType) {
|
|
149
|
-
case "message_start":
|
|
150
|
-
if (json.message?.usage) result.usage = json.message.usage
|
|
151
|
-
break
|
|
152
|
-
case "content_block_start": {
|
|
153
|
-
const block = json.content_block
|
|
154
|
-
if (block?.type === "tool_use") {
|
|
155
|
-
toolBlocks.set(json.index, { id: block.id, name: block.name, arguments: "" })
|
|
156
|
-
}
|
|
157
|
-
break
|
|
158
|
-
}
|
|
159
|
-
case "content_block_delta": {
|
|
160
|
-
const delta = json.delta
|
|
161
|
-
if (delta?.type === "text_delta" && delta.text) {
|
|
162
|
-
result.content += delta.text
|
|
163
|
-
onToken?.(delta.text)
|
|
164
|
-
} else if (delta?.type === "thinking_delta" && delta.thinking) {
|
|
165
|
-
result.reasoning += delta.thinking
|
|
166
|
-
onReasoning?.(delta.thinking)
|
|
167
|
-
} else if (delta?.type === "input_json_delta" && delta.partial_json) {
|
|
168
|
-
const block = toolBlocks.get(json.index)
|
|
169
|
-
if (block) block.arguments += delta.partial_json
|
|
170
|
-
}
|
|
171
|
-
break
|
|
172
|
-
}
|
|
173
|
-
case "message_delta":
|
|
174
|
-
if (json.usage) result.usage = json.usage
|
|
175
|
-
break
|
|
176
|
-
case "message_stop":
|
|
177
|
-
for (const [, block] of toolBlocks) {
|
|
178
|
-
result.toolCalls.push({ id: block.id, name: block.name, arguments: block.arguments })
|
|
179
|
-
}
|
|
180
|
-
break
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
if (!response.body) throw new Error("No stream response body")
|
|
185
|
-
let currentEvent = ""
|
|
186
|
-
let currentData = ""
|
|
187
|
-
|
|
188
|
-
for await (const chunk of response.body) {
|
|
189
|
-
if (signal?.aborted) {
|
|
190
|
-
throw abortError(signal, "provider", "transport-anthropic")
|
|
191
|
-
}
|
|
192
|
-
buffer += decoder.decode(chunk, { stream: true })
|
|
193
|
-
// BOM 剥除(会诊 #12):首个 chunk 可能带 \uFEFF,否则 message_start 事件被静默丢失(含 usage)
|
|
194
|
-
if (buffer.charCodeAt(0) === 0xfeff) buffer = buffer.slice(1)
|
|
195
|
-
const lines = buffer.split("\n")
|
|
196
|
-
buffer = lines.pop()
|
|
197
|
-
|
|
198
|
-
for (const line of lines) {
|
|
199
|
-
if (line.startsWith("event: ")) {
|
|
200
|
-
if (currentEvent) processEvent(currentEvent, currentData)
|
|
201
|
-
currentEvent = line.slice(7).trim()
|
|
202
|
-
currentData = ""
|
|
203
|
-
} else if (line.startsWith("data: ")) {
|
|
204
|
-
currentData = line.slice(6).trim()
|
|
205
|
-
} else if (line === "" || line === "\r") { // CRLF 空行是 "\r"(会诊 #13)
|
|
206
|
-
if (currentEvent) processEvent(currentEvent, currentData)
|
|
207
|
-
currentEvent = ""
|
|
208
|
-
currentData = ""
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
// Flush remaining
|
|
213
|
-
buffer += decoder.decode()
|
|
214
|
-
for (const line of buffer.split("\n")) {
|
|
215
|
-
if (line.startsWith("event: ")) {
|
|
216
|
-
if (currentEvent) processEvent(currentEvent, currentData)
|
|
217
|
-
currentEvent = line.slice(7)
|
|
218
|
-
} else if (line.startsWith("data: ")) {
|
|
219
|
-
currentData = line.slice(6)
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
if (currentEvent) processEvent(currentEvent, currentData)
|
|
223
|
-
|
|
224
|
-
return result
|
|
225
|
-
}
|