Merge remote-tracking branch 'origin/stack/agent-profiles-5-web-ui' into stack/agent-profiles-8-authoring
# Conflicts: # packages/client/connection/README.i18n.yaml # packages/client/connection/README.md # packages/client/connection/README.zh.md
This commit is contained in:
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/session-query/session-query-sqlite/README.md
|
||||
README.md: 4bf4d979f2d2954cd6280c80bf7f5988d8121fd1
|
||||
README.zh.md: 56f7dfa8bad3a04a6bf17eac08b62a1a11f4d53f
|
||||
README.md: dbbb63e9dd18f3c68cc21b84b560403f4a508709
|
||||
README.zh.md: 0b183f63ad2f3cfa670babca80d6e4abee6a4bcb
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
Concrete `ctx.sessionQuery` backend. `SessionQuerySqlite` inherits exact reads, traces, and provider-independent filters from the interface package and implements its two full-text methods with SQLite FTS5. Search uses the live-preferred logical session corpus and groups cross-session results by their strongest event.
|
||||
Concrete `ctx.sessionQuery` provider. `SessionQuerySqlite` inherits exact reads, traces, and provider-independent filters from the Service Definition package and implements its two full-text methods with SQLite FTS5. Search uses the live-preferred logical session corpus and groups cross-session results by their strongest event.
|
||||
|
||||
## Search contract
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
具体 `ctx.sessionQuery` 后端。`SessionQuerySqlite` 从接口包继承精确读取、跟踪和提供方无关的过滤,并使用 SQLite FTS5 实现其两个全文方法。搜索使用实时优先的逻辑会话语料库,并按每个会话中匹配度最高的事件对跨会话结果分组。
|
||||
具体 `ctx.sessionQuery` 提供方。`SessionQuerySqlite` 从 Service Definition 包继承精确读取、跟踪和提供方无关的过滤,并使用 SQLite FTS5 实现其两个全文方法。搜索使用实时优先的逻辑会话语料库,并按每个会话中匹配度最高的事件对跨会话结果分组。
|
||||
|
||||
## 搜索约定
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/session-query/session-query/README.md
|
||||
README.md: b75c1f23264cfa7c9323970b3c1a77ddcfe69be0
|
||||
README.zh.md: 4f1c4749a847326fd9fbc0ffa627651c052ccd71
|
||||
README.md: 5d4d689477fca4fd6b01091f1304ff3065af7443
|
||||
README.zh.md: 957b5c39d9ff2127e7819ae01077fec51950b26f
|
||||
|
||||
@@ -15,7 +15,7 @@ English | [中文](README.zh.md)
|
||||
- `readSurface(sessionId)` returns one cloned header, raw-log capture boundary, and the complete folded current surface in model-history order. A live session wins over persistence; compaction is observed before or after its replacement append, never as a synthetic mixture.
|
||||
- `readEvent(request, signal?)` returns a cloned header, the full target event, and a bounded raw-seq window. `before` and `after` default to zero and may not exceed `readWindowMax`.
|
||||
- `traceSession(sessionId, signal?)` reads the corpus once and returns immediate-to-outward ancestors plus deterministic recursive descendant trees. `complete: false` identifies the first missing parent; a target-connected cycle fails with `SESSION_QUERY_INVALID_LINEAGE`.
|
||||
- `traceEvent(request, signal?)` loads the logical log once and returns its cloned source header with direct positional replacements and direct logged provenance. `replacementChain` follows positional replacers to the final replacement; provenance links remain non-transitive.
|
||||
- `traceEvent(request, signal?)` loads the logical log once and returns its cloned source header with direct positional replacements and direct cited source-event links. `replacementChain` follows positional replacers to the final replacement; source-event links remain non-transitive.
|
||||
|
||||
Persistence is optional and may mount or unmount dynamically. Cross-corpus listing and lineage tracing fail with `SESSION_QUERY_PERSISTENCE_FAILED` while mounted persistence is unreadable; a successfully read durable record that fails Session validation reports `SESSION_QUERY_CORRUPT_SESSION` instead. A title read, event trace, or event read targeting a known live session does not consult persistence, so durable backend health cannot make current in-memory state unreadable. Persisted title and event operations list before loading and reject a metadata mismatch rather than combining inconsistent observations. Lineage-trace cancellation is passed to persisted listing; event-trace and event-read cancellation is passed to persisted listing and inspection. Each waits for the started backend call to settle, then rejects with the signal's exact reason even when the backend ignored that signal. A pre-aborted known-live title read, event trace, or event read rejects before folding or snapshotting without consulting persistence. A batch title observation performs one metadata listing, inspects its unique persisted ids with at most `persistedInspectConcurrency` workers, and preserves each title's own observed header for downstream authorization. Cancellation starts no queued inspections and rejects only after already-started workers settle. `listSessions()` remains lightweight and does not load logs or index titles.
|
||||
|
||||
@@ -33,7 +33,7 @@ The package has no provider coordinator, fallback implementation, or standalone
|
||||
|
||||
`SessionQueryError.code` is a closed union covering request validation, missing targets, malformed surfaces, source conflicts, persistence/index failures, cancellation, and invalid or stale cursors; the exact literals are defined in [`src/config.ts`](src/config.ts).
|
||||
|
||||
`listEvents()`, `readSurface()`, and `traceEvent()` run the same one-pass `dsh-session` surface fold. A loaded log is valid only when event seqs are zero-based and contiguous, surface markers obey event-type eligibility, provenance arrays are nonempty and duplicate-free, references name earlier events, and each positional replacement names and cites every surface node it removes; every violation fails with `SESSION_QUERY_INVALID_SURFACE`.
|
||||
`listEvents()`, `readSurface()`, and `traceEvent()` run the same one-pass `dsh-session` surface fold. A loaded log is valid only when event seqs are zero-based and contiguous, surface markers obey event-type eligibility, source-event arrays are nonempty and duplicate-free, references name earlier events, and each positional replacement names and cites every surface node it removes; every violation fails with `SESSION_QUERY_INVALID_SURFACE`.
|
||||
|
||||
## Configuration
|
||||
|
||||
@@ -53,4 +53,4 @@ None; this package neither assembles nor sends a provider request.
|
||||
## Known Limitations and Deferred Work
|
||||
|
||||
- **No caller authorization** — this is trusted context-wide infrastructure; a future model tool or UI must constrain which sessions its caller may inspect.
|
||||
- **No registries or model-facing tool** — extractor and search-provider registries, recursive event-provenance traversal, and a model-facing tool are absent. The [tracing decision](../../../.agents/notes/implemented/feature/2026-07-13-session-query-tracing.md) owns relationship semantics; SQLite ownership and tokenizer decisions live in the [implemented search note](../../../.agents/notes/implemented/feature/2026-07-10-sqlite-session-query-provider.md).
|
||||
- **No registries or model-facing tool** — extractor and search-provider registries, recursive traversal through cited source events, and a model-facing tool are absent. The [tracing decision](../../../.agents/notes/implemented/feature/2026-07-13-session-query-tracing.md) owns relationship semantics; SQLite ownership and tokenizer decisions live in the [implemented search note](../../../.agents/notes/implemented/feature/2026-07-10-sqlite-session-query-provider.md).
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
- `readSurface(sessionId)` 返回一个克隆 header、原始日志捕获边界,以及按模型历史顺序排列的完整折叠后当前表层。实时会话优先于持久化;压缩(compaction)只会在其替换追加之前或之后被观察,绝不会出现合成混合。
|
||||
- `readEvent(request, signal?)` 返回一个克隆 header、完整目标事件和有界的原始 seq 窗口。`before` 和 `after` 默认为 0,且不得超过 `readWindowMax`。
|
||||
- `traceSession(sessionId, signal?)` 只读取一次语料库,返回从直接父级向外的祖先,以及确定性的递归后代树。`complete: false` 标识第一个缺失父级;与目标相连的循环会以 `SESSION_QUERY_INVALID_LINEAGE` 失败。
|
||||
- `traceEvent(request, signal?)` 只加载一次逻辑日志,返回其克隆源 header、直接位置替换和直接已记录来源信息。`replacementChain` 沿位置替换者跟踪到最终替换;来源链接仍不传递。
|
||||
- `traceEvent(request, signal?)` 只加载一次逻辑日志,返回其克隆源 header、直接位置替换和直接引用的源事件链接。`replacementChain` 沿位置替换者跟踪到最终替换;源事件链接仍不传递。
|
||||
|
||||
持久化是可选的,可动态挂载或卸载。已挂载持久化无法读取时,跨语料库列表和血缘跟踪以 `SESSION_QUERY_PERSISTENCE_FAILED` 失败;已经成功读取、但无法通过 Session 校验的持久化记录则以 `SESSION_QUERY_CORRUPT_SESSION` 失败。针对已知实时会话的标题读取、事件跟踪或事件读取不会查询持久化,因此持久化后端的健康状态无法使当前内存状态变得不可读。持久化标题和事件操作在加载前先执行列表查询,并在元数据不匹配时拒绝,而不会组合不一致的观察。血缘跟踪的取消信号会传递给持久化列表查询;事件跟踪和事件读取的取消信号会传递给持久化列表查询和检查。每项操作都会等待已启动的后端调用结算,然后使用信号的精确原因拒绝,即使后端忽略了该信号。针对已知实时会话且预先中止的标题读取、事件跟踪或事件读取会在 fold 或快照之前拒绝,且不查询持久化。批量标题观察执行一次元数据列表查询,使用最多 `persistedInspectConcurrency` 个 worker 检查唯一持久化 id,并保留每个标题自己观察到的 header,供下游授权使用。取消不会启动已排队检查,且只在已启动 worker 结算后拒绝。`listSessions()` 仍保持轻量,不加载日志或索引标题。
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
`SessionQueryError.code` 是一个封闭联合,覆盖请求验证、缺失目标、格式错误的表层、来源冲突、持久化/索引失败、取消,以及无效或陈旧游标;精确字面值在 [`src/config.ts`](src/config.ts) 中定义。
|
||||
|
||||
`listEvents()`、`readSurface()` 和 `traceEvent()` 执行同一个单遍 `dsh-session` 表层 fold。只有当事件 seq 从零开始且连续、表层标记符合事件类型的适用性要求、来源数组非空且无重复、引用指向较早事件,且每个位置替换都命名并引用它移除的每个表层节点时,加载的日志才有效;任何违规都以 `SESSION_QUERY_INVALID_SURFACE` 失败。
|
||||
`listEvents()`、`readSurface()` 和 `traceEvent()` 执行同一个单遍 `dsh-session` 表层 fold。只有当事件 seq 从零开始且连续、表层标记符合事件类型的适用性要求、源事件数组非空且无重复、引用指向较早事件,且每个位置替换都命名并引用它移除的每个表层节点时,加载的日志才有效;任何违规都以 `SESSION_QUERY_INVALID_SURFACE` 失败。
|
||||
|
||||
## 配置
|
||||
|
||||
@@ -53,4 +53,4 @@
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- **无调用方授权**:这是上下文范围内的可信基础设施;未来的模型工具或 UI 必须限制调用方可检查的会话。
|
||||
- **无注册表或面向模型工具**:尚未提供提取器和搜索提供方注册表、递归事件来源遍历以及面向模型的工具。[跟踪决策](../../../.agents/notes/implemented/feature/2026-07-13-session-query-tracing.md) 负责关系语义;SQLite 归属和 tokenizer 决策位于[已实现搜索记录](../../../.agents/notes/implemented/feature/2026-07-10-sqlite-session-query-provider.md)。
|
||||
- **无注册表或面向模型工具**:尚未提供提取器和搜索提供方注册表、递归遍历所引用的源事件的能力,以及面向模型的工具。[跟踪决策](../../../.agents/notes/implemented/feature/2026-07-13-session-query-tracing.md) 负责关系语义;SQLite 归属和 tokenizer 决策位于[已实现搜索记录](../../../.agents/notes/implemented/feature/2026-07-10-sqlite-session-query-provider.md)。
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Combined session-history reads, traces, filters, and full-text search seam.
|
||||
* Service Definition for combined session-history reads, traces, filters, and full-text search.
|
||||
*
|
||||
* @module @deepseek-ai/dsh-session-query
|
||||
*/
|
||||
@@ -283,11 +283,11 @@ export abstract class SessionQueryService extends Service {
|
||||
}
|
||||
|
||||
/**
|
||||
* Trace one event's direct positional and provenance relationships.
|
||||
* Trace one event's direct positional replacements and cited source events.
|
||||
* @param request - target session id and event seq.
|
||||
* @param signal - optional cancellation for persisted source resolution.
|
||||
* @returns source header, direct links, and the target's positional replacement chain.
|
||||
* @throws when source resolution fails, the target is absent, or surface/provenance validation fails.
|
||||
* @throws when source resolution fails, the target is absent, or surface/source-event validation fails.
|
||||
*/
|
||||
async traceEvent(request: SessionEventTraceRequest, signal?: AbortSignal): Promise<SessionEventTraceObservation> {
|
||||
const loaded = await this._corpus.load(request.sessionId, signal)
|
||||
|
||||
@@ -60,7 +60,7 @@ export function currentSurfaceEvents(
|
||||
* @param sessionId - owner of the event log.
|
||||
* @param events - detached raw event log.
|
||||
* @param seq - target event seq.
|
||||
* @returns direct surface and provenance relationships.
|
||||
* @returns direct surface replacements and relationships to cited source events.
|
||||
*/
|
||||
export function traceEvent(
|
||||
sessionId: SessionId,
|
||||
|
||||
@@ -93,7 +93,7 @@ export type SessionLineageTrace = {
|
||||
}
|
||||
)
|
||||
|
||||
/** Request for direct surface and provenance relationships around one event. */
|
||||
/** Request for direct surface replacements and relationships to cited source events around one event. */
|
||||
export interface SessionEventTraceRequest {
|
||||
/** Session that owns the target event. */
|
||||
sessionId: SessionId
|
||||
@@ -101,7 +101,7 @@ export interface SessionEventTraceRequest {
|
||||
seq: number
|
||||
}
|
||||
|
||||
/** Direct surface and provenance relationships for one event. */
|
||||
/** Direct surface replacements and relationships to cited source events for one event. */
|
||||
export interface SessionEventTrace {
|
||||
/** Lightweight target record. */
|
||||
target: SessionEventRecord
|
||||
@@ -111,9 +111,9 @@ export interface SessionEventTrace {
|
||||
replacementChain: number[]
|
||||
/** Surface nodes directly removed when the target itself performed a replacement. */
|
||||
replacedEventSeqs: number[]
|
||||
/** Direct logged provenance sources in their recorded order. */
|
||||
/** Earlier events cited directly as sources, in their recorded order. */
|
||||
sourceEventSeqs: number[]
|
||||
/** Later events that directly name the target as a provenance source, in log order. */
|
||||
/** Later events that directly cite the target as a source, in log order. */
|
||||
derivedEventSeqs: number[]
|
||||
}
|
||||
|
||||
|
||||
@@ -275,7 +275,7 @@ describe('session lineage tracing', () => {
|
||||
})
|
||||
|
||||
describe('session event tracing', () => {
|
||||
it('returns direct replacement and provenance links in their contract order', async () => {
|
||||
it('returns direct replacement and cited source-event links in their contract order', async () => {
|
||||
const ctx = await queryContext()
|
||||
const session = ctx.sessions.create(SessionId('trace'))
|
||||
appendTraceEvents(session)
|
||||
@@ -380,7 +380,7 @@ describe('session event tracing', () => {
|
||||
.rejects.toThrow(expectCode('SESSION_QUERY_SOURCE_CONFLICT'))
|
||||
})
|
||||
|
||||
it('checks target existence before surface or provenance analysis', async () => {
|
||||
it('checks target existence before surface or source-event analysis', async () => {
|
||||
const bad = header('bad-target')
|
||||
const malformed: SessionEvent[] = [appendEvent(0), {
|
||||
type: 'assistant/message',
|
||||
|
||||
@@ -95,7 +95,7 @@ export function apply(ctx: Context, config: Config): void {
|
||||
|
||||
ctx.tools.register(defineTool({
|
||||
name: 'session_event_trace',
|
||||
description: 'Read every direct replacement and provenance relationship for one event in an authorized session.',
|
||||
description: 'Read every direct replacement and relationship to a cited source event for one event in an authorized session.',
|
||||
parameters: {
|
||||
...toolInput.targetSessionParameter,
|
||||
seq: { type: 'integer', required: true, description: 'Target event sequence number.' },
|
||||
|
||||
@@ -157,7 +157,7 @@ function formatEventTrace(
|
||||
`Replaced by: ${trace.replacedBy ?? 'none'}`,
|
||||
`Replacement chain: ${seqList(trace.replacementChain)}`,
|
||||
`Events replaced by target: ${seqList(trace.replacedEventSeqs)}`,
|
||||
`Direct provenance sources: ${seqList(trace.sourceEventSeqs)}`,
|
||||
`Events cited directly as sources: ${seqList(trace.sourceEventSeqs)}`,
|
||||
`Direct derived events: ${seqList(trace.derivedEventSeqs)}`,
|
||||
].join('\n')
|
||||
}
|
||||
|
||||
@@ -1978,6 +1978,7 @@ describe('trace and exact read rendering', () => {
|
||||
)
|
||||
const result = await mounted.call('session_event_trace', { session_id: session.id, seq: 0 })
|
||||
expect(text(result)).toContain('Replacement chain: 1')
|
||||
expect(text(result)).toContain('Events cited directly as sources: none')
|
||||
expect(text(result)).toContain('Direct derived events: 1')
|
||||
expect(text(result)).toContain(new Date(session.events[0]?.time ?? 0).toISOString())
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user