forked from chriswritescode-dev/opencode-forge
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathloop-helpers.ts
More file actions
76 lines (68 loc) · 3.05 KB
/
loop-helpers.ts
File metadata and controls
76 lines (68 loc) · 3.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import type { PluginConfig, Logger } from '../types'
import type { LoopService } from '../services/loop'
import { parseModelString, resolveFallbackModelEntries, type ResolvedModelEntry } from './model-fallback'
export function resolveLoopModel(
config: PluginConfig,
loopService: LoopService,
loopName: string,
): { providerID: string; modelID: string } | undefined {
const state = loopService.getActiveState(loopName)
if (state?.modelFailed) return undefined
const hasExplicit = state?.executionModel !== undefined && state?.executionModel !== null
if (hasExplicit) return parseModelString(state!.executionModel)
return parseModelString(config.loop?.model) ?? parseModelString(config.executionModel)
}
export function resolveLoopModelFallbacks(config: PluginConfig): ResolvedModelEntry[] {
return resolveFallbackModelEntries(config.agents?.forge?.fallback_models)
}
export function resolveLoopAuditorModel(
config: PluginConfig,
loopService: LoopService,
loopName: string,
logger?: Logger,
): { providerID: string; modelID: string } | undefined {
const state = loopService.getActiveState(loopName)
// If auditorModel was explicitly set on the loop state (even as ''),
// the user made a deliberate choice — don't fall through to config.
// undefined means "not set" (e.g., loop launched via tool without override).
const hasExplicitAuditor = state?.auditorModel !== undefined && state?.auditorModel !== null
const resolved = hasExplicitAuditor
? parseModelString(state!.auditorModel)
: (parseModelString(config.auditorModel) ??
parseModelString(state?.executionModel) ??
parseModelString(config.loop?.model) ??
parseModelString(config.executionModel))
if (logger) {
const source = hasExplicitAuditor
? parseModelString(state!.auditorModel)
? `state.auditorModel=${state!.auditorModel}`
: 'state.auditorModel=(default/session model)'
: parseModelString(config.auditorModel)
? `config.auditorModel=${config.auditorModel}`
: parseModelString(state?.executionModel)
? `state.executionModel=${state?.executionModel}`
: parseModelString(config.loop?.model)
? `config.loop.model=${config.loop?.model}`
: parseModelString(config.executionModel)
? `config.executionModel=${config.executionModel}`
: 'none'
logger.log(
`resolveLoopAuditorModel(${loopName}): resolved from ${source} → ${resolved ? `${resolved.providerID}/${resolved.modelID}` : 'undefined (session model)'}`,
)
}
return resolved
}
export function resolveLoopAuditorFallbacks(config: PluginConfig): ResolvedModelEntry[] {
return resolveFallbackModelEntries(config.agents?.sage?.fallback_models)
}
export function formatDuration(seconds: number): string {
const minutes = Math.floor(seconds / 60)
const secs = seconds % 60
return minutes > 0 ? `${minutes}m ${secs}s` : `${secs}s`
}
export function computeElapsedSeconds(startedAt?: string, endedAt?: string): number {
if (!startedAt) return 0
const start = new Date(startedAt).getTime()
const end = endedAt ? new Date(endedAt).getTime() : Date.now()
return Math.round((end - start) / 1000)
}