Merge remote-tracking branch 'origin/master' into worktree/llm-reasoning-effort
# Conflicts: # docs/architecture.i18n.yaml # docs/config-catalog.md
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { dirname, join } from 'node:path'
|
||||
import { afterEach, describe, expect, it } from 'vitest'
|
||||
|
||||
import { RepositoryCleaner } from './clean.ts'
|
||||
|
||||
const roots: string[] = []
|
||||
|
||||
function fixture(): string {
|
||||
const root = mkdtempSync(join(tmpdir(), 'dsh-clean-'))
|
||||
roots.push(root)
|
||||
return root
|
||||
}
|
||||
|
||||
function write(path: string, content = ''): void {
|
||||
mkdirSync(dirname(path), { recursive: true })
|
||||
writeFileSync(path, content)
|
||||
}
|
||||
|
||||
function addProject(root: string, path: string): void {
|
||||
write(join(root, 'tsconfig.json'), JSON.stringify({ files: [], references: [{ path }] }))
|
||||
write(join(root, path, 'tsconfig.json'), JSON.stringify({
|
||||
compilerOptions: { composite: true, outDir: 'lib/types' },
|
||||
include: ['src'],
|
||||
}))
|
||||
write(join(root, path, 'src/index.ts'), 'export {}\n')
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
for (const root of roots.splice(0)) rmSync(root, { recursive: true, force: true })
|
||||
})
|
||||
|
||||
describe('RepositoryCleaner', () => {
|
||||
it('derives live build outputs from project references and removes safe stale package residue', async () => {
|
||||
const root = fixture()
|
||||
addProject(root, 'products/shell')
|
||||
write(join(root, 'products/shell/lib/types/index.js'))
|
||||
write(join(root, 'products/shell/lib/index.js'))
|
||||
write(join(root, '.typecheck/legacy.tsbuildinfo'))
|
||||
write(join(root, 'root.tsbuildinfo'))
|
||||
write(join(root, 'packages/removed/ghost/node_modules/.bin/tool'))
|
||||
|
||||
await new RepositoryCleaner(root).clean()
|
||||
|
||||
expect(existsSync(join(root, 'products/shell/lib'))).toBe(false)
|
||||
expect(existsSync(join(root, 'products/shell/src/index.ts'))).toBe(true)
|
||||
expect(existsSync(join(root, '.typecheck'))).toBe(false)
|
||||
expect(existsSync(join(root, 'root.tsbuildinfo'))).toBe(false)
|
||||
expect(existsSync(join(root, 'packages/removed/ghost'))).toBe(false)
|
||||
})
|
||||
|
||||
it('does not delete any target when a manifest-less package contains an unknown file', async () => {
|
||||
const root = fixture()
|
||||
addProject(root, 'products/shell')
|
||||
write(join(root, 'products/shell/lib/types/index.js'))
|
||||
write(join(root, 'packages/removed/ghost/notes.txt'))
|
||||
|
||||
await expect(new RepositoryCleaner(root).clean()).rejects.toThrow('packages/removed/ghost/notes.txt')
|
||||
expect(existsSync(join(root, 'products/shell/lib'))).toBe(true)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,165 @@
|
||||
import { lstat, readdir, rm } from 'node:fs/promises'
|
||||
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import ts from 'typescript'
|
||||
import { repositoryConfigHost } from './ts-project.ts'
|
||||
|
||||
const knownOrphanEntries = new Set(['node_modules', 'lib', '.typecheck'])
|
||||
|
||||
function isMissing(error: unknown): boolean {
|
||||
return error instanceof Error && 'code' in error && error.code === 'ENOENT'
|
||||
}
|
||||
|
||||
async function exists(path: string): Promise<boolean> {
|
||||
try {
|
||||
await lstat(path)
|
||||
return true
|
||||
} catch (error) {
|
||||
if (isMissing(error)) return false
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
async function childDirectories(path: string): Promise<string[]> {
|
||||
try {
|
||||
const entries = await readdir(path, { withFileTypes: true })
|
||||
return entries.filter(entry => entry.isDirectory()).map(entry => join(path, entry.name))
|
||||
} catch (error) {
|
||||
if (isMissing(error)) return []
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
function repositoryPath(root: string, path: string): string {
|
||||
return relative(root, path).split(sep).join('/')
|
||||
}
|
||||
|
||||
function parseConfig(configPath: string): ts.ParsedCommandLine {
|
||||
const parsed = ts.getParsedCommandLineOfConfigFile(configPath, {}, repositoryConfigHost)
|
||||
if (!parsed) throw new Error(`clean: cannot parse TypeScript config ${configPath}`)
|
||||
if (parsed.errors.length > 0) {
|
||||
throw new Error(parsed.errors.map(error => ts.flattenDiagnosticMessageText(error.messageText, '\n')).join('\n'))
|
||||
}
|
||||
return parsed
|
||||
}
|
||||
|
||||
/** Plans and removes repository-owned build output without crossing the repository boundary. */
|
||||
export class RepositoryCleaner {
|
||||
constructor(private readonly root: string) {}
|
||||
|
||||
/**
|
||||
* Remove generated build state and package directories containing only known residue.
|
||||
* @returns Repository-relative paths that were removed.
|
||||
*/
|
||||
async clean(): Promise<string[]> {
|
||||
const targets = await this.plan()
|
||||
// Planning validates every target first, so an unsafe orphan prevents all deletion.
|
||||
for (const target of targets) await rm(target, { recursive: true, force: true })
|
||||
return targets.map(target => repositoryPath(this.root, target))
|
||||
}
|
||||
|
||||
private async plan(): Promise<string[]> {
|
||||
const targets = new Set<string>()
|
||||
const unsafeOrphans: string[] = []
|
||||
|
||||
// These checks cover legacy root-level incremental state emitted by older configs.
|
||||
await this.addIfPresent(targets, join(this.root, '.typecheck'))
|
||||
for (const entry of await readdir(this.root, { withFileTypes: true })) {
|
||||
if (entry.isFile() && entry.name.endsWith('.tsbuildinfo')) targets.add(join(this.root, entry.name))
|
||||
}
|
||||
|
||||
// The root project-reference graph is the source of truth for live build targets.
|
||||
// Each emitting project declares lib/types as outDir; its parent lib also owns
|
||||
// the sibling runtime bundles, so the complete build output root is removed.
|
||||
for (const outputDirectory of this.buildOutputDirectories()) {
|
||||
await this.addIfPresent(targets, outputDirectory)
|
||||
}
|
||||
|
||||
for (const groupDirectory of await childDirectories(join(this.root, 'packages'))) {
|
||||
for (const packageDirectory of await childDirectories(groupDirectory)) {
|
||||
// A package.json marks a live package; its output was discovered from the
|
||||
// project graph above, and its package-local node_modules must be preserved.
|
||||
if (await exists(join(packageDirectory, 'package.json'))) {
|
||||
continue
|
||||
}
|
||||
|
||||
// A manifest-less package directory is stale only when every remaining
|
||||
// entry is known generated residue; unknown files make the whole clean fail.
|
||||
const entries = await readdir(packageDirectory)
|
||||
const unknown = entries.filter(entry => !knownOrphanEntries.has(entry) && !entry.endsWith('.tsbuildinfo'))
|
||||
if (unknown.length > 0) {
|
||||
unsafeOrphans.push(...unknown.map(entry => repositoryPath(this.root, join(packageDirectory, entry))))
|
||||
} else {
|
||||
targets.add(packageDirectory)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (unsafeOrphans.length > 0) {
|
||||
throw new Error([
|
||||
'clean: refusing to remove package directories without package.json; unknown entries remain:',
|
||||
...unsafeOrphans.sort().map(path => ` ${path}`),
|
||||
].join('\n'))
|
||||
}
|
||||
|
||||
return [...targets].sort()
|
||||
}
|
||||
|
||||
private buildOutputDirectories(): string[] {
|
||||
const outputs = new Set<string>()
|
||||
const pending = [join(this.root, 'tsconfig.json')]
|
||||
const visited = new Set<string>()
|
||||
|
||||
while (pending.length > 0) {
|
||||
const nextConfigPath = pending.pop()
|
||||
if (nextConfigPath === undefined) break
|
||||
const configPath = resolve(nextConfigPath)
|
||||
if (visited.has(configPath)) continue
|
||||
visited.add(configPath)
|
||||
|
||||
const parsed = parseConfig(configPath)
|
||||
if (parsed.options.outDir !== undefined) {
|
||||
const typesDirectory = resolve(parsed.options.outDir)
|
||||
if (basename(typesDirectory) !== 'types') {
|
||||
throw new Error(`clean: expected TypeScript outDir to end in /types: ${repositoryPath(this.root, typesDirectory)}`)
|
||||
}
|
||||
const outputDirectory = dirname(typesDirectory)
|
||||
this.assertRepositoryTarget(outputDirectory)
|
||||
outputs.add(outputDirectory)
|
||||
}
|
||||
|
||||
for (const reference of parsed.projectReferences ?? []) {
|
||||
pending.push(ts.resolveProjectReferencePath(reference))
|
||||
}
|
||||
}
|
||||
|
||||
return [...outputs]
|
||||
}
|
||||
|
||||
private assertRepositoryTarget(path: string): void {
|
||||
const repositoryRelative = relative(this.root, path)
|
||||
if (repositoryRelative === '' || repositoryRelative === '..' || repositoryRelative.startsWith(`..${sep}`) || isAbsolute(repositoryRelative)) {
|
||||
throw new Error(`clean: refusing build output outside repository: ${path}`)
|
||||
}
|
||||
}
|
||||
|
||||
private async addIfPresent(targets: Set<string>, path: string): Promise<void> {
|
||||
// Missing outputs are normal on a clean checkout; only existing paths become deletion targets.
|
||||
if (await exists(path)) targets.add(path)
|
||||
}
|
||||
}
|
||||
|
||||
const scriptPath = fileURLToPath(import.meta.url)
|
||||
if (process.argv[1] !== undefined && resolve(process.argv[1]) === scriptPath) {
|
||||
try {
|
||||
const removed = await new RepositoryCleaner(resolve(dirname(scriptPath), '..')).clean()
|
||||
if (removed.length === 0) {
|
||||
console.log('clean: already clean')
|
||||
} else {
|
||||
console.log(`clean: removed ${removed.length} paths`)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error instanceof Error ? error.message : error)
|
||||
process.exitCode = 1
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import { spawn } from 'node:child_process'
|
||||
|
||||
// Each UI's node invocation matches its base demo script plus the overlay config.
|
||||
const UIS = new Map([
|
||||
['tui', ['--import', 'tsx', 'packages/examples/tui-demo/src/bin.ts', 'examples/tui-agent/code-mode.cordis.yml']],
|
||||
['tui', ['--import', 'tsx', 'apps/cli/src/bin.ts', '--config', 'examples/tui-agent/code-mode.cordis.yml']],
|
||||
['acp', ['--import', 'tsx', 'packages/examples/acp-demo/src/bin.ts', '--config', 'examples/acp-agent/code-mode.cordis.yml']],
|
||||
])
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"docs/architecture.md": 1800,
|
||||
"docs/cordis-primer.md": 600,
|
||||
"docs/defensive-patterns.md": 550,
|
||||
"docs/testing.md": 1020,
|
||||
"docs/testing.md": 1100,
|
||||
"examples/AGENTS.md": 310,
|
||||
"packages/AGENTS.md": 660,
|
||||
"packages/README.md": 790
|
||||
|
||||
@@ -130,8 +130,10 @@ export const LINK_MAP: Record<string, string> = {
|
||||
SessionEventResultFilter: 'session-query.md',
|
||||
SessionEventSearchDocument: 'session-query.md',
|
||||
SessionEventSearchHit: 'session-query.md',
|
||||
SessionEventSearchPage: 'session-query.md',
|
||||
SessionEventSearchRequest: 'session-query.md',
|
||||
SessionEventTrace: 'session-query.md',
|
||||
SessionEventTraceObservation: 'session-query.md',
|
||||
SessionEventTraceRequest: 'session-query.md',
|
||||
SessionEventWindow: 'session-query.md',
|
||||
SessionLineageTrace: 'session-query.md',
|
||||
@@ -141,6 +143,8 @@ export const LINK_MAP: Record<string, string> = {
|
||||
SessionSearchHit: 'session-query.md',
|
||||
SessionSearchPage: 'session-query.md',
|
||||
SessionSearchRequest: 'session-query.md',
|
||||
SessionTitleObservation: 'session-query.md',
|
||||
SessionTitleObservationResult: 'session-query.md',
|
||||
SessionTitleProvider: 'session-title.md',
|
||||
SessionTitleSnapshot: 'session-title.md',
|
||||
SkillDefinition: 'skills.md',
|
||||
|
||||
@@ -166,8 +166,8 @@ const SERVICE_ROLES: ServiceRole[] = [
|
||||
title: 'Session reads, traces, filters, and search',
|
||||
mode: 'seam',
|
||||
implementations: ['session-query-sqlite'],
|
||||
consumers: ['session-reference'],
|
||||
note: 'The interface supplies exact reads, filters, and traces; its concrete backend adds full-text reconciliation, ranking, snippets, and cursor generations on the same service.',
|
||||
consumers: ['session-reference', 'tool-session-query'],
|
||||
note: 'The interface supplies exact reads, filters, and traces; its concrete backend adds full-text reconciliation, ranking, snippets, and cursor generations, while the model consumer owns workspace authority and cursor-free rendering.',
|
||||
},
|
||||
{
|
||||
key: 'sessionReferences',
|
||||
|
||||
@@ -11,6 +11,8 @@ import { basename, resolve } from 'node:path'
|
||||
import { Context } from 'cordis'
|
||||
import type { ToolSchema } from '@deepseek-ai/dsh-llm'
|
||||
import AgentRegistry from '@deepseek-ai/dsh-agent'
|
||||
import SessionStore from '@deepseek-ai/dsh-session'
|
||||
import SessionQuerySqlite from '@deepseek-ai/dsh-session-query-sqlite'
|
||||
import GoalService from '@deepseek-ai/dsh-goal'
|
||||
import SystemPrompt from '@deepseek-ai/dsh-system-prompt'
|
||||
import ToolRegistry, { type Config as ToolsConfig } from '@deepseek-ai/dsh-tools'
|
||||
@@ -39,6 +41,7 @@ import * as ToolGoal from '@deepseek-ai/dsh-tool-goal'
|
||||
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'
|
||||
import * as ToolSessionQuery from '@deepseek-ai/dsh-tool-session-query'
|
||||
import * as ToolTasks from '@deepseek-ai/dsh-tool-tasks'
|
||||
import * as ToolTodo from '@deepseek-ai/dsh-tool-todo'
|
||||
import * as ToolSubagent from '@deepseek-ai/dsh-tool-subagent'
|
||||
@@ -316,6 +319,20 @@ const TOOL_PACKAGES: ToolPackage[] = [
|
||||
await ctx.plugin(ToolSkill)
|
||||
},
|
||||
},
|
||||
{
|
||||
pkg: '@deepseek-ai/dsh-tool-session-query',
|
||||
dir: 'tool-session-query',
|
||||
source: 'packages/session-query/tool-session-query/src/index.ts',
|
||||
requires: ['ctx.tools', 'ctx.systemPrompt', 'ctx.sessionQuery', 'a calling Agent for workspace authority'],
|
||||
writes: ['tool/call', 'tool/result'],
|
||||
async mount(ctx) {
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionQuerySqlite, { path: ':memory:' })
|
||||
await ctx.plugin(ToolSessionQuery)
|
||||
},
|
||||
note:
|
||||
'The five read-only tools hide provider cursors and authorize every result from the immutable calling agent session. The package is opt-in; compositions that need enforced deadlines or bounded inline output also mount the generic timeout or spill policies.',
|
||||
},
|
||||
{
|
||||
pkg: '@deepseek-ai/dsh-tool-subagent',
|
||||
dir: 'tool-subagent',
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
"required": [
|
||||
".agents/notes/README.md",
|
||||
".agents/notes/implemented/architecture/2026-06-11-content-block-vocabulary.md",
|
||||
".agents/notes/implemented/architecture/2026-06-11-custom-schema-dsl.md",
|
||||
".agents/notes/implemented/architecture/2026-06-11-dev-invariants-over-deep-readonly.md",
|
||||
".agents/notes/implemented/architecture/2026-06-11-event-sourced-sessions.md",
|
||||
".agents/notes/implemented/architecture/2026-06-11-microkernel-event-taxonomy.md",
|
||||
@@ -44,11 +43,9 @@
|
||||
".agents/notes/implemented/architecture/2026-07-19-gui-web-client-architecture.md",
|
||||
".agents/notes/implemented/architecture/2026-07-22-slot-type-chain-implementation.md",
|
||||
".agents/notes/implemented/architecture/2026-07-23-client-plugin-loading-model.md",
|
||||
".agents/notes/implemented/feature/2026-06-14-acp-agent-client-protocol.md",
|
||||
".agents/notes/implemented/feature/2026-06-14-acp-multi-session.md",
|
||||
".agents/notes/implemented/feature/2026-06-15-code-mode.md",
|
||||
".agents/notes/implemented/feature/2026-06-17-filesystem-tool-schemas.md",
|
||||
".agents/notes/implemented/feature/2026-06-18-acp-terminal-and-tool-rendering.md",
|
||||
".agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md",
|
||||
".agents/notes/implemented/feature/2026-06-21-subagent-capability-seam.md",
|
||||
".agents/notes/implemented/feature/2026-06-22-acp-subagent-backend.md",
|
||||
@@ -90,7 +87,6 @@
|
||||
".agents/notes/implemented/process/2026-07-06-export-surface-jsdoc-gate.md",
|
||||
".agents/notes/implemented/process/2026-07-06-generated-config-catalog.md",
|
||||
".agents/notes/implemented/process/2026-07-06-node-engine-floor.md",
|
||||
".agents/notes/implemented/process/2026-07-06-parallel-github-ci-gates.md",
|
||||
".agents/notes/implemented/process/2026-07-06-parallel-pre-push-gates.md",
|
||||
".agents/notes/implemented/process/2026-07-10-readme-known-limitations-gate.md",
|
||||
".agents/notes/implemented/process/2026-07-12-package-model-experience-contract.md",
|
||||
@@ -108,7 +104,6 @@
|
||||
".agents/notes/implemented/simplification/2026-07-04-drop-image-content-block.md",
|
||||
".agents/notes/implemented/simplification/2026-07-04-drop-inert-request-knobs.md",
|
||||
".agents/notes/implemented/simplification/2026-07-04-drop-unconsumed-web-observation-surface.md",
|
||||
".agents/notes/implemented/simplification/2026-07-04-fold-stdio-ui-helper.md",
|
||||
".agents/notes/implemented/simplification/2026-07-04-prune-producerless-vocabulary-variants.md",
|
||||
".agents/notes/implemented/simplification/2026-07-04-prune-write-only-fs-surface.md",
|
||||
".agents/notes/implemented/simplification/2026-07-04-remove-agent-steering-mirror.md",
|
||||
|
||||
@@ -11,7 +11,8 @@ interface ProjectGraph {
|
||||
options: ts.CompilerOptions
|
||||
}
|
||||
|
||||
const configHost: ts.ParseConfigFileHost = {
|
||||
/** TypeScript config host shared by repository scripts. */
|
||||
export const repositoryConfigHost: ts.ParseConfigFileHost = {
|
||||
useCaseSensitiveFileNames: ts.sys.useCaseSensitiveFileNames,
|
||||
readDirectory: (...args) => ts.sys.readDirectory(...args),
|
||||
fileExists: fileName => ts.sys.fileExists(fileName),
|
||||
@@ -52,7 +53,7 @@ function loadProjectGraph(projectRoot: string): ProjectGraph {
|
||||
|
||||
/** Parse one config file and fail loud on any config diagnostic. */
|
||||
function parseConfig(configPath: string): ts.ParsedCommandLine {
|
||||
const parsed = ts.getParsedCommandLineOfConfigFile(configPath, {}, configHost)
|
||||
const parsed = ts.getParsedCommandLineOfConfigFile(configPath, {}, repositoryConfigHost)
|
||||
if (!parsed) throw new Error(`cannot parse TypeScript config ${configPath}`)
|
||||
if (parsed.errors.length > 0) {
|
||||
throw new Error(parsed.errors.map(error => ts.flattenDiagnosticMessageText(error.messageText, '\n')).join('\n'))
|
||||
|
||||
@@ -444,6 +444,16 @@
|
||||
"symbol": "SessionSurfaceSnapshot",
|
||||
"source": "packages/session-query/session-query/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/session-query.md",
|
||||
"symbol": "SessionTitleObservation",
|
||||
"source": "packages/session-query/session-query/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/session-query.md",
|
||||
"symbol": "SessionTitleObservationResult",
|
||||
"source": "packages/session-query/session-query/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/session-query.md",
|
||||
"symbol": "SessionEventRecord",
|
||||
@@ -484,6 +494,11 @@
|
||||
"symbol": "SessionEventTrace",
|
||||
"source": "packages/session-query/session-query/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/session-query.md",
|
||||
"symbol": "SessionEventTraceObservation",
|
||||
"source": "packages/session-query/session-query/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/session-title.md",
|
||||
"symbol": "SessionTitleProviderId",
|
||||
@@ -1244,6 +1259,11 @@
|
||||
"symbol": "SessionSearchPage",
|
||||
"source": "packages/session-query/session-query/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/session-query.md",
|
||||
"symbol": "SessionEventSearchPage",
|
||||
"source": "packages/session-query/session-query/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/session-query.md",
|
||||
"symbol": "SessionEventSearchHit",
|
||||
@@ -1612,6 +1632,16 @@
|
||||
"symbol": "SessionSurfaceSnapshot",
|
||||
"source": "packages/session-query/session-query/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/session-query.zh.md",
|
||||
"symbol": "SessionTitleObservation",
|
||||
"source": "packages/session-query/session-query/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/session-query.zh.md",
|
||||
"symbol": "SessionTitleObservationResult",
|
||||
"source": "packages/session-query/session-query/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/session-query.zh.md",
|
||||
"symbol": "SessionEventRecord",
|
||||
@@ -1652,6 +1682,11 @@
|
||||
"symbol": "SessionSearchPage",
|
||||
"source": "packages/session-query/session-query/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/session-query.zh.md",
|
||||
"symbol": "SessionEventSearchPage",
|
||||
"source": "packages/session-query/session-query/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/session-query.zh.md",
|
||||
"symbol": "SessionEventSearchHit",
|
||||
@@ -1697,6 +1732,11 @@
|
||||
"symbol": "SessionEventTrace",
|
||||
"source": "packages/session-query/session-query/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/session-query.zh.md",
|
||||
"symbol": "SessionEventTraceObservation",
|
||||
"source": "packages/session-query/session-query/src/types.ts"
|
||||
},
|
||||
{
|
||||
"doc": "docs/core-data-structures/tools.zh.md",
|
||||
"symbol": "ToolOutputDefinition",
|
||||
|
||||
@@ -90,6 +90,7 @@ const SENTENCE_MODEL_EXPERIENCE: Readonly<Record<string, SentenceContract>> = {
|
||||
'packages/support/agent-loop-testkit': { kind: 'none', reason: 'The test helper mounts services but neither drives nor modifies model requests.' },
|
||||
'packages/support/invariants': { kind: 'none', reason: 'The observer validates requests but never rewrites their context.' },
|
||||
'packages/support/loader-smoke': { kind: 'none', reason: 'The test harness observes child-process streams without changing live requests.' },
|
||||
'packages/support/llm-mock-server': { kind: 'none', reason: 'The test server substitutes provider wire behavior without invoking a real model.' },
|
||||
'packages/support/llm-replay': { kind: 'none', reason: 'The keyless adapter invokes no provider model.' },
|
||||
'packages/tasks/tasks': { kind: 'indirect', reason: 'Producer and control-surface plugins own all model rendering over the task registry.' },
|
||||
'packages/examples/acp-demo': { kind: 'indirect', reason: 'The app bundle delegates request composition to dsh-agent-spine-demo and dsh-acp.' },
|
||||
|
||||
Reference in New Issue
Block a user