mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
Machine-produced by `pnpm run rescope-vendor --apply` plus the regeneration it prints: `pnpm install` for the lockfile, `pnpm run gen-third-party-notices`, `verify-translation-pairing --write` for the touched bilingual pairs, `gen-doc-graphs`, and one typert snapshot whose ids embed character offsets. `pnpm run rescope-vendor --check` verifies the result. Renames nine vendored packages (cordis, cosmokit, schemastery and the six @cordisjs plugins) and every reference that resolves them: manifest names and dependency keys, module specifiers including declare-module merges, cordis.yml plugin names, tsconfig paths, every Markdown fence, and `docs/` prose. Directory names, upstream versions, and dependency ranges are unchanged, so vendor/README.md still reads as an upstream snapshot; its manifest table gains an upstream-name column so THIRD_PARTY_NOTICES keeps MIT attribution pointed at each fork's origin. The tutorial tier follows the rename end to end: its yaml fences named plugins the Loader can no longer resolve, its `ts ignore-check` fences disagreed with the compiled fences beside them, and its prose quoted both. The contracts that told readers to keep upstream names — the root convention and the vendoring cookbook's tree comment and manifest invariant — now say to rescope instead. Two rules read `@deepseek-ai/` as "another workspace plugin": the client bundle purity gate now names the vendored libraries a browser bundle inlines, and the files where a bare `cordis` is an agent-preset id keep that product data.
77 lines
3.3 KiB
TypeScript
77 lines
3.3 KiB
TypeScript
/** Local durable attachment backend rooted below `DSH_HOME`. @module @deepseek-ai/dsh-attachment-local */
|
|
|
|
import { join, resolve } from 'node:path'
|
|
import { Context } from '@deepseek-ai/cordis'
|
|
import z from '@deepseek-ai/schemastery'
|
|
import { AttachmentStore } from '@deepseek-ai/dsh-attachment'
|
|
import type { ImageAttachmentLimits, ImageAttachmentRef, SaveImageAttachment, StoredImageAttachment } from '@deepseek-ai/dsh-attachment'
|
|
import { resolveDshHome } from '@deepseek-ai/dsh-paths'
|
|
import { readImageFile, saveImageFile, validateImageFile } from './store.ts'
|
|
|
|
export { detectImage } from './image.ts'
|
|
export { readImageFile, saveImageFile, validateImageFile } from './store.ts'
|
|
|
|
/** Default maximum encoded bytes for one image. */
|
|
export const DEFAULT_MAX_IMAGE_BYTES = 5 * 1024 * 1024
|
|
/** Default maximum images in one prompt. */
|
|
export const DEFAULT_MAX_IMAGES_PER_MESSAGE = 10
|
|
/** Default maximum aggregate image bytes in one prompt. */
|
|
export const DEFAULT_MAX_MESSAGE_IMAGE_BYTES = 20 * 1024 * 1024
|
|
/** Default maximum intrinsic pixels for one image. */
|
|
export const DEFAULT_MAX_IMAGE_PIXELS = 40_000_000
|
|
|
|
/** Local attachment backend configuration. */
|
|
export interface Config {
|
|
/** Explicit harness home; omitted follows `DSH_HOME`, then `~/.dsh`. */
|
|
dshHome?: string
|
|
/** Maximum encoded bytes accepted for one image. */
|
|
maxImageBytes?: number
|
|
/** Maximum image count accepted in one submitted message. */
|
|
maxImagesPerMessage?: number
|
|
/** Maximum aggregate encoded image bytes accepted in one submitted message. */
|
|
maxMessageImageBytes?: number
|
|
/** Maximum intrinsic width multiplied by height accepted for one image. */
|
|
maxImagePixels?: number
|
|
}
|
|
|
|
/** Persistent content-addressed local attachment store. */
|
|
export class LocalAttachmentStore extends AttachmentStore {
|
|
static Config: z<Config> = z.object({
|
|
dshHome: z.string(),
|
|
maxImageBytes: z.number().step(1).min(1).default(DEFAULT_MAX_IMAGE_BYTES),
|
|
maxImagesPerMessage: z.number().step(1).min(1).default(DEFAULT_MAX_IMAGES_PER_MESSAGE),
|
|
maxMessageImageBytes: z.number().step(1).min(1).default(DEFAULT_MAX_MESSAGE_IMAGE_BYTES),
|
|
maxImagePixels: z.number().step(1).min(1).default(DEFAULT_MAX_IMAGE_PIXELS),
|
|
})
|
|
|
|
/** Absolute versioned storage root. */
|
|
readonly root: string
|
|
readonly imageLimits: ImageAttachmentLimits
|
|
|
|
constructor(ctx: Context, config: Config) {
|
|
super(ctx)
|
|
this.root = resolve(join(resolveDshHome(config.dshHome), 'attachments', 'v1'))
|
|
this.imageLimits = Object.freeze({
|
|
maxImageBytes: config.maxImageBytes ?? DEFAULT_MAX_IMAGE_BYTES,
|
|
maxImagesPerMessage: config.maxImagesPerMessage ?? DEFAULT_MAX_IMAGES_PER_MESSAGE,
|
|
maxMessageImageBytes: config.maxMessageImageBytes ?? DEFAULT_MAX_MESSAGE_IMAGE_BYTES,
|
|
maxImagePixels: config.maxImagePixels ?? DEFAULT_MAX_IMAGE_PIXELS,
|
|
mediaTypes: Object.freeze(['image/png', 'image/jpeg', 'image/webp', 'image/gif'] as const),
|
|
})
|
|
}
|
|
|
|
async validateImage(input: SaveImageAttachment): Promise<void> {
|
|
await validateImageFile(input, this.imageLimits)
|
|
}
|
|
|
|
async saveImage(input: SaveImageAttachment): Promise<ImageAttachmentRef> {
|
|
return saveImageFile(this.root, input, this.imageLimits)
|
|
}
|
|
|
|
async readImage(ref: ImageAttachmentRef): Promise<StoredImageAttachment> {
|
|
return readImageFile(this.root, ref)
|
|
}
|
|
}
|
|
|
|
export default LocalAttachmentStore
|