Merge remote-tracking branch 'origin/master' into worktree/python-pypi-release-prep

This commit is contained in:
Yichen Jiang
2026-08-11 22:08:54 +08:00
350 changed files with 15072 additions and 819 deletions
+1 -1
View File
@@ -7,5 +7,5 @@
"docs/testing.md": 1150,
"examples/AGENTS.md": 310,
"packages/AGENTS.md": 675,
"packages/README.md": 980
"packages/README.md": 994
}
+1
View File
@@ -40,6 +40,7 @@ const LINK_MAP: Record<string, string> = {
CallId: 'core.md',
ContentBlock: 'core.md',
MessageSource: 'core.md',
ScheduleChange: 'schedule.md',
StreamChunk: 'llm-streaming.md',
TokenUsage: 'llm-streaming.md',
TodoItem: 'session.md',
+27 -2
View File
@@ -50,6 +50,7 @@ import * as ToolStrReplaceEditor from '@deepseek-ai/dsh-tool-str-replace-editor'
import PtyService from '@deepseek-ai/dsh-pty'
import * as ToolPty from '@deepseek-ai/dsh-tool-pty'
import * as ToolGoal from '@deepseek-ai/dsh-tool-goal'
import * as ToolSchedule from '@deepseek-ai/dsh-tool-schedule'
import Lsp from '@deepseek-ai/dsh-lsp'
import * as ToolLsp from '@deepseek-ai/dsh-tool-lsp'
import * as ToolSkill from '@deepseek-ai/dsh-tool-skill'
@@ -114,15 +115,18 @@ const catalogChildScopes = new WeakMap<Context, Agent>()
* schema harvest, without starting a model, Agent loop, or persistence backend.
* @param ctx - catalog context owning the scope.
* @param mountScoped - package installer for the scoped context.
* @param key - agent-like scope key exposed to the package's scope selector.
* @param inject - services the package installer must await before mounting.
*/
async function mountCatalogChildScope(
ctx: Context,
mountScoped: (childCtx: Context) => void,
key: Agent = { id: SessionId('tool-catalog-child') } as Agent,
inject: string[] = ['tools', 'systemPrompt', 'subagents'],
): Promise<void> {
const key = { id: SessionId('tool-catalog-child') } as Agent
await ctx.plugin(Object.assign((inner: Context) => {
mountScoped(createScope(inner, key).ctx)
}, { inject: ['tools', 'systemPrompt', 'subagents'] }))
}, { inject }))
catalogChildScopes.set(ctx, key)
}
@@ -348,6 +352,27 @@ const TOOL_PACKAGES: ToolPackage[] = [
note:
'create, edit, pause, and resume require direct-human root authority; complete and blocked also accept the exact current goal round. The default blocked lower bound is three admitted rounds.',
},
{
pkg: '@deepseek-ai/dsh-tool-schedule',
dir: 'tool-schedule',
source: 'packages/schedule/tool-schedule/src/tools.ts',
requires: ['ctx.tools', 'ctx.sessions', 'Session persistence', 'a future live root Agent'],
writes: ['tool/call', 'schedule/change create or delete', 'tool/result'],
async mount(ctx) {
await ctx.plugin(SessionStore)
const session = ctx.sessions.create(SessionId('tool-catalog-schedule'))
const agent = { id: session.id, session } as Agent
await mountCatalogChildScope(ctx, (childCtx) => {
ToolSchedule.registerScheduleTools(ctx, childCtx, agent, () => {})
}, agent, ['tools', 'systemPrompt'])
},
scope: ctx => catalogChildScopes.get(ctx) as Agent,
note:
'Registered only inside live root Agent scopes created after the opt-in Schedule plugin loads. '
+ 'Version 1 accepts after_seconds, explicit absolute at, and bounded fixed-rate every_seconds, '
+ 'and discloses session-local delivery; '
+ 'management reads and mutations require the shared Session persistence barrier.',
},
{
pkg: '@deepseek-ai/dsh-tool-lsp',
dir: 'tool-lsp',
+1 -1
View File
@@ -307,7 +307,7 @@ describe('docsPages locale routes', () => {
const translated = rootPages.filter(page => page.contentLocale === 'zh-CN')
const fallbacks = rootPages.filter(page => page.contentLocale === 'en-US')
expect(translated).toHaveLength(42)
expect(translated).toHaveLength(43)
expect(translated.every(page => page.source.endsWith('.zh.md'))).toBe(true)
expect(fallbacks).toEqual([])
})
+80
View File
@@ -221,6 +221,86 @@
"symbol": "GoalChanged",
"source": "packages/goal/goal/src/domain.ts"
},
{
"doc": "docs/subsystems/schedule.md",
"symbol": "AfterScheduleRecord",
"source": "packages/schedule/tool-schedule/src/types.ts"
},
{
"doc": "docs/subsystems/schedule.md",
"symbol": "AtScheduleRecord",
"source": "packages/schedule/tool-schedule/src/types.ts"
},
{
"doc": "docs/subsystems/schedule.md",
"symbol": "EveryScheduleRecord",
"source": "packages/schedule/tool-schedule/src/types.ts"
},
{
"doc": "docs/subsystems/schedule.md",
"symbol": "LocalAtInput",
"source": "packages/schedule/tool-schedule/src/types.ts"
},
{
"doc": "docs/subsystems/schedule.md",
"symbol": "AtInput",
"source": "packages/schedule/tool-schedule/src/types.ts"
},
{
"doc": "docs/subsystems/schedule.md",
"symbol": "OneShotScheduleRecord",
"source": "packages/schedule/tool-schedule/src/types.ts"
},
{
"doc": "docs/subsystems/schedule.md",
"symbol": "ScheduleRecord",
"source": "packages/schedule/tool-schedule/src/types.ts"
},
{
"doc": "docs/subsystems/schedule.md",
"symbol": "ScheduleCreateChange",
"source": "packages/schedule/tool-schedule/src/types.ts"
},
{
"doc": "docs/subsystems/schedule.md",
"symbol": "ScheduleDeleteChange",
"source": "packages/schedule/tool-schedule/src/types.ts"
},
{
"doc": "docs/subsystems/schedule.md",
"symbol": "OneShotScheduleDispatchChange",
"source": "packages/schedule/tool-schedule/src/types.ts"
},
{
"doc": "docs/subsystems/schedule.md",
"symbol": "EveryScheduleDispatchChange",
"source": "packages/schedule/tool-schedule/src/types.ts"
},
{
"doc": "docs/subsystems/schedule.md",
"symbol": "ScheduleDispatchChange",
"source": "packages/schedule/tool-schedule/src/types.ts"
},
{
"doc": "docs/subsystems/schedule.md",
"symbol": "ScheduleChange",
"source": "packages/schedule/tool-schedule/src/types.ts"
},
{
"doc": "docs/subsystems/schedule.md",
"symbol": "ScheduleState",
"source": "packages/schedule/tool-schedule/src/types.ts"
},
{
"doc": "docs/subsystems/schedule.md",
"symbol": "ScheduleDeliveryMode",
"source": "packages/schedule/tool-schedule/src/types.ts"
},
{
"doc": "docs/subsystems/schedule.md",
"symbol": "ScheduleView",
"source": "packages/schedule/tool-schedule/src/types.ts"
},
{
"doc": "docs/subsystems/commands.md",
"symbol": "CommandInputDescriptor",
+31
View File
@@ -33,6 +33,7 @@ const root = resolve(import.meta.dirname, '..')
// specifiers resolve from apps/cli rather than the examples workspace.
const appOverlayFiles = new Set([
'examples/web-cordis/cordis.yml',
'examples/web-schedule/cordis.yml',
...globSync('examples/mcp-memory/*.cordis.yml', { cwd: root }),
])
const metadataFields = ['id', 'name', 'group', 'disabled', 'inject', 'intercept', 'isolate'] as const
@@ -79,6 +80,7 @@ errors.push(...validateExampleResolution())
errors.push(...validateAppResolution())
errors.push(...validateSourcePlaneResolution())
errors.push(...validatePresetPlaneSeparation())
errors.push(...validateClientHalvesDeclared())
if (errors.length > 0) {
console.error('verify-cordis-config: invalid Loader metadata or plugin package resolution:')
@@ -88,6 +90,35 @@ if (errors.length > 0) {
console.log(`verify-cordis-config: ${files.length} config files passed.`)
}
/**
* A browser plugin must declare the browser half it ships.
*
* The browser roster is discovered by scanning composed packages for a
* `dsh.client` block, and the node half of a surface plugin is an empty
* `apply`. A `packages/client` package that exports `./client` without that
* block therefore composes, activates, and contributes nothing — its bundle is
* never served and no error is raised anywhere. The mismatch is invisible in
* the composition file, so it is checked against the manifests instead. Only
* this group is checked: a Host package's `./client` export is the typed wire
* face its browser consumers import, not a plugin the roster serves.
* @returns one violation per client package whose `./client` export and
* `dsh.client` declaration disagree.
*/
function validateClientHalvesDeclared(): string[] {
return globSync('packages/client/*/package.json', { cwd: root }).flatMap((manifestPath) => {
const manifest = readManifest(manifestPath) as PackageManifest & {
exports?: Record<string, unknown>
dsh?: { client?: unknown }
}
const shipsClient = manifest.exports !== undefined && Object.hasOwn(manifest.exports, './client')
const declaresClient = manifest.dsh?.client !== undefined
if (shipsClient === declaresClient) return []
return [shipsClient
? `${manifestPath}: exports "./client" but declares no dsh.client, so its browser half is never served`
: `${manifestPath}: declares dsh.client but exports no "./client" entry to serve`]
})
}
/**
* No shipped agent preset may repeat a row the host composition still runs.
*
+3 -1
View File
@@ -84,7 +84,9 @@ const mermaid = (await import('mermaid')).default
// maxEdges: mermaid's default 500-edge render guard; the module graph grows
// with every package edge and crossed it legitimately. Raise the guard here
// (a secure config settable only via initialize) rather than trimming edges.
mermaid.initialize({ startOnLoad: false, maxEdges: 1000 })
// The graph passed 1000 the same way it passed 500, so the headroom doubles
// again rather than being set to whatever the current count happens to be.
mermaid.initialize({ startOnLoad: false, maxEdges: 2000 })
for (const block of blocks) {
try {
await mermaid.parse(block.source, { suppressErrors: false })
@@ -80,6 +80,7 @@ const SENTENCE_MODEL_EXPERIENCE: Readonly<Record<string, SentenceContract>> = {
'packages/client/ui-model': { kind: 'indirect', reason: 'Selection routes session.selectModel; the Host snapshots the selection at the next prompt-assembly boundary and owns the model-visible effect.' },
'packages/client/ui-goal': { kind: 'indirect', reason: 'The strip verbs route goal.* mutations; the host GoalService owns the model-visible goal/change context message.' },
'packages/client/ui-permission': { kind: 'indirect', reason: 'The picker submits the host /permission command; the knob events it appends own the model-visible effect through the sandbox/approval consumers.' },
'packages/client/ui-plugin-config': { kind: 'none', reason: 'Browser-side settings surface; registers no model surface.' },
'packages/client/ui-plan': { kind: 'indirect', reason: 'The chip dispatches /plan off; dsh-plan-mode owns the model-visible policy, exit tool, and logged state.' },
'packages/client/ui-question': { kind: 'indirect', reason: 'The package mounts dsh-tool-ask-user; that tool owns the model-visible schema and answer rendering.' },
'packages/client/ui-trajectory': { kind: 'none', reason: 'Browser-side UI plugin layer; registers nothing model-facing.' },
@@ -126,7 +127,7 @@ const SENTENCE_MODEL_EXPERIENCE: Readonly<Record<string, SentenceContract>> = {
'packages/util/atomic-write': { kind: 'none', reason: 'Pure filesystem write primitive; registers nothing model-facing.' },
'packages/session/session-telemetry': { kind: 'none', reason: 'The seam observes the session stream and hands redacted copies outward; it registers nothing model-facing.' },
'packages/session/session-telemetry-otel': { kind: 'none', reason: 'The backend forwards seam records into the OTel SDK pipeline and registers nothing model-facing.' },
'packages/session/user-id': { kind: 'none', reason: 'The shared identifier appears only in telemetry metadata and a direct human command response; it registers nothing model-facing.' },
'packages/session/user-id': { kind: 'none', reason: 'The shared identifier reaches DeepSeek only as model-hidden HTTP metadata; it registers nothing model-facing.' },
'packages/skill/skill': { kind: 'indirect', reason: 'The provider registry delegates model rendering to dsh-tool-skill.' },
'packages/skill/skill-badge': { kind: 'indirect', reason: 'The bundled provider delegates model rendering to dsh-tool-skill.' },
'packages/skill/skill-local': { kind: 'indirect', reason: 'The provider backend delegates model rendering to dsh-tool-skill.' },