paseo-plugin-zcode-provider 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/NOTICE.md +29 -0
- package/README.md +98 -2
- package/client/diagnostics.tsx +397 -0
- package/client/setup.tsx +347 -0
- package/icon.svg +1 -0
- package/index.client.tsx +22 -0
- package/index.server.ts +21 -0
- package/package.json +75 -4
- package/paseo-plugin.json +6 -0
- package/server/attachments.ts +150 -0
- package/server/build-info.ts +2 -0
- package/server/conversation.ts +319 -0
- package/server/diagnostics.ts +235 -0
- package/server/discovery/discover.ts +225 -0
- package/server/discovery/manifest.ts +36 -0
- package/server/discovery/types.ts +30 -0
- package/server/errors.ts +36 -0
- package/server/host/bridge.ts +463 -0
- package/server/host/schemas.ts +119 -0
- package/server/logger.ts +19 -0
- package/server/mapping.ts +270 -0
- package/server/models.ts +68 -0
- package/server/persistence.ts +146 -0
- package/server/presentation.ts +428 -0
- package/server/provider.ts +831 -0
- package/server/runtime/managed.ts +501 -0
- package/server/runtime/pins.ts +72 -0
- package/server/runtime-setup.ts +102 -0
- package/server/session-types.ts +49 -0
- package/server/session.ts +866 -0
- package/server/status.ts +89 -0
- package/server/timeline.ts +18 -0
- package/server/vendor/zcode/LICENSE +202 -0
- package/server/vendor/zcode/NOTICE.md +70 -0
- package/server/vendor/zcode/THIRD-PARTY-NOTICES.md +37 -0
- package/server/vendor/zcode/packages/model-option-map/src/compiler.ts +92 -0
- package/server/vendor/zcode/packages/model-option-map/src/evaluator.ts +214 -0
- package/server/vendor/zcode/packages/model-option-map/src/index.ts +5 -0
- package/server/vendor/zcode/packages/model-option-map/src/merge-patch.ts +97 -0
- package/server/vendor/zcode/packages/model-option-map/src/option-maps.ts +42 -0
- package/server/vendor/zcode/packages/model-option-map/src/parser.ts +240 -0
- package/server/vendor/zcode/packages/model-option-map/src/tokenizer.ts +141 -0
- package/server/vendor/zcode/packages/model-option-map/src/types.ts +36 -0
- package/server/vendor/zcode/packages/rpc/src/buffer.ts +88 -0
- package/server/vendor/zcode/packages/rpc/src/channelClient.ts +275 -0
- package/server/vendor/zcode/packages/rpc/src/channelServer.ts +283 -0
- package/server/vendor/zcode/packages/rpc/src/channels.shared.ts +66 -0
- package/server/vendor/zcode/packages/rpc/src/channels.ts +4 -0
- package/server/vendor/zcode/packages/rpc/src/delayedChannel.ts +17 -0
- package/server/vendor/zcode/packages/rpc/src/foundation.ts +260 -0
- package/server/vendor/zcode/packages/rpc/src/protocol.ts +397 -0
- package/server/vendor/zcode/packages/rpc/src/proxy-channel.ts +213 -0
- package/server/vendor/zcode/packages/rpc/src/serialization.ts +291 -0
- package/server/vendor/zcode/packages/shared/src/account-provider-state.ts +13 -0
- package/server/vendor/zcode/packages/shared/src/background-bash-output.ts +24 -0
- package/server/vendor/zcode/packages/shared/src/background-task-controls.ts +404 -0
- package/server/vendor/zcode/packages/shared/src/bash-output-display.ts +11 -0
- package/server/vendor/zcode/packages/shared/src/bots.ts +558 -0
- package/server/vendor/zcode/packages/shared/src/browser-use/backend.ts +80 -0
- package/server/vendor/zcode/packages/shared/src/browser-use/command-metadata.ts +170 -0
- package/server/vendor/zcode/packages/shared/src/browser-use/commands.ts +588 -0
- package/server/vendor/zcode/packages/shared/src/browser-use/result.ts +130 -0
- package/server/vendor/zcode/packages/shared/src/browser-use/snapshot.ts +77 -0
- package/server/vendor/zcode/packages/shared/src/command-types.ts +96 -0
- package/server/vendor/zcode/packages/shared/src/config-schema.ts +8 -0
- package/server/vendor/zcode/packages/shared/src/cuaAccessibilitySettings.ts +41 -0
- package/server/vendor/zcode/packages/shared/src/database-startup.ts +178 -0
- package/server/vendor/zcode/packages/shared/src/env.ts +63 -0
- package/server/vendor/zcode/packages/shared/src/execution-output-preview.ts +14 -0
- package/server/vendor/zcode/packages/shared/src/localTtft.ts +192 -0
- package/server/vendor/zcode/packages/shared/src/model-config.ts +123 -0
- package/server/vendor/zcode/packages/shared/src/model-execution.ts +23 -0
- package/server/vendor/zcode/packages/shared/src/model-provider-family.ts +171 -0
- package/server/vendor/zcode/packages/shared/src/model-provider-types.ts +81 -0
- package/server/vendor/zcode/packages/shared/src/model-selection.ts +60 -0
- package/server/vendor/zcode/packages/shared/src/oauth.ts +203 -0
- package/server/vendor/zcode/packages/shared/src/official-mcp-auth.ts +272 -0
- package/server/vendor/zcode/packages/shared/src/official-mcp-tool-error.ts +68 -0
- package/server/vendor/zcode/packages/shared/src/process-diagnostic.ts +42 -0
- package/server/vendor/zcode/packages/shared/src/protocol.ts +369 -0
- package/server/vendor/zcode/packages/shared/src/provider-family-connection-selection.ts +32 -0
- package/server/vendor/zcode/packages/shared/src/remoteAssetInstallMode.ts +11 -0
- package/server/vendor/zcode/packages/shared/src/remoteResourcePackages.ts +91 -0
- package/server/vendor/zcode/packages/shared/src/runtimeEnv.ts +315 -0
- package/server/vendor/zcode/packages/shared/src/settings-source.ts +10 -0
- package/server/vendor/zcode/packages/shared/src/usage-quota.ts +74 -0
- package/server/vendor/zcode/packages/shared/src/usage-stats.ts +462 -0
- package/server/vendor/zcode/packages/shared/src/validationAppSettings.ts +562 -0
- package/server/vendor/zcode/packages/shared/src/workspacePurpose.ts +2 -0
- package/server/vendor/zcode/packages/shared/src/wslUserValidation.ts +33 -0
- package/server/vendor/zcode/packages/shared/src/zcode-agent-policy.ts +25 -0
- package/server/vendor/zcode/packages/shared/src/zcode-media-policy.ts +10 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol/index.ts +3720 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-legacy-types.ts +529 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/apply.ts +218 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/attachment-ref.ts +14 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/command.ts +482 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/core.ts +100 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/create-workflow-display.ts +156 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/cuaPermission.ts +41 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/delta.ts +147 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/input-intent.ts +69 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/rows.ts +432 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/session-config.ts +43 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/sessions-index-workflow-activity.ts +195 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/sessions-index.ts +85 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/shared-context-import.ts +38 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/shared-context-ref.ts +10 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/snapshot.ts +509 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/submission.ts +5 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/toolDisplay.ts +264 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/transport.ts +1152 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire-assembler.ts +574 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire-binary.ts +65 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire-codec.ts +240 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire-fault.ts +39 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire.ts +159 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-artifacts.ts +291 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-observation-display.ts +281 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-row-meta.ts +163 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-run-settings-command.ts +62 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-runs-delta.ts +517 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-runs.ts +512 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workspace-config.ts +81 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workspace-hook-review.ts +210 -0
- package/server/vendor/zcode/packages/shared/src/zcode-task-mode-schema.ts +6 -0
- package/server/vendor/zcode/packages/shared/src/zcode-task-types-core.ts +1187 -0
- package/server/vendor/zcode/packages/shared/src/zcodeEndpoint.ts +296 -0
- package/server/vendor/zcode/provenance.json +405 -0
- package/shared/diagnostics.ts +52 -0
- package/shared/runtime-setup.ts +75 -0
- package/vendor/acp-registry/LICENSE +176 -0
- package/vendor/paseo/LICENSE +211 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// sessions-index topic:列表活性数据源;conflated 最新态,永不溢出。
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { timestampSchema } from "./core.js";
|
|
4
|
+
import { sessionWorkflowActivitySchema } from "./sessions-index-workflow-activity.js";
|
|
5
|
+
import {
|
|
6
|
+
goalStateSchema,
|
|
7
|
+
interactionAutoResolutionSchema,
|
|
8
|
+
sessionMetaStateSchema,
|
|
9
|
+
sessionPhaseSchema,
|
|
10
|
+
} from "./snapshot.js";
|
|
11
|
+
|
|
12
|
+
export const sessionPendingInteractionSummarySchema = z.object({
|
|
13
|
+
interactionId: z.string(),
|
|
14
|
+
kind: z.enum(["permission", "userInput"]),
|
|
15
|
+
// 只下发轻量工具身份,侧栏据此区分 AskUserQuestion 与其他阻塞确认;不携带问题或答案。
|
|
16
|
+
toolName: z.string().optional(),
|
|
17
|
+
autoResolution: interactionAutoResolutionSchema.optional(),
|
|
18
|
+
});
|
|
19
|
+
export type SessionPendingInteractionSummary = z.infer<
|
|
20
|
+
typeof sessionPendingInteractionSummarySchema
|
|
21
|
+
>;
|
|
22
|
+
|
|
23
|
+
export const pendingInteractionSummarySchema = z.object({
|
|
24
|
+
permissionCount: z.number().int().nonnegative(),
|
|
25
|
+
userInputCount: z.number().int().nonnegative(),
|
|
26
|
+
});
|
|
27
|
+
export type PendingInteractionSummary = z.infer<typeof pendingInteractionSummarySchema>;
|
|
28
|
+
|
|
29
|
+
export const sessionSummarySchema = z.object({
|
|
30
|
+
sessionId: z.string(),
|
|
31
|
+
workspaceId: z.string(),
|
|
32
|
+
// fork 树。
|
|
33
|
+
parentSessionId: z.string().optional(),
|
|
34
|
+
title: z.string(),
|
|
35
|
+
// custom = 用户显式重命名;default/generated 都不是产品语义上的手动标题。
|
|
36
|
+
// optional 是为了兼容旧 sessions-index frame / 旧持久化摘要。
|
|
37
|
+
titleSource: sessionMetaStateSchema.shape.titleSource.optional(),
|
|
38
|
+
phase: sessionPhaseSchema,
|
|
39
|
+
sessionEnded: z.boolean(),
|
|
40
|
+
// 列表小圆点用(此处保留布尔,避免为侧栏订阅整个 backgroundWorks)。
|
|
41
|
+
hasBackgroundWork: z.boolean(),
|
|
42
|
+
// 侧栏工作流运行行:有界的 run 摘要,
|
|
43
|
+
// 只装画迷你轨道要的字段;会话没有任何 run 时缺席。optional 兼容旧 frame / 旧 CLI。
|
|
44
|
+
workflowActivity: sessionWorkflowActivitySchema.optional(),
|
|
45
|
+
pendingInteraction: sessionPendingInteractionSummarySchema.optional(),
|
|
46
|
+
// 侧栏只需要 kind/count,不下发问题、命令或答案等敏感 payload。
|
|
47
|
+
// optional 兼容旧 sessions-index frame / stored summary。
|
|
48
|
+
pendingInteractionSummary: pendingInteractionSummarySchema.optional(),
|
|
49
|
+
goalStatus: goalStateSchema.shape.status.optional(),
|
|
50
|
+
// 未读推导:客户端本地记 lastSeenActivityAt 比较(不用 seq,epoch 会重置)。
|
|
51
|
+
lastActivityAt: timestampSchema,
|
|
52
|
+
// ≤120 字符。
|
|
53
|
+
lastAssistantPreview: z.string().optional(),
|
|
54
|
+
createdAt: timestampSchema,
|
|
55
|
+
});
|
|
56
|
+
export type SessionSummary = z.infer<typeof sessionSummarySchema>;
|
|
57
|
+
|
|
58
|
+
export const sessionsIndexSnapshotSchema = z.object({
|
|
59
|
+
protocolVersion: z.literal(1),
|
|
60
|
+
workspaceId: z.string(),
|
|
61
|
+
// host 级列表日志代际(与各 session 的 logEpoch 无关)。
|
|
62
|
+
logEpoch: z.string(),
|
|
63
|
+
// 无序;排序是客户端展示逻辑。
|
|
64
|
+
sessions: z.array(sessionSummarySchema),
|
|
65
|
+
});
|
|
66
|
+
export type SessionsIndexSnapshot = z.infer<typeof sessionsIndexSnapshotSchema>;
|
|
67
|
+
|
|
68
|
+
export const sessionsIndexDeltaSchema = z.discriminatedUnion("op", [
|
|
69
|
+
// conflation key = sessionId。
|
|
70
|
+
z.object({ op: z.literal("session.upserted"), session: sessionSummarySchema }),
|
|
71
|
+
z.object({ op: z.literal("session.removed"), sessionId: z.string() }),
|
|
72
|
+
]);
|
|
73
|
+
export type SessionsIndexDelta = z.infer<typeof sessionsIndexDeltaSchema>;
|
|
74
|
+
|
|
75
|
+
/** sessions-index topic key 构造(与 parseSessionsIndexTopic 对偶)。 */
|
|
76
|
+
export function sessionsIndexTopic(workspaceId: string): string {
|
|
77
|
+
return `sessions-index/${workspaceId}`;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** sessions-index topic key 解析("sessions-index/<workspaceId>")。 */
|
|
81
|
+
export function parseSessionsIndexTopic(topic: string): string | null {
|
|
82
|
+
if (!topic.startsWith("sessions-index/")) return null;
|
|
83
|
+
const workspaceId = topic.slice("sessions-index/".length);
|
|
84
|
+
return workspaceId.length > 0 ? workspaceId : null;
|
|
85
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
const sharedContextImportV2StateSchema = z
|
|
4
|
+
.object({
|
|
5
|
+
contextId: z.string().trim().min(1),
|
|
6
|
+
title: z.string().trim().min(1),
|
|
7
|
+
shareUrl: z
|
|
8
|
+
.string()
|
|
9
|
+
.url()
|
|
10
|
+
.refine((value) => {
|
|
11
|
+
try {
|
|
12
|
+
const url = new URL(value);
|
|
13
|
+
return (
|
|
14
|
+
(url.protocol === "https:" || url.protocol === "http:") &&
|
|
15
|
+
url.search === "" &&
|
|
16
|
+
url.hash === "" &&
|
|
17
|
+
/^\/cn\/share\/[^/]+$/u.test(url.pathname)
|
|
18
|
+
);
|
|
19
|
+
} catch {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
}, "shareUrl must use the canonical /cn/share/<code> path"),
|
|
23
|
+
status: z.enum(["pending", "reserved", "attached", "discarded"]),
|
|
24
|
+
})
|
|
25
|
+
.strict();
|
|
26
|
+
// shareUrl 硬绑 /cn/share/<code>。将来换域名、或改用英文站 /share/<code> 作为
|
|
27
|
+
// canonical 时,存量会话的持久化 provenance 会校验失败(本地持久化,不是 wire,所以不在
|
|
28
|
+
// 「响应宽容」那条纪律的覆盖范围内)。真要改 canonical URL 形状时,这里要先加一个接受旧形状
|
|
29
|
+
// 的 legacy 分支——照 legacySharedContextImportStateSchema 的做法。
|
|
30
|
+
|
|
31
|
+
const legacySharedContextImportStateSchema = z.object({ title: z.string().trim().min(1) }).strict();
|
|
32
|
+
|
|
33
|
+
export const sharedContextImportStateSchema = z.union([
|
|
34
|
+
sharedContextImportV2StateSchema,
|
|
35
|
+
legacySharedContextImportStateSchema,
|
|
36
|
+
]);
|
|
37
|
+
|
|
38
|
+
export type SharedContextImportState = z.infer<typeof sharedContextImportStateSchema>;
|
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
/* oxlint-disable max-lines -- v4 snapshot schema is a frozen cross-process contract; additions stay grouped here. */
|
|
2
|
+
// ConversationSnapshot A 区。
|
|
3
|
+
// A 区更新语义 = 字段级整体替换(state.updated),绝不深合并——深合并是错乱之母。
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { sharedContextImportStateSchema } from "./shared-context-import.js";
|
|
6
|
+
export { sharedContextImportStateSchema } from "./shared-context-import.js";
|
|
7
|
+
import { conversationInputDispatchSchema, conversationInputIntentSchema } from "./input-intent.js";
|
|
8
|
+
import {
|
|
9
|
+
zcodeContextUsageBreakdownSchema,
|
|
10
|
+
zcodeInteractionRequestOriginSchema,
|
|
11
|
+
zcodePermissionResponseSchema,
|
|
12
|
+
zcodeSessionContextCacheUsageSchema,
|
|
13
|
+
} from "../zcode-protocol-legacy-types.js";
|
|
14
|
+
import { timestampSchema } from "./core.js";
|
|
15
|
+
import { conversationRowSchema } from "./rows.js";
|
|
16
|
+
import { toolCallDisplaySchema } from "./toolDisplay.js";
|
|
17
|
+
|
|
18
|
+
import { workspaceHookReviewRequestPayloadSchema } from "./workspace-hook-review.js";
|
|
19
|
+
import { workflowRunsStateSchema } from "./workflow-runs.js";
|
|
20
|
+
import { sessionConfigStateSchema, sessionModelTransitionSchema } from "./session-config.js";
|
|
21
|
+
export {
|
|
22
|
+
sessionConfigStateSchema,
|
|
23
|
+
sessionModelTransitionSchema,
|
|
24
|
+
type SessionConfigState,
|
|
25
|
+
type SessionModelTransition,
|
|
26
|
+
} from "./session-config.js";
|
|
27
|
+
// ── SessionControl ──
|
|
28
|
+
export const sessionPhaseSchema = z.enum([
|
|
29
|
+
// draft 裁决保留——纯内存态、sessions-index 可见、无 row、
|
|
30
|
+
// 不落盘、CLI 重启即消失;firstInput 到达 → prewarming/running。
|
|
31
|
+
"draft",
|
|
32
|
+
"prewarming",
|
|
33
|
+
"running",
|
|
34
|
+
"completedSuccess",
|
|
35
|
+
"completedInterrupted",
|
|
36
|
+
"error",
|
|
37
|
+
]);
|
|
38
|
+
export type SessionPhase = z.infer<typeof sessionPhaseSchema>;
|
|
39
|
+
|
|
40
|
+
export const stopTargetKindSchema = z.enum([
|
|
41
|
+
"assistant",
|
|
42
|
+
"tool",
|
|
43
|
+
"subagent",
|
|
44
|
+
"compact",
|
|
45
|
+
"goalVerifier",
|
|
46
|
+
"goalContinuation",
|
|
47
|
+
"turnSteer",
|
|
48
|
+
"mixed",
|
|
49
|
+
"unknown",
|
|
50
|
+
]);
|
|
51
|
+
export type StopTargetKind = z.infer<typeof stopTargetKindSchema>;
|
|
52
|
+
|
|
53
|
+
export const activeWorkSummarySchema = z.object({
|
|
54
|
+
kind: z.enum([
|
|
55
|
+
"primaryTurn",
|
|
56
|
+
"foregroundSubagent",
|
|
57
|
+
"compact",
|
|
58
|
+
"goalVerifier",
|
|
59
|
+
"goalContinuation",
|
|
60
|
+
"turnSteer",
|
|
61
|
+
]),
|
|
62
|
+
foregroundExecutionId: z.string().min(1).optional(),
|
|
63
|
+
startedAt: timestampSchema,
|
|
64
|
+
});
|
|
65
|
+
export type ActiveWorkSummary = z.infer<typeof activeWorkSummarySchema>;
|
|
66
|
+
|
|
67
|
+
// 错误码分为 fault.*、proto.* 与 guard.*。
|
|
68
|
+
export const errorAttributionSchema = z
|
|
69
|
+
.object({
|
|
70
|
+
source: z.enum(["provider", "runtime", "tool", "network"]).optional(),
|
|
71
|
+
reason: z.string().min(1).max(160).optional(),
|
|
72
|
+
errorPhase: z
|
|
73
|
+
.enum([
|
|
74
|
+
"prepare",
|
|
75
|
+
"configuration",
|
|
76
|
+
"connect",
|
|
77
|
+
"response",
|
|
78
|
+
"stream",
|
|
79
|
+
"parse",
|
|
80
|
+
"validation",
|
|
81
|
+
"unhandled",
|
|
82
|
+
])
|
|
83
|
+
.optional(),
|
|
84
|
+
exceptionKind: z
|
|
85
|
+
.enum([
|
|
86
|
+
"api_call",
|
|
87
|
+
"generic",
|
|
88
|
+
"protocol",
|
|
89
|
+
"provider_business",
|
|
90
|
+
"transport",
|
|
91
|
+
"type_error",
|
|
92
|
+
"validation",
|
|
93
|
+
])
|
|
94
|
+
.optional(),
|
|
95
|
+
providerId: z.string().min(1).max(160).optional(),
|
|
96
|
+
modelId: z.string().min(1).max(160).optional(),
|
|
97
|
+
providerKind: z.string().min(1).max(160).optional(),
|
|
98
|
+
transport: z.enum(["http", "sse", "websocket"]).optional(),
|
|
99
|
+
statusCode: z.number().int().min(100).max(599).optional(),
|
|
100
|
+
providerErrorCode: z.string().min(1).max(160).optional(),
|
|
101
|
+
retryable: z.boolean().optional(),
|
|
102
|
+
})
|
|
103
|
+
.strict();
|
|
104
|
+
export type ErrorAttribution = z.infer<typeof errorAttributionSchema>;
|
|
105
|
+
|
|
106
|
+
export const sessionErrorInfoSchema = z.object({
|
|
107
|
+
code: z.string(),
|
|
108
|
+
message: z.string(),
|
|
109
|
+
recoverable: z.boolean(),
|
|
110
|
+
at: timestampSchema,
|
|
111
|
+
source: z.enum(["provider", "runtime", "tool", "network"]),
|
|
112
|
+
traceId: z.string().optional(),
|
|
113
|
+
detail: z.string().optional(),
|
|
114
|
+
underlyingErrorMessage: z.string().optional(),
|
|
115
|
+
underlyingErrorDetail: z.string().optional(),
|
|
116
|
+
attribution: errorAttributionSchema.optional(),
|
|
117
|
+
});
|
|
118
|
+
export type SessionErrorInfo = z.infer<typeof sessionErrorInfoSchema>;
|
|
119
|
+
|
|
120
|
+
export const apiRetryStateSchema = z.object({
|
|
121
|
+
attempt: z.number(),
|
|
122
|
+
maxAttempts: z.number(),
|
|
123
|
+
nextRetryAt: timestampSchema,
|
|
124
|
+
reasonCode: z.string(),
|
|
125
|
+
});
|
|
126
|
+
export type ApiRetryState = z.infer<typeof apiRetryStateSchema>;
|
|
127
|
+
|
|
128
|
+
export const sessionControlSchema = z.object({
|
|
129
|
+
phase: sessionPhaseSchema,
|
|
130
|
+
// 派生值(= phase ∈ completed*),为 UI 便利保留。
|
|
131
|
+
sessionEnded: z.boolean(),
|
|
132
|
+
canStop: z.boolean(),
|
|
133
|
+
stopState: z.enum(["idle", "stoppable", "stopping"]),
|
|
134
|
+
stopTargetKind: stopTargetKindSchema,
|
|
135
|
+
// 轻量证据/悬浮提示用,UI 不得据此推导 flag。
|
|
136
|
+
// hasBackgroundWork 不在载荷内:客户端按 backgroundWorks.some(w => w.status === "running") 一行派生。
|
|
137
|
+
activeWorks: z.array(activeWorkSummarySchema),
|
|
138
|
+
lastError: sessionErrorInfoSchema.nullable(),
|
|
139
|
+
apiRetry: apiRetryStateSchema.nullable(),
|
|
140
|
+
});
|
|
141
|
+
export type SessionControl = z.infer<typeof sessionControlSchema>;
|
|
142
|
+
|
|
143
|
+
// ── availability 与 inputRouting ──
|
|
144
|
+
export const actionAvailabilitySchema = z.discriminatedUnion("allowed", [
|
|
145
|
+
z.object({ allowed: z.literal(true) }),
|
|
146
|
+
// reasonCode = product-protocol guard id,驱动禁用态 tooltip。
|
|
147
|
+
z.object({ allowed: z.literal(false), reasonCode: z.string() }),
|
|
148
|
+
]);
|
|
149
|
+
export type ActionAvailability = z.infer<typeof actionAvailabilitySchema>;
|
|
150
|
+
|
|
151
|
+
export const sessionActionAvailabilitySchema = z.object({
|
|
152
|
+
fork: actionAvailabilitySchema,
|
|
153
|
+
compact: actionAvailabilitySchema,
|
|
154
|
+
switchModelConfig: actionAvailabilitySchema,
|
|
155
|
+
setFollowupMode: actionAvailabilitySchema,
|
|
156
|
+
queueEdit: actionAvailabilitySchema,
|
|
157
|
+
sendQueuedNow: actionAvailabilitySchema,
|
|
158
|
+
pauseGoal: actionAvailabilitySchema,
|
|
159
|
+
resumeGoal: actionAvailabilitySchema,
|
|
160
|
+
});
|
|
161
|
+
export type SessionActionAvailability = z.infer<typeof sessionActionAvailabilitySchema>;
|
|
162
|
+
|
|
163
|
+
export const inputRoutingSchema = z.object({
|
|
164
|
+
// choice:held(completed+queue>0+autoDrain=false)下
|
|
165
|
+
// 输入不静默入队,客户端呈现「清空 queue 后发送 / 保留 queue 立即发送」。
|
|
166
|
+
mode: z.enum(["startNow", "enqueue", "guide", "reject", "choice"]),
|
|
167
|
+
// mode=reject 必带;enqueue/guide/choice 可带(如 guide 不合格回退原因)。
|
|
168
|
+
reasonCode: z.string().optional(),
|
|
169
|
+
});
|
|
170
|
+
export type InputRouting = z.infer<typeof inputRoutingSchema>;
|
|
171
|
+
|
|
172
|
+
// ── meta(会话级元信息:标题)。renameSession/自动标题落此。──
|
|
173
|
+
export const sessionMetaStateSchema = z.object({
|
|
174
|
+
title: z.string(),
|
|
175
|
+
// default = 未命名;generated = 模型自动生成;custom = 用户显式重命名(不再被自动标题覆盖)。
|
|
176
|
+
titleSource: z.enum(["default", "generated", "custom"]),
|
|
177
|
+
});
|
|
178
|
+
export type SessionMetaState = z.infer<typeof sessionMetaStateSchema>;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* 分享导入的只读来源标记。
|
|
182
|
+
*
|
|
183
|
+
* shared_context 正文只给模型使用,不能通过 userInput row 伪造到会话气泡里;
|
|
184
|
+
* 这个 additive 元数据让 Desktop 在新会话中仍能明确告诉用户上下文来自哪里。
|
|
185
|
+
*/
|
|
186
|
+
export type { SharedContextImportState } from "./shared-context-import.js";
|
|
187
|
+
|
|
188
|
+
// ── usage。conflation:值未变不下发──
|
|
189
|
+
export const sessionUsageStateSchema = z.object({
|
|
190
|
+
contextWindow: z
|
|
191
|
+
.object({
|
|
192
|
+
usedTokens: z.number(),
|
|
193
|
+
maxTokens: z.number(),
|
|
194
|
+
autoCompactThresholdTokens: z.number().nullable(),
|
|
195
|
+
cache: zcodeSessionContextCacheUsageSchema.optional(),
|
|
196
|
+
breakdown: zcodeContextUsageBreakdownSchema.optional(),
|
|
197
|
+
})
|
|
198
|
+
.nullable(),
|
|
199
|
+
cumulative: z.object({
|
|
200
|
+
inputTokens: z.number(),
|
|
201
|
+
outputTokens: z.number(),
|
|
202
|
+
cacheReadTokens: z.number(),
|
|
203
|
+
cacheWriteTokens: z.number(),
|
|
204
|
+
}),
|
|
205
|
+
});
|
|
206
|
+
export type SessionUsageState = z.infer<typeof sessionUsageStateSchema>;
|
|
207
|
+
|
|
208
|
+
// ── queue(不持久化,裁决:CLI 进程死亡即丢,客户端对账后由用户决定重发)──
|
|
209
|
+
export const queueItemSchema = conversationInputIntentSchema.extend({
|
|
210
|
+
dispatch: conversationInputDispatchSchema.extend({
|
|
211
|
+
state: z.enum(["queued", "reserved", "promoting"]),
|
|
212
|
+
}),
|
|
213
|
+
toolDisallowlist: z.array(z.string().min(1)).optional(),
|
|
214
|
+
});
|
|
215
|
+
export type QueueItem = z.infer<typeof queueItemSchema>;
|
|
216
|
+
|
|
217
|
+
export const queueStateSchema = z.object({
|
|
218
|
+
items: z.array(queueItemSchema),
|
|
219
|
+
// stop 后 = false(暂停队列);setAutoDrain 恢复。
|
|
220
|
+
autoDrain: z.boolean(),
|
|
221
|
+
// additive:旧快照缺省时 UI 使用通用暂停文案;Stop/TurnError 可显示原因文案。
|
|
222
|
+
pauseReason: z.enum(["stopped", "manual", "error"]).optional(),
|
|
223
|
+
});
|
|
224
|
+
export type QueueState = z.infer<typeof queueStateSchema>;
|
|
225
|
+
|
|
226
|
+
// ── pendingInteractions(阻塞交互 → 状态)──
|
|
227
|
+
export const MAX_PERMISSION_FEEDBACK_CHARS = 4_096;
|
|
228
|
+
|
|
229
|
+
export const PERMISSION_FULL_ACCESS_OPTION_ID = "fullAccess";
|
|
230
|
+
const permissionOptionSchema = z.object({
|
|
231
|
+
optionId: z.string(),
|
|
232
|
+
label: z.string(),
|
|
233
|
+
kind: z.enum(["allowOnce", "allowAlways", "deny", "custom"]),
|
|
234
|
+
response: zcodePermissionResponseSchema.optional(),
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
export const permissionRequestPayloadSchema = z.object({
|
|
238
|
+
kind: z.literal("permission"),
|
|
239
|
+
toolCallId: z.string(),
|
|
240
|
+
toolName: z.string(),
|
|
241
|
+
summary: z.string(),
|
|
242
|
+
detail: z.unknown(),
|
|
243
|
+
// additive:旧 snapshot 缺省时 UI 不显示反馈输入;V4 新投影可显式开启。
|
|
244
|
+
freeText: z.boolean().optional(),
|
|
245
|
+
origin: zcodeInteractionRequestOriginSchema.optional(),
|
|
246
|
+
// 工具自报的确认预览,复用 row 的 display 投影(同一有界形状)。缺省 = 纯文本 ask。
|
|
247
|
+
// 同样不设门:预览解析失败退化成纯文本 ask,不拒整份 snapshot(见 toolDisplay.ts 注释)。
|
|
248
|
+
display: toolCallDisplaySchema.optional().catch(undefined),
|
|
249
|
+
// 独立 additive 能力:旧 UI 忽略此字段,仍只显示原 options,不出现半实现授权入口。
|
|
250
|
+
fullAccessOption: permissionOptionSchema
|
|
251
|
+
.extend({
|
|
252
|
+
optionId: z.literal(PERMISSION_FULL_ACCESS_OPTION_ID),
|
|
253
|
+
kind: z.literal("custom"),
|
|
254
|
+
})
|
|
255
|
+
.optional(),
|
|
256
|
+
options: z.array(permissionOptionSchema),
|
|
257
|
+
});
|
|
258
|
+
export type PermissionRequestPayload = z.infer<typeof permissionRequestPayloadSchema>;
|
|
259
|
+
|
|
260
|
+
export const userInputOptionPayloadSchema = z.object({
|
|
261
|
+
value: z.string(),
|
|
262
|
+
label: z.string(),
|
|
263
|
+
description: z.string().optional(),
|
|
264
|
+
preview: z.string().optional(),
|
|
265
|
+
});
|
|
266
|
+
export type UserInputOptionPayload = z.infer<typeof userInputOptionPayloadSchema>;
|
|
267
|
+
|
|
268
|
+
export const userInputQuestionPayloadSchema = z.object({
|
|
269
|
+
question: z.string(),
|
|
270
|
+
header: z.string(),
|
|
271
|
+
options: z.array(userInputOptionPayloadSchema),
|
|
272
|
+
multiSelect: z.boolean().optional(),
|
|
273
|
+
});
|
|
274
|
+
export type UserInputQuestionPayload = z.infer<typeof userInputQuestionPayloadSchema>;
|
|
275
|
+
|
|
276
|
+
export const userInputRequestPayloadSchema = z.object({
|
|
277
|
+
kind: z.literal("userInput"),
|
|
278
|
+
prompt: z.string(),
|
|
279
|
+
freeText: z.boolean(),
|
|
280
|
+
options: z.array(z.object({ optionId: z.string(), label: z.string() })).optional(),
|
|
281
|
+
// true → 输入框按密码处理,客户端不入草稿/历史。
|
|
282
|
+
sensitive: z.boolean().optional(),
|
|
283
|
+
toolName: z.string().optional(),
|
|
284
|
+
toolCallId: z.string().optional(),
|
|
285
|
+
traceId: z.string().optional(),
|
|
286
|
+
input: z.unknown().optional(),
|
|
287
|
+
schema: z.unknown().optional(),
|
|
288
|
+
questions: z.array(userInputQuestionPayloadSchema).optional(),
|
|
289
|
+
currentQuestionIndex: z.number().optional(),
|
|
290
|
+
answerDrafts: z.record(z.string(), z.array(z.string())).optional(),
|
|
291
|
+
origin: zcodeInteractionRequestOriginSchema.optional(),
|
|
292
|
+
});
|
|
293
|
+
export type UserInputRequestPayload = z.infer<typeof userInputRequestPayloadSchema>;
|
|
294
|
+
|
|
295
|
+
export const interactionAutoResolutionSchema = z.discriminatedUnion("state", [
|
|
296
|
+
z.object({
|
|
297
|
+
state: z.enum(["hiddenGrace", "visibleCountdown"]),
|
|
298
|
+
startedAt: timestampSchema,
|
|
299
|
+
visibleAt: timestampSchema,
|
|
300
|
+
deadlineAt: timestampSchema,
|
|
301
|
+
}),
|
|
302
|
+
z.object({
|
|
303
|
+
state: z.literal("snoozed"),
|
|
304
|
+
startedAt: timestampSchema,
|
|
305
|
+
snoozedAt: timestampSchema,
|
|
306
|
+
}),
|
|
307
|
+
]);
|
|
308
|
+
export type InteractionAutoResolution = z.infer<typeof interactionAutoResolutionSchema>;
|
|
309
|
+
|
|
310
|
+
export const pendingInteractionSchema = z
|
|
311
|
+
.object({
|
|
312
|
+
interactionId: z.string(),
|
|
313
|
+
kind: z.enum(["permission", "userInput", "workspaceHookReview"]),
|
|
314
|
+
// null = 会话级(如 provider 交互和 workspace Hook review)。
|
|
315
|
+
anchorRowId: z.number().nullable(),
|
|
316
|
+
createdAt: timestampSchema,
|
|
317
|
+
autoResolution: interactionAutoResolutionSchema.optional(),
|
|
318
|
+
payload: z.discriminatedUnion("kind", [
|
|
319
|
+
permissionRequestPayloadSchema,
|
|
320
|
+
userInputRequestPayloadSchema,
|
|
321
|
+
workspaceHookReviewRequestPayloadSchema,
|
|
322
|
+
]),
|
|
323
|
+
})
|
|
324
|
+
.superRefine((interaction, context) => {
|
|
325
|
+
if (interaction.kind !== interaction.payload.kind) {
|
|
326
|
+
context.addIssue({
|
|
327
|
+
code: z.ZodIssueCode.custom,
|
|
328
|
+
path: ["kind"],
|
|
329
|
+
message: "pending interaction kind must match payload kind",
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
if (interaction.kind === "workspaceHookReview" && interaction.autoResolution) {
|
|
333
|
+
context.addIssue({
|
|
334
|
+
code: z.ZodIssueCode.custom,
|
|
335
|
+
path: ["autoResolution"],
|
|
336
|
+
message: "workspaceHookReview cannot use AskUserQuestion auto-resolution",
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
if (
|
|
340
|
+
interaction.payload.kind === "workspaceHookReview" &&
|
|
341
|
+
interaction.interactionId !== interaction.payload.interactionId
|
|
342
|
+
) {
|
|
343
|
+
context.addIssue({
|
|
344
|
+
code: z.ZodIssueCode.custom,
|
|
345
|
+
path: ["interactionId"],
|
|
346
|
+
message: "workspaceHookReview interaction id must match its immutable payload",
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
export type PendingInteraction = z.infer<typeof pendingInteractionSchema>;
|
|
351
|
+
|
|
352
|
+
// ── pendingCommands / backgroundWorks ──
|
|
353
|
+
export const commandStateSummarySchema = z.object({
|
|
354
|
+
commandId: z.string(),
|
|
355
|
+
clientId: z.string(),
|
|
356
|
+
type: z.string(),
|
|
357
|
+
state: z.enum(["accepted", "executing"]),
|
|
358
|
+
at: timestampSchema,
|
|
359
|
+
});
|
|
360
|
+
export type CommandStateSummary = z.infer<typeof commandStateSummarySchema>;
|
|
361
|
+
|
|
362
|
+
export const backgroundWorkSummarySchema = z.object({
|
|
363
|
+
workId: z.string(),
|
|
364
|
+
// workflow = workflow run(CreateWorkflow)。**闭集加值的偏斜代价**:
|
|
365
|
+
// 旧桌面收到未知值时整个 state.updated patch 解析失败(已知键的非法值是错误,不是剥离),
|
|
366
|
+
// 于是整帧被 assembler 拒收,且 resync 的 snapshot 携带同一个值、同样失败——不能优雅降级。
|
|
367
|
+
// CLI 与桌面同批发布才使它可接受。
|
|
368
|
+
kind: z.enum(["bash", "subagent", "workflow"]),
|
|
369
|
+
title: z.string(),
|
|
370
|
+
// resultPending = 已完成、结果在 continuation inbox 等待前台空闲;
|
|
371
|
+
// 投递后条目消失(结果本体成为 origin=backgroundResult 的 userInput row)。
|
|
372
|
+
status: z.enum(["running", "resultPending", "failed", "cancelled"]),
|
|
373
|
+
startedAt: timestampSchema,
|
|
374
|
+
endedAt: timestampSchema.optional(),
|
|
375
|
+
cancellable: z.boolean().optional(),
|
|
376
|
+
blocked: z.boolean().optional(),
|
|
377
|
+
anchorRowId: z.number().nullable(),
|
|
378
|
+
childSessionId: z.string().optional(),
|
|
379
|
+
});
|
|
380
|
+
export type BackgroundWorkSummary = z.infer<typeof backgroundWorkSummarySchema>;
|
|
381
|
+
|
|
382
|
+
// subagent 运行态属于 conversation 权威投影,而不是 renderer 查询缓存。
|
|
383
|
+
// ended 详情保持 cursor query;snapshot 只携带目录总数,避免运行中并发数量依赖查询时序。
|
|
384
|
+
export const runningSubagentSummarySchema = z.object({
|
|
385
|
+
childSessionId: z.string(),
|
|
386
|
+
agentId: z.string().optional(),
|
|
387
|
+
toolCallId: z.string().optional(),
|
|
388
|
+
subagentType: z.string(),
|
|
389
|
+
title: z.string(),
|
|
390
|
+
summary: z.string().optional(),
|
|
391
|
+
status: z.enum(["running", "waiting", "blocked"]),
|
|
392
|
+
startedAt: timestampSchema.optional(),
|
|
393
|
+
});
|
|
394
|
+
export type RunningSubagentSummary = z.infer<typeof runningSubagentSummarySchema>;
|
|
395
|
+
|
|
396
|
+
export const subagentProjectionStateSchema = z.object({
|
|
397
|
+
revision: z.number().int().nonnegative(),
|
|
398
|
+
childSessionIds: z.array(z.string()),
|
|
399
|
+
running: z.array(runningSubagentSummarySchema),
|
|
400
|
+
endedTotal: z.number().int().nonnegative(),
|
|
401
|
+
});
|
|
402
|
+
export type SubagentProjectionState = z.infer<typeof subagentProjectionStateSchema>;
|
|
403
|
+
|
|
404
|
+
// ── goal / plan ──
|
|
405
|
+
export const planItemSchema = z.object({
|
|
406
|
+
id: z.string(),
|
|
407
|
+
content: z.string(),
|
|
408
|
+
status: z.enum(["pending", "inProgress", "completed"]),
|
|
409
|
+
});
|
|
410
|
+
export type PlanItem = z.infer<typeof planItemSchema>;
|
|
411
|
+
|
|
412
|
+
export const goalIterationStateSchema = z.object({
|
|
413
|
+
iteration: z.number().int().positive(),
|
|
414
|
+
items: z.array(planItemSchema),
|
|
415
|
+
updatedAt: timestampSchema,
|
|
416
|
+
});
|
|
417
|
+
export type GoalIterationState = z.infer<typeof goalIterationStateSchema>;
|
|
418
|
+
|
|
419
|
+
export const goalStateSchema = z.object({
|
|
420
|
+
// default 仅用于旧快照兼容;新投影始终携带当前 target 身份和计时事实。
|
|
421
|
+
targetId: z.string().default(""),
|
|
422
|
+
objective: z.string(),
|
|
423
|
+
summaryTitle: z.string().nullable().default(null),
|
|
424
|
+
timeUsedSeconds: z.number().int().nonnegative().default(0),
|
|
425
|
+
activeRunStartedAtMs: z.number().int().nonnegative().nullable().default(null),
|
|
426
|
+
// paused:stop 作用于任何 foreground work 时 target 强制进入(stopPausesActiveGoalTarget)。
|
|
427
|
+
// notSatisfied 与 failed 分离:前者是有效结论,后者是验证过程失败。
|
|
428
|
+
status: z.enum(["active", "paused", "verifying", "verified", "notSatisfied", "failed"]),
|
|
429
|
+
iteration: z.number(),
|
|
430
|
+
verifications: z.array(
|
|
431
|
+
z.object({
|
|
432
|
+
iteration: z.number(),
|
|
433
|
+
outcome: z.enum(["pass", "notSatisfied", "failed"]),
|
|
434
|
+
at: timestampSchema,
|
|
435
|
+
anchorRowId: z.number().nullable(),
|
|
436
|
+
reason: z.string().optional(),
|
|
437
|
+
nextAction: z.string().optional(),
|
|
438
|
+
}),
|
|
439
|
+
),
|
|
440
|
+
iterations: z.array(goalIterationStateSchema).default([]),
|
|
441
|
+
});
|
|
442
|
+
export type GoalState = z.infer<typeof goalStateSchema>;
|
|
443
|
+
|
|
444
|
+
export const planStateSchema = z.object({
|
|
445
|
+
items: z.array(planItemSchema),
|
|
446
|
+
updatedAt: timestampSchema,
|
|
447
|
+
});
|
|
448
|
+
export type PlanState = z.infer<typeof planStateSchema>;
|
|
449
|
+
|
|
450
|
+
// ── Snapshot 总览 ──
|
|
451
|
+
export const rowsWindowSchema = z.object({
|
|
452
|
+
// 尾部窗口,rowId 升序。
|
|
453
|
+
window: z.array(conversationRowSchema),
|
|
454
|
+
// 当前全序行数(截断后会减小;仅用于滚动条估计)。
|
|
455
|
+
totalCount: z.number(),
|
|
456
|
+
// 全序第一行 rowId;window 首行等于它 ⇔ 已到顶(游标分页判定)。
|
|
457
|
+
firstRowId: z.number().nullable(),
|
|
458
|
+
});
|
|
459
|
+
export type RowsWindow = z.infer<typeof rowsWindowSchema>;
|
|
460
|
+
|
|
461
|
+
// 软门禁(Soft Gate):会话级待审核 hook 准入状态。
|
|
462
|
+
// snapshot 与 StatePatch(delta.ts)共用,保证投影补丁与快照字段同构。
|
|
463
|
+
export const workspaceHookAdmissionStateSchema = z.object({
|
|
464
|
+
pendingCount: z.number().int().nonnegative(),
|
|
465
|
+
bundleDigest: z.string(),
|
|
466
|
+
workspaceIdentity: z.string().optional(),
|
|
467
|
+
});
|
|
468
|
+
export type WorkspaceHookAdmissionSnapshotState = z.infer<typeof workspaceHookAdmissionStateSchema>;
|
|
469
|
+
|
|
470
|
+
export const conversationSnapshotSchema = z.object({
|
|
471
|
+
protocolVersion: z.literal(1),
|
|
472
|
+
sessionId: z.string(),
|
|
473
|
+
logEpoch: z.string(),
|
|
474
|
+
// 快照对齐水位(= 所在帧 toSeq;从内存投影原子取值)。
|
|
475
|
+
seq: z.number(),
|
|
476
|
+
revision: z.number(),
|
|
477
|
+
// A 区
|
|
478
|
+
control: sessionControlSchema,
|
|
479
|
+
availability: sessionActionAvailabilitySchema,
|
|
480
|
+
inputRouting: inputRoutingSchema,
|
|
481
|
+
// meta 是冻结 schema之后的
|
|
482
|
+
// additive 新增,必须带 default 才不破坏旧快照/旧发送端的解析——备份分支曾把它设为
|
|
483
|
+
// 必填,shared 的 round-trip 测试在该分支上一直是红的(当时未跑 root vitest 漏网)。
|
|
484
|
+
meta: sessionMetaStateSchema.default({ title: "", titleSource: "default" }),
|
|
485
|
+
// Additive:旧 CLI/旧快照不带该字段时仍按普通会话处理。
|
|
486
|
+
sharedContextImport: sharedContextImportStateSchema.optional(),
|
|
487
|
+
config: sessionConfigStateSchema,
|
|
488
|
+
// 持久化稳定事实供 live 客户端识别一次性提示;旧快照缺字段时不触发。
|
|
489
|
+
modelTransition: sessionModelTransitionSchema.nullable().default(null),
|
|
490
|
+
usage: sessionUsageStateSchema,
|
|
491
|
+
queue: queueStateSchema,
|
|
492
|
+
pendingInteractions: z.array(pendingInteractionSchema),
|
|
493
|
+
pendingCommands: z.array(commandStateSummarySchema),
|
|
494
|
+
backgroundWorks: z.array(backgroundWorkSummarySchema),
|
|
495
|
+
// optional 只服务旧快照 wire 兼容;新 CLI 的初始态和每次投影都始终携带该字段。
|
|
496
|
+
subagents: subagentProjectionStateSchema.optional(),
|
|
497
|
+
// 冷快照必须携带 workflowRuns:漏这一处,刷新/重连后正在跑的 run 会静默消失
|
|
498
|
+
// (详情页因此空白,而 run 本身仍在飞)。optional 同样只服务旧快照 wire 兼容。
|
|
499
|
+
workflowRuns: workflowRunsStateSchema.optional(),
|
|
500
|
+
goal: goalStateSchema.nullable(),
|
|
501
|
+
plan: planStateSchema.nullable(),
|
|
502
|
+
// 软门禁(Soft Gate):additive 字段,必须带 default(null)。
|
|
503
|
+
// 旧快照/旧发送端不携带此字段 → 解析得 null,不破坏兼容性(遵守冻结规则)。
|
|
504
|
+
// pendingCount === 0 时投影层置 null(提示条消失)。
|
|
505
|
+
workspaceHookAdmission: workspaceHookAdmissionStateSchema.nullable().default(null),
|
|
506
|
+
// B 区
|
|
507
|
+
rows: rowsWindowSchema,
|
|
508
|
+
});
|
|
509
|
+
export type ConversationSnapshot = z.infer<typeof conversationSnapshotSchema>;
|