mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-09-14 04:01:35 +00:00
Merge remote-tracking branch 'github/master' into xtr/session-log-read-api
# Conflicts: # .agents/notes/implemented/architecture/2026-07-25-web-client-session-scope-and-provide-channel.i18n.yaml # .agents/notes/implemented/architecture/2026-07-25-web-client-session-scope-and-provide-channel.md # .agents/notes/implemented/architecture/2026-07-25-web-client-session-scope-and-provide-channel.zh.md # .agents/notes/implemented/feature/2026-08-05-context-form-vocabulary.i18n.yaml # .agents/notes/implemented/feature/2026-08-05-context-form-vocabulary.md # .agents/notes/implemented/feature/2026-08-05-context-form-vocabulary.zh.md # packages/examples/agent-spine-demo/tests/agent-core.spec.ts # packages/skill/tool-skill/tests/tool-skill.spec.ts
This commit is contained in:
@@ -27,6 +27,8 @@ export type PendingSubmissionRetirement =
|
||||
|
||||
/** Input registering one local submission echo ahead of its prompt call. */
|
||||
export interface BeginSubmissionInput {
|
||||
/** Delivery mode used with the upcoming prompt. */
|
||||
readonly mode: 'queue' | 'steer'
|
||||
/** Prompt text exactly as the upcoming prompt will send it. */
|
||||
readonly text: string
|
||||
/** Ordered image previews matching the upcoming prompt's image parts. */
|
||||
|
||||
@@ -30,6 +30,9 @@ export interface PendingSubmissionImage {
|
||||
readonly height?: number
|
||||
}
|
||||
|
||||
/** Client surface selected when a local submission begins. */
|
||||
export type PendingSubmissionPlacement = 'transcript' | 'queued' | 'steering'
|
||||
|
||||
/**
|
||||
* One local prompt-submission echo: inserted synchronously when a submission
|
||||
* begins, so the conversation can show the message before serialization,
|
||||
@@ -39,6 +42,8 @@ export interface PendingSubmissionImage {
|
||||
export interface PendingSubmission {
|
||||
/** The prompt RPC identity; the durable `user/message` source echoes it as `rpcId`. */
|
||||
readonly requestId: SessionRequestId
|
||||
/** Expected surface until the Host reports the admitted queue or durable occurrence. */
|
||||
readonly placement: PendingSubmissionPlacement
|
||||
/** Client wall-clock ms when the submission began. */
|
||||
readonly time: number
|
||||
/** Prompt text exactly as it will be sent (one text block). */
|
||||
|
||||
@@ -60,6 +60,7 @@ export type {
|
||||
OpenState,
|
||||
PendingSubmission,
|
||||
PendingSubmissionImage,
|
||||
PendingSubmissionPlacement,
|
||||
PromptError,
|
||||
QueuedMessage,
|
||||
SessionSnapshot,
|
||||
|
||||
@@ -5,8 +5,11 @@ import type { QueuedMessage } from '../contract/snapshot.ts'
|
||||
|
||||
const QUEUE_PREVIEW_CHARS = 200
|
||||
|
||||
// Image blocks are excluded: queue presentation renders them as thumbnails
|
||||
// from `content`, so the text preview covers only what has no visual form.
|
||||
function previewOf(content: readonly ContentBlock[]): string {
|
||||
const flat = content
|
||||
.filter(block => block.type !== 'image')
|
||||
.map(block => (block.type === 'text' ? block.text : `[${block.type}]`))
|
||||
.join(' ').replace(/\s+/g, ' ').trim()
|
||||
const chars = Array.from(flat)
|
||||
|
||||
@@ -184,6 +184,9 @@ export class Session implements SessionFace {
|
||||
const requestId = randomUUID() as SessionRequestId
|
||||
this.pendingSubmissions = [...this.pendingSubmissions, {
|
||||
requestId,
|
||||
placement: this.running
|
||||
? input.mode === 'steer' ? 'steering' : 'queued'
|
||||
: 'transcript',
|
||||
time: Date.now(),
|
||||
text: input.text,
|
||||
images: input.images,
|
||||
|
||||
@@ -4,12 +4,12 @@ import { randomUUID } from 'node:crypto'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import { brandString } from '@deepseek-ai/dsh-brand'
|
||||
import type { Agent, ModelSelection as AgentModelSelection } from '@deepseek-ai/dsh-agent'
|
||||
import { AttachmentError, admitEncodedImages } from '@deepseek-ai/dsh-attachment'
|
||||
import { AttachmentError, admitPromptContent } from '@deepseek-ai/dsh-attachment'
|
||||
import type { ImageAttachmentRef } from '@deepseek-ai/dsh-attachment'
|
||||
import {
|
||||
ReasoningEffortId, createUserMessage, freezeMessage,
|
||||
} from '@deepseek-ai/dsh-llm'
|
||||
import type { ContentBlock, MessageSource } from '@deepseek-ai/dsh-llm'
|
||||
import type { MessageSource } from '@deepseek-ai/dsh-llm'
|
||||
import type { SessionEvent, SessionHeader, SessionId, UserMessage } from '@deepseek-ai/dsh-session'
|
||||
import { SessionQueryError, type SessionObservation } from '@deepseek-ai/dsh-session-query'
|
||||
import { SessionTitleInvalidError } from '@deepseek-ai/dsh-session-title'
|
||||
@@ -319,7 +319,7 @@ export class SessionCommandController {
|
||||
)
|
||||
}
|
||||
}
|
||||
const content = await durablePromptContent(this.ctx, request.content)
|
||||
const content = await admitPromptContent(this.ctx.attachments, request.content)
|
||||
const message: UserMessage = createUserMessage({ content, source })
|
||||
if (request.mode === 'steer') agent.steer(message)
|
||||
else agent.followup(message)
|
||||
@@ -492,21 +492,6 @@ export class SessionCommandController {
|
||||
}
|
||||
}
|
||||
|
||||
async function durablePromptContent(
|
||||
ctx: Context,
|
||||
content: readonly SessionPromptRequest['content'][number][],
|
||||
): Promise<ContentBlock[]> {
|
||||
if (content.every(part => part.type === 'text')) {
|
||||
return content.map(part => ({ type: 'text', text: part.text }))
|
||||
}
|
||||
const refs = await admitEncodedImages(ctx.attachments, content.filter(part => part.type === 'image'))
|
||||
let next = 0
|
||||
return content.map(part => part.type === 'text'
|
||||
? { type: 'text', text: part.text }
|
||||
// admitEncodedImages returns one reference per image part in order.
|
||||
: { type: 'image', attachment: refs[next++] as ImageAttachmentRef })
|
||||
}
|
||||
|
||||
function imageBlockIn(
|
||||
content: unknown,
|
||||
match: (ref: ImageAttachmentRef) => boolean,
|
||||
|
||||
Reference in New Issue
Block a user