mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-09-12 04:01:20 +00:00
fix(session-controller): derive queues from projections
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
/** Live Session queue, jobs, and projection state with reconnect baselines. */
|
||||
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent, InboxState } from '@deepseek-ai/dsh-agent'
|
||||
import type { JobSnapshot } from '@deepseek-ai/dsh-jobs'
|
||||
import type {
|
||||
JsonValue, Session, SessionEvent, SessionEventMap, SessionId, UserMessage,
|
||||
JsonValue, Session, SessionId,
|
||||
} from '@deepseek-ai/dsh-session'
|
||||
import type {
|
||||
SessionControlBaseline,
|
||||
@@ -21,7 +21,6 @@ export class SessionControlController {
|
||||
|
||||
/** @param ctx - Host context carrying live Agent, projection, and jobs services. */
|
||||
constructor(private readonly ctx: Context) {
|
||||
ctx.on('session/event', (session, event) => { this.onSessionEvent(session, event) })
|
||||
ctx.inject(['sessionProjections'], (projectionCtx) => {
|
||||
projectionCtx.sessionProjections.onChanged((session, key, value, seq) => {
|
||||
this.broadcast({
|
||||
@@ -31,6 +30,14 @@ export class SessionControlController {
|
||||
value: value as JsonValue,
|
||||
seq,
|
||||
})
|
||||
if (key !== 'inbox') return
|
||||
const agent = this.ctx.agents.get(session.id)
|
||||
if (agent?.session !== session) return
|
||||
this.broadcast({
|
||||
type: 'queue',
|
||||
sessionId: session.id,
|
||||
items: queueItemsFromInbox(value as InboxState),
|
||||
})
|
||||
})
|
||||
})
|
||||
ctx.inject(['jobs'], (jobsCtx) => {
|
||||
@@ -98,17 +105,6 @@ export class SessionControlController {
|
||||
return blocks
|
||||
}
|
||||
|
||||
private onSessionEvent(session: Session, event: SessionEvent): void {
|
||||
if (event.type !== 'agent/inbox/spliced') return
|
||||
const agent = this.ctx.agents.get(session.id)
|
||||
if (agent?.session !== session) return
|
||||
this.broadcast({
|
||||
type: 'queue',
|
||||
sessionId: session.id,
|
||||
items: queueItems(agent, event.data),
|
||||
})
|
||||
}
|
||||
|
||||
private onJobsChanged(owner: Agent | undefined): void {
|
||||
if (owner !== undefined) {
|
||||
this.broadcast({ type: 'jobs', sessionId: owner.id, jobs: this.jobsFor(owner) })
|
||||
@@ -174,23 +170,21 @@ class ControlQueue {
|
||||
}
|
||||
}
|
||||
|
||||
function queueItems(
|
||||
agent: Agent,
|
||||
splice?: SessionEventMap['agent/inbox/spliced'],
|
||||
): SessionQueuedItem[] {
|
||||
const project = (target: 'next-turn' | 'next-step'): readonly UserMessage[] => {
|
||||
const messages = target === 'next-turn' ? agent.inbox.nextTurn : agent.inbox.nextStep
|
||||
return splice?.target === target
|
||||
? messages.toSpliced(splice.start, splice.removedCount ?? 0, ...splice.inserted)
|
||||
: messages
|
||||
}
|
||||
function queueItems(agent: Agent): SessionQueuedItem[] {
|
||||
return queueItemsFromInbox({
|
||||
'next-turn': agent.inbox.nextTurn,
|
||||
'next-step': agent.inbox.nextStep,
|
||||
})
|
||||
}
|
||||
|
||||
function queueItemsFromInbox(inbox: InboxState): SessionQueuedItem[] {
|
||||
return [
|
||||
...project('next-turn').map(message => ({
|
||||
...inbox['next-turn'].map(message => ({
|
||||
id: message.id,
|
||||
placement: 'queued' as const,
|
||||
message: { id: message.id, content: message.content as unknown as JsonValue[] },
|
||||
})),
|
||||
...project('next-step').map(message => ({
|
||||
...inbox['next-step'].map(message => ({
|
||||
id: message.id,
|
||||
placement: message.source.kind === 'user' ? 'steering' as const : 'context' as const,
|
||||
message: { id: message.id, content: message.content as unknown as JsonValue[] },
|
||||
|
||||
Reference in New Issue
Block a user