| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- /**
- * Active Loader-backed plugin package inventory for official DeepSeek requests.
- * Host entries and the requesting agent's standing preset are resolved at request time;
- * installed dependencies and plugin fibers without Loader package provenance are excluded.
- * @module @deepseek-ai/dsh-plugin-package-inventory-deepseek
- */
- import { existsSync, readFileSync } from 'node:fs'
- import { createRequire } from 'node:module'
- import { dirname, isAbsolute, join, parse } from 'node:path'
- import { fileURLToPath, pathToFileURL } from 'node:url'
- import { FiberState, type Context } from '@deepseek-ai/cordis'
- import z from '@deepseek-ai/schemastery'
- import { brandString } from '@deepseek-ai/dsh-brand'
- import type { Entry, EntryTree } from '@deepseek-ai/cordis-plugin-loader'
- import type {} from '@deepseek-ai/dsh-agent'
- import type {} from '@deepseek-ai/dsh-deepseek-llm-api-extensions'
- import type { SessionId } from '@deepseek-ai/dsh-session'
- import type {} from '@deepseek-ai/dsh-agent-presets'
- import type { DeepSeekPluginPackageIdentity, DeepSeekPluginPackageInventoryExtension } from './types.ts'
- import type {} from './types.ts'
- export type * from './types.ts'
- /** Cordis plugin name. */
- export const name = 'plugin-package-inventory-deepseek'
- /** Services required to locate host/requesting-agent entries and contribute the field. */
- export const inject = ['agents', 'deepseekLlmApiExtensions', 'loader']
- /** Plugin-package request contribution configuration. */
- export interface Config {
- /** Contribute `dsh_plugin_packages` to official DeepSeek requests. Defaults to `true`. */
- enabled?: boolean
- }
- /** Validated plugin-package request contribution configuration. */
- export const Config: z<Config> = z.object({
- enabled: z.boolean().default(true),
- })
- interface PackageManifest {
- readonly name?: unknown
- readonly version?: unknown
- }
- interface ActiveEntry {
- readonly entry: Entry
- /** Bare-package base used by the Loader path that activated this entry. */
- readonly bareBaseUrl?: string
- }
- /** Parse a bare package or package-subpath specifier into its package name. */
- function barePackageName(specifier: string): string | undefined {
- if (specifier.startsWith('.') || specifier.includes(':') || isAbsolute(specifier)) return undefined
- const [first = '', second = ''] = specifier.split('/')
- // An active Loader entry already passed module resolution, so a scoped bare name has its package segment.
- return first.startsWith('@') ? `${first}/${second}` : first
- }
- /** Read one manifest identity, optionally treating an absent name as a loose-module marker. */
- function identityFromManifest(path: string, allowAnonymous: boolean): DeepSeekPluginPackageIdentity | undefined {
- const manifest = JSON.parse(readFileSync(path, 'utf8')) as PackageManifest
- if (allowAnonymous && manifest.name === undefined) return undefined
- if (typeof manifest.name !== 'string' || manifest.name.length === 0
- || typeof manifest.version !== 'string' || manifest.version.length === 0) {
- throw new Error(`plugin-package-inventory-deepseek: ${path} must declare non-empty name and version`)
- }
- return { name: manifest.name, version: manifest.version }
- }
- /** Resolve a bare package without requiring it to export `./package.json`. */
- function barePackageManifest(packageName: string, anchors: readonly string[]): string | undefined {
- for (const anchor of anchors) {
- const searchPaths = createRequire(anchor).resolve.paths(packageName)
- /* v8 ignore next -- active non-builtin package entries always have Node package search paths */
- if (searchPaths === null) continue
- for (const searchPath of searchPaths) {
- const manifest = join(searchPath, packageName, 'package.json')
- if (existsSync(manifest)) return manifest
- }
- }
- return undefined
- }
- /** Find the nearest owning manifest for a relative or absolute plugin module. */
- function nearestManifest(modulePath: string): string | undefined {
- let current = dirname(modulePath)
- const root = parse(current).root
- while (true) {
- const manifest = join(current, 'package.json')
- if (existsSync(manifest)) return manifest
- if (current === root) return undefined
- current = dirname(current)
- }
- }
- /** Exact package identity resolver with immutable per-process manifest caching. */
- class PackageIdentityResolver {
- // TODO: Invalidate manifest identities if in-process package-version replacement becomes a supported upgrade path.
- private readonly cache = new Map<string, DeepSeekPluginPackageIdentity | undefined>()
- constructor(private readonly hostBaseUrl: string) {}
- /** Resolve one Loader entry's owning package, or absence for a non-package loose module. */
- resolve({ entry, bareBaseUrl }: ActiveEntry): DeepSeekPluginPackageIdentity | undefined {
- /* v8 ignore next -- Loader entry trees inherit a base URL; the fallback supports direct embedders. */
- const treeBase = entry.parent.tree.ctx.baseUrl ?? this.hostBaseUrl
- const anchors = [...new Set([bareBaseUrl ?? treeBase, treeBase, this.hostBaseUrl, import.meta.url])]
- const key = `${anchors.join('\u0000')}\u0000${entry.options.name}`
- if (this.cache.has(key)) return this.cache.get(key)
- const packageName = barePackageName(entry.options.name)
- let manifest: string | undefined
- if (packageName !== undefined) {
- manifest = barePackageManifest(packageName, anchors)
- if (manifest === undefined) {
- throw new Error(`plugin-package-inventory-deepseek: cannot resolve active package ${JSON.stringify(packageName)}`)
- }
- } else if (!entry.options.name.startsWith('cordis:')) {
- const moduleUrl = isAbsolute(entry.options.name)
- ? pathToFileURL(entry.options.name)
- : new URL(entry.options.name, treeBase)
- if (moduleUrl.protocol === 'file:') manifest = nearestManifest(fileURLToPath(moduleUrl))
- }
- const identity = manifest === undefined ? undefined : identityFromManifest(manifest, packageName === undefined)
- this.cache.set(key, identity)
- return identity
- }
- }
- /** Yield active, non-structural entries from one Loader tree. */
- function activeEntries(tree: EntryTree, rootBareBaseUrl?: string): ActiveEntry[] {
- return [...tree.entries()]
- .filter(entry => !entry.options.group
- && !entry.disabled
- && entry.fiber?.state === FiberState.ACTIVE)
- .map(entry => ({
- entry,
- ...entry.parent.tree === tree && rootBareBaseUrl !== undefined
- ? { bareBaseUrl: rootBareBaseUrl }
- : {},
- }))
- }
- /** Deterministic text order independent of the host's ICU data and locale. */
- function compareWireText(left: string, right: string): number {
- return left < right ? -1 : left > right ? 1 : 0
- }
- /** Collect the full active package set for one request. */
- async function collectActivePluginPackages(
- ctx: Context,
- resolver: PackageIdentityResolver,
- hostBaseUrl: string,
- sessionId?: string,
- ): Promise<DeepSeekPluginPackageIdentity[]> {
- const entries = activeEntries(ctx.loader)
- if (sessionId !== undefined && ctx.get('agentPresets') !== undefined) {
- const agent = ctx.agents.get(brandString<SessionId>(sessionId))
- if (agent !== undefined) {
- // The optional peer is loaded only when its service is present. Its existing
- // mount query keeps Loader internals off the public AgentPresets service.
- const { standingMountFor } = await import('@deepseek-ai/dsh-agent-presets')
- const presetTree = standingMountFor(agent.ctx)?.tree
- // PresetTree deliberately resolves its root bare rows from the harness;
- // nested ordinary includes retain their own tree base.
- if (presetTree !== undefined) entries.push(...activeEntries(presetTree, hostBaseUrl))
- }
- }
- const unique = new Map<string, DeepSeekPluginPackageIdentity>()
- for (const activeEntry of entries) {
- const identity = resolver.resolve(activeEntry)
- if (identity === undefined) continue
- unique.set(`${identity.name}\u0000${identity.version}`, identity)
- }
- return [...unique.values()].sort((left, right) => (
- compareWireText(left.name, right.name) || compareWireText(left.version, right.version)
- ))
- }
- /**
- * Register the complete `dsh_plugin_packages` request contribution when enabled.
- * @param ctx - plugin context carrying Loader provenance and the DeepSeek request-extension registry.
- * @param config - validated default-on configuration.
- */
- export function apply(ctx: Context, config: Config): void {
- if (config.enabled === false) return
- const hostBaseUrl = ctx.baseUrl ?? import.meta.url
- const resolver = new PackageIdentityResolver(hostBaseUrl)
- ctx.deepseekLlmApiExtensions.register('dsh_plugin_packages', {
- prepare: async (request) => {
- const value: DeepSeekPluginPackageInventoryExtension = {
- version: 1,
- packages: await collectActivePluginPackages(ctx, resolver, hostBaseUrl, request.sessionId),
- }
- return { value }
- },
- })
- }
|