mirror of
https://github.com/AgentSeal/codeburn.git
synced 2026-08-21 14:34:32 +00:00
fix(hermes): fail closed on unknown GLM, namespaces, and ACP identity
Extra High review held #1039. Stop pricing every future glm-5.x as 5.2, stop collapsing unknown provider/org/model trees onto a priced leaf, and stop calling ACP Buzz — source=acp is a transport and the DB has no client field. Strip trailing punctuation on PR URLs and bump the Hermes parse version so old cache rows reparse.
This commit is contained in:
parent
66a776acfa
commit
10fdec6037
6 changed files with 35 additions and 22 deletions
|
|
@ -630,8 +630,7 @@ function routedModelCandidates(model: string): string[] {
|
|||
ids.push(value)
|
||||
}
|
||||
push(model)
|
||||
let current = getCanonicalName(model)
|
||||
push(current)
|
||||
let current = model
|
||||
let peeled = true
|
||||
while (peeled) {
|
||||
peeled = false
|
||||
|
|
@ -644,13 +643,9 @@ function routedModelCandidates(model: string): string[] {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (current.includes('/')) push(current.slice(current.lastIndexOf('/') + 1))
|
||||
const leaf = current.includes('/') ? current.slice(current.lastIndexOf('/') + 1) : current
|
||||
if (/^glm-5(?:\.\d+)?$/i.test(leaf)) {
|
||||
push('glm-5p2')
|
||||
push('glm-5p1')
|
||||
push('glm-5')
|
||||
}
|
||||
// One house-style vendor strip (anthropic/foo → foo). Do not keep
|
||||
// collapsing unknown provider/org/model trees onto a priced leaf.
|
||||
push(getCanonicalName(current))
|
||||
return ids
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2493,7 +2493,7 @@ function providerCallToCachedCall(call: ParsedProviderCall): CachedCall {
|
|||
webSearchRequests: call.webSearchRequests,
|
||||
cacheCreationOneHourTokens: 0,
|
||||
},
|
||||
costUSD: (call.provider === 'mistral-vibe' || call.provider === 'antigravity' || call.provider === 'devin' || call.provider === 'vercel-gateway' || call.provider === 'hermes' || call.provider === 'buzz' || call.provider === 'kiro' || call.provider === 'codewhale' || call.provider === 'quickdesk' || call.provider === 'cline-cli') ? call.costUSD : undefined,
|
||||
costUSD: (call.provider === 'mistral-vibe' || call.provider === 'antigravity' || call.provider === 'devin' || call.provider === 'vercel-gateway' || call.provider === 'hermes' || call.provider === 'kiro' || call.provider === 'codewhale' || call.provider === 'quickdesk' || call.provider === 'cline-cli') ? call.costUSD : undefined,
|
||||
isEstimated: call.costIsEstimated || undefined,
|
||||
speed: call.speed,
|
||||
timestamp: call.timestamp,
|
||||
|
|
|
|||
|
|
@ -99,7 +99,8 @@ function extractGithubPullUrls(...texts: Array<string | null | undefined>): stri
|
|||
if (!text) continue
|
||||
for (const match of text.matchAll(re)) {
|
||||
try {
|
||||
const url = new URL(match[0])
|
||||
const raw = match[0].replace(/[).,\]]:;]+$/g, '')
|
||||
const url = new URL(raw)
|
||||
if (url.protocol !== 'https:') continue
|
||||
if (!/^\/[^/]+\/[^/]+\/pull\/\d+$/.test(url.pathname)) continue
|
||||
found.add(`${url.origin}${url.pathname}`)
|
||||
|
|
@ -280,15 +281,11 @@ function isRealWorkspace(cwd: string | null | undefined): cwd is string {
|
|||
return true
|
||||
}
|
||||
|
||||
function hermesSurfaceProvider(source: string | null | undefined): 'hermes' | 'buzz' {
|
||||
return source === 'acp' ? 'buzz' : 'hermes'
|
||||
}
|
||||
|
||||
function resolveHermesWorkspace(
|
||||
row: HermesSessionRow,
|
||||
messages: HermesMessageRow[],
|
||||
): { project: string; projectPath?: string; provider: 'hermes' | 'buzz' } {
|
||||
const provider = hermesSurfaceProvider(row.source)
|
||||
): { project: string; projectPath?: string; provider: 'hermes' } {
|
||||
const provider = 'hermes' as const
|
||||
const repo = row.git_repo_root?.trim()
|
||||
if (isRealWorkspace(repo)) {
|
||||
return { project: sanitizeProject(basename(repo)), projectPath: repo, provider }
|
||||
|
|
|
|||
|
|
@ -292,7 +292,7 @@ export const PROVIDER_PARSE_VERSIONS: Record<string, string> = {
|
|||
// replays (double-counted before), takes the model from the reporting
|
||||
// assistant/message, and keeps agent-injected context out of the preview.
|
||||
dsh: 'seed-aware-v1',
|
||||
hermes: 'reasoning-output-accounting-v1-est-cost',
|
||||
hermes: 'reasoning-output-accounting-v1-est-cost-routed-ids-workspace-pr-v2',
|
||||
'lingtai-tui': 'token-ledger-registry-activity-v3',
|
||||
'ibm-bob': 'worktree-project-grouping-v1',
|
||||
// project-path-v1: the parser now records the session's full working
|
||||
|
|
|
|||
|
|
@ -71,8 +71,9 @@ describe('getModelCosts', () => {
|
|||
expect(upper!.outputCostPerToken).toBe(sibling!.outputCostPerToken)
|
||||
expect(getModelCosts('cp/cline-pass/glm-5.3')!.inputCostPerToken).toBe(sibling!.inputCostPerToken)
|
||||
expect(getModelCosts('omniroute:cp/cline-pass/glm-5.3')!.inputCostPerToken).toBe(sibling!.inputCostPerToken)
|
||||
expect(getModelCosts('glm-5.4')!.inputCostPerToken).toBe(sibling!.inputCostPerToken)
|
||||
expect(getModelCosts('cmd/deepseek/deepseek-v4-flash')).not.toBeNull()
|
||||
expect(getModelCosts('glm-5.4')).toBeNull()
|
||||
expect(getModelCosts('provider/org/glm-5.3')).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -520,6 +520,26 @@ skipUnlessSqlite('hermes provider', () => {
|
|||
expect(calls[0]?.project).toBe('hermes')
|
||||
})
|
||||
|
||||
it('captures GitHub pull URLs that are wrapped in prose punctuation', async () => {
|
||||
const dbPath = createHermesDb(tmpDir)
|
||||
withTestDb(dbPath, (db) => {
|
||||
insertSession(db, {
|
||||
id: 'pr-punct',
|
||||
inputTokens: 10,
|
||||
outputTokens: 5,
|
||||
cacheReadTokens: 0,
|
||||
cacheWriteTokens: 0,
|
||||
reasoningTokens: 0,
|
||||
startedAt: 1779549200,
|
||||
})
|
||||
db.prepare('INSERT INTO messages (session_id, role, content, timestamp) VALUES (?, ?, ?, ?)')
|
||||
.run('pr-punct', 'assistant', 'See (https://github.com/getagentseal/codeburn/pull/1037).', 1779549201)
|
||||
})
|
||||
|
||||
const calls = await collectCalls(tmpDir, `${dbPath}#hermes-session=pr-punct`)
|
||||
expect(calls[0]?.prLinks).toEqual(['https://github.com/getagentseal/codeburn/pull/1037'])
|
||||
})
|
||||
|
||||
it('ignores GitHub pull URLs that only appear in tool dumps', async () => {
|
||||
const dbPath = createHermesDb(tmpDir)
|
||||
withTestDb(dbPath, (db) => {
|
||||
|
|
@ -542,7 +562,7 @@ skipUnlessSqlite('hermes provider', () => {
|
|||
expect(calls[0]?.prLinks).toBeUndefined()
|
||||
})
|
||||
|
||||
it('treats ACP sessions as the Buzz app, not a Hermes folder', async () => {
|
||||
it('keeps ACP sessions on Hermes because source=acp is a transport, not Buzz', async () => {
|
||||
const dbPath = createHermesDb(tmpDir)
|
||||
withTestDb(dbPath, (db) => {
|
||||
insertSession(db, {
|
||||
|
|
@ -561,8 +581,8 @@ skipUnlessSqlite('hermes provider', () => {
|
|||
|
||||
const calls = await collectCalls(tmpDir, `${dbPath}#hermes-session=acp-session`)
|
||||
expect(calls[0]).toMatchObject({
|
||||
provider: 'buzz',
|
||||
project: 'buzz',
|
||||
provider: 'hermes',
|
||||
project: 'hermes',
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue