diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 99c537a4..77b9854d 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -39,7 +39,9 @@ this package adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [Unreleased] -- Add candidate-only benchmark component switches with conservative patch editing, composed-config verification and a bounded readiness turn. Archive effective switches, show them in reports, and reject comparisons across different candidate switch sets (#296). +- 收敛所有 DSH 产品类型、懒加载 scope 与 profile carrier 入口到项目自有 `adapter/dsh` 边界;保持现有 Cordis 工具注册、提示词、权限、subprocess、PTC、结果与 UI 行为不变,并将宿主兼容声明扩展至 `>=0.2.0-rc.2 <0.2.2-0`,覆盖已验证的 DSH 0.2.1-rc.4。 +- Converge DSH product types, lazy scope loading and profile-carrier entrypoints behind the project-owned `adapter/dsh` boundary without changing existing Cordis tool, prompt, policy, subprocess, PTC, result or UI behavior; widen the bounded host range to `>=0.2.0-rc.2 <0.2.2-0`, including validated DSH 0.2.1-rc.4. + with conservative patch editing, composed-config verification and a bounded readiness turn. Archive effective switches, show them in reports, and reject comparisons across different candidate switch sets (#296). - 为 benchmark 增加仅作用于 candidate 的组件开关,保守编辑补丁并核验合成配置及有时限的就绪 turn;归档实际开关、在报告中展示,并拒绝不同 candidate 开关集的混配(#296)。 - Make benchmark model/reasoning selections actual shared routing conditions, archive composed configuration, and record the condition in sealed evidence. Repeated selections produce separate condition groups and reports; cross-condition pairing is refused, while historical runs remain readable as unknown (#294). diff --git a/docs/host-integration.md b/docs/host-integration.md index f69bdda8..78fc270a 100644 --- a/docs/host-integration.md +++ b/docs/host-integration.md @@ -87,13 +87,7 @@ use the PTC SDK loader under the host's `run_code` presentation. Check the scope assembled tools and presentation, not just a global registry or a prompt section name. An empty discovery section alone does not identify the cause. -Host support declarations and component resource exports are addressed in -[PR #395](https://github.com/T-Auto/dsh-ops/pull/395), with explicit 0.2.0-rc.2 and -0.2.1-rc.2 coverage. The text-only PTC hook adaptation in -[PR #390](https://github.com/T-Auto/dsh-ops/pull/390) is not full 0.2.1-rc.3 support. -[PR #383](https://github.com/T-Auto/dsh-ops/pull/383) and #390 address unnecessary -session work and append-time Bash publication. Check whether the installed version -actually contains these changes before attributing its behavior to them. +Host support declarations and component resource exports are covered by the current adapter boundary. The package declares and tests the bounded range `>=0.2.0-rc.2 <0.2.2-0`, including rc2, rc3, rc4 and the 0.2.1 stable line; the isolated host matrix compares the rc4 graph against the locked rc2 control. The text-only PTC hook adaptation is not used as the sole compatibility proof. The original #346 report also describes an enabled row and a stalled publication chain. The profile checks above do not prove that failure fixed. If the row is diff --git a/docs/usage.md b/docs/usage.md index 9a9ba1e4..857428a0 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -121,11 +121,7 @@ The ordinary DSH CLI cannot manage the reserved `desktop` profile; do not confus ### Host compatibility and display metadata -The package declares **DSH 0.2.0-rc.2 and 0.2.1-rc.2** explicitly in both `engines.dsh` -and the legacy DSH peer dependency. DSH 0.2.1 uses `engines.dsh` in preference to peers. -Other prereleases, including 0.2.1-rc.3, are outside this declaration: accepting its -text-only prompt hook does not establish compatibility with all presentation and -official-tool replacement APIs. +The package declares the bounded DSH compatibility range `>=0.2.0-rc.2 <0.2.2-0` in both `engines.dsh` and the legacy DSH peer dependency. This includes `0.2.0-rc.2`, `0.2.1-rc.2`, `0.2.1-rc.3`, `0.2.1-rc.4` and the `0.2.1` stable line, while rejecting `0.2.0-rc.1`, `0.2.2` prereleases and `0.3.0`. The rc4 host graph is validated separately in the isolated host matrix; the plugin's native adapter preserves the existing Cordis tool, prompt, policy, subprocess, PTC and UI behavior. The bundle icon comes from the root manifest. Each component exports its own `dsh-ops//icon` and `locale/*.json`; DSH 0.2.1 does not use a component's diff --git "a/docs/\344\275\277\347\224\250\346\214\207\345\215\227.md" "b/docs/\344\275\277\347\224\250\346\214\207\345\215\227.md" index 34e44898..a1ad19cd 100644 --- "a/docs/\344\275\277\347\224\250\346\214\207\345\215\227.md" +++ "b/docs/\344\275\277\347\224\250\346\214\207\345\215\227.md" @@ -102,9 +102,7 @@ dsh plugin --profile dsh-tui add dsh-ops ### 宿主兼容范围与展示元数据 -包在 `engines.dsh` 和旧版 DSH peer 依赖中明确声明 **DSH 0.2.0-rc.2 与 0.2.1-rc.2**。 -DSH 0.2.1 优先使用 `engines.dsh`。其他预发布版本(包括 0.2.1-rc.3)不在声明范围内: -适配只含文本的 prompt hook,并不代表所有展示与官方工具替换接口均已兼容。 +包在 `engines.dsh` 和旧版 DSH peer 依赖中声明有界范围 `>=0.2.0-rc.2 <0.2.2-0`,覆盖 `0.2.0-rc.2`、`0.2.1-rc.2`、`0.2.1-rc.3`、`0.2.1-rc.4` 与 `0.2.1` 稳定线,同时拒绝 `0.2.0-rc.1`、`0.2.2` 预发布版本和 `0.3.0`。隔离宿主矩阵会单独验证 rc4;OPS 自有 DSH adapter 保持现有 Cordis 工具、提示词、权限、subprocess、PTC 与 UI 行为。 bundle 图标来自顶层清单。每个组件单独导出 `dsh-ops/<组件>/icon` 和 `locale/*.json`; DSH 0.2.1 不再通过组件 `package.json` 读取这些资源。元数据门禁通过宿主 API 读取 PNG diff --git "a/docs/\345\256\277\344\270\273\351\233\206\346\210\220.md" "b/docs/\345\256\277\344\270\273\351\233\206\346\210\220.md" index f3f7dd58..5c3b4a24 100644 --- "a/docs/\345\256\277\344\270\273\351\233\206\346\210\220.md" +++ "b/docs/\345\256\277\344\270\273\351\233\206\346\210\220.md" @@ -68,11 +68,7 @@ dsh --profile ops-test --dump-config-schema `run_code` 展示使用 PTC SDK loader。应检查具体作用域的装配工具和展示模式,不只查看 全局注册表或提示词段名称。discovery 段为空本身不足以确定原因。 -[PR #395](https://github.com/T-Auto/dsh-ops/pull/395) 处理宿主兼容声明与组件资源导出, -明确覆盖 0.2.0-rc.2 和 0.2.1-rc.2。 -[PR #390](https://github.com/T-Auto/dsh-ops/pull/390) 的纯文本 PTC hook 适配不代表完整 -支持 0.2.1-rc.3。[PR #383](https://github.com/T-Auto/dsh-ops/pull/383) 与 #390 处理会话 -重复工作及 append 期间 Bash 发布问题。判断行为前,先确认安装版本确实包含这些改动。 +当前 adapter 边界覆盖有界范围 `>=0.2.0-rc.2 <0.2.2-0`,包括 rc2、rc3、rc4 与 0.2.1 稳定线;隔离宿主矩阵会将 rc4 依赖图与锁定的 rc2 对照。纯文本 PTC hook 不再作为唯一兼容性依据。 #346 原始报告也包含“行已启用,但发布链停滞”的情况,上述 profile 检查不能证明它已被 修复。若行已启用而预期的作用域工具仍缺失,应提供最小 profile、准确版本、Native/PTC diff --git a/package-lock.json b/package-lock.json index 9129ea7f..55b42836 100644 --- a/package-lock.json +++ b/package-lock.json @@ -67,11 +67,11 @@ }, "engines": { "node": "^22.19 || >=24", - "dsh": "0.2.0-rc.2 || 0.2.1-rc.2" + "dsh": ">=0.2.0-rc.2 <0.2.2-0" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.4", - "@deepseek-ai/dsh": "0.2.0-rc.2 || 0.2.1-rc.2" + "@deepseek-ai/dsh": ">=0.2.0-rc.2 <0.2.2-0" }, "peerDependenciesMeta": { "@deepseek-ai/cordis": { diff --git a/package.json b/package.json index 23e383c4..aa82ef0f 100644 --- a/package.json +++ b/package.json @@ -122,6 +122,9 @@ "./compat/package.json": "./lib/components/compat/package.json", "./compat/locale/*.json": "./lib/components/compat/locale/*.json", "./compat/icon": "./lib/components/compat/icon.png", + "./adapter/dsh": { + "default": "./lib/adapter/dsh/host.js" + }, "./client": { "default": "./lib/client.js" } @@ -193,7 +196,7 @@ }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.4", - "@deepseek-ai/dsh": "0.2.0-rc.2 || 0.2.1-rc.2" + "@deepseek-ai/dsh": ">=0.2.0-rc.2 <0.2.2-0" }, "peerDependenciesMeta": { "@deepseek-ai/cordis": { @@ -253,6 +256,6 @@ }, "engines": { "node": "^22.19 || >=24", - "dsh": "0.2.0-rc.2 || 0.2.1-rc.2" + "dsh": ">=0.2.0-rc.2 <0.2.2-0" } } diff --git a/scripts/validate-manifest.mjs b/scripts/validate-manifest.mjs index 1b18715e..143ac067 100644 --- a/scripts/validate-manifest.mjs +++ b/scripts/validate-manifest.mjs @@ -562,9 +562,12 @@ check( typeof pkg.engines?.dsh === 'string' && pkg.engines.dsh === pkg.peerDependencies?.['@deepseek-ai/dsh'], 'engines.dsh and the legacy DSH peer declare the same compatibility range', ) -for (const version of ['0.2.0-rc.2', '0.2.1-rc.2']) { +for (const version of ['0.2.0-rc.2', '0.2.1-rc.2', '0.2.1-rc.3', '0.2.1-rc.4', '0.2.1']) { check(evaluatePluginCompatibility(pkg, {}, version) === undefined, `the declared range accepts DSH ${version}`) } +for (const version of ['0.2.0-rc.1', '0.2.2-rc.1', '0.3.0']) { + check(evaluatePluginCompatibility(pkg, {}, version) !== undefined, `the declared range rejects DSH ${version}`) +} for (const component of [...COMPONENTS, 'background']) { const resource = pkg.exports?.[`./${component}/icon`] check(typeof resource === 'string' && fs.existsSync(path.join(PACKAGE_ROOT, resource)), diff --git a/src/adapter/dsh/host.ts b/src/adapter/dsh/host.ts new file mode 100644 index 00000000..7e9b4358 --- /dev/null +++ b/src/adapter/dsh/host.ts @@ -0,0 +1,32 @@ +/** Runtime half of the DSH product adapter. Optional host services stay optional. */ +import { createRequire } from 'node:module' +import { pathToFileURL } from 'node:url' +import path from 'node:path' +import type { AtomicApi, BootApi, Context } from './types.js' + +export interface CarrierHost { boot: BootApi; yaml: typeof import('yaml'); atomic: AtomicApi } + +export function service(ctx: Pick, name: string): T | undefined { + try { + const value = ctx.get(name as never) + return value === undefined || value === null ? undefined : value as T + } catch { return undefined } +} + +/** Scope helpers are deliberately lazy: load-time plugin evaluation needs no DSH scope package. */ +export async function loadScopes(): Promise { + return import('@deepseek-ai/dsh-scope') +} + +export async function loadCarrierHost(anchor: string): Promise { + if (!path.isAbsolute(anchor)) throw new Error('--host-anchor must be an absolute path to the host package.json.') + const require = createRequire(anchor) + const editorRequire = createRequire(require.resolve('@deepseek-ai/dsh-config-editor')) + const boot = await import(pathToFileURL(require.resolve('@deepseek-ai/dsh-app-boot')).href) as unknown as BootApi + const yaml = await import(pathToFileURL(editorRequire.resolve('yaml')).href) as typeof import('yaml') + const atomic = await import(pathToFileURL(editorRequire.resolve('@deepseek-ai/dsh-atomic-write')).href) as unknown as AtomicApi + for (const name of ['loadProfileDirectory', 'composeEntries', 'readProfilePatches', 'resolveBundleDir', 'loadOverlayPatches'] as const) { + if (typeof boot[name] !== 'function') throw new Error(`Host profile API unavailable: ${name}`) + } + return { boot, yaml, atomic } +} diff --git a/src/adapter/dsh/types.ts b/src/adapter/dsh/types.ts new file mode 100644 index 00000000..296db0de --- /dev/null +++ b/src/adapter/dsh/types.ts @@ -0,0 +1,37 @@ +/** + * The only source-level boundary to DSH product APIs. + * + * OPS owns its kernels and contracts; this module is the product adapter's type + * surface. It contains type-only exports, so importing OPS never evaluates a + * DSH package at load time. Runtime host lookups belong in host.ts. + */ +export type { Context, Fiber } from '@deepseek-ai/cordis' +export type { EntryOptions } from '@deepseek-ai/cordis-plugin-loader' +export type { Agent } from '@deepseek-ai/dsh-agent' +export type { FileSystem, FsTarget, FsInfo, FsObservation } from '@deepseek-ai/dsh-fs' +export type { GenerateOptions, StreamChunk } from '@deepseek-ai/dsh-llm' +export type { Session } from '@deepseek-ai/dsh-session' +export type { SettingsPathOpView } from '@deepseek-ai/dsh-settings/types' +export type { AssembleContext, PromptAssembly, SystemPrompt } from '@deepseek-ai/dsh-system-prompt' +export type { SandboxPolicyService } from '@deepseek-ai/dsh-sandbox-policy' +export type { SubprocessHandle, SubprocessOutputRead, SubprocessOutputReader, SubprocessRuntime } from '@deepseek-ai/dsh-subprocess' +export type { InvocationDescriptor, RemoteResult, TypertCodec, TypertGatewayBinding } from '@deepseek-ai/dsh-typert-protocol' +export type { JsonSchemaNode, JsonSchemaType, ObjectJsonSchema, ToolDefinition, ToolExecution, + ToolExecutionResult, ToolExecutionToken, ToolGuard, ToolPresentationMode, ToolRunContext } from '@deepseek-ai/dsh-tools' +export type { default as ToolRuntime } from '@deepseek-ai/dsh-tools' +export type { ConfinedArgv, RunnerFailureRule, SandboxExecutionPolicy, SandboxMode, SandboxProvider } from '@deepseek-ai/dsh-sandbox' +export type { ConfigPageForm, PluginConfigViewProps } from '@deepseek-ai/dsh-client-ui-plugin-manager/client' +export type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots' +export type { ProfileContext } from '@deepseek-ai/dsh-app-boot' +export type * as Atomic from '@deepseek-ai/dsh-atomic-write' +export type * as Boot from '@deepseek-ai/dsh-app-boot' +import type {} from '@deepseek-ai/dsh-api-gateway/client' +import type {} from '@deepseek-ai/dsh-client-locale/client' +import type {} from '@deepseek-ai/dsh-client-ui-renderer/client' +import type {} from '@deepseek-ai/dsh-config-editor' +import type {} from '@deepseek-ai/dsh-typert-registry' + +/** Narrow runtime shapes consumed by the profile carrier. */ +export type BootApi = Pick +export type AtomicApi = Pick \ No newline at end of file diff --git a/src/authority-paths.ts b/src/authority-paths.ts index 2bea8c0f..3b59a21b 100644 --- a/src/authority-paths.ts +++ b/src/authority-paths.ts @@ -1,5 +1,5 @@ /** Resolve only host-owned anchors; caller-selected descendants retain native no-follow checks. */ -import type { SandboxExecutionPolicy } from '@deepseek-ai/dsh-sandbox' +import type { SandboxExecutionPolicy } from './adapter/dsh/types.js' import fs from 'node:fs' import path from 'node:path' import { tmpdir } from 'node:os' diff --git a/src/capabilities/discovery.ts b/src/capabilities/discovery.ts index ddb9b4de..1c62575f 100644 --- a/src/capabilities/discovery.ts +++ b/src/capabilities/discovery.ts @@ -1,4 +1,4 @@ -import type { JsonSchemaNode } from '@deepseek-ai/dsh-tools' +import type { JsonSchemaNode } from '../adapter/dsh/types.js' import type { ParameterSchema } from './types.js' /** Reviewed, currently implemented advanced operations. Future formats are absent. */ diff --git a/src/capabilities/documents.ts b/src/capabilities/documents.ts index 8a0a6b2d..235e0f4c 100644 --- a/src/capabilities/documents.ts +++ b/src/capabilities/documents.ts @@ -1,5 +1,5 @@ /** Document schemas describe their bounded observation scope; registration remains catalogue-owned. */ -import type { JsonSchemaNode } from '@deepseek-ai/dsh-tools' +import type { JsonSchemaNode } from '../adapter/dsh/types.js' import type { ParameterSchema } from './types.js' import { STORAGE_REFERENCE } from './result.js' const string: JsonSchemaNode = { type: 'string' } diff --git a/src/capabilities/file.ts b/src/capabilities/file.ts index a6bd8d2b..a975b79c 100644 --- a/src/capabilities/file.ts +++ b/src/capabilities/file.ts @@ -1,5 +1,5 @@ /** File capability data; no host services or registration side effects. */ -import type { JsonSchemaNode } from '@deepseek-ai/dsh-tools' +import type { JsonSchemaNode } from '../adapter/dsh/types.js' import { DOCUMENT_PARAMETERS, DOCUMENT_DESCRIPTIONS, documentOutput } from './documents.js' import { STORAGE_REFERENCE } from './result.js' import type { ParameterSchema } from './types.js' diff --git a/src/capabilities/ptc.ts b/src/capabilities/ptc.ts index 8dbfac9d..9149add8 100644 --- a/src/capabilities/ptc.ts +++ b/src/capabilities/ptc.ts @@ -1,5 +1,5 @@ /** Batch and PTC result schemas; the same result capability also owns a Native projection. */ -import type { JsonSchemaNode } from '@deepseek-ai/dsh-tools' +import type { JsonSchemaNode } from '../adapter/dsh/types.js' import { STORAGE_REFERENCE, RESULT_PAGE_PARAMETERS } from './result.js' import type { ParameterSchema } from './types.js' diff --git a/src/capabilities/result.ts b/src/capabilities/result.ts index 904755f4..ee8a282e 100644 --- a/src/capabilities/result.ts +++ b/src/capabilities/result.ts @@ -1,5 +1,5 @@ /** Shared stored-reference wire metadata and the Native projection of the result capability. */ -import type { JsonSchemaNode } from '@deepseek-ai/dsh-tools' +import type { JsonSchemaNode } from '../adapter/dsh/types.js' import type { ParameterSchema } from './types.js' const string: JsonSchemaNode = { type: 'string' } const integer: JsonSchemaNode = { type: 'integer' } diff --git a/src/capabilities/sdk.ts b/src/capabilities/sdk.ts index 7414ac36..b02ecfa3 100644 --- a/src/capabilities/sdk.ts +++ b/src/capabilities/sdk.ts @@ -1,4 +1,4 @@ -import type { JsonSchemaNode } from '@deepseek-ai/dsh-tools' +import type { JsonSchemaNode } from '../adapter/dsh/types.js' import type { ParameterSchema, SchemaCapability } from './types.js' export const SDK_PARAMETERS: ParameterSchema = { type: 'object', properties: { tools: { type: 'array', items: { type: 'string' }, diff --git a/src/capabilities/types.ts b/src/capabilities/types.ts index 43c1739b..2649179c 100644 --- a/src/capabilities/types.ts +++ b/src/capabilities/types.ts @@ -1,4 +1,4 @@ -import type { JsonSchemaNode, ObjectJsonSchema, ToolPresentationMode } from '@deepseek-ai/dsh-tools' +import type { JsonSchemaNode, ObjectJsonSchema, ToolPresentationMode } from '../adapter/dsh/types.js' export type Component = 'file' | 'ptc' | 'shell' | 'discovery' export type ParameterSchema = ObjectJsonSchema & Record & { diff --git a/src/client/forms.tsx b/src/client/forms.tsx index 6ed6dc27..f98c87ac 100644 --- a/src/client/forms.tsx +++ b/src/client/forms.tsx @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react' -import type { ConfigPageForm, PluginConfigViewProps } from '@deepseek-ai/dsh-client-ui-plugin-manager/client' -import type { SettingsPathOpView } from '@deepseek-ai/dsh-settings/types' +import type { ConfigPageForm, PluginConfigViewProps } from '../adapter/dsh/types.js' +import type { SettingsPathOpView } from '../adapter/dsh/types.js' import type { Translator } from './locales.js' export type SettingsProps = PluginConfigViewProps & { t: Translator } export const strings = (value: unknown): string[] => Array.isArray(value) ? value.filter((item): item is string => typeof item === 'string') : [] diff --git a/src/client/index.tsx b/src/client/index.tsx index 57b6c44f..16a45c77 100644 --- a/src/client/index.tsx +++ b/src/client/index.tsx @@ -1,7 +1,7 @@ -import type { Context } from '@deepseek-ai/cordis' -import type {} from '@deepseek-ai/dsh-client-ui-renderer/client' -import type {} from '@deepseek-ai/dsh-client-locale/client' -import type {} from '@deepseek-ai/dsh-api-gateway/client' +import type { Context } from '../adapter/dsh/types.js' +import type {} from '../adapter/dsh/types.js' +import type {} from '../adapter/dsh/types.js' +import type {} from '../adapter/dsh/types.js' import { RUNTIME_REMOTE } from '../settings/runtime-contract.js' import { en, zh } from './locales.js' import { DiscoveryForm } from './selections.js' diff --git a/src/client/locales.ts b/src/client/locales.ts index b4513839..a9bce74c 100644 --- a/src/client/locales.ts +++ b/src/client/locales.ts @@ -1,4 +1,4 @@ -import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots' +import type { TranslateNS } from '../adapter/dsh/types.js' export const en = { replacements: 'Choose which official tools OPS replaces.', discovery: 'Choose discoverable and always-loaded capabilities.', shell: 'Manage Bash and the standard host PowerShell installation.', modeMinimal: 'Preset enhancement: adds OPS tools to Minimal sessions and replaces the official Windows shell.', modeStandard: 'Preset enhancement: replaces the official read, glob and grep tools and the Windows shell for Standard sessions.', diff --git a/src/components/background/index.ts b/src/components/background/index.ts index c8707d73..91a23238 100644 --- a/src/components/background/index.ts +++ b/src/components/background/index.ts @@ -5,7 +5,7 @@ * Existing profiles still carry this row, so it keeps loading: it accepts any config without * validating it, publishes nothing, and says once that the row can be deleted. */ -import type { Context } from '@deepseek-ai/cordis' +import type { Context } from '../../adapter/dsh/types.js' export const name = "dsh-ops-background" export const REMOVED_MESSAGE = "dsh-ops: the dsh-ops/background component (FastCtx background jobs) was removed in this version; it publishes no tools. Delete this row from the profile configuration." export function apply(ctx: Context | null | undefined, _config?: unknown): void { diff --git a/src/components/compat/index.ts b/src/components/compat/index.ts index f3bb2512..7b57876d 100644 --- a/src/components/compat/index.ts +++ b/src/components/compat/index.ts @@ -1,5 +1,5 @@ /** Compatibility switch: keep the official tools exposed instead of replaced. */ -import type { Context } from '@deepseek-ai/cordis' +import type { Context } from '../../adapter/dsh/types.js' import { joinCompatibility } from '../../modes/registry.js' export const name = 'dsh-ops-compat' export function apply(ctx: Context): void { diff --git a/src/components/file/index.ts b/src/components/file/index.ts index c8c73008..702916db 100644 --- a/src/components/file/index.ts +++ b/src/components/file/index.ts @@ -1,4 +1,4 @@ -import type { Context } from '@deepseek-ai/cordis' +import type { Context } from '../../adapter/dsh/types.js' import { applyComponent } from '../../index.js' export { Config } from '../../settings/file-config.js' export const name = 'dsh-ops-file' diff --git a/src/components/mode-cordis/index.ts b/src/components/mode-cordis/index.ts index 235db021..089e03a1 100644 --- a/src/components/mode-cordis/index.ts +++ b/src/components/mode-cordis/index.ts @@ -1,5 +1,5 @@ /** One enhanced built-in preset. The row publishes OPS only for sessions of that preset. */ -import type { Context } from '@deepseek-ai/cordis' +import type { Context } from '../../adapter/dsh/types.js' import { applyMode } from '../../modes/apply.js' import { modeConfigForm } from '../../modes/config.js' export const name = 'dsh-ops-mode-cordis' diff --git a/src/components/mode-minimal/index.ts b/src/components/mode-minimal/index.ts index 755d069c..f747498c 100644 --- a/src/components/mode-minimal/index.ts +++ b/src/components/mode-minimal/index.ts @@ -1,5 +1,5 @@ /** One enhanced built-in preset. The row publishes OPS only for sessions of that preset. */ -import type { Context } from '@deepseek-ai/cordis' +import type { Context } from '../../adapter/dsh/types.js' import { applyMode } from '../../modes/apply.js' import { modeConfigForm } from '../../modes/config.js' export const name = 'dsh-ops-mode-minimal' diff --git a/src/components/mode-ptc/index.ts b/src/components/mode-ptc/index.ts index 01d72a6a..142aa702 100644 --- a/src/components/mode-ptc/index.ts +++ b/src/components/mode-ptc/index.ts @@ -1,5 +1,5 @@ /** One enhanced built-in preset. The row publishes OPS only for sessions of that preset. */ -import type { Context } from '@deepseek-ai/cordis' +import type { Context } from '../../adapter/dsh/types.js' import { applyMode } from '../../modes/apply.js' import { modeConfigForm } from '../../modes/config.js' export const name = 'dsh-ops-mode-ptc' diff --git a/src/components/mode-standard/index.ts b/src/components/mode-standard/index.ts index b0321024..95b42e43 100644 --- a/src/components/mode-standard/index.ts +++ b/src/components/mode-standard/index.ts @@ -1,5 +1,5 @@ /** One enhanced built-in preset. The row publishes OPS only for sessions of that preset. */ -import type { Context } from '@deepseek-ai/cordis' +import type { Context } from '../../adapter/dsh/types.js' import { applyMode } from '../../modes/apply.js' import { modeConfigForm } from '../../modes/config.js' export const name = 'dsh-ops-mode-standard' diff --git a/src/components/panel/index.ts b/src/components/panel/index.ts index 6745a4bb..d3425fa1 100644 --- a/src/components/panel/index.ts +++ b/src/components/panel/index.ts @@ -1,6 +1,6 @@ /** Opt-in capture. A disabled row registers nothing and starts no filesystem work. */ -import type { Context } from '@deepseek-ai/cordis' -import type {} from '@deepseek-ai/dsh-session' +import type { Context } from '../../adapter/dsh/types.js' +import type {} from '../../adapter/dsh/types.js' import { readFileSync } from 'node:fs' import { createPanelCollector, resolvePanelConfig } from '../../panel/collect.js' import { configObject, editable, settingsConfig } from '../../settings/schema.js' diff --git a/src/components/ptc/index.ts b/src/components/ptc/index.ts index 6d2b0c39..aab8b611 100644 --- a/src/components/ptc/index.ts +++ b/src/components/ptc/index.ts @@ -1,4 +1,4 @@ -import type { Context } from '@deepseek-ai/cordis' +import type { Context } from '../../adapter/dsh/types.js' import { apply as mount } from '../../ptc/index.js' import { resolvePtcConfig } from '../../config.js' import { editable, settingsConfig } from '../../settings/schema.js' diff --git a/src/components/shell/index.ts b/src/components/shell/index.ts index 78870fa7..4834749f 100644 --- a/src/components/shell/index.ts +++ b/src/components/shell/index.ts @@ -1,4 +1,4 @@ -import type { Context } from '@deepseek-ai/cordis' +import type { Context } from '../../adapter/dsh/types.js' import { applyComponent } from '../../index.js' import { mountRuntimeSettings } from '../../settings/runtime-host.js' import { resolveConfig } from '../../config.js' diff --git a/src/components/tui/index.ts b/src/components/tui/index.ts index b33c9c70..6a60bd4c 100644 --- a/src/components/tui/index.ts +++ b/src/components/tui/index.ts @@ -1,6 +1,6 @@ /** Optional read-only panel. Missing tuiPanels leaves only this component pending. */ -import type { Context } from '@deepseek-ai/cordis' -import type {} from '@deepseek-ai/dsh-session' +import type { Context } from '../../adapter/dsh/types.js' +import type {} from '../../adapter/dsh/types.js' import type { AttentionLevel } from '../../tui/attention.js' import { createActivityStore, resolveActivityConfig } from '../../tui/activity.js' import { createOpsPanel } from '../../tui/panel.js' diff --git a/src/config-updates.ts b/src/config-updates.ts index fceddbaf..e2ddc3ec 100644 --- a/src/config-updates.ts +++ b/src/config-updates.ts @@ -7,8 +7,8 @@ * profile or rename dsh-ops/file: name-qualified overrides would be skipped. * Explicit legacy panel capture:false is retained; no migration may start capture. */ -import type { Context } from '@deepseek-ai/cordis' -import type {} from '@deepseek-ai/dsh-config-editor' +import type { Context } from './adapter/dsh/types.js' +import type {} from './adapter/dsh/types.js' import { LEGACY_FASTCTX_KEYS } from './config.js' export const CONFIG_UPDATE_VERSION = 2 diff --git a/src/discovery/index.ts b/src/discovery/index.ts index 6bf67774..f414e54a 100644 --- a/src/discovery/index.ts +++ b/src/discovery/index.ts @@ -1,11 +1,12 @@ -import type { Context, Fiber } from '@deepseek-ai/cordis' -import type { Agent } from '@deepseek-ai/dsh-agent' -import type { ToolDefinition } from '@deepseek-ai/dsh-tools' -import type { PromptAssembly } from '@deepseek-ai/dsh-system-prompt' -import type {} from '@deepseek-ai/dsh-sandbox-policy' +import type { Context, Fiber } from '../adapter/dsh/types.js' +import type { Agent } from '../adapter/dsh/types.js' +import type { ToolDefinition } from '../adapter/dsh/types.js' +import type { PromptAssembly } from '../adapter/dsh/types.js' +import type {} from '../adapter/dsh/types.js' import { resolveDiscoveryConfig } from '../config.js' import { NativeFileTools } from '../file/runtime.js' import { nativeProviders, registerNativeProviderAtScope, claimNativeSelection } from '../file/result-provider.js' +import { loadScopes } from '../adapter/dsh/host.js' import { onToolChange } from '../tool-changes.js' import { ownScopes } from '../scoped-ownership.js' import { isNativePresentation, isPresentationProbe } from '../presentation.js' @@ -232,7 +233,7 @@ export function apply(root: Context, raw: unknown): void { for (const entry of entries.values()) invalidate(entry) void reconcile() } - ;({ scopeChainOf } = await import('@deepseek-ai/dsh-scope')) + ;({ scopeChainOf } = await loadScopes()) onToolChange(ctx, scopes => { if (mutating || ownership?.publishing()) return if (!scopes?.length) { refresh(); return } diff --git a/src/file/contract.ts b/src/file/contract.ts index 937d3cbf..4b15a455 100644 --- a/src/file/contract.ts +++ b/src/file/contract.ts @@ -1,4 +1,4 @@ -import type { ToolDefinition } from '@deepseek-ai/dsh-tools' +import type { ToolDefinition } from '../adapter/dsh/types.js' import { publicToolName } from '../policy.js' import { capability } from '../capabilities/registry.js' import type { FileToolName } from '../capabilities/registry.js' diff --git a/src/file/result-provider.ts b/src/file/result-provider.ts index 0e7de99f..a9d6a10e 100644 --- a/src/file/result-provider.ts +++ b/src/file/result-provider.ts @@ -1,7 +1,8 @@ /** Exact visible OPS registrations supply Native projections; no shared registry mutation. */ -import type { ToolDefinition } from '@deepseek-ai/dsh-tools' -import type { Context } from '@deepseek-ai/cordis' +import type { ToolDefinition } from '../adapter/dsh/types.js' +import type { Context } from '../adapter/dsh/types.js' import { withToolChange } from '../tool-changes.js' +import { loadScopes } from '../adapter/dsh/host.js' interface Host { root?: object; emit?(name: 'tools/change'): unknown; get(name: 'tools'): { get(name: string, scope?: unknown): ToolDefinition | undefined } | undefined } export interface NativeProvider { definition: ToolDefinition; scope: unknown; active: boolean; inheritable: boolean; priority: number } interface Provider extends NativeProvider { publish(visible: boolean): void } @@ -36,7 +37,7 @@ function refresh(owner: State, scope: unknown): void { }) } export async function registerNativeProvider(ctx: Host, definitions: ToolDefinition[], register: (tool: ToolDefinition) => (() => void), options: { inheritable?: boolean; priority?: number } = {}): Promise<() => void> { - const { scopeOf } = await import('@deepseek-ai/dsh-scope') + const { scopeOf } = await loadScopes() return registerNativeProviderAtScope(ctx, scopeOf(ctx as Context), definitions, register, options) } /** Callers that already resolved the public scope API can commit synchronously. */ diff --git a/src/file/result.ts b/src/file/result.ts index ef468b94..a156f9b8 100644 --- a/src/file/result.ts +++ b/src/file/result.ts @@ -1,6 +1,6 @@ /** Native page/release adapter over the same result kernel bridge used by PTC. */ import path from 'node:path' -import type { ToolDefinition } from '@deepseek-ai/dsh-tools' +import type { ToolDefinition } from '../adapter/dsh/types.js' import { capability } from '../capabilities/registry.js' import { publicToolName } from '../policy.js' import { OUTPUT } from '../capabilities/ptc.js' diff --git a/src/file/runtime.ts b/src/file/runtime.ts index 86d75f64..765d70ac 100644 --- a/src/file/runtime.ts +++ b/src/file/runtime.ts @@ -1,5 +1,5 @@ -import type { Context } from '@deepseek-ai/cordis' -import type { ToolDefinition } from '@deepseek-ai/dsh-tools' +import type { Context } from '../adapter/dsh/types.js' +import type { ToolDefinition } from '../adapter/dsh/types.js' import type { FileToolName } from '../capabilities/registry.js' import { WORKER_TIMEOUT_MS } from '../worker-protocol.js' import { publicToolName } from '../policy.js' diff --git a/src/file/worker.ts b/src/file/worker.ts index ee7b1902..a8e460cf 100644 --- a/src/file/worker.ts +++ b/src/file/worker.ts @@ -1,10 +1,10 @@ /** Native file worker bridge. The host owns path resolution and DSH authority. */ -import type { Context } from '@deepseek-ai/cordis' -import type { SubprocessRuntime } from '@deepseek-ai/dsh-subprocess' -import type { SandboxPolicyService } from '@deepseek-ai/dsh-sandbox-policy' -import type { ToolRunContext } from '@deepseek-ai/dsh-tools' -import type { FileSystem, FsTarget, FsInfo, FsObservation } from '@deepseek-ai/dsh-fs' -import type { SandboxExecutionPolicy } from '@deepseek-ai/dsh-sandbox' +import type { Context } from '../adapter/dsh/types.js' +import type { SubprocessRuntime } from '../adapter/dsh/types.js' +import type { SandboxPolicyService } from '../adapter/dsh/types.js' +import type { ToolRunContext } from '../adapter/dsh/types.js' +import type { FileSystem, FsTarget, FsInfo, FsObservation } from '../adapter/dsh/types.js' +import type { SandboxExecutionPolicy } from '../adapter/dsh/types.js' import type { EffectState } from '../kernel/outcome.js' import type { WorkerInvokeConfig } from '../worker-boundary.js' import { record, errorText } from '../worker-boundary.js' diff --git a/src/index.ts b/src/index.ts index eabf76ec..72556253 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,8 +1,8 @@ /** dsh-ops host half. Own registrations only; no @deepseek-ai value imports. */ -import type { Context } from '@deepseek-ai/cordis' -import type { Agent } from '@deepseek-ai/dsh-agent' -import type {} from '@deepseek-ai/dsh-tools' -import type {} from '@deepseek-ai/dsh-system-prompt' +import type { Context } from './adapter/dsh/types.js' +import type { Agent } from './adapter/dsh/types.js' +import type {} from './adapter/dsh/types.js' +import type {} from './adapter/dsh/types.js' import { resolveConfig } from './config.js' import { mountConfigUpdates, updatedConfig } from './config-updates.js' import { SECTION_ORDERS, TOOLING_SECTION, BASH_TOOL, publicToolName, hostShellRefusal, renderToolingPolicy } from './policy.js' diff --git a/src/kernel/result-storage.ts b/src/kernel/result-storage.ts index f9110c9d..5bdb189b 100644 --- a/src/kernel/result-storage.ts +++ b/src/kernel/result-storage.ts @@ -3,7 +3,7 @@ import { createHash } from 'node:crypto' import fs from 'node:fs' import path from 'node:path' import { tmpdir } from 'node:os' -import type { SandboxExecutionPolicy, ConfinedArgv } from '@deepseek-ai/dsh-sandbox' +import type { SandboxExecutionPolicy, ConfinedArgv } from '../adapter/dsh/types.js' import type { WorkerStorage } from '../worker-protocol.js' import { workerEnvelope } from '../worker-protocol.js' import { CAPABILITIES } from '../capabilities/registry.js' diff --git a/src/modes/apply.ts b/src/modes/apply.ts index 85d13d10..3d9db0f3 100644 --- a/src/modes/apply.ts +++ b/src/modes/apply.ts @@ -8,8 +8,8 @@ * whose OPS counterpart is visible. Compatibility mode is a runtime switch that * lifts those hides without unloading any row. */ -import type { Context } from '@deepseek-ai/cordis' -import type { Agent } from '@deepseek-ai/dsh-agent' +import type { Context } from '../adapter/dsh/types.js' +import type { Agent } from '../adapter/dsh/types.js' import { apply as mountPtc } from '../ptc/index.js' import { mountSessionBash, type BashGate } from '../session-shells.js' import { resolveShells } from '../shells.js' diff --git a/src/modes/detect.ts b/src/modes/detect.ts index f85dbfd2..5180fc74 100644 --- a/src/modes/detect.ts +++ b/src/modes/detect.ts @@ -9,8 +9,8 @@ * deployment (headless/SDK), which this plugin treats as the built-in Standard * composition so OPS keeps working there. */ -import type { Context } from '@deepseek-ai/cordis' -import type { Agent } from '@deepseek-ai/dsh-agent' +import type { Context } from '../adapter/dsh/types.js' +import type { Agent } from '../adapter/dsh/types.js' import { MODE_IDS, MODE_PRESET, type ModeId } from './types.js' interface PresetRegistry { composedPreset(ctx: Context): string | undefined } diff --git a/src/modes/native.ts b/src/modes/native.ts index 3d5f6368..8c409da1 100644 --- a/src/modes/native.ts +++ b/src/modes/native.ts @@ -7,9 +7,9 @@ * when the registry reports a change, which is the only way a blank session can * move between modes. */ -import type { Context, Fiber } from '@deepseek-ai/cordis' -import type { Agent } from '@deepseek-ai/dsh-agent' -import type {} from '@deepseek-ai/dsh-system-prompt' +import type { Context, Fiber } from '../adapter/dsh/types.js' +import type { Agent } from '../adapter/dsh/types.js' +import type {} from '../adapter/dsh/types.js' import { NativeFileTools } from '../file/runtime.js' import { registerNativeProviderAtScope } from '../file/result-provider.js' import { resolveWorker } from '../file/worker.js' diff --git a/src/modes/native/read-dedup.ts b/src/modes/native/read-dedup.ts index 89860c5b..b386a522 100644 --- a/src/modes/native/read-dedup.ts +++ b/src/modes/native/read-dedup.ts @@ -1,7 +1,7 @@ -import type { Context } from '@deepseek-ai/cordis' -import type { Agent } from '@deepseek-ai/dsh-agent' -import type { GenerateOptions, StreamChunk } from '@deepseek-ai/dsh-llm' -import type { ToolDefinition, ToolExecution, ToolExecutionResult, ToolExecutionToken } from '@deepseek-ai/dsh-tools' +import type { Context } from '../../adapter/dsh/types.js' +import type { Agent } from '../../adapter/dsh/types.js' +import type { GenerateOptions, StreamChunk } from '../../adapter/dsh/types.js' +import type { ToolDefinition, ToolExecution, ToolExecutionResult, ToolExecutionToken } from '../../adapter/dsh/types.js' import { publicToolName } from '../../policy.js' import { CAPABILITIES, OBSERVED_READ_TOOLS } from '../../capabilities/registry.js' import { exactJson, observeRead, unchangedContent } from './read-observation.js' diff --git a/src/modes/native/read-evidence.ts b/src/modes/native/read-evidence.ts index 7d3de159..a10417c3 100644 --- a/src/modes/native/read-evidence.ts +++ b/src/modes/native/read-evidence.ts @@ -1,7 +1,7 @@ -import type { Agent } from '@deepseek-ai/dsh-agent' -import type { GenerateOptions } from '@deepseek-ai/dsh-llm' -import type { Session } from '@deepseek-ai/dsh-session' -import type { ToolExecution } from '@deepseek-ai/dsh-tools' +import type { Agent } from '../../adapter/dsh/types.js' +import type { GenerateOptions } from '../../adapter/dsh/types.js' +import type { Session } from '../../adapter/dsh/types.js' +import type { ToolExecution } from '../../adapter/dsh/types.js' import { exactJson } from './read-observation.js' import type { ReadObservation } from './read-observation.js' diff --git a/src/modes/native/read-observation.ts b/src/modes/native/read-observation.ts index 3f358b3e..6d4c8152 100644 --- a/src/modes/native/read-observation.ts +++ b/src/modes/native/read-observation.ts @@ -1,6 +1,6 @@ import { lstatSync } from 'node:fs' import { isAbsolute } from 'node:path' -import type { ToolDefinition, ToolExecution, ToolExecutionResult } from '@deepseek-ai/dsh-tools' +import type { ToolDefinition, ToolExecution, ToolExecutionResult } from '../../adapter/dsh/types.js' import { publicToolName } from '../../policy.js' export interface ReadObservation { diff --git a/src/modes/ptc/canonical-schema.ts b/src/modes/ptc/canonical-schema.ts index 65c9cfbc..ca5deaf7 100644 --- a/src/modes/ptc/canonical-schema.ts +++ b/src/modes/ptc/canonical-schema.ts @@ -1,5 +1,5 @@ /** Typed fields describe canonical data, independently of the Native display projection. */ -import type { JsonSchemaNode } from '@deepseek-ai/dsh-tools' +import type { JsonSchemaNode } from '../../adapter/dsh/types.js' import { DOCUMENT_FACTS, isDocumentTool } from '../../capabilities/documents.js' import { capability } from '../../capabilities/registry.js' import type { FileToolName, PtcToolName } from '../../capabilities/registry.js' diff --git a/src/modes/ptc/schema.ts b/src/modes/ptc/schema.ts index 2767e645..2f0e9a82 100644 --- a/src/modes/ptc/schema.ts +++ b/src/modes/ptc/schema.ts @@ -1,5 +1,5 @@ /** Discriminated PTC envelopes feed the pinned host's validation and SDK generator. */ -import type { JsonSchemaNode } from '@deepseek-ai/dsh-tools' +import type { JsonSchemaNode } from '../../adapter/dsh/types.js' const string: JsonSchemaNode = { type: 'string' } const integer: JsonSchemaNode = { type: 'integer' } const object = (properties: Record, required: string[]): JsonSchemaNode => diff --git a/src/modes/registry.ts b/src/modes/registry.ts index 5eceff3e..26f6152c 100644 --- a/src/modes/registry.ts +++ b/src/modes/registry.ts @@ -5,7 +5,7 @@ * Loader rows; they share one small registry keyed by the Cordis root so each * row can see which modes are on without importing another row's module state. */ -import type { Context } from '@deepseek-ai/cordis' +import type { Context } from '../adapter/dsh/types.js' import type { ModeConfig } from './config.js' import type { ModeId } from './types.js' diff --git a/src/modes/replacements.ts b/src/modes/replacements.ts index 67567b4e..379b4928 100644 --- a/src/modes/replacements.ts +++ b/src/modes/replacements.ts @@ -6,10 +6,10 @@ * when the counterpart is missing: a session keeps the official workflow rather * than losing a capability to an unfinished publication. */ -import type { Context } from '@deepseek-ai/cordis' -import type { Agent } from '@deepseek-ai/dsh-agent' -import type { ToolGuard } from '@deepseek-ai/dsh-tools' -import type {} from '@deepseek-ai/dsh-system-prompt' +import type { Context } from '../adapter/dsh/types.js' +import type { Agent } from '../adapter/dsh/types.js' +import type { ToolGuard } from '../adapter/dsh/types.js' +import type {} from '../adapter/dsh/types.js' import { OFFICIAL_REPLACEMENTS } from '../official-tool-catalog.js' import { BASH_TOOL } from '../policy.js' import { visibleNames } from '../surface.js' diff --git a/src/official-tool-hiding.ts b/src/official-tool-hiding.ts index 522c779f..01e221c6 100644 --- a/src/official-tool-hiding.ts +++ b/src/official-tool-hiding.ts @@ -2,8 +2,8 @@ * Only explicit reviewed selections are masked. Missing selected counterparts * block the affected scope and restore its official tools until readiness returns. */ -import type { Context } from '@deepseek-ai/cordis' -import type { ToolGuard } from '@deepseek-ai/dsh-tools' +import type { Context } from './adapter/dsh/types.js' +import type { ToolGuard } from './adapter/dsh/types.js' import type { OfficialReplacement } from './official-tool-catalog.js' import { nativeProviders } from './file/result-provider.js' import { isPresentationProbe } from './presentation.js' diff --git a/src/permissions.ts b/src/permissions.ts index f9c6f22b..e3a76f55 100644 --- a/src/permissions.ts +++ b/src/permissions.ts @@ -1,5 +1,5 @@ /** Shared DSH permission vocabulary. Model inputs never select an authority mode. */ -import type { SandboxExecutionPolicy, SandboxMode } from '@deepseek-ai/dsh-sandbox' +import type { SandboxExecutionPolicy, SandboxMode } from './adapter/dsh/types.js' export type AuthorityPolicy = Pick export const MODES: readonly SandboxMode[] = ['read-only', 'workspace-write', 'danger-full-access'] diff --git a/src/presentation.ts b/src/presentation.ts index be704d6c..8e93175e 100644 --- a/src/presentation.ts +++ b/src/presentation.ts @@ -1,6 +1,6 @@ /** Inspect public presentation before publishing a replacement. Inspection is * marked by exact context identity and never becomes a provider request. */ -import type { AssembleContext, PromptAssembly, SystemPrompt } from '@deepseek-ai/dsh-system-prompt' +import type { AssembleContext, PromptAssembly, SystemPrompt } from './adapter/dsh/types.js' const probes = new WeakSet() export function isPresentationProbe(context: AssembleContext): boolean { return probes.has(context) } diff --git a/src/ptc/contract.ts b/src/ptc/contract.ts index 85e277be..20bee8d7 100644 --- a/src/ptc/contract.ts +++ b/src/ptc/contract.ts @@ -1,5 +1,5 @@ /** PTC-only typed projection over the shared capability catalogue and canonical worker. */ -import type { ToolDefinition } from '@deepseek-ai/dsh-tools' +import type { ToolDefinition } from '../adapter/dsh/types.js' import { publicToolName } from '../policy.js' import { capability, FILE_TOOLS, PTC_TOOLS } from '../capabilities/registry.js' import type { FileToolName, PtcToolName } from '../capabilities/registry.js' diff --git a/src/ptc/index.ts b/src/ptc/index.ts index 39444d10..b3fab354 100644 --- a/src/ptc/index.ts +++ b/src/ptc/index.ts @@ -1,9 +1,10 @@ /** Independent PTC SDK: scoped publication through public host APIs only. */ -import type { Context, Fiber } from '@deepseek-ai/cordis' -import type { Agent } from '@deepseek-ai/dsh-agent' -import type { ToolDefinition, ToolRunContext } from '@deepseek-ai/dsh-tools' -import type {} from '@deepseek-ai/dsh-sandbox-policy' -import type { PromptAssembly } from '@deepseek-ai/dsh-system-prompt' +import type { Context, Fiber } from '../adapter/dsh/types.js' +import type { Agent } from '../adapter/dsh/types.js' +import type { ToolDefinition, ToolRunContext } from '../adapter/dsh/types.js' +import type {} from '../adapter/dsh/types.js' +import type { PromptAssembly } from '../adapter/dsh/types.js' +import { loadScopes } from '../adapter/dsh/host.js' import { inspectPresentation, isPresentationProbe } from '../presentation.js' import { WORKER_TIMEOUT_MS } from '../worker-protocol.js' import { FILE_TOOLS, PTC_TOOLS } from '../capabilities/registry.js' @@ -308,7 +309,7 @@ export function apply(root: Context, rawConfig: unknown, gate: PtcGate = { allow // An unknown session keeps the unqualified (whole-fleet) pass. void reconcile(true, affected.size ? affected : undefined) }) - ;({ scopeChainOf } = await import('@deepseek-ai/dsh-scope')) + ;({ scopeChainOf } = await loadScopes()) if (gate.watch) ctx.effect(() => gate.watch!(() => { void reconcile(true) }), 'dsh-ops: PTC mode observer') ownership = await ownPtcScopes(ctx, () => { mutating = true diff --git a/src/ptc/invoke.ts b/src/ptc/invoke.ts index afdcd88e..85c901f5 100644 --- a/src/ptc/invoke.ts +++ b/src/ptc/invoke.ts @@ -1,5 +1,5 @@ -import type { Context } from '@deepseek-ai/cordis' -import type { ToolRunContext } from '@deepseek-ai/dsh-tools' +import type { Context } from '../adapter/dsh/types.js' +import type { ToolRunContext } from '../adapter/dsh/types.js' import { FILE_TOOLS } from '../capabilities/registry.js' import { invoke as fileInvoke } from '../file/worker.js' import { invoke } from './worker.js' diff --git a/src/ptc/ownership.ts b/src/ptc/ownership.ts index f46352ea..74391992 100644 --- a/src/ptc/ownership.ts +++ b/src/ptc/ownership.ts @@ -1,3 +1,3 @@ -import type { Context } from '@deepseek-ai/cordis' +import type { Context } from '../adapter/dsh/types.js' import { ownScopes } from '../scoped-ownership.js' export const ownPtcScopes = (ctx: Context, changed: () => void) => ownScopes(ctx, 'ptc', changed) diff --git a/src/ptc/sdk.ts b/src/ptc/sdk.ts index 9c51c2e9..9e86bff6 100644 --- a/src/ptc/sdk.ts +++ b/src/ptc/sdk.ts @@ -1,4 +1,4 @@ -import type { ToolDefinition } from '@deepseek-ai/dsh-tools' +import type { ToolDefinition } from '../adapter/dsh/types.js' import { SDK_CAPABILITIES } from '../capabilities/sdk.js' import { publicToolName } from '../policy.js' import { migrateRawNames } from '../compat/alias.js' diff --git a/src/ptc/worker.ts b/src/ptc/worker.ts index f62fb342..8933cf35 100644 --- a/src/ptc/worker.ts +++ b/src/ptc/worker.ts @@ -1,9 +1,9 @@ /** Native worker bridge. Every execution uses DSH policy, confinement and process governance. */ -import type { Context } from '@deepseek-ai/cordis' -import type { SubprocessRuntime } from '@deepseek-ai/dsh-subprocess' -import type { SandboxPolicyService } from '@deepseek-ai/dsh-sandbox-policy' -import type { ToolRunContext } from '@deepseek-ai/dsh-tools' -import type { SandboxExecutionPolicy, ConfinedArgv, RunnerFailureRule } from '@deepseek-ai/dsh-sandbox' +import type { Context } from '../adapter/dsh/types.js' +import type { SubprocessRuntime } from '../adapter/dsh/types.js' +import type { SandboxPolicyService } from '../adapter/dsh/types.js' +import type { ToolRunContext } from '../adapter/dsh/types.js' +import type { SandboxExecutionPolicy, ConfinedArgv, RunnerFailureRule } from '../adapter/dsh/types.js' import type { EffectState } from '../kernel/outcome.js' import type { WorkerInvokeConfig } from '../worker-boundary.js' import { record, errorText } from '../worker-boundary.js' diff --git a/src/scoped-ownership.ts b/src/scoped-ownership.ts index e0ebf848..e4343318 100644 --- a/src/scoped-ownership.ts +++ b/src/scoped-ownership.ts @@ -1,11 +1,11 @@ -import type { Context } from '@deepseek-ai/cordis' -import type { Agent } from '@deepseek-ai/dsh-agent' +import type { Context, Agent } from './adapter/dsh/types.js' +import { loadScopes } from './adapter/dsh/host.js' interface Row { scope?: object; changed(): void } interface State { rows: Row[]; agents: Set; publishing: number; sequence: number } const roots = new WeakMap>() /** The nearest plugin row owns the SDK; overlapping rows never double-register one layer. */ export async function ownScopes(ctx: Context, family: string, changed: () => void) { - const { scopeOf, scopeChainOf } = await import('@deepseek-ai/dsh-scope') + const { scopeOf, scopeChainOf } = await loadScopes() const key = ctx.root ?? ctx let families = roots.get(key) if (!families) { families = new Map(); roots.set(key, families) } diff --git a/src/session-shells.ts b/src/session-shells.ts index b5e0859c..93dc4657 100644 --- a/src/session-shells.ts +++ b/src/session-shells.ts @@ -1,7 +1,7 @@ /** Plugin-owned bash layers; permission changes never mutate the shared registry. */ import path from 'node:path' -import type { Context, Fiber } from '@deepseek-ai/cordis' -import type { Agent } from '@deepseek-ai/dsh-agent' +import type { Context, Fiber } from './adapter/dsh/types.js' +import type { Agent } from './adapter/dsh/types.js' import type { ResolvedConfig } from './config.js' import type { ShellResolution } from './shells/paths.js' import type { HostShellDefinition, ShellJobs, ShellResult } from './shells/types.js' diff --git a/src/settings/carrier-plan.ts b/src/settings/carrier-plan.ts index 17e19c1d..7eb419bd 100644 --- a/src/settings/carrier-plan.ts +++ b/src/settings/carrier-plan.ts @@ -7,14 +7,13 @@ import fs from 'node:fs' import path from 'node:path' import { isDeepStrictEqual } from 'node:util' -import type * as Boot from '@deepseek-ai/dsh-app-boot' +import type { AtomicApi, BootApi, ProfileContext } from '../adapter/dsh/types.js' import type * as Yaml from 'yaml' -import type * as Atomic from '@deepseek-ai/dsh-atomic-write' -import type { EntryOptions } from '@deepseek-ai/cordis-plugin-loader' +import type { EntryOptions } from '../adapter/dsh/types.js' import { COMPONENTS } from '../components/defaults.js' export const CLIENT_BUNDLE = 'dsh-ops/lib/profiles/client' -export interface CarrierHost { boot: typeof Boot; yaml: typeof Yaml; atomic: typeof Atomic } +export interface CarrierHost { boot: BootApi; yaml: typeof Yaml; atomic: AtomicApi } export interface CarrierLocation { dir: string; home: string; installAnchor: string } export interface FileChange { path: string; before?: string; after: string; mode: number } export interface CarrierPlan { files: FileChange[]; beforeRows: EntryOptions[]; afterRows: EntryOptions[]; location: CarrierLocation } @@ -33,7 +32,7 @@ function read(file: string, optional = false): { text?: string; mode: number } { } } const flatten = (rows: EntryOptions[]): EntryOptions[] => rows.flatMap(row => [row, ...row.group && Array.isArray(row.config) ? flatten(row.config as EntryOptions[]) : []]) -export function profileContext(location: CarrierLocation): Boot.ProfileContext { +export function profileContext(location: CarrierLocation): ProfileContext { return { ...location, name: path.basename(location.dir), cwd: location.dir, patchPath: path.join(location.dir, 'cordis.patch.yml'), startedBundles: [], overlays: [], telemetryDisabledEnv: process.env.DSH_TELEMETRY_DISABLED } } export function prepareCarrier(host: CarrierHost, location: CarrierLocation): CarrierPlan { diff --git a/src/settings/runtime-actions.ts b/src/settings/runtime-actions.ts index f18222d2..3d8f83c0 100644 --- a/src/settings/runtime-actions.ts +++ b/src/settings/runtime-actions.ts @@ -1,7 +1,7 @@ /** Operator runtime plans: fixed actions, one-use previews, serialized execution. */ import { randomUUID, createHash } from 'node:crypto' import path from 'node:path' -import type { TypertGatewayBinding } from '@deepseek-ai/dsh-typert-protocol' +import type { TypertGatewayBinding } from '../adapter/dsh/types.js' import { PACKAGE_ROOT } from '../paths.js' import { gitBashCandidates, managedBashInventory, removeManagedBash, selectBashRuntime } from '../shells/manager.js' import { shellUpstreamPin, provisionedShellVersionDir } from '../shells/pins.js' diff --git a/src/settings/runtime-contract.ts b/src/settings/runtime-contract.ts index 24c0cb72..c13cf918 100644 --- a/src/settings/runtime-contract.ts +++ b/src/settings/runtime-contract.ts @@ -1,5 +1,5 @@ /** Shared strict descriptors for operator-only settings actions; no host value imports. */ -import type { InvocationDescriptor, RemoteResult, TypertCodec } from '@deepseek-ai/dsh-typert-protocol' +import type { InvocationDescriptor, RemoteResult, TypertCodec } from '../adapter/dsh/types.js' export const RUNTIME_ACTIONS = ['install-bash', 'remove-bash', 'upgrade-pwsh'] as const export type RuntimeAction = typeof RUNTIME_ACTIONS[number] export type BashSource = 'managed' | 'git' diff --git a/src/settings/runtime-host.ts b/src/settings/runtime-host.ts index f936ab2a..eb2be86b 100644 --- a/src/settings/runtime-host.ts +++ b/src/settings/runtime-host.ts @@ -1,8 +1,8 @@ /** Mount only package-owned descriptors; the host gateway supplies operator admission. */ import path from 'node:path' -import type { Context } from '@deepseek-ai/cordis' -import type {} from '@deepseek-ai/dsh-typert-registry' -import type { SubprocessRuntime } from '@deepseek-ai/dsh-subprocess' +import type { Context } from '../adapter/dsh/types.js' +import type {} from '../adapter/dsh/types.js' +import type { SubprocessRuntime } from '../adapter/dsh/types.js' import { dshHome, PACKAGE_ROOT } from '../paths.js' import { RuntimeActions } from './runtime-actions.js' import type { RuntimeProcessRunner } from './runtime-actions.js' diff --git a/src/shells/execution.ts b/src/shells/execution.ts index 654f3848..621d43b1 100644 --- a/src/shells/execution.ts +++ b/src/shells/execution.ts @@ -1,6 +1,6 @@ /** Live Bash command over the host subprocess service; no service registration. */ import { Buffer } from 'node:buffer' -import type { SubprocessHandle, SubprocessOutputReader, SubprocessOutputRead } from '@deepseek-ai/dsh-subprocess' +import type { SubprocessHandle, SubprocessOutputReader, SubprocessOutputRead } from '../adapter/dsh/types.js' import type { ShellExecutorOptions, ShellExecutionSpec, ShellCall, ShellExecution, ShellResult, ShellStream } from './types.js' import { DEFAULT_MAX_OUTPUT_BYTES, DEFAULT_MAX_SPILL_BYTES, shellEnvOverrides } from './constants.js' import { formatBashSpawnError } from './spawn-error.js' diff --git a/src/shells/host-contract.ts b/src/shells/host-contract.ts index eab11561..90aea0a7 100644 --- a/src/shells/host-contract.ts +++ b/src/shells/host-contract.ts @@ -1,6 +1,6 @@ // Adapted from @deepseek-ai/dsh-tool-bash 0.2.0-rc.2 (MIT). See licenses/deepseek-harness/LICENSE. /** DSH 0.2.0-rc.2 shell DTO and rendering, with explicit OPS compatibility fields. */ -import type { JsonSchemaNode, JsonSchemaType } from '@deepseek-ai/dsh-tools' +import type { JsonSchemaNode, JsonSchemaType } from '../adapter/dsh/types.js' import type { ShellResult, HostForeground, HostBashResult } from './types.js' import { bashFailure } from './failure.js' import { BASH_OUTPUT_SCHEMA, renderBashResult, withBashStatus } from './tool.js' diff --git a/src/shells/host-tool.ts b/src/shells/host-tool.ts index f5b62c3e..e3e756c6 100644 --- a/src/shells/host-tool.ts +++ b/src/shells/host-tool.ts @@ -1,7 +1,7 @@ // Adapted from @deepseek-ai/dsh-tool-bash 0.2.0-rc.2 (MIT). See licenses/deepseek-harness/LICENSE. /** Host-compatible consumer over an OPS-owned executor; host services stay scoped and borrowed. */ -import type { ToolDefinition } from '@deepseek-ai/dsh-tools' -import type { JsonSchemaNode } from '@deepseek-ai/dsh-tools' +import type { ToolDefinition } from '../adapter/dsh/types.js' +import type { JsonSchemaNode } from '../adapter/dsh/types.js' import type { ShellContext, ShellBase, ShellCall, ShellPolicy, CreateShellExecution, StartShell, ShellExecution, ShellJobs, HostBashResult, HostShellDefinition } from './types.js' import { errorMessage } from './types.js' import { BashArgumentError, isBashArgumentError } from './argument-error.js' diff --git a/src/shells/json-digest.ts b/src/shells/json-digest.ts index 9851cd90..2d978d2f 100644 --- a/src/shells/json-digest.ts +++ b/src/shells/json-digest.ts @@ -2,7 +2,7 @@ import { constants } from 'node:fs' import { lstat, open } from 'node:fs/promises' import path from 'node:path' -import type { ToolDefinition, ToolExecutionToken } from '@deepseek-ai/dsh-tools' +import type { ToolDefinition, ToolExecutionToken } from '../adapter/dsh/types.js' import type { HostBashResult, ShellCall } from './types.js' import { renderHostBash } from './host-contract.js' diff --git a/src/shells/presentation.ts b/src/shells/presentation.ts index 050cdd96..c85b6a1d 100644 --- a/src/shells/presentation.ts +++ b/src/shells/presentation.ts @@ -1,5 +1,5 @@ /** Pure, replayable shell cards through the host's public presentation contract. */ -import type { ToolDefinition } from '@deepseek-ai/dsh-tools' +import type { ToolDefinition } from '../adapter/dsh/types.js' const record = (value: unknown): value is Record => value !== null && typeof value === 'object' && !Array.isArray(value) diff --git a/src/shells/publish.ts b/src/shells/publish.ts index 2b598d2c..99e1ef90 100644 --- a/src/shells/publish.ts +++ b/src/shells/publish.ts @@ -22,7 +22,7 @@ * @module dsh-ops/shells/publish */ -import type { Context } from '@deepseek-ai/cordis' +import type { Context } from '../adapter/dsh/types.js' import type { ResolvedConfig } from '../config.js' import type { ShellResolution } from './paths.js' import { errorMessage } from './types.js' diff --git a/src/shells/session-execution.ts b/src/shells/session-execution.ts index 3a28b88d..12a3f77c 100644 --- a/src/shells/session-execution.ts +++ b/src/shells/session-execution.ts @@ -1,6 +1,6 @@ /** Resolve and confine every invocation using the current session authority. */ import path from 'node:path' -import type { ConfinedArgv } from '@deepseek-ai/dsh-sandbox' +import type { ConfinedArgv } from '../adapter/dsh/types.js' import type { ShellContext, ShellCall, ShellPolicy, ExecutionOptions, ShellExecution, ShellResult } from './types.js' import { bashToolDefinition, withBashStatus } from './tool.js' import { confinedBash } from '../bash-ipc.js' diff --git a/src/shells/tool.ts b/src/shells/tool.ts index 4fe4b812..48de92e3 100644 --- a/src/shells/tool.ts +++ b/src/shells/tool.ts @@ -14,7 +14,7 @@ */ import fs from 'node:fs' -import type { JsonSchemaNode } from '@deepseek-ai/dsh-tools' +import type { JsonSchemaNode } from '../adapter/dsh/types.js' import type { ShellStream, ShellResult, SettledShellResult, ShellExecutorOptions, LegacyShellDefinition } from './types.js' import { BASH_ARGUMENTS, diff --git a/src/shells/types.ts b/src/shells/types.ts index 4bb1275e..12896391 100644 --- a/src/shells/types.ts +++ b/src/shells/types.ts @@ -1,10 +1,10 @@ /** Typed OPS shell boundary; host classes are borrowed through services, never imported as values. */ import type { OpsErrorPayload } from '../kernel/outcome.js' -import type { ToolDefinition, ToolRunContext } from '@deepseek-ai/dsh-tools' -import type { JsonSchemaNode } from '@deepseek-ai/dsh-tools' -import type { SandboxExecutionPolicy, SandboxProvider } from '@deepseek-ai/dsh-sandbox' -import type { SandboxPolicyService } from '@deepseek-ai/dsh-sandbox-policy' -import type { SubprocessRuntime, SubprocessOutputReader } from '@deepseek-ai/dsh-subprocess' +import type { ToolDefinition, ToolRunContext } from '../adapter/dsh/types.js' +import type { JsonSchemaNode } from '../adapter/dsh/types.js' +import type { SandboxExecutionPolicy, SandboxProvider } from '../adapter/dsh/types.js' +import type { SandboxPolicyService } from '../adapter/dsh/types.js' +import type { SubprocessRuntime, SubprocessOutputReader } from '../adapter/dsh/types.js' export type ShellCall = Partial> export type ShellPolicy = SandboxExecutionPolicy diff --git a/src/surface.ts b/src/surface.ts index cc6a2734..b6c0770e 100644 --- a/src/surface.ts +++ b/src/surface.ts @@ -1,6 +1,6 @@ /** The tool surface a presentation probe reads, shared by both PTC rows. */ -import type { Agent } from '@deepseek-ai/dsh-agent' -import type ToolRuntime from '@deepseek-ai/dsh-tools' +import type { Agent } from './adapter/dsh/types.js' +import type { ToolRuntime } from './adapter/dsh/types.js' /** * The part of a scope view this module reads: the names and definitions a scope can see. diff --git a/src/tool-changes.ts b/src/tool-changes.ts index 4b207fd7..aba2a3ab 100644 --- a/src/tool-changes.ts +++ b/src/tool-changes.ts @@ -1,5 +1,5 @@ /** One-shot attribution captured at dispatch entry, before arbitrary event listeners run. */ -import type { Context } from '@deepseek-ai/cordis' +import type { Context } from './adapter/dsh/types.js' interface Attribution { scopes: readonly object[]; consumed: boolean } let changing: Attribution | undefined const dispatches = new WeakMap() diff --git a/src/workspace-preparation.ts b/src/workspace-preparation.ts index dfe3f5ff..315464d5 100644 --- a/src/workspace-preparation.ts +++ b/src/workspace-preparation.ts @@ -3,8 +3,8 @@ * directory-only WRITE_OWNER. The DSH provider still owns confinement/grants. */ import fs from 'node:fs' -import type { Context } from '@deepseek-ai/cordis' -import type { SandboxExecutionPolicy } from '@deepseek-ai/dsh-sandbox' +import type { Context } from './adapter/dsh/types.js' +import type { SandboxExecutionPolicy } from './adapter/dsh/types.js' import type { SpawnOptionsWithStdioTuple, StdioNull, StdioPipe } from 'node:child_process' import os from 'node:os' import path from 'node:path' diff --git a/test/adapter-boundary.test.mjs b/test/adapter-boundary.test.mjs new file mode 100644 index 00000000..c50ef51c --- /dev/null +++ b/test/adapter-boundary.test.mjs @@ -0,0 +1,32 @@ +import fs from 'node:fs' +import path from 'node:path' +import { assert, test, report, PACKAGE_ROOT } from './lib/harness.mjs' + +const source = path.join(PACKAGE_ROOT, 'src') +const adapter = path.join(source, 'adapter', 'dsh') + +await test('all host-facing DSH imports converge through the project adapter', () => { + const offenders = [] + const upstream = /^\s*(?:import|export)\s+(?:type\s+)?(?:[^;]*?\s+from\s+)?(['"])(@deepseek-ai\/[^'"]+)\1|^\s*import\s*\(\s*(['"])(@deepseek-ai\/[^'"]+)\3\s*\)/gmu + function visit(directory) { + for (const entry of fs.readdirSync(directory, { withFileTypes: true })) { + const file = path.join(directory, entry.name) + if (entry.isDirectory()) visit(file) + else if (/\.(?:ts|tsx)$/u.test(entry.name) && path.resolve(file) !== path.resolve(path.join(adapter, 'types.ts')) && path.resolve(file) !== path.resolve(path.join(adapter, 'host.ts'))) { + const text = fs.readFileSync(file, 'utf8') + for (const match of text.matchAll(upstream)) offenders.push(`${path.relative(PACKAGE_ROOT, file)} -> ${match[2]}`) + } + } + } + visit(source) + assert.deepEqual(offenders, [], `upstream imports escaped the adapter:\n${offenders.join('\n')}`) +}) + +await test('the adapter keeps scope discovery lazy', () => { + const text = fs.readFileSync(path.join(adapter, 'host.ts'), 'utf8') + assert.match(text, /async function loadScopes/u) + assert.match(text, /return import\('@deepseek-ai\/dsh-scope'\)/u) + assert.doesNotMatch(text, /^import .*dsh-scope/m) +}) + +report('adapter-boundary') diff --git a/test/host-metadata.test.mjs b/test/host-metadata.test.mjs index ef16580d..47173249 100644 --- a/test/host-metadata.test.mjs +++ b/test/host-metadata.test.mjs @@ -24,8 +24,8 @@ await test(`explicit host compatibility is consistent and bounded (${boot.getDsh // read peers, newer hosts prefer engines, so test both independently. for (const range of [pkg.engines.dsh, pkg.peerDependencies['@deepseek-ai/dsh']]) { const candidate = { name: pkg.name, version: pkg.version, engines: { dsh: range }, peerDependencies: { '@deepseek-ai/dsh': range } } - for (const version of ['0.2.0-rc.2', '0.2.1-rc.2']) assert.equal(boot.evaluatePluginCompatibility(candidate, {}, version), undefined) - for (const version of ['0.2.0-rc.1', '0.2.1-rc.3', '0.3.0']) assert.ok(boot.evaluatePluginCompatibility(candidate, {}, version), `must not claim ${version}`) + for (const version of ['0.2.0-rc.2', '0.2.1-rc.2', '0.2.1-rc.3', '0.2.1-rc.4']) assert.equal(boot.evaluatePluginCompatibility(candidate, {}, version), undefined) + for (const version of ['0.2.0-rc.1', '0.2.2-rc.1', '0.3.0']) assert.ok(boot.evaluatePluginCompatibility(candidate, {}, version), `must not claim ${version}`) } }) diff --git a/test/package-source.test.mjs b/test/package-source.test.mjs index 0ab86f02..6e3c4fb8 100644 --- a/test/package-source.test.mjs +++ b/test/package-source.test.mjs @@ -33,6 +33,7 @@ await test('npm pack includes compiled host code and native sources, never host 'native/crates/ops-documents/src/pdf_container.rs', 'native/crates/ops-documents/src/pdf_container_tests.rs', 'licenses/documents/THIRD-PARTY-NOTICES.txt'] for (const name of required) assert.ok(files.includes(name), `missing source-build dependency: ${name}`) + for (const name of ['lib/adapter/dsh/host.js', 'lib/adapter/dsh/types.js']) assert.ok(files.includes(name), `adapter resource missing: ${name}`) assert.equal(files.some(name => name.startsWith('src/')), false, 'host source must not ship beside compiled lib/') assert.equal(files.some(name => /^native\/(?:target[^/]*|(?:windows|darwin)-metadata\/target)\//u.test(name)), false) const pending = ['native/Cargo.toml'], visited = new Set()