Merge remote-tracking branch 'origin/master' into workflow-vm-to-workerthread
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"AGENTS.md": 1690,
|
||||
"AGENTS.md": 1691,
|
||||
"docs/AGENTS.md": 1315,
|
||||
"docs/architecture.md": 1630,
|
||||
"docs/architecture.md": 1640,
|
||||
"docs/cordis-primer.md": 550,
|
||||
"docs/defensive-patterns.md": 550,
|
||||
"docs/testing.md": 800,
|
||||
"examples/AGENTS.md": 610,
|
||||
"packages/AGENTS.md": 450,
|
||||
"packages/README.md": 605
|
||||
"packages/README.md": 610
|
||||
}
|
||||
|
||||
@@ -25,9 +25,8 @@
|
||||
*/
|
||||
|
||||
import { execFileSync } from 'node:child_process'
|
||||
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
|
||||
import { globSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
|
||||
import { join, relative, resolve } from 'node:path'
|
||||
import { glob } from 'node:fs/promises'
|
||||
import ts from 'typescript'
|
||||
|
||||
const root = resolve(import.meta.dirname, '..')
|
||||
@@ -139,7 +138,7 @@ const markdownGlobs = ['README.md', 'docs/**/*.md', 'packages/*/*.md', 'packages
|
||||
|
||||
const files: string[] = []
|
||||
for (const pattern of markdownGlobs) {
|
||||
for await (const match of glob(pattern, { cwd: root })) files.push(resolve(root, match))
|
||||
for (const match of globSync(pattern, { cwd: root })) files.push(resolve(root, match))
|
||||
}
|
||||
files.sort()
|
||||
|
||||
|
||||
@@ -97,6 +97,8 @@ export const LINK_MAP: Record<string, string> = {
|
||||
BashRunResult: 'bash.md',
|
||||
BashTask: 'bash.md',
|
||||
BashTaskRead: 'bash.md',
|
||||
CodeRunRequest: 'code-runtime.md',
|
||||
CodeRunResult: 'code-runtime.md',
|
||||
FsEditOutcome: 'filesystem.md',
|
||||
FsEditRequest: 'filesystem.md',
|
||||
FsInfo: 'filesystem.md',
|
||||
|
||||
@@ -121,9 +121,18 @@ const SERVICE_ROLES: ServiceRole[] = [
|
||||
pkg: 'tools',
|
||||
title: 'Tool registry and execution waterfall',
|
||||
mode: 'core',
|
||||
consumers: ['agent-loop', 'tool-bash', 'tool-fs', 'tool-subagent', 'tool-todo', 'tool-web', 'acp'],
|
||||
consumers: ['agent-loop', 'tool-ask-user', 'tool-bash', 'tool-fs', 'tool-subagent', 'tool-todo', 'tool-web', 'acp'],
|
||||
note: 'Registers tool definitions, exposes schemas to the prompt, and routes calls through tools/pre-execute and tools/post-execute.',
|
||||
},
|
||||
{
|
||||
key: 'userInteraction',
|
||||
pkg: 'user-interaction',
|
||||
title: 'Human question/answer seam',
|
||||
mode: 'seam',
|
||||
implementations: ['stdio-agent', 'acp'],
|
||||
consumers: ['tool-ask-user', 'stdio-agent', 'acp'],
|
||||
note: 'UI front doors provide the active human-answer provider; tool-ask-user pauses a tool call on the provider-neutral ask() promise.',
|
||||
},
|
||||
{
|
||||
key: 'agents',
|
||||
pkg: 'agent',
|
||||
@@ -149,6 +158,15 @@ const SERVICE_ROLES: ServiceRole[] = [
|
||||
consumers: ['tool-bash', 'hooks-claude', 'hooks-codex'],
|
||||
note: 'The model-facing bash tools and hook bridges consume this seam; sandboxed or remote executors can replace bash-local.',
|
||||
},
|
||||
{
|
||||
key: 'codeRuntime',
|
||||
pkg: 'code-runtime',
|
||||
title: 'Code-execution seam',
|
||||
mode: 'seam',
|
||||
implementations: ['code-runtime-worker'],
|
||||
consumers: [],
|
||||
note: 'Runs one model-written program against host-provided async bindings; backends differ by substrate and language (the Code Mode RFC specifies the worker-thread backend and the tool-registry consumer).',
|
||||
},
|
||||
{
|
||||
key: 'fs',
|
||||
pkg: 'fs',
|
||||
@@ -638,7 +656,7 @@ function renderToolPipeline(): string {
|
||||
const maintenance = 'curated Mermaid flow; exact tool schemas and event signatures live in generated catalogs'
|
||||
return [
|
||||
...generatedHeader('Tool Execution Pipeline'),
|
||||
'This graph shows where policy, hooks, sandboxing, filesystem guards, result rewriting, and UI rendering fit without changing the loop. The key extension points are the `tools/pre-execute` and `tools/post-execute` waterfalls.',
|
||||
'This graph shows where policy, hooks, sandboxing, filesystem guards, result rewriting, and UI rendering fit without changing the loop. The key extension points are the `tools/pre-execute`, `tools/execute`, and `tools/post-execute` waterfalls.',
|
||||
'',
|
||||
'```mermaid',
|
||||
'flowchart TD',
|
||||
@@ -647,6 +665,7 @@ function renderToolPipeline(): string {
|
||||
' presentCall["UI pending card<br/>presentCall(args)"]',
|
||||
` pre["${mermaidCode('tools/pre-execute')} waterfall<br/>hooks, permission, sandbox"]`,
|
||||
' denied["deny or ask<br/>tool body skipped"]',
|
||||
` around["${mermaidCode('tools/execute')} waterfall<br/>timeout, retry, metrics (around dispatch)"]`,
|
||||
' toolBody["Registered tool execute() body"]',
|
||||
` fsGate["${mermaidCode('fs/write-intent')} or ${mermaidCode('fs/edit-intent')}<br/>tool-fs mutations only"]`,
|
||||
` owned["Tool-owned session events<br/>${mermaidCode('todo/write')}, ${mermaidCode('fs/observed')}, ${mermaidCode('hook/invoked')}, ${mermaidCode('hook/result')}"]`,
|
||||
@@ -657,19 +676,21 @@ function renderToolPipeline(): string {
|
||||
' model --> toolCall',
|
||||
' toolCall --> presentCall',
|
||||
' toolCall --> pre',
|
||||
' pre -->|allow| toolBody',
|
||||
' pre -->|allow| around',
|
||||
' around --> toolBody',
|
||||
' pre -->|deny or ask| denied',
|
||||
' denied --> post',
|
||||
' toolBody --> fsGate',
|
||||
' fsGate --> toolBody',
|
||||
' toolBody --> owned',
|
||||
' toolBody --> post',
|
||||
' toolBody --> around',
|
||||
' around --> post',
|
||||
' post --> context',
|
||||
' post --> toolResult',
|
||||
' toolResult --> presentResult',
|
||||
'```',
|
||||
'',
|
||||
'Filesystem read-before-edit checks live below `tool-fs` on the `fs/*` event gate, while hook bridges and future permission prompts live on the generic tool waterfalls. That split lets the same hooks observe bash, fs, web, todo, and subagent calls without coupling those tools to one policy service.',
|
||||
'Filesystem read-before-edit checks live below `tool-fs` on the `fs/*` event gate; hook bridges and future permission prompts live on the generic pre/post tool waterfalls; and around-dispatch concerns like the tool-call timeout policy (`@deepseek-ai/dsh-timeout-policy`) wrap core dispatch on `tools/execute`. That split lets the same hooks observe bash, fs, web, todo, and subagent calls without coupling those tools to one policy service.',
|
||||
'',
|
||||
...maintenanceFooter(maintenance),
|
||||
].join('\n')
|
||||
|
||||
@@ -45,6 +45,7 @@ const GROUP_ORDER = [
|
||||
'compact',
|
||||
'subagent',
|
||||
'web',
|
||||
'timeout',
|
||||
'todo',
|
||||
'hooks',
|
||||
'session-persistence',
|
||||
|
||||
@@ -41,11 +41,13 @@ import SystemPrompt from '@deepseek-ai/dsh-system-prompt'
|
||||
import ToolRegistry from '@deepseek-ai/dsh-tools'
|
||||
import LocalBashExecutor from '@deepseek-ai/dsh-bash-local'
|
||||
import LocalFileSystem from '@deepseek-ai/dsh-fs-local'
|
||||
import UserInteractionService from '@deepseek-ai/dsh-user-interaction'
|
||||
import WebService from '@deepseek-ai/dsh-web'
|
||||
import * as WebSearchExa from '@deepseek-ai/dsh-web-search-exa'
|
||||
import * as WebFetchLocal from '@deepseek-ai/dsh-web-fetch-local'
|
||||
import SubagentService from '@deepseek-ai/dsh-subagent'
|
||||
import * as SubagentMock from '@deepseek-ai/dsh-subagent-mock'
|
||||
import * as ToolAskUser from '@deepseek-ai/dsh-tool-ask-user'
|
||||
import * as ToolBash from '@deepseek-ai/dsh-tool-bash'
|
||||
import * as ToolFs from '@deepseek-ai/dsh-tool-fs'
|
||||
import * as ToolTodo from '@deepseek-ai/dsh-tool-todo'
|
||||
@@ -102,6 +104,19 @@ interface ToolPackage {
|
||||
* guard proves it is exhaustive against the on-disk glob.
|
||||
*/
|
||||
const TOOL_PACKAGES: ToolPackage[] = [
|
||||
{
|
||||
pkg: '@deepseek-ai/dsh-tool-ask-user',
|
||||
dir: 'tool-ask-user',
|
||||
source: 'packages/ui/tool-ask-user/src/index.ts',
|
||||
requires: ['ctx.tools', 'ctx.userInteraction'],
|
||||
writes: ['tool/call', 'tool/result after a UI/provider answers the question'],
|
||||
async mount(ctx) {
|
||||
await ctx.plugin(UserInteractionService)
|
||||
await ctx.plugin(ToolAskUser)
|
||||
},
|
||||
note:
|
||||
'ask_user_question pauses the tool call until the active UI provider returns a human answer.',
|
||||
},
|
||||
{
|
||||
pkg: '@deepseek-ai/dsh-tool-bash',
|
||||
dir: 'tool-bash',
|
||||
|
||||
@@ -310,10 +310,11 @@ function builtBinSmokeGate(): Gate {
|
||||
'vitest.e2e.config.ts',
|
||||
'packages/ui/stdio-agent/tests/built-bin.e2e.ts',
|
||||
'packages/ui/acp-agent/tests/built-bin.e2e.ts',
|
||||
// The workflow engine's built worker bundle: the only automated proof
|
||||
// The worker-entry packages' built bundles: the only automated proof
|
||||
// that lib/index.js resolves its sibling lib/worker.js under plain node
|
||||
// (the e2e lane runs unbuilt, so this file self-skips there).
|
||||
// (the e2e lane runs unbuilt, so these files self-skip there).
|
||||
'packages/workflow/workflow-workerthread/tests/built-worker.e2e.ts',
|
||||
'packages/code-runtime/code-runtime-worker/tests/built-lib.e2e.ts',
|
||||
], {
|
||||
label: 'built-bin smoke',
|
||||
needs: ['build'],
|
||||
|
||||
@@ -48,6 +48,14 @@
|
||||
{ "doc": "docs/core-data-structures/tools.md", "symbol": "StructuredSchemaNode", "source": "packages/core/tools/src/json-schema.ts" },
|
||||
{ "doc": "docs/core-data-structures/tools.md", "symbol": "StructuredOutputSchema", "source": "packages/core/tools/src/json-schema.ts" },
|
||||
|
||||
{ "doc": "docs/core-data-structures/user-interaction.md", "symbol": "AskUserQuestionOption", "source": "packages/ui/user-interaction/src/index.ts" },
|
||||
{ "doc": "docs/core-data-structures/user-interaction.md", "symbol": "AskUserQuestionItem", "source": "packages/ui/user-interaction/src/index.ts" },
|
||||
{ "doc": "docs/core-data-structures/user-interaction.md", "symbol": "AskUserQuestionRequest", "source": "packages/ui/user-interaction/src/index.ts" },
|
||||
{ "doc": "docs/core-data-structures/user-interaction.md", "symbol": "AskUserQuestionAnswerItem", "source": "packages/ui/user-interaction/src/index.ts" },
|
||||
{ "doc": "docs/core-data-structures/user-interaction.md", "symbol": "AskUserQuestionAnswer", "source": "packages/ui/user-interaction/src/index.ts" },
|
||||
{ "doc": "docs/core-data-structures/user-interaction.md", "symbol": "UserInteractionProvider", "source": "packages/ui/user-interaction/src/index.ts" },
|
||||
{ "doc": "docs/core-data-structures/user-interaction.md", "symbol": "UserInteractionError", "source": "packages/ui/user-interaction/src/index.ts" },
|
||||
|
||||
{ "doc": "docs/core-data-structures/bash.md", "symbol": "BashExecRequest", "source": "packages/bash/bash/src/types.ts" },
|
||||
{ "doc": "docs/core-data-structures/bash.md", "symbol": "BashExecSpec", "source": "packages/bash/bash/src/types.ts" },
|
||||
{ "doc": "docs/core-data-structures/bash.md", "symbol": "BashRunResult", "source": "packages/bash/bash/src/types.ts" },
|
||||
@@ -55,6 +63,13 @@
|
||||
{ "doc": "docs/core-data-structures/bash.md", "symbol": "BashTask", "source": "packages/bash/bash/src/types.ts" },
|
||||
{ "doc": "docs/core-data-structures/bash.md", "symbol": "BashTaskRead", "source": "packages/bash/bash/src/types.ts" },
|
||||
|
||||
{ "doc": "docs/core-data-structures/code-runtime.md", "symbol": "CodeRunRequest", "source": "packages/code-runtime/code-runtime/src/types.ts" },
|
||||
{ "doc": "docs/core-data-structures/code-runtime.md", "symbol": "CodeRunResult", "source": "packages/code-runtime/code-runtime/src/types.ts" },
|
||||
{ "doc": "docs/core-data-structures/code-runtime.md", "symbol": "CodeBindingNamespace", "source": "packages/code-runtime/code-runtime/src/types.ts" },
|
||||
{ "doc": "docs/core-data-structures/code-runtime.md", "symbol": "CodeBindingFunction", "source": "packages/code-runtime/code-runtime/src/types.ts" },
|
||||
{ "doc": "docs/core-data-structures/code-runtime.md", "symbol": "CodeLogEntry", "source": "packages/code-runtime/code-runtime/src/types.ts" },
|
||||
{ "doc": "docs/core-data-structures/code-runtime.md", "symbol": "CodeRunFailure", "source": "packages/code-runtime/code-runtime/src/types.ts" },
|
||||
|
||||
{ "doc": "docs/core-data-structures/filesystem.md", "symbol": "FsTarget", "source": "packages/fs/fs/src/types.ts" },
|
||||
{ "doc": "docs/core-data-structures/filesystem.md", "symbol": "FsTargetKey", "source": "packages/fs/fs/src/types.ts" },
|
||||
{ "doc": "docs/core-data-structures/filesystem.md", "symbol": "FsVersion", "source": "packages/fs/fs/src/types.ts" },
|
||||
|
||||
@@ -26,9 +26,8 @@
|
||||
* Run: `tsx scripts/verify-doc-refs.ts`.
|
||||
*/
|
||||
|
||||
import { existsSync, readFileSync } from 'node:fs'
|
||||
import { existsSync, globSync, readFileSync } from 'node:fs'
|
||||
import { relative, resolve } from 'node:path'
|
||||
import { glob } from 'node:fs/promises'
|
||||
|
||||
const root = resolve(import.meta.dirname, '..')
|
||||
|
||||
@@ -77,7 +76,7 @@ function findViolations(absPath: string): Violation[] {
|
||||
const all: Violation[] = []
|
||||
let checked = 0
|
||||
for (const pattern of PATTERNS) {
|
||||
for await (const match of glob(pattern, { cwd: root })) {
|
||||
for (const match of globSync(pattern, { cwd: root })) {
|
||||
if (isExcluded(match)) continue
|
||||
checked++
|
||||
all.push(...findViolations(resolve(root, match)))
|
||||
|
||||
@@ -32,9 +32,8 @@
|
||||
* Run: `tsx scripts/verify-md-links.ts`.
|
||||
*/
|
||||
|
||||
import { existsSync, readFileSync, realpathSync } from 'node:fs'
|
||||
import { existsSync, globSync, readFileSync, realpathSync } from 'node:fs'
|
||||
import { dirname, relative, resolve } from 'node:path'
|
||||
import { glob } from 'node:fs/promises'
|
||||
import { fromMarkdown } from 'mdast-util-from-markdown'
|
||||
import { gfmFromMarkdown } from 'mdast-util-gfm'
|
||||
import { gfm } from 'micromark-extension-gfm'
|
||||
@@ -134,7 +133,7 @@ const seen = new Set<string>()
|
||||
const all: Violation[] = []
|
||||
let checked = 0
|
||||
for (const pattern of PATTERNS) {
|
||||
for await (const match of glob(pattern, { cwd: root })) {
|
||||
for (const match of globSync(pattern, { cwd: root })) {
|
||||
const abs = resolve(root, match)
|
||||
// CLAUDE.md symlinks resolve onto AGENTS.md; dedupe by real path so a file
|
||||
// matched twice (or via symlink) is checked once.
|
||||
|
||||
@@ -25,9 +25,8 @@
|
||||
* Run: `tsx scripts/verify-md-wrap.ts`.
|
||||
*/
|
||||
|
||||
import { readFileSync, realpathSync } from 'node:fs'
|
||||
import { globSync, readFileSync, realpathSync } from 'node:fs'
|
||||
import { relative, resolve } from 'node:path'
|
||||
import { glob } from 'node:fs/promises'
|
||||
import { fromMarkdown } from 'mdast-util-from-markdown'
|
||||
import { gfmFromMarkdown } from 'mdast-util-gfm'
|
||||
import { gfm } from 'micromark-extension-gfm'
|
||||
@@ -76,7 +75,7 @@ const seen = new Set<string>()
|
||||
const all: Violation[] = []
|
||||
let checked = 0
|
||||
for (const pattern of PATTERNS) {
|
||||
for await (const match of glob(pattern, { cwd: root })) {
|
||||
for (const match of globSync(pattern, { cwd: root })) {
|
||||
const abs = resolve(root, match)
|
||||
// CLAUDE.md symlinks resolve onto AGENTS.md; dedupe by real path so a file
|
||||
// matched twice (or via symlink) is checked once.
|
||||
|
||||
@@ -12,9 +12,8 @@
|
||||
* Run: `tsx scripts/verify-mermaid.ts`.
|
||||
*/
|
||||
|
||||
import { readFileSync, realpathSync } from 'node:fs'
|
||||
import { globSync, readFileSync, realpathSync } from 'node:fs'
|
||||
import { resolve } from 'node:path'
|
||||
import { glob } from 'node:fs/promises'
|
||||
import { fromMarkdown } from 'mdast-util-from-markdown'
|
||||
import { gfmFromMarkdown } from 'mdast-util-gfm'
|
||||
import { gfm } from 'micromark-extension-gfm'
|
||||
@@ -72,7 +71,7 @@ const blocks: Block[] = []
|
||||
const seen = new Set<string>()
|
||||
let checkedFiles = 0
|
||||
for (const pattern of PATTERNS) {
|
||||
for await (const match of glob(pattern, { cwd: root })) {
|
||||
for (const match of globSync(pattern, { cwd: root })) {
|
||||
const real = realpathSync(resolve(root, match))
|
||||
if (seen.has(real)) continue
|
||||
seen.add(real)
|
||||
|
||||
@@ -39,9 +39,8 @@
|
||||
* Run: `tsx scripts/verify-package-paths.ts`.
|
||||
*/
|
||||
|
||||
import { existsSync, readdirSync, readFileSync, realpathSync } from 'node:fs'
|
||||
import { existsSync, globSync, readdirSync, readFileSync, realpathSync } from 'node:fs'
|
||||
import { relative, resolve } from 'node:path'
|
||||
import { glob } from 'node:fs/promises'
|
||||
|
||||
const root = resolve(import.meta.dirname, '..')
|
||||
|
||||
@@ -144,7 +143,7 @@ const all: Violation[] = []
|
||||
let checked = 0
|
||||
const seen = new Set<string>()
|
||||
for (const pattern of PATTERNS) {
|
||||
for await (const match of glob(pattern, { cwd: root })) {
|
||||
for (const match of globSync(pattern, { cwd: root })) {
|
||||
if (isExcluded(match)) continue
|
||||
// Dedup by real path: the root/packages CLAUDE.md are symlinks to AGENTS.md.
|
||||
const real = realpathSync(resolve(root, match))
|
||||
|
||||
@@ -44,9 +44,8 @@
|
||||
*/
|
||||
|
||||
import { createHash } from 'node:crypto'
|
||||
import { existsSync, readFileSync, writeFileSync } from 'node:fs'
|
||||
import { existsSync, globSync, readFileSync, writeFileSync } from 'node:fs'
|
||||
import { basename, join, resolve } from 'node:path'
|
||||
import { glob } from 'node:fs/promises'
|
||||
import { fromMarkdown } from 'mdast-util-from-markdown'
|
||||
import { gfmFromMarkdown } from 'mdast-util-gfm'
|
||||
import { gfm } from 'micromark-extension-gfm'
|
||||
@@ -211,7 +210,7 @@ function parse(content: string): Nodes {
|
||||
// Enumerate the scope once.
|
||||
const files = new Set<string>()
|
||||
for (const pattern of SCOPE_PATTERNS) {
|
||||
for await (const match of glob(pattern, { cwd: root })) files.add(match)
|
||||
for (const match of globSync(pattern, { cwd: root })) files.add(match)
|
||||
}
|
||||
const translations = [...files].filter(f => f.endsWith('.zh.md')).sort()
|
||||
const metas = [...files].filter(f => f.endsWith('.i18n.yaml')).sort()
|
||||
|
||||
@@ -22,9 +22,8 @@
|
||||
* Run: `tsx scripts/verify-type-equiv.ts`.
|
||||
*/
|
||||
|
||||
import { readFileSync, existsSync } from 'node:fs'
|
||||
import { globSync, readFileSync, existsSync } from 'node:fs'
|
||||
import { resolve } from 'node:path'
|
||||
import { glob } from 'node:fs/promises'
|
||||
import ts from 'typescript'
|
||||
|
||||
const root = resolve(import.meta.dirname, '..')
|
||||
@@ -148,7 +147,7 @@ const keyOf = (x: { doc: string; symbol: string }): string => `${x.doc}::${x.sym
|
||||
// as an orphan rather than silently skipped.
|
||||
const docSet = new Set<string>()
|
||||
for (const pattern of MARKDOWN_GLOBS) {
|
||||
for await (const match of glob(pattern, { cwd: root })) docSet.add(match)
|
||||
for (const match of globSync(pattern, { cwd: root })) docSet.add(match)
|
||||
}
|
||||
const blocks: EquivBlock[] = [...docSet].sort().flatMap(extractEquivBlocks)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user