feat(session): add cross-session references

This commit is contained in:
Yichen Jiang
2026-07-21 16:46:48 +08:00
parent 9a5c81f9e5
commit 32d786c439
81 files changed
+2837 -160

No files matched your search

+5 -4
View File
@@ -207,9 +207,10 @@ export class ReactLoopAgent implements Agent {
*/
private acceptMessage(content: ContentBlock[], options?: SendOptions): InboxMessage {
const source = this.resolveSource(options)
const accepted = snapshotJsonValue({ content, source })
const contexts = options?.contexts ?? []
const accepted = snapshotJsonValue({ content, source, contexts })
if (accepted === undefined) {
throw new TypeError('agent message content and source must be losslessly JSON-serializable')
throw new TypeError('agent message content, source, and contexts must be losslessly JSON-serializable')
}
return deepFreeze(accepted)
}
@@ -232,7 +233,7 @@ export class ReactLoopAgent implements Agent {
this.assertNotDisposed()
const accepted = this.acceptMessage(content, options)
this.#inbox.enqueue(accepted)
const info = { source: accepted.source, steering: false } as const
const info = { source: accepted.source, contexts: accepted.contexts, steering: false } as const
agentEvents(this.loopCtx, this).emit('agent/queued', accepted.content, info)
}
@@ -241,7 +242,7 @@ export class ReactLoopAgent implements Agent {
if (this._status !== 'running') { this.send(content, options); return }
const accepted = this.acceptMessage(content, options)
this.#inbox.steer(accepted)
const info = { source: accepted.source, steering: true } as const
const info = { source: accepted.source, contexts: accepted.contexts, steering: true } as const
agentEvents(this.loopCtx, this).emit('agent/queued', accepted.content, info)
}
+2
View File
@@ -7,11 +7,13 @@
*/
import type { ContentBlock, MessageSource } from '@deepseek-ai/dsh-llm'
import type { HookContext } from '@deepseek-ai/dsh-agent'
/** One message waiting in an agent's inbox. */
export interface InboxMessage {
content: ContentBlock[]
source: MessageSource
contexts: HookContext[]
}
/**
+8 -2
View File
@@ -207,6 +207,9 @@ async function runTurn(
const messages = handle.inbox.drainSteering()
for (const message of messages) {
session.append('steering/message', { turn, content: message.content, source: message.source }, { surfaceOp: 'append' })
for (const context of message.contexts) {
session.append('context/message', context, { surfaceOp: 'append' })
}
}
return messages.length > 0
}
@@ -263,7 +266,10 @@ async function runTurn(
// throws) is caught below and the turn still closes.
const promptDecision = await events.waterfall(
'agent/prompt-submit', message.content, message.source,
() => Promise.resolve<PromptDecision>({ kind: 'allow' }),
() => Promise.resolve<PromptDecision>({
kind: 'allow',
...message.contexts.length === 0 ? {} : { additionalContexts: message.contexts },
}),
)
if (promptDecision.kind === 'block') {
session.append('prompt/blocked', { content: message.content, source: message.source, reason: promptDecision.reason })
@@ -502,7 +508,7 @@ async function runTurn(
// A continuation reason becomes next-step steering.
if (decision.action === 'continue' && decision.reason) {
handle.inbox.steer({ content: decision.reason.content, source: decision.reason.source })
handle.inbox.steer({ content: decision.reason.content, source: decision.reason.source, contexts: [] })
}
let shouldContinue = decision.action === 'continue'