diff --git a/packages/session-title/session-title/package.json b/packages/session-title/session-title/package.json index 7377c6b25a..7f114b386f 100644 --- a/packages/session-title/session-title/package.json +++ b/packages/session-title/session-title/package.json @@ -15,9 +15,13 @@ "types": "./lib/types/invariant.d.ts", "default": "./lib/invariant.js" }, + "./types": { + "types": "./lib/types/types.d.ts", + "default": "./lib/types/types.js" + }, "./client/types": { - "types": "./lib/types/client/types.d.ts", - "default": "./lib/types/client/types.js" + "types": "./lib/types/client/index.d.ts", + "default": "./lib/types/client/index.js" }, "./src/*": "./src/*", "./package.json": "./package.json" diff --git a/packages/session-title/session-title/src/client/index.ts b/packages/session-title/session-title/src/client/index.ts new file mode 100644 index 0000000000..019626d044 --- /dev/null +++ b/packages/session-title/session-title/src/client/index.ts @@ -0,0 +1,10 @@ +/** + * Browser half-entry of the title domain: a pure re-export of the package's + * types outlet. Client code imports ONLY the client namespace (repo + * discipline), so `./client/types` projects the same single-source content + * `./types` serves to host consumers — zero duplication. + * + * @module @deepseek-ai/dsh-session-title/client/types + */ + +export type * from '../types.ts' diff --git a/packages/session-title/session-title/src/index.ts b/packages/session-title/session-title/src/index.ts index ea5020b1a2..a9a7fa3d03 100644 --- a/packages/session-title/session-title/src/index.ts +++ b/packages/session-title/session-title/src/index.ts @@ -17,12 +17,11 @@ import type { } from '@deepseek-ai/dsh-session' // Type-only: resolves ctx.sessionProjections for the optional unit child. import type {} from '@deepseek-ai/dsh-session-projection' -// The `title` projection-key declaration lives in the client outlet (its one -// home). A PLAIN side-effect import, not `import type`: declaration emit -// elides type-only imports, and the aggregate programs resolve this package -// through its emitted declarations — the merge must survive in index.d.ts. -// The imported module is types-only, so the runtime edge is an empty module. -import './client/types.ts' +// The `title` projection-key declaration lives in src/types.ts (its one home); +// this re-export projects the type face onto the package root AND keeps the +// module edge in the emitted index.d.ts, so aggregate programs consuming the +// declarations still receive the SessionProjectionMap merge. +export type * from './types.ts' import { fallbackSessionTitle, normalizeSessionTitle } from './normalize.ts' export { fallbackSessionTitle, normalizeSessionTitle, truncateTitleUtf8 } from './normalize.ts' diff --git a/packages/session-title/session-title/src/client/types.ts b/packages/session-title/session-title/src/types.ts similarity index 53% rename from packages/session-title/session-title/src/client/types.ts rename to packages/session-title/session-title/src/types.ts index 62ca756fff..76b27dc9b1 100644 --- a/packages/session-title/session-title/src/client/types.ts +++ b/packages/session-title/session-title/src/types.ts @@ -1,12 +1,11 @@ /** - * Pure-type client outlet of the title domain: the ONE home of the `title` - * projection-key declaration, importable from client aggregates without - * dragging this package's host-side value imports (cordis service, - * schemastery, the llm seam). The host entry (`index.ts`) imports this module - * type-only to reuse the same merge — one declaration serves both program - * sides. + * Pure types of the title domain: the ONE home of the `title` projection-key + * declaration, free of this package's host-side value imports (cordis + * service, schemastery, the llm seam). Two namespace projections serve it — + * `./types` for host consumers, `./client/types` (the browser half-entry's + * re-export) for client aggregates — with zero content duplication. * - * @module @deepseek-ai/dsh-session-title/client/types + * @module @deepseek-ai/dsh-session-title/types */ // Marks this file a module so the declaration below AUGMENTS the projection diff --git a/packages/todo/tool-todo/package.json b/packages/todo/tool-todo/package.json index 8c6d9b1a1b..1c228b15ec 100644 --- a/packages/todo/tool-todo/package.json +++ b/packages/todo/tool-todo/package.json @@ -15,9 +15,13 @@ "types": "./lib/types/invariant.d.ts", "default": "./lib/invariant.js" }, + "./types": { + "types": "./lib/types/types.d.ts", + "default": "./lib/types/types.js" + }, "./client/types": { - "types": "./lib/types/client/types.d.ts", - "default": "./lib/types/client/types.js" + "types": "./lib/types/client/index.d.ts", + "default": "./lib/types/client/index.js" }, "./src/*": "./src/*", "./package.json": "./package.json" diff --git a/packages/todo/tool-todo/src/client/index.ts b/packages/todo/tool-todo/src/client/index.ts new file mode 100644 index 0000000000..9875a234d8 --- /dev/null +++ b/packages/todo/tool-todo/src/client/index.ts @@ -0,0 +1,10 @@ +/** + * Browser half-entry of the todo domain: a pure re-export of the package's + * types outlet. Client code imports ONLY the client namespace (repo + * discipline), so `./client/types` projects the same single-source content + * `./types` serves to host consumers — zero duplication. + * + * @module @deepseek-ai/dsh-tool-todo/client/types + */ + +export type * from '../types.ts' diff --git a/packages/todo/tool-todo/src/index.ts b/packages/todo/tool-todo/src/index.ts index 68bab005c5..4bda32c30b 100644 --- a/packages/todo/tool-todo/src/index.ts +++ b/packages/todo/tool-todo/src/index.ts @@ -12,12 +12,11 @@ import { defineTool } from '@deepseek-ai/dsh-tools' import type { TodoItem } from '@deepseek-ai/dsh-session' // Type-only: resolves ctx.sessionProjections for the optional unit child. import type {} from '@deepseek-ai/dsh-session-projection' -// The `todos` projection-key declaration lives in the client outlet (its one -// home). A PLAIN side-effect import, not `import type`: declaration emit -// elides type-only imports, and the aggregate programs resolve this package -// through its emitted declarations — the merge must survive in index.d.ts. -// The imported module is types-only, so the runtime edge is an empty module. -import './client/types.ts' +// The `todos` projection-key declaration lives in src/types.ts (its one home); +// this re-export projects the type face onto the package root AND keeps the +// module edge in the emitted index.d.ts, so aggregate programs consuming the +// declarations still receive the SessionProjectionMap merge. +export type * from './types.ts' export const name = 'tool-todo' export const inject = ['tools'] diff --git a/packages/todo/tool-todo/src/client/types.ts b/packages/todo/tool-todo/src/types.ts similarity index 55% rename from packages/todo/tool-todo/src/client/types.ts rename to packages/todo/tool-todo/src/types.ts index 192f0a3adc..fe37e65d55 100644 --- a/packages/todo/tool-todo/src/client/types.ts +++ b/packages/todo/tool-todo/src/types.ts @@ -1,11 +1,11 @@ /** - * Pure-type client outlet of the todo domain: the ONE home of the `todos` - * projection-key declaration, importable from client aggregates without - * dragging this package's host-side value imports (dsh-tools, zod). The host - * entry (`index.ts`) imports this module type-only to reuse the same merge — - * one declaration serves both program sides. + * Pure types of the todo domain: the ONE home of the `todos` projection-key + * declaration plus its payload types, free of this package's host-side value + * imports (dsh-tools, zod). Two namespace projections serve it — `./types` + * for host consumers, `./client/types` (the browser half-entry's re-export) + * for client aggregates — with zero content duplication. * - * @module @deepseek-ai/dsh-tool-todo/client/types + * @module @deepseek-ai/dsh-tool-todo/types */ import type { TodoItem } from '@deepseek-ai/dsh-session/types' diff --git a/tsconfig.base.json b/tsconfig.base.json index 9325c5af4e..8dc1726aaa 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -42,8 +42,10 @@ "@deepseek-ai/dsh-session/types": ["./packages/core/session/src/types.ts"], "@deepseek-ai/dsh-session/surface": ["./packages/core/session/src/surface.ts"], "@deepseek-ai/dsh-session-projection/types": ["./packages/session-projection/session-projection/src/types.ts"], - "@deepseek-ai/dsh-tool-todo/client/types": ["./packages/todo/tool-todo/src/client/types.ts"], - "@deepseek-ai/dsh-session-title/client/types": ["./packages/session-title/session-title/src/client/types.ts"], + "@deepseek-ai/dsh-tool-todo/types": ["./packages/todo/tool-todo/src/types.ts"], + "@deepseek-ai/dsh-tool-todo/client/types": ["./packages/todo/tool-todo/src/client/index.ts"], + "@deepseek-ai/dsh-session-title/types": ["./packages/session-title/session-title/src/types.ts"], + "@deepseek-ai/dsh-session-title/client/types": ["./packages/session-title/session-title/src/client/index.ts"], "@deepseek-ai/dsh-llm/types": ["./packages/llm/llm/src/types.ts"], "@deepseek-ai/dsh-llm/brand": ["./packages/llm/llm/src/brand.ts"], "@deepseek-ai/dsh-tools/presentation": ["./packages/core/tools/src/presentation.ts"],