@auto-ai/agent 2.1.189 → 2.1.192
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/dist/safe-a/404/index.html +1 -1
- package/dist/safe-a/404.html +1 -1
- package/dist/safe-a/_next/static/chunks/5f0286b194e88c68.js +1 -0
- package/dist/safe-a/_next/static/chunks/65982c1925fca4ab.js +1 -0
- package/dist/safe-a/_next/static/chunks/69aecc2a7893ba05.js +1 -0
- package/dist/safe-a/_next/static/chunks/743bc613bbda46b4.css +1 -0
- package/dist/safe-a/_next/static/chunks/{5022180fa579a73a.js → 760380631ca561e0.js} +1 -1
- package/dist/safe-a/_next/static/chunks/{2bac8f0a4e762326.js → 9dcb662588dbf520.js} +1 -1
- package/dist/safe-a/_next/static/chunks/cb85ccd601c65174.js +1 -0
- package/dist/safe-a/_next/static/chunks/e784a1fa0acaaaa0.css +7 -0
- package/dist/safe-a/_next/static/chunks/{2d7f6aa6628bccd0.js → eca5690d7fb3d712.js} +1 -1
- package/dist/safe-a/index.html +2 -2
- package/dist/safe-a/index.txt +10 -10
- package/dist/safe-a/manage/about/index.html +2 -2
- package/dist/safe-a/manage/about/index.txt +11 -11
- package/dist/safe-a/manage/env/index.html +2 -2
- package/dist/safe-a/manage/env/index.txt +13 -13
- package/dist/safe-a/manage/geelib/index.html +2 -2
- package/dist/safe-a/manage/geelib/index.txt +13 -13
- package/dist/safe-a/manage/general/index.html +2 -2
- package/dist/safe-a/manage/general/index.txt +11 -11
- package/dist/safe-a/manage/git/index.html +2 -2
- package/dist/safe-a/manage/git/index.txt +13 -13
- package/dist/safe-a/manage/im/index.html +2 -2
- package/dist/safe-a/manage/im/index.txt +13 -13
- package/dist/safe-a/manage/index.html +2 -2
- package/dist/safe-a/manage/index.txt +8 -8
- package/dist/safe-a/manage/library/index.html +2 -2
- package/dist/safe-a/manage/library/index.txt +11 -11
- package/dist/safe-a/manage/mcp/index.html +2 -2
- package/dist/safe-a/manage/mcp/index.txt +11 -11
- package/dist/safe-a/manage/permissions/index.html +2 -2
- package/dist/safe-a/manage/permissions/index.txt +11 -11
- package/dist/safe-a/manage/skills/index.html +2 -2
- package/dist/safe-a/manage/skills/index.txt +11 -11
- package/dist/safe-a/manage/system/index.html +2 -2
- package/dist/safe-a/manage/system/index.txt +13 -13
- package/dist/safe-a/manage/task/index.html +2 -2
- package/dist/safe-a/manage/task/index.txt +11 -11
- package/dist/safe-a/manage/teams/index.html +2 -2
- package/dist/safe-a/manage/teams/index.txt +11 -11
- package/dist/safe-a/manage/tools/index.html +2 -2
- package/dist/safe-a/manage/tools/index.txt +11 -11
- package/dist/ws-test/ws-test.js +218 -4
- package/mcps-runtime/claude-ws-channel/server/gateway.bundle.mjs +87 -74
- package/package.json +6 -6
- package/dist/safe-a/_next/static/chunks/26f5809c84b263c0.css +0 -7
- package/dist/safe-a/_next/static/chunks/a5b851b271052e89.js +0 -1
- package/dist/safe-a/_next/static/chunks/a6aafbc087d75717.js +0 -1
- package/dist/safe-a/_next/static/chunks/d16ae4f1eb111da5.js +0 -1
- package/dist/safe-a/_next/static/chunks/d47487bdc4a277fd.css +0 -1
- package/dist/safe-a/_next/static/chunks/e00679a7df05e016.js +0 -1
- /package/dist/safe-a/_next/static/{XxDw4q1JeD7OUmzpG1zOw → jccK1lHzHeCZKJ8IiMFik}/_buildManifest.js +0 -0
- /package/dist/safe-a/_next/static/{XxDw4q1JeD7OUmzpG1zOw → jccK1lHzHeCZKJ8IiMFik}/_clientMiddlewareManifest.json +0 -0
- /package/dist/safe-a/_next/static/{XxDw4q1JeD7OUmzpG1zOw → jccK1lHzHeCZKJ8IiMFik}/_ssgManifest.js +0 -0
package/dist/ws-test/ws-test.js
CHANGED
|
@@ -1534,6 +1534,7 @@
|
|
|
1534
1534
|
const item = ev.payload
|
|
1535
1535
|
const m = item && item.message ? item.message : null
|
|
1536
1536
|
if (!m) return ''
|
|
1537
|
+
if (m.type === 'user' && !shouldShowWsUserMessage(m)) return ''
|
|
1537
1538
|
if (m.type === 'user' || m.type === 'assistant') {
|
|
1538
1539
|
const blocks = getMessageContentBlocks(m)
|
|
1539
1540
|
const nonTool = blocks.filter(function (b) {
|
|
@@ -2035,6 +2036,7 @@
|
|
|
2035
2036
|
shouldShowWsUserMessage(msg)
|
|
2036
2037
|
) {
|
|
2037
2038
|
clearPendingUserEcho()
|
|
2039
|
+
refreshSessionTitleFromChat(sessionIdInput.value.trim())
|
|
2038
2040
|
}
|
|
2039
2041
|
requestRenderChat()
|
|
2040
2042
|
return true
|
|
@@ -2482,6 +2484,7 @@
|
|
|
2482
2484
|
sessionReplayInProgress = false
|
|
2483
2485
|
flushPendingConversationDeltas()
|
|
2484
2486
|
requestRenderChat()
|
|
2487
|
+
refreshSessionTitleFromChat(sid)
|
|
2485
2488
|
}
|
|
2486
2489
|
}
|
|
2487
2490
|
|
|
@@ -4633,8 +4636,217 @@
|
|
|
4633
4636
|
}
|
|
4634
4637
|
}
|
|
4635
4638
|
|
|
4639
|
+
/** 曾从 transcript / 对话中提取过的会话标题,避免列表刷新后丢失 */
|
|
4640
|
+
const sessionTitleById = Object.create(null)
|
|
4641
|
+
/** 正在拉 replay 补标题的 session,避免重复请求 */
|
|
4642
|
+
const sessionTitleHydrateInflight = new Set()
|
|
4643
|
+
|
|
4644
|
+
function rememberSessionTitle(sessionId, title) {
|
|
4645
|
+
const sid = typeof sessionId === 'string' ? sessionId.trim() : ''
|
|
4646
|
+
const t = typeof title === 'string' ? title.trim() : ''
|
|
4647
|
+
if (!sid || !t) return
|
|
4648
|
+
sessionTitleById[sid] = t
|
|
4649
|
+
}
|
|
4650
|
+
|
|
4651
|
+
/** 旧版 API 从 tool input 误抓的 CVE 摘要,不得作为标题 */
|
|
4652
|
+
function isPoisonedSessionSummary(summary) {
|
|
4653
|
+
const s = typeof summary === 'string' ? summary.trim() : ''
|
|
4654
|
+
return /^CVE-\d{4}-\d+$/i.test(s)
|
|
4655
|
+
}
|
|
4656
|
+
|
|
4657
|
+
/** 无首条用户输入时服务端回退的 sessionId 短标签 */
|
|
4658
|
+
function isSessionIdFallbackTitle(title, sessionId) {
|
|
4659
|
+
const t = typeof title === 'string' ? title.trim() : ''
|
|
4660
|
+
const sid = typeof sessionId === 'string' ? sessionId.trim() : ''
|
|
4661
|
+
if (!t || !sid) return false
|
|
4662
|
+
if (t === sid) return true
|
|
4663
|
+
if (t.endsWith('…') && sid.startsWith(t.slice(0, -1))) return true
|
|
4664
|
+
if (t.endsWith('...') && sid.startsWith(t.slice(0, -3))) return true
|
|
4665
|
+
return false
|
|
4666
|
+
}
|
|
4667
|
+
|
|
4668
|
+
/**
|
|
4669
|
+
* 从 /api/sessions 单条记录解析标题:优先 firstPrompt,否则用同口径 summary。
|
|
4670
|
+
* 排除 CVE 误抓;sessionId 短标签视为无效标题。
|
|
4671
|
+
*/
|
|
4672
|
+
function sessionTitleFromApiItem(s) {
|
|
4673
|
+
if (!s || typeof s !== 'object') return ''
|
|
4674
|
+
const fp = typeof s.firstPrompt === 'string' ? s.firstPrompt.trim() : ''
|
|
4675
|
+
if (fp && !isSessionIdFallbackTitle(fp, s.sessionId)) return fp
|
|
4676
|
+
const sum = typeof s.summary === 'string' ? s.summary.trim() : ''
|
|
4677
|
+
if (!sum || sum === '新对话' || isPoisonedSessionSummary(sum)) return ''
|
|
4678
|
+
if (isSessionIdFallbackTitle(sum, s.sessionId)) return ''
|
|
4679
|
+
return sum
|
|
4680
|
+
}
|
|
4681
|
+
|
|
4682
|
+
function needsSessionTitleHydration(s) {
|
|
4683
|
+
if (!s || !s.sessionId) return false
|
|
4684
|
+
const title = sessionTitleFromApiItem(s)
|
|
4685
|
+
const remembered = sessionTitleById[s.sessionId.trim()]
|
|
4686
|
+
if (remembered && remembered.trim()) return false
|
|
4687
|
+
return !title
|
|
4688
|
+
}
|
|
4689
|
+
|
|
4690
|
+
/**
|
|
4691
|
+
* 解析侧栏/顶栏展示标题:仅首条用户输入。
|
|
4692
|
+
*/
|
|
4693
|
+
function pickSessionFirstPrompt(s) {
|
|
4694
|
+
if (!s || typeof s !== 'object') return ''
|
|
4695
|
+
const fp = typeof s.firstPrompt === 'string' ? s.firstPrompt.trim() : ''
|
|
4696
|
+
if (fp && !isSessionIdFallbackTitle(fp, s.sessionId)) return fp
|
|
4697
|
+
const fromApi = sessionTitleFromApiItem(s)
|
|
4698
|
+
if (fromApi) return fromApi
|
|
4699
|
+
const remembered =
|
|
4700
|
+
typeof s.sessionId === 'string' ? sessionTitleById[s.sessionId.trim()] : ''
|
|
4701
|
+
return typeof remembered === 'string' ? remembered.trim() : ''
|
|
4702
|
+
}
|
|
4703
|
+
|
|
4704
|
+
/** 从 replay 信封提取首条用户输入(与侧栏 hydrate 同源) */
|
|
4705
|
+
function extractFirstUserPromptFromReplayEnvelopes(envelopes) {
|
|
4706
|
+
if (!Array.isArray(envelopes)) return ''
|
|
4707
|
+
for (let i = 0; i < envelopes.length; i++) {
|
|
4708
|
+
const env = envelopes[i]
|
|
4709
|
+
if (!env || env.protocolVersion !== 3 || env.type !== 'conversation.delta') continue
|
|
4710
|
+
const payload = env.data && typeof env.data === 'object' ? env.data : {}
|
|
4711
|
+
if (payload.action !== 'message_added') continue
|
|
4712
|
+
const msg = payload.message
|
|
4713
|
+
if (!msg || msg.type !== 'user' || !shouldShowWsUserMessage(msg)) continue
|
|
4714
|
+
const blocks = getMessageContentBlocks(msg)
|
|
4715
|
+
const nonToolBlocks = blocks.filter(function (b) {
|
|
4716
|
+
return b && b.type !== 'tool_result'
|
|
4717
|
+
})
|
|
4718
|
+
if (!nonToolBlocks.length) continue
|
|
4719
|
+
const body = unwrapChannelWrappedText(
|
|
4720
|
+
contentToPlainText(nonToolBlocks).trim(),
|
|
4721
|
+
).body.trim()
|
|
4722
|
+
if (body) return body.length > 120 ? body.slice(0, 120) : body
|
|
4723
|
+
}
|
|
4724
|
+
return ''
|
|
4725
|
+
}
|
|
4726
|
+
|
|
4727
|
+
/**
|
|
4728
|
+
* 列表接口常缺 firstPrompt(仅带 summary 或 sessionId 短标签)。
|
|
4729
|
+
* 首次进页时对缺标题会话并行拉 replay 补首条用户输入。
|
|
4730
|
+
*/
|
|
4731
|
+
async function hydrateMissingSessionTitles(sessions) {
|
|
4732
|
+
const list = Array.isArray(sessions) ? sessions : []
|
|
4733
|
+
const targets = list.filter(function (s) {
|
|
4734
|
+
if (!s || !s.sessionId) return false
|
|
4735
|
+
if (sessionTitleHydrateInflight.has(s.sessionId)) return false
|
|
4736
|
+
return needsSessionTitleHydration(s)
|
|
4737
|
+
})
|
|
4738
|
+
if (!targets.length) return
|
|
4739
|
+
await Promise.all(
|
|
4740
|
+
targets.map(async function (s) {
|
|
4741
|
+
const sid = s.sessionId
|
|
4742
|
+
sessionTitleHydrateInflight.add(sid)
|
|
4743
|
+
try {
|
|
4744
|
+
const r = await fetch(buildSessionReplayUrl(sid))
|
|
4745
|
+
const data = await r.json()
|
|
4746
|
+
if (!r.ok) return
|
|
4747
|
+
const title = extractFirstUserPromptFromReplayEnvelopes(data.envelopes)
|
|
4748
|
+
if (!title) return
|
|
4749
|
+
patchSessionListFirstPrompt(sid, title)
|
|
4750
|
+
} catch {
|
|
4751
|
+
/* 单条失败不影响其它 session */
|
|
4752
|
+
} finally {
|
|
4753
|
+
sessionTitleHydrateInflight.delete(sid)
|
|
4754
|
+
}
|
|
4755
|
+
}),
|
|
4756
|
+
)
|
|
4757
|
+
}
|
|
4758
|
+
|
|
4759
|
+
/**
|
|
4760
|
+
* 从已加载的对话状态提取首条用户输入,供标题展示。
|
|
4761
|
+
* 与 shouldShowWsUserMessage / unwrapChannelWrappedText 规则一致。
|
|
4762
|
+
*/
|
|
4763
|
+
function extractFirstUserPromptFromChatState() {
|
|
4764
|
+
const mainRun = chatState.messagesByRun.get('main')
|
|
4765
|
+
if (!Array.isArray(mainRun)) return ''
|
|
4766
|
+
for (let i = 0; i < mainRun.length; i++) {
|
|
4767
|
+
const item = mainRun[i]
|
|
4768
|
+
const m = item && item.message ? item.message : null
|
|
4769
|
+
if (!m || m.type !== 'user' || !shouldShowWsUserMessage(m)) continue
|
|
4770
|
+
const blocks = getMessageContentBlocks(m)
|
|
4771
|
+
const nonToolBlocks = blocks.filter(function (b) {
|
|
4772
|
+
return b && b.type !== 'tool_result'
|
|
4773
|
+
})
|
|
4774
|
+
if (!nonToolBlocks.length) continue
|
|
4775
|
+
const body = unwrapChannelWrappedText(contentToPlainText(nonToolBlocks).trim()).body.trim()
|
|
4776
|
+
if (body) return body.length > 120 ? body.slice(0, 120) : body
|
|
4777
|
+
}
|
|
4778
|
+
return ''
|
|
4779
|
+
}
|
|
4780
|
+
|
|
4781
|
+
/** 将首条用户输入写回侧栏会话缓存,保证标题与 transcript 一致 */
|
|
4782
|
+
function patchSessionListFirstPrompt(sessionId, firstPrompt) {
|
|
4783
|
+
const sid = typeof sessionId === 'string' ? sessionId.trim() : ''
|
|
4784
|
+
const fp = typeof firstPrompt === 'string' ? firstPrompt.trim() : ''
|
|
4785
|
+
if (!sid || !fp || !Array.isArray(window.__lastSessions)) return
|
|
4786
|
+
rememberSessionTitle(sid, fp)
|
|
4787
|
+
let changed = false
|
|
4788
|
+
for (let i = 0; i < window.__lastSessions.length; i++) {
|
|
4789
|
+
const s = window.__lastSessions[i]
|
|
4790
|
+
if (!s || s.sessionId !== sid) continue
|
|
4791
|
+
if (s.firstPrompt !== fp) {
|
|
4792
|
+
s.firstPrompt = fp
|
|
4793
|
+
s.summary = fp
|
|
4794
|
+
changed = true
|
|
4795
|
+
}
|
|
4796
|
+
break
|
|
4797
|
+
}
|
|
4798
|
+
if (changed) renderSessionList(window.__lastSessions)
|
|
4799
|
+
}
|
|
4800
|
+
|
|
4801
|
+
/**
|
|
4802
|
+
* 合并 /api/sessions 响应与本地已解析标题,避免轮询刷新把侧栏标题冲成(无标题)。
|
|
4803
|
+
*/
|
|
4804
|
+
function mergeSessionsWithRememberedTitles(incoming) {
|
|
4805
|
+
const list = Array.isArray(incoming) ? incoming.slice() : []
|
|
4806
|
+
const prevById = new Map()
|
|
4807
|
+
if (Array.isArray(window.__lastSessions)) {
|
|
4808
|
+
for (let i = 0; i < window.__lastSessions.length; i++) {
|
|
4809
|
+
const s = window.__lastSessions[i]
|
|
4810
|
+
if (s && s.sessionId) prevById.set(s.sessionId, s)
|
|
4811
|
+
}
|
|
4812
|
+
}
|
|
4813
|
+
return list.map(function (s) {
|
|
4814
|
+
if (!s || !s.sessionId) return s
|
|
4815
|
+
const fromApi = sessionTitleFromApiItem(s)
|
|
4816
|
+
if (fromApi) {
|
|
4817
|
+
rememberSessionTitle(s.sessionId, fromApi)
|
|
4818
|
+
return { ...s, firstPrompt: fromApi, summary: fromApi }
|
|
4819
|
+
}
|
|
4820
|
+
const prev = prevById.get(s.sessionId)
|
|
4821
|
+
const prevTitle = prev ? sessionTitleFromApiItem(prev) : ''
|
|
4822
|
+
const remembered = sessionTitleById[s.sessionId] || prevTitle
|
|
4823
|
+
if (remembered) {
|
|
4824
|
+
rememberSessionTitle(s.sessionId, remembered)
|
|
4825
|
+
return { ...s, firstPrompt: remembered, summary: remembered }
|
|
4826
|
+
}
|
|
4827
|
+
return s
|
|
4828
|
+
})
|
|
4829
|
+
}
|
|
4830
|
+
|
|
4831
|
+
/** 会话标题仅取自首条用户输入 */
|
|
4636
4832
|
function sessionTitle(s) {
|
|
4637
|
-
|
|
4833
|
+
const fp = pickSessionFirstPrompt(s)
|
|
4834
|
+
if (fp) return fp.slice(0, 120)
|
|
4835
|
+
if (s && s.sessionId === sessionIdInput.value.trim()) {
|
|
4836
|
+
const fromChat = extractFirstUserPromptFromChatState()
|
|
4837
|
+
if (fromChat) return fromChat
|
|
4838
|
+
}
|
|
4839
|
+
return '(无标题)'
|
|
4840
|
+
}
|
|
4841
|
+
|
|
4842
|
+
/** 历史回放或实时消息落盘后,用 transcript 首条用户输入刷新标题 */
|
|
4843
|
+
function refreshSessionTitleFromChat(sessionId) {
|
|
4844
|
+
const sid = typeof sessionId === 'string' ? sessionId.trim() : ''
|
|
4845
|
+
if (!sid || sessionIdInput.value.trim() !== sid) return
|
|
4846
|
+
const title = extractFirstUserPromptFromChatState()
|
|
4847
|
+
if (!title) return
|
|
4848
|
+
patchSessionListFirstPrompt(sid, title)
|
|
4849
|
+
updateMainHeader(title)
|
|
4638
4850
|
}
|
|
4639
4851
|
|
|
4640
4852
|
function monthKeyFromSession(s) {
|
|
@@ -4769,7 +4981,7 @@
|
|
|
4769
4981
|
const list = hasCurrent
|
|
4770
4982
|
? rawList
|
|
4771
4983
|
: current
|
|
4772
|
-
? [{ sessionId: current, summary: '新对话' }].concat(rawList)
|
|
4984
|
+
? [{ sessionId: current, firstPrompt: '新对话', summary: '新对话' }].concat(rawList)
|
|
4773
4985
|
: rawList
|
|
4774
4986
|
sessionListEl.innerHTML = ''
|
|
4775
4987
|
updateMainHeader()
|
|
@@ -4980,8 +5192,10 @@
|
|
|
4980
5192
|
'个会话 · agent: ' +
|
|
4981
5193
|
ag +
|
|
4982
5194
|
(dir ? ' · ' + dir : '')
|
|
4983
|
-
|
|
4984
|
-
|
|
5195
|
+
const merged = mergeSessionsWithRememberedTitles(sessions)
|
|
5196
|
+
window.__lastSessions = merged
|
|
5197
|
+
renderSessionList(merged)
|
|
5198
|
+
void hydrateMissingSessionTitles(merged)
|
|
4985
5199
|
const shouldActivateFirst = !!(options && options.activateFirstIfEmpty)
|
|
4986
5200
|
if (shouldActivateFirst && sessionIdInput && !sessionIdInput.value.trim() && sessions.length) {
|
|
4987
5201
|
const firstId = sessions[0] && typeof sessions[0].sessionId === 'string'
|
|
@@ -51002,6 +51002,14 @@ function extractJsonStringField(text, key) {
|
|
|
51002
51002
|
}
|
|
51003
51003
|
return;
|
|
51004
51004
|
}
|
|
51005
|
+
function extractLastMetadataStringField(tail, entryType, fieldKey) {
|
|
51006
|
+
const prefix = `{"type":"${entryType}"`;
|
|
51007
|
+
const line = tail.split(`
|
|
51008
|
+
`).findLast((l) => l.startsWith(prefix));
|
|
51009
|
+
if (!line)
|
|
51010
|
+
return;
|
|
51011
|
+
return extractLastJsonStringField(line, fieldKey);
|
|
51012
|
+
}
|
|
51005
51013
|
function extractLastJsonStringField(text, key) {
|
|
51006
51014
|
const patterns = [`"${key}":"`, `"${key}": "`];
|
|
51007
51015
|
let lastValue;
|
|
@@ -51029,6 +51037,12 @@ function extractLastJsonStringField(text, key) {
|
|
|
51029
51037
|
}
|
|
51030
51038
|
return lastValue;
|
|
51031
51039
|
}
|
|
51040
|
+
function unwrapChannelWrappedPrompt(text) {
|
|
51041
|
+
const matched = text.match(/^<channel\s+[^>]+>\s*([\s\S]*?)\s*<\/channel>\s*$/i);
|
|
51042
|
+
if (!matched)
|
|
51043
|
+
return text;
|
|
51044
|
+
return (matched[1] ?? "").trim();
|
|
51045
|
+
}
|
|
51032
51046
|
function extractFirstPromptFromHead(head) {
|
|
51033
51047
|
let start = 0;
|
|
51034
51048
|
let commandFallback = "";
|
|
@@ -51078,7 +51092,7 @@ function extractFirstPromptFromHead(head) {
|
|
|
51078
51092
|
}
|
|
51079
51093
|
}
|
|
51080
51094
|
for (const raw of texts) {
|
|
51081
|
-
let result = raw.replace(/\n/g, " ").trim();
|
|
51095
|
+
let result = unwrapChannelWrappedPrompt(raw).replace(/\n/g, " ").trim();
|
|
51082
51096
|
if (!result)
|
|
51083
51097
|
continue;
|
|
51084
51098
|
const cmdMatch = COMMAND_NAME_RE.exec(result);
|
|
@@ -296049,7 +296063,7 @@ function migrateLegacyAttachmentTypes(message) {
|
|
|
296049
296063
|
}
|
|
296050
296064
|
return message;
|
|
296051
296065
|
}
|
|
296052
|
-
function deserializeMessagesWithInterruptDetection(serializedMessages) {
|
|
296066
|
+
function deserializeMessagesWithInterruptDetection(serializedMessages, options) {
|
|
296053
296067
|
try {
|
|
296054
296068
|
const migratedMessages = serializedMessages.map(migrateLegacyAttachmentTypes);
|
|
296055
296069
|
const validModes = new Set(PERMISSION_MODES);
|
|
@@ -296060,10 +296074,10 @@ function deserializeMessagesWithInterruptDetection(serializedMessages) {
|
|
|
296060
296074
|
}
|
|
296061
296075
|
const filteredToolUses = filterUnresolvedToolUses(migratedMessages);
|
|
296062
296076
|
const filteredThinking = filterOrphanedThinkingOnlyMessages(filteredToolUses);
|
|
296063
|
-
const filteredMessages =
|
|
296077
|
+
const filteredMessages = filteredThinking;
|
|
296064
296078
|
const internalState = detectTurnInterruption(filteredMessages);
|
|
296065
296079
|
let turnInterruptionState;
|
|
296066
|
-
if (internalState.kind === "interrupted_turn") {
|
|
296080
|
+
if (internalState.kind === "interrupted_turn" && !options?.skipInterruptedPlaceholders) {
|
|
296067
296081
|
const [continuationMessage] = normalizeMessages([
|
|
296068
296082
|
createUserMessage({
|
|
296069
296083
|
content: "Continue from where you left off.",
|
|
@@ -296078,11 +296092,13 @@ function deserializeMessagesWithInterruptDetection(serializedMessages) {
|
|
|
296078
296092
|
} else {
|
|
296079
296093
|
turnInterruptionState = internalState;
|
|
296080
296094
|
}
|
|
296081
|
-
|
|
296082
|
-
|
|
296083
|
-
|
|
296084
|
-
|
|
296085
|
-
|
|
296095
|
+
if (!options?.skipInterruptedPlaceholders) {
|
|
296096
|
+
const lastRelevantIdx = filteredMessages.findLastIndex((m4) => m4.type !== "system" && m4.type !== "progress");
|
|
296097
|
+
if (lastRelevantIdx !== -1 && filteredMessages[lastRelevantIdx].type === "user") {
|
|
296098
|
+
filteredMessages.splice(lastRelevantIdx + 1, 0, createAssistantMessage({
|
|
296099
|
+
content: NO_RESPONSE_REQUESTED
|
|
296100
|
+
}));
|
|
296101
|
+
}
|
|
296086
296102
|
}
|
|
296087
296103
|
return { messages: filteredMessages, turnInterruptionState };
|
|
296088
296104
|
} catch (error49) {
|
|
@@ -296221,7 +296237,9 @@ async function loadConversationForResume(source, sourceJsonlFile, options) {
|
|
|
296221
296237
|
checkResumeConsistency(messages);
|
|
296222
296238
|
}
|
|
296223
296239
|
restoreSkillStateFromMessages(messages);
|
|
296224
|
-
const deserialized = deserializeMessagesWithInterruptDetection(messages
|
|
296240
|
+
const deserialized = deserializeMessagesWithInterruptDetection(messages, {
|
|
296241
|
+
skipInterruptedPlaceholders: options?.skipInterruptedPlaceholders
|
|
296242
|
+
});
|
|
296225
296243
|
messages = deserialized.messages;
|
|
296226
296244
|
const hookMessages = options?.headlessWsResume ? [] : await processSessionStartHooks("resume", { sessionId });
|
|
296227
296245
|
messages.push(...hookMessages);
|
|
@@ -325630,7 +325648,7 @@ function parseSessionInfoFromLite(sessionId, lite, projectPath) {
|
|
|
325630
325648
|
if (!Number.isNaN(parsed))
|
|
325631
325649
|
createdAt = parsed;
|
|
325632
325650
|
}
|
|
325633
|
-
const summary =
|
|
325651
|
+
const summary = firstPrompt || fallbackSessionSummary(sessionId);
|
|
325634
325652
|
const gitBranch = extractLastJsonStringField(tail, "gitBranch") || extractJsonStringField(head, "gitBranch") || undefined;
|
|
325635
325653
|
const sessionCwd = extractJsonStringField(head, "cwd") || projectPath || undefined;
|
|
325636
325654
|
const tagLine = tail.split(`
|
|
@@ -388005,7 +388023,7 @@ function normalizeMessagesForAPI(messages, tools = []) {
|
|
|
388005
388023
|
timestamp: message.timestamp
|
|
388006
388024
|
});
|
|
388007
388025
|
const lastMessage = last_default(result);
|
|
388008
|
-
if (lastMessage?.type === "user") {
|
|
388026
|
+
if (lastMessage?.type === "user" && canMergeAdjacentUserMessages(lastMessage, userMsg)) {
|
|
388009
388027
|
result[result.length - 1] = mergeUserMessages(lastMessage, userMsg);
|
|
388010
388028
|
return;
|
|
388011
388029
|
}
|
|
@@ -388054,7 +388072,7 @@ function normalizeMessagesForAPI(messages, tools = []) {
|
|
|
388054
388072
|
}
|
|
388055
388073
|
}
|
|
388056
388074
|
const lastMessage = last_default(result);
|
|
388057
|
-
if (lastMessage?.type === "user") {
|
|
388075
|
+
if (lastMessage?.type === "user" && canMergeAdjacentUserMessages(lastMessage, normalizedMessage)) {
|
|
388058
388076
|
result[result.length - 1] = mergeUserMessages(lastMessage, normalizedMessage);
|
|
388059
388077
|
return;
|
|
388060
388078
|
}
|
|
@@ -388111,7 +388129,21 @@ function normalizeMessagesForAPI(messages, tools = []) {
|
|
|
388111
388129
|
const attachmentMessage = checkStatsigFeatureGate_CACHED_MAY_BE_STALE("tengu_chair_sermon") ? rawAttachmentMessage.map(ensureSystemReminderWrap) : rawAttachmentMessage;
|
|
388112
388130
|
const lastMessage = last_default(result);
|
|
388113
388131
|
if (lastMessage?.type === "user") {
|
|
388114
|
-
|
|
388132
|
+
const mergedUsers = [];
|
|
388133
|
+
let acc = lastMessage;
|
|
388134
|
+
for (const candidate of attachmentMessage) {
|
|
388135
|
+
if (canMergeAdjacentUserMessages(acc, candidate)) {
|
|
388136
|
+
acc = mergeUserMessagesAndToolResults(acc, candidate);
|
|
388137
|
+
} else {
|
|
388138
|
+
mergedUsers.push(acc);
|
|
388139
|
+
acc = candidate;
|
|
388140
|
+
}
|
|
388141
|
+
}
|
|
388142
|
+
mergedUsers.push(acc);
|
|
388143
|
+
result[result.length - 1] = mergedUsers[0];
|
|
388144
|
+
for (let i6 = 1;i6 < mergedUsers.length; i6 += 1) {
|
|
388145
|
+
result.push(mergedUsers[i6]);
|
|
388146
|
+
}
|
|
388115
388147
|
return;
|
|
388116
388148
|
}
|
|
388117
388149
|
result.push(...attachmentMessage);
|
|
@@ -388122,8 +388154,7 @@ function normalizeMessagesForAPI(messages, tools = []) {
|
|
|
388122
388154
|
const relocated = checkStatsigFeatureGate_CACHED_MAY_BE_STALE("tengu_toolref_defer_j8m") ? relocateToolReferenceSiblings(result) : result;
|
|
388123
388155
|
const withFilteredOrphans = filterOrphanedThinkingOnlyMessages(relocated);
|
|
388124
388156
|
const withFilteredThinking = filterTrailingThinkingFromLastAssistant(withFilteredOrphans);
|
|
388125
|
-
const
|
|
388126
|
-
const withNonEmpty = ensureNonEmptyAssistantContent(withFilteredWhitespace);
|
|
388157
|
+
const withNonEmpty = ensureNonEmptyAssistantContent(withFilteredThinking);
|
|
388127
388158
|
const smooshed = checkStatsigFeatureGate_CACHED_MAY_BE_STALE("tengu_chair_sermon") ? smooshSystemReminderSiblings(mergeAdjacentUserMessages(withNonEmpty)) : withNonEmpty;
|
|
388128
388159
|
const sanitized = sanitizeErrorToolResultContent(smooshed);
|
|
388129
388160
|
if (false) {}
|
|
@@ -388131,10 +388162,14 @@ function normalizeMessagesForAPI(messages, tools = []) {
|
|
|
388131
388162
|
return sanitized;
|
|
388132
388163
|
}
|
|
388133
388164
|
function mergeUserMessagesAndToolResults(a5, b5) {
|
|
388165
|
+
if (!canMergeAdjacentUserMessages(a5, b5)) {
|
|
388166
|
+
return b5;
|
|
388167
|
+
}
|
|
388134
388168
|
const lastContent = normalizeUserTextContent(a5.message.content);
|
|
388135
388169
|
const currentContent = normalizeUserTextContent(b5.message.content);
|
|
388136
388170
|
return {
|
|
388137
388171
|
...a5,
|
|
388172
|
+
isMeta: a5.isMeta && b5.isMeta ? true : undefined,
|
|
388138
388173
|
message: {
|
|
388139
388174
|
...a5.message,
|
|
388140
388175
|
content: hoistToolResults(mergeUserContentBlocks(lastContent, currentContent))
|
|
@@ -388159,12 +388194,16 @@ function isToolResultMessage(msg) {
|
|
|
388159
388194
|
return false;
|
|
388160
388195
|
return content.some((block) => block.type === "tool_result");
|
|
388161
388196
|
}
|
|
388197
|
+
function canMergeAdjacentUserMessages(a5, b5) {
|
|
388198
|
+
return Boolean(a5.isMeta) === Boolean(b5.isMeta);
|
|
388199
|
+
}
|
|
388162
388200
|
function mergeUserMessages(a5, b5) {
|
|
388163
388201
|
const lastContent = normalizeUserTextContent(a5.message.content);
|
|
388164
388202
|
const currentContent = normalizeUserTextContent(b5.message.content);
|
|
388165
388203
|
if (false) {}
|
|
388166
388204
|
return {
|
|
388167
388205
|
...a5,
|
|
388206
|
+
isMeta: a5.isMeta && b5.isMeta ? true : undefined,
|
|
388168
388207
|
uuid: a5.isMeta ? b5.uuid : a5.uuid,
|
|
388169
388208
|
message: {
|
|
388170
388209
|
...a5.message,
|
|
@@ -388176,7 +388215,7 @@ function mergeAdjacentUserMessages(msgs) {
|
|
|
388176
388215
|
const out = [];
|
|
388177
388216
|
for (const m4 of msgs) {
|
|
388178
388217
|
const prev = out.at(-1);
|
|
388179
|
-
if (m4.type === "user" && prev?.type === "user") {
|
|
388218
|
+
if (m4.type === "user" && prev?.type === "user" && canMergeAdjacentUserMessages(prev, m4)) {
|
|
388180
388219
|
out[out.length - 1] = mergeUserMessages(prev, m4);
|
|
388181
388220
|
} else {
|
|
388182
388221
|
out.push(m4);
|
|
@@ -389608,53 +389647,6 @@ function filterTrailingThinkingFromLastAssistant(messages) {
|
|
|
389608
389647
|
};
|
|
389609
389648
|
return result;
|
|
389610
389649
|
}
|
|
389611
|
-
function hasOnlyWhitespaceTextContent(content) {
|
|
389612
|
-
if (content.length === 0) {
|
|
389613
|
-
return false;
|
|
389614
|
-
}
|
|
389615
|
-
for (const block of content) {
|
|
389616
|
-
if (block.type !== "text") {
|
|
389617
|
-
return false;
|
|
389618
|
-
}
|
|
389619
|
-
if (block.text !== undefined && block.text.trim() !== "") {
|
|
389620
|
-
return false;
|
|
389621
|
-
}
|
|
389622
|
-
}
|
|
389623
|
-
return true;
|
|
389624
|
-
}
|
|
389625
|
-
function filterWhitespaceOnlyAssistantMessages(messages) {
|
|
389626
|
-
let hasChanges = false;
|
|
389627
|
-
const filtered = messages.filter((message) => {
|
|
389628
|
-
if (message.type !== "assistant") {
|
|
389629
|
-
return true;
|
|
389630
|
-
}
|
|
389631
|
-
const content = message.message.content;
|
|
389632
|
-
if (!Array.isArray(content) || content.length === 0) {
|
|
389633
|
-
return true;
|
|
389634
|
-
}
|
|
389635
|
-
if (hasOnlyWhitespaceTextContent(content)) {
|
|
389636
|
-
hasChanges = true;
|
|
389637
|
-
logEvent("tengu_filtered_whitespace_only_assistant", {
|
|
389638
|
-
messageUUID: message.uuid
|
|
389639
|
-
});
|
|
389640
|
-
return false;
|
|
389641
|
-
}
|
|
389642
|
-
return true;
|
|
389643
|
-
});
|
|
389644
|
-
if (!hasChanges) {
|
|
389645
|
-
return messages;
|
|
389646
|
-
}
|
|
389647
|
-
const merged = [];
|
|
389648
|
-
for (const message of filtered) {
|
|
389649
|
-
const prev = merged.at(-1);
|
|
389650
|
-
if (message.type === "user" && prev?.type === "user") {
|
|
389651
|
-
merged[merged.length - 1] = mergeUserMessages(prev, message);
|
|
389652
|
-
} else {
|
|
389653
|
-
merged.push(message);
|
|
389654
|
-
}
|
|
389655
|
-
}
|
|
389656
|
-
return merged;
|
|
389657
|
-
}
|
|
389658
389650
|
function ensureNonEmptyAssistantContent(messages) {
|
|
389659
389651
|
if (messages.length === 0) {
|
|
389660
389652
|
return messages;
|
|
@@ -398792,27 +398784,28 @@ function getFirstMeaningfulUserMessageTextContent(transcript) {
|
|
|
398792
398784
|
for (const textContent of texts) {
|
|
398793
398785
|
if (!textContent)
|
|
398794
398786
|
continue;
|
|
398795
|
-
const
|
|
398787
|
+
const normalized = unwrapChannelWrappedPrompt(textContent);
|
|
398788
|
+
const commandNameTag = extractTag(normalized, COMMAND_NAME_TAG);
|
|
398796
398789
|
if (commandNameTag) {
|
|
398797
398790
|
const commandName = commandNameTag.replace(/^\//, "");
|
|
398798
398791
|
if (builtInCommandNames().has(commandName)) {
|
|
398799
398792
|
continue;
|
|
398800
398793
|
} else {
|
|
398801
|
-
const commandArgs = extractTag(
|
|
398794
|
+
const commandArgs = extractTag(normalized, "command-args")?.trim();
|
|
398802
398795
|
if (!commandArgs) {
|
|
398803
398796
|
continue;
|
|
398804
398797
|
}
|
|
398805
398798
|
return `${commandNameTag} ${commandArgs}`;
|
|
398806
398799
|
}
|
|
398807
398800
|
}
|
|
398808
|
-
const bashInput = extractTag(
|
|
398801
|
+
const bashInput = extractTag(normalized, "bash-input");
|
|
398809
398802
|
if (bashInput) {
|
|
398810
398803
|
return `! ${bashInput}`;
|
|
398811
398804
|
}
|
|
398812
|
-
if (SKIP_FIRST_PROMPT_PATTERN2.test(
|
|
398805
|
+
if (SKIP_FIRST_PROMPT_PATTERN2.test(normalized)) {
|
|
398813
398806
|
continue;
|
|
398814
398807
|
}
|
|
398815
|
-
return
|
|
398808
|
+
return normalized;
|
|
398816
398809
|
}
|
|
398817
398810
|
}
|
|
398818
398811
|
return;
|
|
@@ -400394,10 +400387,12 @@ async function readLiteMetadata(filePath, fileSize, buf) {
|
|
|
400394
400387
|
const projectPath = extractJsonStringField(head, "cwd");
|
|
400395
400388
|
const teamName = extractJsonStringField(head, "teamName");
|
|
400396
400389
|
const agentSetting = extractJsonStringField(head, "agentSetting");
|
|
400397
|
-
const firstPrompt =
|
|
400390
|
+
const firstPrompt = extractLastMetadataStringField(tail, "last-prompt", "lastPrompt") || extractFirstPromptFromChunk(head) || extractJsonStringFieldPrefix(head, "content", 200) || extractJsonStringFieldPrefix(head, "text", 200) || "";
|
|
400398
400391
|
const customTitle = extractLastJsonStringField(tail, "customTitle") ?? extractLastJsonStringField(head, "customTitle") ?? extractLastJsonStringField(tail, "aiTitle") ?? extractLastJsonStringField(head, "aiTitle");
|
|
400399
|
-
const summary =
|
|
400400
|
-
const
|
|
400392
|
+
const summary = extractLastMetadataStringField(tail, "summary", "summary");
|
|
400393
|
+
const tagLine = tail.split(`
|
|
400394
|
+
`).findLast((l4) => l4.startsWith('{"type":"tag"'));
|
|
400395
|
+
const tag2 = tagLine ? extractLastJsonStringField(tagLine, "tag") || undefined : undefined;
|
|
400401
400396
|
const gitBranch = extractLastJsonStringField(tail, "gitBranch") ?? extractJsonStringField(head, "gitBranch");
|
|
400402
400397
|
const prUrl = extractLastJsonStringField(tail, "prUrl");
|
|
400403
400398
|
const prRepository = extractLastJsonStringField(tail, "prRepository");
|
|
@@ -400468,7 +400463,9 @@ function extractFirstPromptFromChunk(chunk) {
|
|
|
400468
400463
|
for (const text2 of texts) {
|
|
400469
400464
|
if (!text2)
|
|
400470
400465
|
continue;
|
|
400471
|
-
let result = text2.replace(/\n/g, " ").trim();
|
|
400466
|
+
let result = unwrapChannelWrappedPrompt(text2).replace(/\n/g, " ").trim();
|
|
400467
|
+
if (!result)
|
|
400468
|
+
continue;
|
|
400472
400469
|
const commandNameTag = extractTag(result, COMMAND_NAME_TAG);
|
|
400473
400470
|
if (commandNameTag) {
|
|
400474
400471
|
const name3 = commandNameTag.replace(/^\//, "");
|
|
@@ -405853,6 +405850,20 @@ function messagesToWsV3Envelopes(args) {
|
|
|
405853
405850
|
}
|
|
405854
405851
|
|
|
405855
405852
|
// src/server/api/sessionReplayController.ts
|
|
405853
|
+
async function isSessionChildRunning(agent, storageId) {
|
|
405854
|
+
const socket = process.env.WS_MAIN_RPC_SOCKET?.trim();
|
|
405855
|
+
if (!socket) {
|
|
405856
|
+
return false;
|
|
405857
|
+
}
|
|
405858
|
+
const statuses = await new MainRpcClient(socket).listSessionRuntimeStatus(agent);
|
|
405859
|
+
if (!statuses?.length) {
|
|
405860
|
+
return false;
|
|
405861
|
+
}
|
|
405862
|
+
return statuses.some((st) => {
|
|
405863
|
+
const key2 = resolveSessionTranscriptStorageId(st.sessionId) ?? st.sessionId;
|
|
405864
|
+
return key2 === storageId && st.running === true;
|
|
405865
|
+
});
|
|
405866
|
+
}
|
|
405856
405867
|
async function handleSessionReplayApi(req, url3) {
|
|
405857
405868
|
if (url3.pathname !== "/api/sessions/replay") {
|
|
405858
405869
|
return;
|
|
@@ -405903,8 +405914,10 @@ async function handleSessionReplayApi(req, url3) {
|
|
|
405903
405914
|
let messages = [];
|
|
405904
405915
|
try {
|
|
405905
405916
|
await access3(jsonlPath);
|
|
405917
|
+
const childRunning = await isSessionChildRunning(agent, storageId);
|
|
405906
405918
|
const loaded = await loadConversationForResume(storageId, jsonlPath, {
|
|
405907
|
-
headlessWsResume: true
|
|
405919
|
+
headlessWsResume: true,
|
|
405920
|
+
skipInterruptedPlaceholders: childRunning
|
|
405908
405921
|
});
|
|
405909
405922
|
messages = loaded?.messages ?? [];
|
|
405910
405923
|
} catch (e5) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@auto-ai/agent",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.192",
|
|
4
4
|
"description": "Auto AI Agent 网关 CLI(WebSocket,独立二进制,无需 Bun)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"maintainers": [
|
|
@@ -32,11 +32,11 @@
|
|
|
32
32
|
"zod": "^4.3.6"
|
|
33
33
|
},
|
|
34
34
|
"optionalDependencies": {
|
|
35
|
-
"@auto-ai/agent-linux-x64": "2.1.
|
|
36
|
-
"@auto-ai/agent-linux-arm64": "2.1.
|
|
37
|
-
"@auto-ai/agent-darwin-x64": "2.1.
|
|
38
|
-
"@auto-ai/agent-darwin-arm64": "2.1.
|
|
39
|
-
"@auto-ai/agent-win-x64": "2.1.
|
|
35
|
+
"@auto-ai/agent-linux-x64": "2.1.192",
|
|
36
|
+
"@auto-ai/agent-linux-arm64": "2.1.192",
|
|
37
|
+
"@auto-ai/agent-darwin-x64": "2.1.192",
|
|
38
|
+
"@auto-ai/agent-darwin-arm64": "2.1.192",
|
|
39
|
+
"@auto-ai/agent-win-x64": "2.1.192"
|
|
40
40
|
},
|
|
41
41
|
"scripts": {
|
|
42
42
|
"prepare": "node ../../scripts/sync-launcher-env.js",
|