refactor: apply repository naming contract
Apply the accepted pre-release package, service, type, directory, and role renames as one repository-wide change.
This commit is contained in:
445
packages/goal/goal-round-driver/src/index.ts
Normal file
445
packages/goal/goal-round-driver/src/index.ts
Normal file
@@ -0,0 +1,445 @@
|
||||
/**
|
||||
* Same-session goal-round driver over public agent, session, and goal services.
|
||||
* @module @deepseek-ai/dsh-goal-round-driver
|
||||
*/
|
||||
|
||||
import { isDeepStrictEqual } from 'node:util'
|
||||
import { FiberState } from '@deepseek-ai/cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import type { Agent, PreStepDecision } from '@deepseek-ai/dsh-agent'
|
||||
import type { GoalMessageSource, GoalRef, GoalView } from '@deepseek-ai/dsh-goal'
|
||||
import { createUserMessage } from '@deepseek-ai/dsh-llm'
|
||||
import type { ContentBlock, MessageId, MessageSource } from '@deepseek-ai/dsh-llm'
|
||||
import type { Session, SessionEvent, UserMessage } from '@deepseek-ai/dsh-session'
|
||||
import { renderGoalRoundPrompt } from './prompt.ts'
|
||||
|
||||
export { renderGoalRoundPrompt } from './prompt.ts'
|
||||
|
||||
export const name = 'goal-round-driver'
|
||||
export const inject = ['agents', 'goals', 'sessions']
|
||||
|
||||
/** Identity reserved before a goal continuation enters the agent inbox. */
|
||||
interface RoundIdentity {
|
||||
readonly goalId: GoalRef['id']
|
||||
readonly revision: number
|
||||
readonly round: number
|
||||
}
|
||||
|
||||
/** One queued, claimed, or admitted goal message retained until whole-agent quiescence. */
|
||||
interface RoundAttempt extends RoundIdentity {
|
||||
readonly messageId: MessageId
|
||||
readonly content: ContentBlock[]
|
||||
phase: 'queued' | 'claimed' | 'admitted'
|
||||
cancelled: boolean
|
||||
stale: boolean
|
||||
}
|
||||
|
||||
/** Serialized process-local scheduling state for one exact Agent lifecycle. */
|
||||
interface DriverState {
|
||||
readonly agent: Agent
|
||||
attempt: RoundAttempt | undefined
|
||||
competingQueued: boolean
|
||||
needsCheckpoint: boolean
|
||||
requested: boolean
|
||||
run: Promise<void> | undefined
|
||||
stopping: boolean
|
||||
}
|
||||
|
||||
/** Whether a source identifies an automatic, positive-numbered goal round. */
|
||||
function isGoalRoundSource(source: MessageSource): source is GoalMessageSource {
|
||||
return source.kind === 'goal' && source.round > 0
|
||||
}
|
||||
|
||||
/** Compare a source to one reserved identity. */
|
||||
function sameRound(source: GoalMessageSource, round: RoundIdentity): boolean {
|
||||
return source.goalId === round.goalId
|
||||
&& source.revision === round.revision
|
||||
&& source.round === round.round
|
||||
}
|
||||
|
||||
/** Compare the complete queued record to the driver's reservation. */
|
||||
function sameQueued(content: ContentBlock[], source: MessageSource, attempt: RoundAttempt): boolean {
|
||||
return isGoalRoundSource(source) && sameRound(source, attempt) && isDeepStrictEqual(content, attempt.content)
|
||||
}
|
||||
|
||||
/** Exact current ref for a view. */
|
||||
function goalRef(goal: GoalView): GoalRef {
|
||||
return { id: goal.id, revision: goal.revision }
|
||||
}
|
||||
|
||||
/** Human-readable unexpected values for logs. */
|
||||
function renderThrown(value: unknown): string {
|
||||
return value instanceof Error ? value.message : String(value)
|
||||
}
|
||||
|
||||
/** Install automatic same-session continuation and its race fences. */
|
||||
export function apply(ctx: Context): void {
|
||||
const states = new Map<Agent, DriverState>()
|
||||
|
||||
/** Create state for an exact currently live agent. */
|
||||
function stateFor(agent: Agent): DriverState {
|
||||
const existing = states.get(agent)
|
||||
if (existing !== undefined) return existing
|
||||
const state: DriverState = {
|
||||
agent,
|
||||
attempt: undefined,
|
||||
competingQueued: false,
|
||||
needsCheckpoint: false,
|
||||
requested: false,
|
||||
run: undefined,
|
||||
stopping: false,
|
||||
}
|
||||
states.set(agent, state)
|
||||
return state
|
||||
}
|
||||
|
||||
/** Read only when the exact Agent remains live. */
|
||||
function currentGoal(state: DriverState): GoalView | undefined {
|
||||
if (ctx.agents.get(state.agent.id) !== state.agent) return undefined
|
||||
return ctx.goals.get(state.agent)
|
||||
}
|
||||
|
||||
/** Whether this exact lifecycle is quiescent with no competing prompt. */
|
||||
function readyToDrive(state: DriverState): boolean {
|
||||
return ctx.fiber.state === FiberState.ACTIVE
|
||||
&& !state.stopping
|
||||
&& ctx.agents.get(state.agent.id) === state.agent
|
||||
&& state.agent.status === 'idle'
|
||||
&& !state.competingQueued
|
||||
}
|
||||
|
||||
/** Recheck every condition that an awaited checkpoint may have changed. */
|
||||
function readyAfterCheckpoint(state: DriverState): boolean {
|
||||
return readyToDrive(state) && !state.needsCheckpoint
|
||||
}
|
||||
|
||||
/** Remove automatic authority while preserving the durable phase. */
|
||||
function disarm(state: DriverState): void {
|
||||
try {
|
||||
const goal = currentGoal(state)
|
||||
if (goal?.activation === 'armed') ctx.goals.disarm(state.agent)
|
||||
} catch (error: unknown) {
|
||||
ctx.logger.warn(`goal-round-driver: could not disarm agent "${state.agent.id}": ${renderThrown(error)}`)
|
||||
}
|
||||
}
|
||||
|
||||
/** Preserve claimed step context when this driver drops only its own round. */
|
||||
function restoreOtherClaimed(agent: Agent, messages: UserMessage[], messageId: MessageId): void {
|
||||
const retained = messages.filter(message => message.id !== messageId
|
||||
&& !(message.source.kind === 'goal' && message.source.round === 0))
|
||||
for (const message of retained.toReversed()) {
|
||||
if (agent.inbox.nextStep.some(candidate => candidate.id === message.id)
|
||||
|| agent.inbox.nextTurn.some(candidate => candidate.id === message.id)) continue
|
||||
agent.inbox.prepend('next-step', message)
|
||||
}
|
||||
}
|
||||
|
||||
/** Process admitted work at quiescence, then reserve at most one next round. */
|
||||
async function drive(state: DriverState): Promise<void> {
|
||||
const { agent } = state
|
||||
if (!readyToDrive(state)) return
|
||||
|
||||
if (state.needsCheckpoint) {
|
||||
state.needsCheckpoint = false
|
||||
try {
|
||||
await ctx.sessions.flush(agent.session)
|
||||
} catch (error: unknown) {
|
||||
ctx.logger.warn(`goal-round-driver: durability checkpoint failed for agent "${agent.id}": ${renderThrown(error)}`)
|
||||
disarm(state)
|
||||
return
|
||||
}
|
||||
// A mutation or ordinary prompt may have arrived while the checkpoint
|
||||
// was settling. Give it its own checkpoint / turn before reserving.
|
||||
if (!readyAfterCheckpoint(state)) return
|
||||
}
|
||||
|
||||
const attempt = state.attempt
|
||||
if (attempt !== undefined) {
|
||||
state.attempt = undefined
|
||||
state.needsCheckpoint = true
|
||||
state.requested = true
|
||||
return
|
||||
}
|
||||
|
||||
const goal = currentGoal(state)
|
||||
if (goal === undefined || goal.phase !== 'active' || goal.activation !== 'armed') return
|
||||
if (goal.roundsStarted >= goal.maxGoalRounds) {
|
||||
ctx.goals.block(agent, goalRef(goal), {
|
||||
code: 'round-limit',
|
||||
message: `Goal reached its configured limit of ${goal.maxGoalRounds} rounds.`,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const round = goal.roundsStarted + 1
|
||||
const content = renderGoalRoundPrompt(goal, round)
|
||||
const message = createUserMessage({
|
||||
content,
|
||||
source: { kind: 'goal', goalId: goal.id, revision: goal.revision, round },
|
||||
})
|
||||
const reservation: RoundAttempt = {
|
||||
goalId: goal.id,
|
||||
revision: goal.revision,
|
||||
round,
|
||||
messageId: message.id,
|
||||
content,
|
||||
phase: 'queued',
|
||||
cancelled: false,
|
||||
stale: false,
|
||||
}
|
||||
state.attempt = reservation
|
||||
try {
|
||||
agent.followup(message)
|
||||
} catch (error: unknown) {
|
||||
state.attempt = undefined
|
||||
ctx.logger.warn(`goal-round-driver: could not queue round ${round} for agent "${agent.id}": ${renderThrown(error)}`)
|
||||
const latest = currentGoal(state)
|
||||
if (latest !== undefined && latest.id === goal.id && latest.revision === goal.revision
|
||||
&& latest.phase === 'active' && latest.activation === 'armed') {
|
||||
ctx.goals.block(agent, goalRef(latest), {
|
||||
code: 'queue-failed',
|
||||
message: `Could not queue goal round ${round}: ${renderThrown(error)}`,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Coalesce triggers onto one agent-local serialized driver. */
|
||||
function requestDrive(state: DriverState): void {
|
||||
/* v8 ignore next -- teardown may race a final trigger after synchronously closing the step fence */
|
||||
if (state.stopping) return
|
||||
state.requested = true
|
||||
if (state.run !== undefined) return
|
||||
let run: Promise<void>
|
||||
try {
|
||||
run = ctx.agents.withoutInitiator(async () => {
|
||||
while (state.requested && !state.stopping) {
|
||||
state.requested = false
|
||||
try {
|
||||
await drive(state)
|
||||
} catch (error: unknown) {
|
||||
ctx.logger.warn(`goal-round-driver: driver failed for agent "${state.agent.id}": ${renderThrown(error)}`)
|
||||
disarm(state)
|
||||
}
|
||||
}
|
||||
})
|
||||
} catch (error: unknown) {
|
||||
ctx.logger.warn(`goal-round-driver: could not start driver for agent "${state.agent.id}": ${renderThrown(error)}`)
|
||||
disarm(state)
|
||||
return
|
||||
}
|
||||
state.run = run
|
||||
const retire = (): void => {
|
||||
state.run = undefined
|
||||
if (state.requested && !state.stopping) requestDrive(state)
|
||||
}
|
||||
void run.then(retire, (error: unknown) => {
|
||||
ctx.logger.warn(`goal-round-driver: driver task rejected for agent "${state.agent.id}": ${renderThrown(error)}`)
|
||||
disarm(state)
|
||||
retire()
|
||||
})
|
||||
}
|
||||
|
||||
// One composite effect keeps the step fence installed until this
|
||||
// plugin's own scheduling tasks settle.
|
||||
ctx.effect(function* () {
|
||||
ctx.on('agent/error', ({ agent }) => {
|
||||
const state = stateFor(agent)
|
||||
disarm(state)
|
||||
})
|
||||
|
||||
ctx.on('agent/created', ({ agent }) => { stateFor(agent) })
|
||||
ctx.on('agent/disposed', ({ agent }) => { states.delete(agent) })
|
||||
ctx.on('agent/session-start', ({ agent }) => {
|
||||
const state = stateFor(agent)
|
||||
state.attempt = undefined
|
||||
state.competingQueued = false
|
||||
state.needsCheckpoint = false
|
||||
})
|
||||
ctx.on('agent/status', ({ agent, status }) => {
|
||||
const state = stateFor(agent)
|
||||
if (status === 'idle') {
|
||||
state.competingQueued = false
|
||||
const attempt = state.attempt
|
||||
const goal = currentGoal(state)
|
||||
if ((attempt?.phase === 'queued' || attempt?.phase === 'claimed' || attempt?.cancelled)
|
||||
&& goal?.phase === 'active' && goal.activation === 'armed') {
|
||||
state.attempt = undefined
|
||||
try {
|
||||
ctx.goals.pause(agent, goalRef(goal))
|
||||
} catch (error: unknown) {
|
||||
ctx.logger.warn(`goal-round-driver: could not pause cancelled goal for agent "${agent.id}": ${renderThrown(error)}`)
|
||||
disarm(state)
|
||||
}
|
||||
}
|
||||
requestDrive(state)
|
||||
}
|
||||
})
|
||||
ctx.on('goal/changed', ({ agent }) => {
|
||||
const state = stateFor(agent)
|
||||
state.needsCheckpoint = true
|
||||
requestDrive(state)
|
||||
})
|
||||
|
||||
ctx.on('agent/inbox/inserted', ({ agent, message }) => {
|
||||
if (!agent.inbox.nextTurn.some(candidate => candidate.id === message.id)) return
|
||||
const state = stateFor(agent)
|
||||
const attempt = state.attempt
|
||||
if (attempt !== undefined && sameQueued(message.content, message.source, attempt)) return
|
||||
state.competingQueued = true
|
||||
if (attempt?.phase === 'queued') attempt.stale = true
|
||||
})
|
||||
ctx.on('agent/inbox/claimed', ({ agent, message }) => {
|
||||
const state = stateFor(agent)
|
||||
const attempt = state.attempt
|
||||
if (attempt !== undefined && sameQueued(message.content, message.source, attempt)) {
|
||||
attempt.phase = 'claimed'
|
||||
}
|
||||
})
|
||||
ctx.on('agent/inbox/discarded', ({ agent, message }) => {
|
||||
const state = stateFor(agent)
|
||||
const attempt = state.attempt
|
||||
if (attempt !== undefined && sameQueued(message.content, message.source, attempt)) {
|
||||
attempt.cancelled = true
|
||||
}
|
||||
})
|
||||
|
||||
ctx.on('session/event', (session: Session, event: SessionEvent) => {
|
||||
const agent = ctx.agents.get(session.id)
|
||||
if (agent === undefined || agent.session !== session) return
|
||||
const state = stateFor(agent)
|
||||
switch (event.type) {
|
||||
case 'user/message':
|
||||
if (state.attempt !== undefined && event.data.id === state.attempt.messageId) {
|
||||
state.attempt.phase = 'admitted'
|
||||
}
|
||||
return
|
||||
case 'turn/end':
|
||||
if (event.data.reason.kind === 'max-tokens') {
|
||||
disarm(state)
|
||||
return
|
||||
}
|
||||
if (event.data.reason.kind !== 'aborted') return
|
||||
if (state.attempt?.phase === 'claimed' || state.attempt?.phase === 'admitted') {
|
||||
state.attempt.cancelled = true
|
||||
}
|
||||
else disarm(state)
|
||||
return
|
||||
default:
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
/** Fail closed unless the queued prompt still owns the exact live revision. */
|
||||
function validReservation(
|
||||
state: DriverState,
|
||||
content: ContentBlock[],
|
||||
source: GoalMessageSource,
|
||||
): boolean {
|
||||
const attempt = state.attempt
|
||||
const goal = currentGoal(state)
|
||||
return ctx.fiber.state === FiberState.ACTIVE
|
||||
&& !state.stopping && attempt !== undefined && attempt.phase === 'claimed'
|
||||
&& !attempt.stale && sameQueued(content, source, attempt)
|
||||
&& goal !== undefined && goal.id === source.goalId && goal.revision === source.revision
|
||||
&& goal.phase === 'active' && goal.activation === 'armed'
|
||||
&& source.round === goal.roundsStarted + 1
|
||||
}
|
||||
|
||||
ctx.on('agent/pre-step', async ({ agent, messages, signal }, next): Promise<PreStepDecision> => {
|
||||
const submitted = messages.find((message): message is UserMessage & { source: GoalMessageSource } =>
|
||||
isGoalRoundSource(message.source))
|
||||
if (submitted === undefined) return next()
|
||||
const { content, source } = submitted
|
||||
const state = stateFor(agent)
|
||||
let valid = false
|
||||
try {
|
||||
valid = validReservation(state, content, source)
|
||||
} catch (error: unknown) {
|
||||
ctx.logger.warn(`goal-round-driver: pre-step check failed for agent "${agent.id}": ${renderThrown(error)}`)
|
||||
disarm(state)
|
||||
}
|
||||
if (!valid) {
|
||||
const attempt = state.attempt
|
||||
if (attempt !== undefined && sameRound(source, attempt)) {
|
||||
attempt.stale = true
|
||||
state.attempt = undefined
|
||||
}
|
||||
restoreOtherClaimed(agent, messages, submitted.id)
|
||||
requestDrive(state)
|
||||
return { kind: 'reject' }
|
||||
}
|
||||
let decision: PreStepDecision
|
||||
try {
|
||||
decision = await next()
|
||||
} catch (error: unknown) {
|
||||
if (signal.aborted) throw error
|
||||
// A throwing downstream hook drops the whole step proposal. Clear the
|
||||
// reservation before the balanced no-step turn returns to idle so the
|
||||
// next drive pass can reschedule the round.
|
||||
state.attempt = undefined
|
||||
requestDrive(state)
|
||||
throw error
|
||||
}
|
||||
if (signal.aborted) {
|
||||
if (decision.kind === 'enter') restoreOtherClaimed(agent, decision.messages, submitted.id)
|
||||
return decision
|
||||
}
|
||||
if (decision.kind === 'reject') {
|
||||
state.attempt = undefined
|
||||
const goal = currentGoal(state)
|
||||
if (goal !== undefined && goal.id === source.goalId && goal.revision === source.revision
|
||||
&& goal.phase === 'active' && goal.activation === 'armed') {
|
||||
ctx.goals.block(agent, goalRef(goal), {
|
||||
code: 'prompt-rejected',
|
||||
message: 'Goal round was rejected before entering its step.',
|
||||
})
|
||||
}
|
||||
return decision
|
||||
}
|
||||
try {
|
||||
valid = validReservation(state, content, source)
|
||||
} catch (error: unknown) {
|
||||
ctx.logger.warn(`goal-round-driver: post-decision check failed for agent "${agent.id}": ${renderThrown(error)}`)
|
||||
disarm(state)
|
||||
valid = false
|
||||
}
|
||||
if (!valid) {
|
||||
state.attempt = undefined
|
||||
restoreOtherClaimed(agent, decision.messages, submitted.id)
|
||||
requestDrive(state)
|
||||
return { kind: 'reject' }
|
||||
}
|
||||
return decision
|
||||
})
|
||||
|
||||
// Loading a lifecycle driver over existing agents never inherits hidden
|
||||
// automatic authority from an earlier producer instance.
|
||||
for (const agent of ctx.agents.list()) {
|
||||
const state = stateFor(agent)
|
||||
disarm(state)
|
||||
}
|
||||
|
||||
// Yielded after listener registration, so this close runs first and the
|
||||
// composite effect removes listeners only after its promise settles.
|
||||
yield async () => {
|
||||
const waits: Promise<void>[] = []
|
||||
for (const state of states.values()) {
|
||||
state.stopping = true
|
||||
disarm(state)
|
||||
const attempt = state.attempt
|
||||
if (attempt !== undefined) {
|
||||
attempt.stale = true
|
||||
/* v8 ignore next -- followup reserves the live agent before publishing a queued attempt */
|
||||
if (state.agent.status === 'running') {
|
||||
state.agent.cancel({ kind: 'parent' })
|
||||
waits.push(state.agent.whenIdle())
|
||||
}
|
||||
}
|
||||
if (state.run !== undefined) waits.push(state.run)
|
||||
}
|
||||
await Promise.allSettled(waits)
|
||||
states.clear()
|
||||
}
|
||||
}, 'goal-round-driver lifecycle')
|
||||
}
|
||||
84
packages/goal/goal-round-driver/src/invariant.ts
Normal file
84
packages/goal/goal-round-driver/src/invariant.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
/** Package-owned goal-round prompt invariants. @module @deepseek-ai/dsh-goal-round-driver/invariant */
|
||||
|
||||
import { isDeepStrictEqual } from 'node:util'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import { foldGoal, type FoldedGoal, type GoalMessageSource, type GoalView } from '@deepseek-ai/dsh-goal'
|
||||
import type { InvariantFailure, InvariantInstaller } from '@deepseek-ai/dsh-invariants'
|
||||
import type { Session, SessionEvent } from '@deepseek-ai/dsh-session'
|
||||
import { renderGoalRoundPrompt } from './prompt.ts'
|
||||
|
||||
const PACKAGE_NAME = '@deepseek-ai/dsh-goal-round-driver'
|
||||
|
||||
/** Cordis companion plugin name. */
|
||||
export const name = 'goal-round-driver-invariant'
|
||||
/** Service required before the companion can reserve package ownership. */
|
||||
export const inject = ['invariants']
|
||||
|
||||
/** Attribute strict goal-fold failures to this companion's reconstruction. */
|
||||
function foldChecked(events: readonly SessionEvent[], fail: InvariantFailure): FoldedGoal {
|
||||
try {
|
||||
return foldGoal(events)
|
||||
} catch (error: unknown) {
|
||||
/* v8 ignore next -- the strict goal decoder throws Error instances */
|
||||
const message = error instanceof Error ? error.message : String(error)
|
||||
return fail(`cannot reconstruct the goal before a continuation message: ${message}`)
|
||||
}
|
||||
}
|
||||
|
||||
/** Recreate the live-shaped view consumed by the package's pure prompt renderer. */
|
||||
function goalView(folded: FoldedGoal, source: GoalMessageSource, fail: InvariantFailure): GoalView {
|
||||
const goal = folded.goal
|
||||
if (goal === undefined || folded.createdAt === undefined || folded.updatedAt === undefined
|
||||
|| goal.phase !== 'active' || goal.id !== source.goalId || goal.revision !== source.revision
|
||||
|| source.round !== folded.roundsStarted + 1 || source.round > goal.maxGoalRounds) {
|
||||
return fail(`goal round ${source.round} cannot be reconstructed from the preceding durable goal state`)
|
||||
}
|
||||
return {
|
||||
...goal,
|
||||
roundsStarted: folded.roundsStarted,
|
||||
createdAt: folded.createdAt,
|
||||
updatedAt: folded.updatedAt,
|
||||
activation: 'armed',
|
||||
}
|
||||
}
|
||||
|
||||
/** Validate one package-owned continuation message against its durable prefix. */
|
||||
function validateEvent(
|
||||
prior: readonly SessionEvent[],
|
||||
event: SessionEvent,
|
||||
fail: InvariantFailure,
|
||||
): void {
|
||||
if (event.type !== 'user/message') return
|
||||
const source = event.data.source
|
||||
if (source.kind !== 'goal' || source.round <= 0) return
|
||||
const expected = renderGoalRoundPrompt(goalView(foldChecked(prior, fail), source, fail), source.round)
|
||||
if (!isDeepStrictEqual(event.data.content, expected)) {
|
||||
fail(`goal round ${source.round} content does not match the package-owned continuation prompt`)
|
||||
}
|
||||
}
|
||||
|
||||
/** Check existing sessions and every candidate event before Session publishes it. */
|
||||
const install: InvariantInstaller = Object.assign((ctx: Context, fail: InvariantFailure) => {
|
||||
for (const session of ctx.sessions.list()) {
|
||||
const prior: SessionEvent[] = []
|
||||
for (const event of session.events) {
|
||||
validateEvent(prior, event, fail)
|
||||
prior.push(event)
|
||||
}
|
||||
}
|
||||
/* jscpd:ignore-start -- package companions share dispatch and registration plumbing */
|
||||
ctx.on('internal/dispatch', (_mode, eventName, args) => {
|
||||
if (eventName !== 'session/event') return
|
||||
const [session, event] = args as [Session, SessionEvent]
|
||||
validateEvent(session.events, event, fail)
|
||||
}, { global: true })
|
||||
}, { inject: ['sessions'] })
|
||||
|
||||
/**
|
||||
* Register the goal-round-driver invariant companion.
|
||||
* @param ctx - Cordis context carrying the invariant service.
|
||||
* @returns the installed registration's disposer after setup succeeds.
|
||||
*/
|
||||
export const apply = (ctx: Context): Promise<() => void> =>
|
||||
Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install))
|
||||
/* jscpd:ignore-end */
|
||||
26
packages/goal/goal-round-driver/src/prompt.ts
Normal file
26
packages/goal/goal-round-driver/src/prompt.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
/** Model-visible continuation prompt for one same-session goal round. */
|
||||
|
||||
import type { ContentBlock } from '@deepseek-ai/dsh-llm'
|
||||
import type { GoalView } from '@deepseek-ai/dsh-goal'
|
||||
|
||||
/**
|
||||
* Render the complete goal-round instruction retained in session history.
|
||||
* @param goal - exact active goal revision being admitted.
|
||||
* @param round - next positive round number.
|
||||
* @returns a fresh one-block prompt for `Agent.followup()`.
|
||||
*/
|
||||
export function renderGoalRoundPrompt(goal: GoalView, round: number): ContentBlock[] {
|
||||
return [{
|
||||
type: 'text',
|
||||
text: '<goal_round>\n'
|
||||
+ `Objective: ${JSON.stringify(goal.objective)}\n`
|
||||
+ `Round: ${round}/${goal.maxGoalRounds}\n\n`
|
||||
+ 'Continue working toward the objective in this same session. Treat the current workspace, '
|
||||
+ 'tool results, and durable session state as authoritative; inspect them instead of assuming '
|
||||
+ 'earlier narration is still current. Make concrete progress and verify the result. Before '
|
||||
+ 'claiming completion, gather evidence that the whole objective is achieved, read the current '
|
||||
+ 'goal, and mark it complete. If work remains, leave the goal active for the next round. Follow '
|
||||
+ 'the configured goal-tool policy before reporting a blocker.\n'
|
||||
+ '</goal_round>',
|
||||
}]
|
||||
}
|
||||
Reference in New Issue
Block a user