dsh-pf-stream 0.0.0-stage → 0.1.2

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.
Files changed (92) hide show
  1. package/LICENSE +201 -0
  2. package/README.en.md +110 -0
  3. package/README.md +109 -2
  4. package/cordis.patch.yml +2 -0
  5. package/lib/entry/adapter.d.ts +21 -0
  6. package/lib/entry/adapter.js +112 -0
  7. package/lib/entry/adapter.js.map +1 -0
  8. package/lib/entry/legacyNormalizer.d.ts +16 -0
  9. package/lib/entry/legacyNormalizer.js +86 -0
  10. package/lib/entry/legacyNormalizer.js.map +1 -0
  11. package/lib/errors.d.ts +7 -0
  12. package/lib/errors.js +12 -0
  13. package/lib/errors.js.map +1 -0
  14. package/lib/index.d.ts +108 -0
  15. package/lib/index.js +109 -0
  16. package/lib/index.js.map +1 -0
  17. package/lib/session/state.d.ts +25 -0
  18. package/lib/session/state.js +255 -0
  19. package/lib/session/state.js.map +1 -0
  20. package/lib/stage0/decoder.d.ts +57 -0
  21. package/lib/stage0/decoder.js +229 -0
  22. package/lib/stage0/decoder.js.map +1 -0
  23. package/lib/stage0/ffmpeg.d.ts +34 -0
  24. package/lib/stage0/ffmpeg.js +90 -0
  25. package/lib/stage0/ffmpeg.js.map +1 -0
  26. package/lib/stage0/probe.d.ts +47 -0
  27. package/lib/stage0/probe.js +150 -0
  28. package/lib/stage0/probe.js.map +1 -0
  29. package/lib/stage1/gradient.d.ts +27 -0
  30. package/lib/stage1/gradient.js +85 -0
  31. package/lib/stage1/gradient.js.map +1 -0
  32. package/lib/stage1/perceive.d.ts +66 -0
  33. package/lib/stage1/perceive.js +233 -0
  34. package/lib/stage1/perceive.js.map +1 -0
  35. package/lib/stage2/stateMachine.d.ts +70 -0
  36. package/lib/stage2/stateMachine.js +180 -0
  37. package/lib/stage2/stateMachine.js.map +1 -0
  38. package/lib/stage2/switchDetector.d.ts +18 -0
  39. package/lib/stage2/switchDetector.js +34 -0
  40. package/lib/stage2/switchDetector.js.map +1 -0
  41. package/lib/stage3/deterministicRouter.d.ts +44 -0
  42. package/lib/stage3/deterministicRouter.js +203 -0
  43. package/lib/stage3/deterministicRouter.js.map +1 -0
  44. package/lib/stage3/streamSampler.d.ts +74 -0
  45. package/lib/stage3/streamSampler.js +497 -0
  46. package/lib/stage3/streamSampler.js.map +1 -0
  47. package/lib/stage4/canvasPacker.d.ts +60 -0
  48. package/lib/stage4/canvasPacker.js +161 -0
  49. package/lib/stage4/canvasPacker.js.map +1 -0
  50. package/lib/stage4/markers.d.ts +19 -0
  51. package/lib/stage4/markers.js +98 -0
  52. package/lib/stage4/markers.js.map +1 -0
  53. package/lib/stage4/viewport.d.ts +61 -0
  54. package/lib/stage4/viewport.js +151 -0
  55. package/lib/stage4/viewport.js.map +1 -0
  56. package/lib/stage5/controller.d.ts +61 -0
  57. package/lib/stage5/controller.js +260 -0
  58. package/lib/stage5/controller.js.map +1 -0
  59. package/lib/stage5/intent.d.ts +27 -0
  60. package/lib/stage5/intent.js +87 -0
  61. package/lib/stage5/intent.js.map +1 -0
  62. package/lib/stage6/history.d.ts +52 -0
  63. package/lib/stage6/history.js +155 -0
  64. package/lib/stage6/history.js.map +1 -0
  65. package/lib/stage6/precheck.d.ts +56 -0
  66. package/lib/stage6/precheck.js +86 -0
  67. package/lib/stage6/precheck.js.map +1 -0
  68. package/lib/tool/handler.d.ts +35 -0
  69. package/lib/tool/handler.js +56 -0
  70. package/lib/tool/handler.js.map +1 -0
  71. package/lib/tool/schema.d.ts +29 -0
  72. package/lib/tool/schema.js +59 -0
  73. package/lib/tool/schema.js.map +1 -0
  74. package/lib/tool/streamCall.d.ts +41 -0
  75. package/lib/tool/streamCall.js +105 -0
  76. package/lib/tool/streamCall.js.map +1 -0
  77. package/lib/types.d.ts +355 -0
  78. package/lib/types.js +11 -0
  79. package/lib/types.js.map +1 -0
  80. package/lib/utils/ffmpegBin.d.ts +20 -0
  81. package/lib/utils/ffmpegBin.js +62 -0
  82. package/lib/utils/ffmpegBin.js.map +1 -0
  83. package/lib/utils/hash.d.ts +13 -0
  84. package/lib/utils/hash.js +24 -0
  85. package/lib/utils/hash.js.map +1 -0
  86. package/lib/utils/image.d.ts +32 -0
  87. package/lib/utils/image.js +135 -0
  88. package/lib/utils/image.js.map +1 -0
  89. package/lib/utils/pts.d.ts +15 -0
  90. package/lib/utils/pts.js +50 -0
  91. package/lib/utils/pts.js.map +1 -0
  92. package/package.json +55 -4
@@ -0,0 +1,86 @@
1
+ /**
2
+ * 历史便捷字段归一化(《五、双层自适应调节与统一参数映射》§1.1)。
3
+ *
4
+ * 输入便利层:start_time/end_time/time_range/timestamps/fps/interval/num_frames/
5
+ * frame_count/crop/bbox/roi/probe_only → 标准 IntentDirective 字段。
6
+ * 判秒规则:数值 ≤ 时长(秒)×1.5 判秒,超过判毫秒;归一化来源记入 normalizedFrom。
7
+ */
8
+ /** 数值或字符串时间 → 毫秒(判秒规则见模块注释)。 */
9
+ export function toMs(value, durationMs) {
10
+ const n = typeof value === 'string' ? Number.parseFloat(value) : value;
11
+ if (!Number.isFinite(n))
12
+ throw new Error(`时间值无法解析:${String(value)}`);
13
+ const secThreshold = (durationMs / 1000) * 1.5;
14
+ const ms = n <= secThreshold ? n * 1000 : n;
15
+ return Math.round(ms);
16
+ }
17
+ function normalizeRoi(raw) {
18
+ const clamp01 = (v) => Math.min(Math.max(v, 0), 1);
19
+ return {
20
+ x: clamp01(raw.x),
21
+ y: clamp01(raw.y),
22
+ w: Math.min(Math.max(raw.w, 0), 1 - clamp01(raw.x)),
23
+ h: Math.min(Math.max(raw.h, 0), 1 - clamp01(raw.y)),
24
+ };
25
+ }
26
+ export function normalizeLegacyArgs(args, durationMs) {
27
+ const intent = {};
28
+ const normalizedFrom = [];
29
+ const has = (k) => Object.prototype.hasOwnProperty.call(args, k) && args[k] !== undefined;
30
+ if (has('start_time') || has('end_time') || has('time_range')) {
31
+ const start = has('start_time') ? toMs(args['start_time'], durationMs) : 0;
32
+ const end = has('end_time')
33
+ ? toMs(args['end_time'], durationMs)
34
+ : Math.max(start, durationMs);
35
+ intent.pts_window = [start, end];
36
+ normalizedFrom.push('start_time/end_time');
37
+ }
38
+ if (has('time_range') && Array.isArray(args['time_range']) && args['time_range'].length === 2) {
39
+ const [a, b] = args['time_range'];
40
+ if (a !== undefined && b !== undefined) {
41
+ intent.pts_window = [toMs(a, durationMs), toMs(b, durationMs)];
42
+ normalizedFrom.push('time_range');
43
+ }
44
+ }
45
+ if (has('timestamps') && Array.isArray(args['timestamps'])) {
46
+ intent.timestamps_ms = args['timestamps'].map((t) => toMs(t, durationMs));
47
+ intent.action = 'timestamps';
48
+ normalizedFrom.push('timestamps');
49
+ }
50
+ if (has('fps')) {
51
+ const fps = Number(args['fps']);
52
+ if (Number.isFinite(fps) && fps > 0) {
53
+ intent.interval_ms = Math.round(1000 / fps);
54
+ intent.action = 'uniform';
55
+ normalizedFrom.push('fps');
56
+ }
57
+ }
58
+ if (has('interval')) {
59
+ const iv = Number(args['interval']);
60
+ if (Number.isFinite(iv) && iv > 0) {
61
+ intent.interval_ms = toMs(iv, durationMs);
62
+ intent.action = 'uniform';
63
+ normalizedFrom.push('interval');
64
+ }
65
+ }
66
+ if (has('num_frames') || has('frame_count')) {
67
+ const fc = Number(args['num_frames'] ?? args['frame_count']);
68
+ if (Number.isFinite(fc) && fc >= 1) {
69
+ intent.frame_count = Math.min(Math.round(fc), 128);
70
+ if (intent.action == null)
71
+ intent.action = 'uniform';
72
+ normalizedFrom.push('num_frames/frame_count');
73
+ }
74
+ }
75
+ const roiRaw = (args['crop'] ?? args['bbox'] ?? args['roi']);
76
+ if (roiRaw && typeof roiRaw === 'object') {
77
+ intent.roi_hint = normalizeRoi(roiRaw);
78
+ normalizedFrom.push('crop/bbox/roi');
79
+ }
80
+ if (args['probe_only'] === true) {
81
+ intent.action = 'probe';
82
+ normalizedFrom.push('probe_only');
83
+ }
84
+ return { intent, normalizedFrom };
85
+ }
86
+ //# sourceMappingURL=legacyNormalizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"legacyNormalizer.js","sourceRoot":"","sources":["../../src/entry/legacyNormalizer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * 插件参数化错误。错误码命名空间:PFSTREAM_<模块>_<原因>。
3
+ */
4
+ export declare class PfStreamError extends Error {
5
+ readonly code: string;
6
+ constructor(code: string, message: string);
7
+ }
package/lib/errors.js ADDED
@@ -0,0 +1,12 @@
1
+ /**
2
+ * 插件参数化错误。错误码命名空间:PFSTREAM_<模块>_<原因>。
3
+ */
4
+ export class PfStreamError extends Error {
5
+ code;
6
+ constructor(code, message) {
7
+ super(message);
8
+ this.code = code;
9
+ this.name = 'PfStreamError';
10
+ }
11
+ }
12
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,OAAO,aAAc,SAAQ,KAAK;IAE3B;IADX,YACW,IAAY,EACrB,OAAe;QAEf,KAAK,CAAC,OAAO,CAAC,CAAC;QAHN,SAAI,GAAJ,IAAI,CAAQ;QAIrB,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,108 @@
1
+ /**
2
+ * dsh-pf-stream — DeepSeek Harness 视频感知插件入口。
3
+ *
4
+ * 统一 action 路由:动态流式采样(pf_stream)与内建确定性检视
5
+ * (probe / timestamps / uniform / RoI)共用主工具 dsh-pf-stream。
6
+ *
7
+ * 工具表稳定性(Prefix KV-Cache):tools.register 在 apply 期一次装齐、
8
+ * dispose 期统一注销,运行中不增删。
9
+ */
10
+ import Schema from '@deepseek-ai/schemastery';
11
+ import type { Context } from '@deepseek-ai/cordis';
12
+ import type { PfStreamPluginConfig } from './types.js';
13
+ import { type ToolCallArgs, type ToolExec, type ToolResult } from './tool/handler.js';
14
+ export declare const name = "dsh-pf-stream";
15
+ export declare const inject: string[];
16
+ /** 56 MiB = 58,720,256 字节(含 8 MiB Base64 编码膨胀与协议结构预留)。 */
17
+ export declare const DEFAULT_MAX_REQUEST_BYTES: number;
18
+ export declare const Config: Schema<Schemastery.ObjectS<NoInfer<{
19
+ renderVisualId: Schema<boolean, boolean, "defined">;
20
+ maxPacketsPerCall: Schema<number, number, "defined">;
21
+ maxTokensBudgetPerCall: Schema<number, number, "defined">;
22
+ maxRequestBytes: Schema<number, number, "defined">;
23
+ maxColdRefs: Schema<number, number, "defined">;
24
+ telemetryEnabled: Schema<boolean, boolean, "defined">;
25
+ ffmpegPath: Schema<string, string, "plain">;
26
+ ffprobePath: Schema<string, string, "plain">;
27
+ tempDir: Schema<string, string, "plain">;
28
+ contentHashFallback: Schema<boolean, boolean, "defined">;
29
+ defaultStreamWindowMs: Schema<number, number, "defined">;
30
+ streamWorkMaxEdge: Schema<number, number, "defined">;
31
+ epochCompactionWindow: Schema<number, number, "defined">;
32
+ meteringProfile: Schema<Schemastery.ObjectS<NoInfer<{
33
+ superpixelPx: Schema<42, 42, "plain">;
34
+ rounding: Schema<"ceil", "ceil", "plain">;
35
+ maxTokensPerImage: Schema<number, number, "defined">;
36
+ maxImagesPerRequest: Schema<number, number, "defined">;
37
+ imageCountTiersEnabled: Schema<boolean, boolean, "defined">;
38
+ legacyModes: Schema<string[], string[], "defined">;
39
+ }>>, Schemastery.ObjectT<NoInfer<{
40
+ superpixelPx: Schema<42, 42, "plain">;
41
+ rounding: Schema<"ceil", "ceil", "plain">;
42
+ maxTokensPerImage: Schema<number, number, "defined">;
43
+ maxImagesPerRequest: Schema<number, number, "defined">;
44
+ imageCountTiersEnabled: Schema<boolean, boolean, "defined">;
45
+ legacyModes: Schema<string[], string[], "defined">;
46
+ }>>, "plain">;
47
+ }>>, Schemastery.ObjectT<NoInfer<{
48
+ renderVisualId: Schema<boolean, boolean, "defined">;
49
+ maxPacketsPerCall: Schema<number, number, "defined">;
50
+ maxTokensBudgetPerCall: Schema<number, number, "defined">;
51
+ maxRequestBytes: Schema<number, number, "defined">;
52
+ maxColdRefs: Schema<number, number, "defined">;
53
+ telemetryEnabled: Schema<boolean, boolean, "defined">;
54
+ ffmpegPath: Schema<string, string, "plain">;
55
+ ffprobePath: Schema<string, string, "plain">;
56
+ tempDir: Schema<string, string, "plain">;
57
+ contentHashFallback: Schema<boolean, boolean, "defined">;
58
+ defaultStreamWindowMs: Schema<number, number, "defined">;
59
+ streamWorkMaxEdge: Schema<number, number, "defined">;
60
+ epochCompactionWindow: Schema<number, number, "defined">;
61
+ meteringProfile: Schema<Schemastery.ObjectS<NoInfer<{
62
+ superpixelPx: Schema<42, 42, "plain">;
63
+ rounding: Schema<"ceil", "ceil", "plain">;
64
+ maxTokensPerImage: Schema<number, number, "defined">;
65
+ maxImagesPerRequest: Schema<number, number, "defined">;
66
+ imageCountTiersEnabled: Schema<boolean, boolean, "defined">;
67
+ legacyModes: Schema<string[], string[], "defined">;
68
+ }>>, Schemastery.ObjectT<NoInfer<{
69
+ superpixelPx: Schema<42, 42, "plain">;
70
+ rounding: Schema<"ceil", "ceil", "plain">;
71
+ maxTokensPerImage: Schema<number, number, "defined">;
72
+ maxImagesPerRequest: Schema<number, number, "defined">;
73
+ imageCountTiersEnabled: Schema<boolean, boolean, "defined">;
74
+ legacyModes: Schema<string[], string[], "defined">;
75
+ }>>, "plain">;
76
+ }>>, "plain">;
77
+ /** 流式单次调用阻塞上限:宿主死线减 40s 余量(超时协作式,signal 绝不硬终止)。 */
78
+ export declare const TOOL_TIMEOUT_MS = 900000;
79
+ export declare const SELF_MANAGED_BLOCK_CEILING_MS: number;
80
+ /** 宿主 tools 服务;运行时由 inject=['tools'] 保证存在(类型未随 cordis 包发布)。 */
81
+ export interface ToolsService {
82
+ register(definition: unknown): () => void;
83
+ }
84
+ /** 结构化宿主上下文:cordis Context 加 tools 服务。 */
85
+ export type HostContext = Context & {
86
+ tools: ToolsService;
87
+ };
88
+ export declare function buildToolDefinition(_deps: {
89
+ ctx: HostContext;
90
+ config: PfStreamPluginConfig;
91
+ }): {
92
+ name: string;
93
+ description: string;
94
+ parameters: Record<string, import("./tool/schema.js").ValueSchema>;
95
+ output: {
96
+ schema: {
97
+ readonly type: "object";
98
+ };
99
+ render: (_args: unknown, value: unknown) => {
100
+ type: "text";
101
+ text: string;
102
+ };
103
+ };
104
+ timeoutMs: number;
105
+ isConcurrencySafe: () => boolean;
106
+ execute(args: ToolCallArgs, exec: ToolExec | undefined): Promise<ToolResult>;
107
+ };
108
+ export declare function apply(ctx: Context, config: PfStreamPluginConfig): void;
package/lib/index.js ADDED
@@ -0,0 +1,109 @@
1
+ /**
2
+ * dsh-pf-stream — DeepSeek Harness 视频感知插件入口。
3
+ *
4
+ * 统一 action 路由:动态流式采样(pf_stream)与内建确定性检视
5
+ * (probe / timestamps / uniform / RoI)共用主工具 dsh-pf-stream。
6
+ *
7
+ * 工具表稳定性(Prefix KV-Cache):tools.register 在 apply 期一次装齐、
8
+ * dispose 期统一注销,运行中不增删。
9
+ */
10
+ import Schema from '@deepseek-ai/schemastery';
11
+ import { handleToolCall, } from './tool/handler.js';
12
+ import { TOOL_NAME, TOOL_DESCRIPTION, toolOutputSchema, toolParameters } from './tool/schema.js';
13
+ import { probeVideo } from './stage0/probe.js';
14
+ import { runDeterministicInspection } from './stage3/deterministicRouter.js';
15
+ import { runStreamCall } from './tool/streamCall.js';
16
+ import { resolveBinPaths } from './utils/ffmpegBin.js';
17
+ export const name = 'dsh-pf-stream';
18
+ export const inject = ['tools', 'subprocess'];
19
+ /** 56 MiB = 58,720,256 字节(含 8 MiB Base64 编码膨胀与协议结构预留)。 */
20
+ export const DEFAULT_MAX_REQUEST_BYTES = 56 * 1024 * 1024;
21
+ export const Config = Schema.object({
22
+ renderVisualId: Schema.boolean().default(true).description('渲染超像素微型反色角标'),
23
+ maxPacketsPerCall: Schema.number().default(64).description('单次调用画布包数上限'),
24
+ maxTokensBudgetPerCall: Schema.number().default(65536).description('单次调用视觉 Token 预算上限(intent.max_tokens_budget 受此钳制)'),
25
+ maxRequestBytes: Schema.number().default(DEFAULT_MAX_REQUEST_BYTES).description('请求字节软水位'),
26
+ maxColdRefs: Schema.number().default(4).description('冷区引用数量上限'),
27
+ telemetryEnabled: Schema.boolean().default(true).description('遥测开关'),
28
+ ffmpegPath: Schema.string().description('ffmpeg 可执行文件路径(缺省自动探测)'),
29
+ ffprobePath: Schema.string().description('ffprobe 可执行文件路径(缺省自动探测)'),
30
+ tempDir: Schema.string().description('临时目录(缺省系统临时目录)'),
31
+ contentHashFallback: Schema.boolean().default(false).description('内容哈希降级轨开关'),
32
+ defaultStreamWindowMs: Schema.number().default(10000).description('流式窗口缺省长度(毫秒)'),
33
+ streamWorkMaxEdge: Schema.number().default(2048).description('流式解码工作分辨率长边上限'),
34
+ epochCompactionWindow: Schema.number().default(6).description('热转冷批量收敛窗口(包数)'),
35
+ meteringProfile: Schema.object({
36
+ superpixelPx: Schema.const(42).description('超像素边长(像素)'),
37
+ rounding: Schema.const('ceil').description('计费序列长度取整方式'),
38
+ maxTokensPerImage: Schema.number().default(1024).description('单图视觉 Token 上限(v4.1 口径 1024;384 为 legacy 枚举位)'),
39
+ maxImagesPerRequest: Schema.number().default(600).description('单次请求图像张数上限(代际参数)'),
40
+ imageCountTiersEnabled: Schema.boolean().default(false).description('≥15 图单边 4096px 规则门控'),
41
+ legacyModes: Schema.array(String).default([]).description('legacy 计量口径枚举位'),
42
+ }),
43
+ });
44
+ /** 流式单次调用阻塞上限:宿主死线减 40s 余量(超时协作式,signal 绝不硬终止)。 */
45
+ export const TOOL_TIMEOUT_MS = 900_000;
46
+ export const SELF_MANAGED_BLOCK_CEILING_MS = TOOL_TIMEOUT_MS - 40_000;
47
+ export function buildToolDefinition(_deps) {
48
+ const { config } = _deps;
49
+ const bins = resolveBinPaths({ ffmpegPath: config.ffmpegPath, ffprobePath: config.ffprobePath });
50
+ const probe = (videoPath, signal) => probeVideo(videoPath, { ffprobePath: bins.ffprobe, signal });
51
+ const inspect = (videoPath, probeResult, intent, signal) => runDeterministicInspection(videoPath, probeResult, intent, {
52
+ ffmpegPath: bins.ffmpeg,
53
+ renderVisualId: config.renderVisualId,
54
+ packetIdStart: 1,
55
+ globalIdStart: 1,
56
+ appliedIntentId: 'intent_1',
57
+ maxRequestBytes: config.maxRequestBytes,
58
+ maxTokensPerImage: config.meteringProfile.maxTokensPerImage,
59
+ signal,
60
+ });
61
+ const stream = (videoPath, probeResult, intent, sessionId, signal) => runStreamCall(videoPath, probeResult, intent, sessionId ?? 'default', {
62
+ ffmpegPath: bins.ffmpeg,
63
+ renderVisualId: config.renderVisualId,
64
+ defaultStreamWindowMs: config.defaultStreamWindowMs,
65
+ streamWorkMaxEdge: config.streamWorkMaxEdge,
66
+ maxPacketsPerCall: config.maxPacketsPerCall,
67
+ maxTokensBudgetPerCall: config.maxTokensBudgetPerCall,
68
+ maxRequestBytes: config.maxRequestBytes,
69
+ maxColdRefs: config.maxColdRefs,
70
+ epochCompactionWindow: config.epochCompactionWindow,
71
+ imageCountTiersEnabled: config.meteringProfile.imageCountTiersEnabled,
72
+ maxTokensPerImage: config.meteringProfile.maxTokensPerImage,
73
+ signal,
74
+ });
75
+ return {
76
+ name: TOOL_NAME,
77
+ description: TOOL_DESCRIPTION,
78
+ parameters: toolParameters,
79
+ output: {
80
+ schema: toolOutputSchema,
81
+ render: (_args, value) => ({
82
+ type: 'text',
83
+ text: JSON.stringify(value, null, 2),
84
+ }),
85
+ },
86
+ timeoutMs: TOOL_TIMEOUT_MS,
87
+ // 同一 (sessionId, videoKey) 的调用经 per-key promise 队列串行化,
88
+ // 会话级状态使并发不安全。
89
+ isConcurrencySafe: () => false,
90
+ async execute(args, exec) {
91
+ return handleToolCall(args, exec, { probe, inspect, stream });
92
+ },
93
+ };
94
+ }
95
+ export function apply(ctx, config) {
96
+ const host = ctx;
97
+ const dispose = host.tools.register(buildToolDefinition({ ctx: host, config }));
98
+ // register 返回的 disposer 为主注销路径;'dispose' 事件为兜底
99
+ // (经 events 服务注册,事件名不受 keyof Events 约束)。
100
+ ctx.events.on('dispose', () => {
101
+ try {
102
+ dispose();
103
+ }
104
+ catch {
105
+ // 卸载期清理失败不再抛出
106
+ }
107
+ });
108
+ }
109
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,MAAM,MAAM,0BAA0B,CAAC;AAG9C,OAAO,EACL,cAAc,GAOf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACjG,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,MAAM,CAAC,MAAM,IAAI,GAAG,eAAe,CAAC;AAEpC,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;AAE9C,0DAA0D;AAC1D,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAE1D,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAClC,cAAc,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC;IACzE,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC;IACxE,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,kDAAkD,CAAC;IACtH,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC,WAAW,CAAC,SAAS,CAAC;IAC1F,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,UAAU,CAAC;IAC/D,gBAAgB,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC;IACpE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,wBAAwB,CAAC;IACjE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,yBAAyB,CAAC;IACnE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,gBAAgB,CAAC;IACtD,mBAAmB,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,WAAW,CAAC;IAC7E,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,cAAc,CAAC;IACjF,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,eAAe,CAAC;IAC7E,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,eAAe,CAAC;IAC9E,eAAe,EAAE,MAAM,CAAC,MAAM,CAAC;QAC7B,YAAY,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,WAAW,CAAC;QACvD,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC;QACxD,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,8CAA8C,CAAC;QAC5G,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC,kBAAkB,CAAC;QACjF,sBAAsB,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,qBAAqB,CAAC;QAC1F,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,gBAAgB,CAAC;KAC5E,CAAC;CACH,CAAC,CAAC;AAEH,mDAAmD;AACnD,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC;AACvC,MAAM,CAAC,MAAM,6BAA6B,GAAG,eAAe,GAAG,MAAM,CAAC;AAUtE,MAAM,UAAU,mBAAmB,CAAC,KAAyD;IAC3F,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IACzB,MAAM,IAAI,GAAG,eAAe,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;IACjG,MAAM,KAAK,GAAY,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,CAC3C,UAAU,CAAC,SAAS,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/D,MAAM,OAAO,GAAc,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,CACpE,0BAA0B,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE;QACzD,UAAU,EAAE,IAAI,CAAC,MAAM;QACvB,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,aAAa,EAAE,CAAC;QAChB,aAAa,EAAE,CAAC;QAChB,eAAe,EAAE,UAAU;QAC3B,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,iBAAiB,EAAE,MAAM,CAAC,eAAe,CAAC,iBAAiB;QAC3D,MAAM;KACP,CAAC,CAAC;IACL,MAAM,MAAM,GAAa,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,CAC7E,aAAa,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,IAAI,SAAS,EAAE;QACpE,UAAU,EAAE,IAAI,CAAC,MAAM;QACvB,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,qBAAqB,EAAE,MAAM,CAAC,qBAAqB;QACnD,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;QAC3C,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;QAC3C,sBAAsB,EAAE,MAAM,CAAC,sBAAsB;QACrD,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,qBAAqB,EAAE,MAAM,CAAC,qBAAqB;QACnD,sBAAsB,EAAE,MAAM,CAAC,eAAe,CAAC,sBAAsB;QACrE,iBAAiB,EAAE,MAAM,CAAC,eAAe,CAAC,iBAAiB;QAC3D,MAAM;KACP,CAAC,CAAC;IACL,OAAO;QACL,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,gBAAgB;QAC7B,UAAU,EAAE,cAAc;QAC1B,MAAM,EAAE;YACN,MAAM,EAAE,gBAAgB;YACxB,MAAM,EAAE,CAAC,KAAc,EAAE,KAAc,EAAE,EAAE,CAAC,CAAC;gBAC3C,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;aACrC,CAAC;SACH;QACD,SAAS,EAAE,eAAe;QAC1B,uDAAuD;QACvD,eAAe;QACf,iBAAiB,EAAE,GAAG,EAAE,CAAC,KAAK;QAC9B,KAAK,CAAC,OAAO,CAAC,IAAkB,EAAE,IAA0B;YAC1D,OAAO,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QAChE,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,GAAY,EAAE,MAA4B;IAC9D,MAAM,IAAI,GAAG,GAAkB,CAAC;IAChC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IAChF,+CAA+C;IAC/C,yCAAyC;IACzC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;QAC5B,IAAI,CAAC;YACH,OAAO,EAAE,CAAC;QACZ,CAAC;QAAC,MAAM,CAAC;YACP,cAAc;QAChB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * 会话状态(SessionState / StreamCursor / LRU 管理)。
3
+ *
4
+ * LRU 上限(2 个视频/会话):每视频驻留状态约 1MB 量级
5
+ * (单槽位擂台图 ~450KB + 待发 P 队列),会话内存占用有界。
6
+ * M2 为进程内内存态;持久层(storageDomain)在 M4 接入(ADR-005)。
7
+ */
8
+ import type { SessionIntent, SessionState, SessionVideoState, VideoFingerprint } from '../types.js';
9
+ /** 视频指纹:规范化路径 + size + mtime 联合哈希前 16 hex。 */
10
+ export declare function fingerprintOf(videoPath: string): VideoFingerprint;
11
+ export declare function defaultSessionIntent(): SessionIntent;
12
+ export declare function createSessionState(sessionId: string): SessionState;
13
+ /** LRU 上限(会话内视频数)。 */
14
+ export declare const VIDEO_LRU_LIMIT = 2;
15
+ /** 取视频槽位(不存在则创建);超过上限淘汰最旧未使用槽位。 */
16
+ export declare function getVideoSlot(state: SessionState, fingerprint: VideoFingerprint): SessionVideoState;
17
+ export declare function getSessionState(sessionId: string): SessionState;
18
+ /** 测试辅助:清空进程内会话存储。 */
19
+ export declare function resetMemorySessions(): void;
20
+ /** 测试辅助:将重建的会话状态放回进程内存储(importSessionSnapshot 配套)。 */
21
+ export declare function setMemorySession(state: SessionState): void;
22
+ /** 导出会话快照(JSON 文本;Buffer 字段 base64 编码)。 */
23
+ export declare function exportSessionSnapshot(state: SessionState): string;
24
+ /** 从快照重建会话状态(exportSessionSnapshot 的逆操作)。 */
25
+ export declare function importSessionSnapshot(json: string): SessionState;
@@ -0,0 +1,255 @@
1
+ /**
2
+ * 会话状态(SessionState / StreamCursor / LRU 管理)。
3
+ *
4
+ * LRU 上限(2 个视频/会话):每视频驻留状态约 1MB 量级
5
+ * (单槽位擂台图 ~450KB + 待发 P 队列),会话内存占用有界。
6
+ * M2 为进程内内存态;持久层(storageDomain)在 M4 接入(ADR-005)。
7
+ */
8
+ import { createHash } from 'node:crypto';
9
+ import { statSync } from 'node:fs';
10
+ import { resolve } from 'node:path';
11
+ /** 视频指纹:规范化路径 + size + mtime 联合哈希前 16 hex。 */
12
+ export function fingerprintOf(videoPath) {
13
+ const normalizedPath = resolve(videoPath).replaceAll('\\', '/').toLowerCase();
14
+ const st = statSync(normalizedPath);
15
+ const digest = createHash('sha256')
16
+ .update(`${normalizedPath}|${st.size}|${Math.round(st.mtimeMs)}`)
17
+ .digest('hex');
18
+ return {
19
+ normalizedPath,
20
+ sizeBytes: st.size,
21
+ mtimeMs: Math.round(st.mtimeMs),
22
+ sha256Short: digest.slice(0, 16),
23
+ };
24
+ }
25
+ export function defaultSessionIntent() {
26
+ return { intentId: 'intent_0', mode: 'standard', focus: 'balanced', fullFrame: false };
27
+ }
28
+ export function createSessionState(sessionId) {
29
+ return {
30
+ sessionId,
31
+ intent: defaultSessionIntent(),
32
+ videos: new Map(),
33
+ fUnitCache: new Map(),
34
+ globalUnitSeq: 0,
35
+ packetSeq: 0,
36
+ intentSeq: 0,
37
+ ctrlSeq: new Map(),
38
+ heartbeatSeq: 0,
39
+ };
40
+ }
41
+ /** LRU 上限(会话内视频数)。 */
42
+ export const VIDEO_LRU_LIMIT = 2;
43
+ /** 取视频槽位(不存在则创建);超过上限淘汰最旧未使用槽位。 */
44
+ export function getVideoSlot(state, fingerprint) {
45
+ const key = fingerprint.sha256Short;
46
+ const existing = state.videos.get(key);
47
+ if (existing) {
48
+ // LRU 触达:移到 Map 尾部(最新)
49
+ state.videos.delete(key);
50
+ state.videos.set(key, existing);
51
+ return existing;
52
+ }
53
+ while (state.videos.size >= VIDEO_LRU_LIMIT) {
54
+ const oldest = state.videos.keys().next().value;
55
+ if (oldest == null)
56
+ break;
57
+ state.videos.delete(oldest);
58
+ }
59
+ const slot = {
60
+ cursor: {
61
+ fingerprint,
62
+ lastConsumedPtsMs: 0,
63
+ lastEmittedPacketPtsMs: null,
64
+ snapshot: {
65
+ state: 'STATIC',
66
+ enteredAtPtsMs: 0,
67
+ integratorA: 0,
68
+ gEma: 0,
69
+ emaWarmupLeft: 0,
70
+ settleStartPtsMs: null,
71
+ lastKCandidates: null,
72
+ lastMotionVec: null,
73
+ arena: null,
74
+ },
75
+ pendingPUnits: [],
76
+ lastAnchorF: null,
77
+ },
78
+ history: { packets: [] },
79
+ epoch: { pendingNew: 0, coldRefs: [] },
80
+ };
81
+ state.videos.set(key, slot);
82
+ return slot;
83
+ }
84
+ /** M2 进程内会话存储(key = sessionId);M4 换 storageDomain 持久层。 */
85
+ const memorySessions = new Map();
86
+ export function getSessionState(sessionId) {
87
+ let state = memorySessions.get(sessionId);
88
+ if (!state) {
89
+ state = createSessionState(sessionId);
90
+ memorySessions.set(sessionId, state);
91
+ }
92
+ return state;
93
+ }
94
+ /** 测试辅助:清空进程内会话存储。 */
95
+ export function resetMemorySessions() {
96
+ memorySessions.clear();
97
+ }
98
+ /** 测试辅助:将重建的会话状态放回进程内存储(importSessionSnapshot 配套)。 */
99
+ export function setMemorySession(state) {
100
+ memorySessions.set(state.sessionId, state);
101
+ }
102
+ /** 导出会话快照(JSON 文本;Buffer 字段 base64 编码)。 */
103
+ export function exportSessionSnapshot(state) {
104
+ const videos = [];
105
+ for (const [key, slot] of state.videos) {
106
+ const c = slot.cursor;
107
+ videos.push([
108
+ key,
109
+ {
110
+ fingerprint: c.fingerprint,
111
+ lastConsumedPtsMs: c.lastConsumedPtsMs,
112
+ lastEmittedPacketPtsMs: c.lastEmittedPacketPtsMs,
113
+ snapshot: {
114
+ ...c.snapshot,
115
+ arena: c.snapshot.arena == null
116
+ ? null
117
+ : {
118
+ ptsMs: c.snapshot.arena.ptsMs,
119
+ rho: c.snapshot.arena.rho,
120
+ g: c.snapshot.arena.g,
121
+ image672: c.snapshot.arena.image672.toString('base64'),
122
+ sourceCropBbox: c.snapshot.arena.sourceCropBbox,
123
+ },
124
+ },
125
+ pendingPUnits: c.pendingPUnits.map((p) => ({
126
+ ptsMs: p.ptsMs,
127
+ image336: p.image336.toString('base64'),
128
+ sourceCropBbox: p.sourceCropBbox,
129
+ })),
130
+ lastAnchorF: c.lastAnchorF,
131
+ history: {
132
+ packets: slot.history.packets.map((h) => ({
133
+ packet: h.packet,
134
+ imageBytes: h.imageBytes.toString('base64'),
135
+ anchorBytes: h.anchorBytes ? h.anchorBytes.toString('base64') : null,
136
+ anchorFContentHash: h.anchorFContentHash,
137
+ })),
138
+ },
139
+ epoch: {
140
+ pendingNew: slot.epoch.pendingNew,
141
+ coldRefs: slot.epoch.coldRefs.map((r) => ({
142
+ refPacketId: r.refPacketId,
143
+ sourcePacketId: r.sourcePacketId,
144
+ anchorFId: r.anchorFId,
145
+ anchorFSha256: r.anchorFSha256,
146
+ ptsMs: r.ptsMs,
147
+ eventType: r.eventType,
148
+ sourceCropBbox: r.sourceCropBbox,
149
+ bytes: r.bytes.toString('base64'),
150
+ contentHash: r.contentHash,
151
+ })),
152
+ },
153
+ },
154
+ ]);
155
+ }
156
+ const doc = {
157
+ version: 1,
158
+ sessionId: state.sessionId,
159
+ intent: state.intent,
160
+ globalUnitSeq: state.globalUnitSeq,
161
+ packetSeq: state.packetSeq,
162
+ intentSeq: state.intentSeq,
163
+ heartbeatSeq: state.heartbeatSeq,
164
+ ctrlSeq: [...state.ctrlSeq.entries()],
165
+ fUnitCache: [...state.fUnitCache.values()].map((e) => ({
166
+ anchorFId: e.anchorFId,
167
+ packetId: e.packetId,
168
+ ptsMs: e.ptsMs,
169
+ independentBytes: e.independentBytes.toString('base64'),
170
+ anchorFSha256: e.anchorFSha256,
171
+ stripBytes: e.stripBytes?.toString('base64'),
172
+ stripSha256: e.stripSha256,
173
+ contentHash: e.contentHash,
174
+ })),
175
+ videos,
176
+ };
177
+ return JSON.stringify(doc);
178
+ }
179
+ /** 从快照重建会话状态(exportSessionSnapshot 的逆操作)。 */
180
+ export function importSessionSnapshot(json) {
181
+ const doc = JSON.parse(json);
182
+ if (doc.version !== 1)
183
+ throw new Error(`不支持的会话快照版本:${doc.version}`);
184
+ const state = createSessionState(doc.sessionId);
185
+ state.intent = doc.intent;
186
+ state.globalUnitSeq = doc.globalUnitSeq;
187
+ state.packetSeq = doc.packetSeq;
188
+ state.intentSeq = doc.intentSeq;
189
+ state.heartbeatSeq = doc.heartbeatSeq;
190
+ state.ctrlSeq = new Map(doc.ctrlSeq);
191
+ state.fUnitCache = new Map(doc.fUnitCache.map((e) => [
192
+ e.anchorFId,
193
+ {
194
+ anchorFId: e.anchorFId,
195
+ packetId: e.packetId,
196
+ ptsMs: e.ptsMs,
197
+ independentBytes: Buffer.from(e.independentBytes, 'base64'),
198
+ anchorFSha256: e.anchorFSha256,
199
+ stripBytes: e.stripBytes != null ? Buffer.from(e.stripBytes, 'base64') : undefined,
200
+ stripSha256: e.stripSha256,
201
+ contentHash: e.contentHash,
202
+ },
203
+ ]));
204
+ for (const [key, v] of doc.videos) {
205
+ state.videos.set(key, {
206
+ cursor: {
207
+ fingerprint: v.fingerprint,
208
+ lastConsumedPtsMs: v.lastConsumedPtsMs,
209
+ lastEmittedPacketPtsMs: v.lastEmittedPacketPtsMs,
210
+ snapshot: {
211
+ ...v.snapshot,
212
+ arena: v.snapshot.arena == null
213
+ ? null
214
+ : {
215
+ ptsMs: v.snapshot.arena.ptsMs,
216
+ rho: v.snapshot.arena.rho,
217
+ g: v.snapshot.arena.g,
218
+ image672: Buffer.from(v.snapshot.arena.image672, 'base64'),
219
+ sourceCropBbox: v.snapshot.arena.sourceCropBbox,
220
+ },
221
+ },
222
+ pendingPUnits: v.pendingPUnits.map((p) => ({
223
+ ptsMs: p.ptsMs,
224
+ image336: Buffer.from(p.image336, 'base64'),
225
+ sourceCropBbox: p.sourceCropBbox,
226
+ })),
227
+ lastAnchorF: v.lastAnchorF,
228
+ },
229
+ history: {
230
+ packets: v.history.packets.map((h) => ({
231
+ packet: h.packet,
232
+ imageBytes: Buffer.from(h.imageBytes, 'base64'),
233
+ anchorBytes: h.anchorBytes != null ? Buffer.from(h.anchorBytes, 'base64') : null,
234
+ anchorFContentHash: h.anchorFContentHash,
235
+ })),
236
+ },
237
+ epoch: {
238
+ pendingNew: v.epoch.pendingNew,
239
+ coldRefs: v.epoch.coldRefs.map((r) => ({
240
+ refPacketId: r.refPacketId,
241
+ sourcePacketId: r.sourcePacketId,
242
+ anchorFId: r.anchorFId,
243
+ anchorFSha256: r.anchorFSha256,
244
+ ptsMs: r.ptsMs,
245
+ eventType: r.eventType,
246
+ sourceCropBbox: r.sourceCropBbox,
247
+ bytes: Buffer.from(r.bytes, 'base64'),
248
+ contentHash: r.contentHash,
249
+ })),
250
+ },
251
+ });
252
+ }
253
+ return state;
254
+ }
255
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/session/state.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,8CAA8C;AAC9C,MAAM,UAAU,aAAa,CAAC,SAAiB;IAC7C,MAAM,cAAc,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IAC9E,MAAM,EAAE,GAAG,QAAQ,CAAC,cAAc,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC;SAChC,MAAM,CAAC,GAAG,cAAc,IAAI,EAAE,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;SAChE,MAAM,CAAC,KAAK,CAAC,CAAC;IACjB,OAAO;QACL,cAAc;QACd,SAAS,EAAE,EAAE,CAAC,IAAI;QAClB,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC;QAC/B,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;KACjC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;AACzF,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,SAAiB;IAClD,OAAO;QACL,SAAS;QACT,MAAM,EAAE,oBAAoB,EAAE;QAC9B,MAAM,EAAE,IAAI,GAAG,EAAE;QACjB,UAAU,EAAE,IAAI,GAAG,EAAE;QACrB,aAAa,EAAE,CAAC;QAChB,SAAS,EAAE,CAAC;QACZ,SAAS,EAAE,CAAC;QACZ,OAAO,EAAE,IAAI,GAAG,EAAE;QAClB,YAAY,EAAE,CAAC;KAChB,CAAC;AACJ,CAAC;AAED,sBAAsB;AACtB,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC;AAEjC,mCAAmC;AACnC,MAAM,UAAU,YAAY,CAAC,KAAmB,EAAE,WAA6B;IAC7E,MAAM,GAAG,GAAG,WAAW,CAAC,WAAW,CAAC;IACpC,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACvC,IAAI,QAAQ,EAAE,CAAC;QACb,uBAAuB;QACvB,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACzB,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAChC,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,IAAI,eAAe,EAAE,CAAC;QAC5C,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;QAChD,IAAI,MAAM,IAAI,IAAI;YAAE,MAAM;QAC1B,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;IACD,MAAM,IAAI,GAAG;QACX,MAAM,EAAE;YACN,WAAW;YACX,iBAAiB,EAAE,CAAC;YACpB,sBAAsB,EAAE,IAAI;YAC5B,QAAQ,EAAE;gBACR,KAAK,EAAE,QAAiB;gBACxB,cAAc,EAAE,CAAC;gBACjB,WAAW,EAAE,CAAC;gBACd,IAAI,EAAE,CAAC;gBACP,aAAa,EAAE,CAAC;gBAChB,gBAAgB,EAAE,IAAI;gBACtB,eAAe,EAAE,IAAI;gBACrB,aAAa,EAAE,IAAI;gBACnB,KAAK,EAAE,IAAI;aACZ;YACD,aAAa,EAAE,EAAE;YACjB,WAAW,EAAE,IAAI;SAClB;QACD,OAAO,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;QACxB,KAAK,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;KACvC,CAAC;IACF,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC5B,OAAO,IAAI,CAAC;AACd,CAAC;AAED,0DAA0D;AAC1D,MAAM,cAAc,GAAG,IAAI,GAAG,EAAwB,CAAC;AAEvD,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,IAAI,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC1C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;QACtC,cAAc,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,sBAAsB;AACtB,MAAM,UAAU,mBAAmB;IACjC,cAAc,CAAC,KAAK,EAAE,CAAC;AACzB,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,gBAAgB,CAAC,KAAmB;IAClD,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;AAC7C,CAAC;AA0DD,2CAA2C;AAC3C,MAAM,UAAU,qBAAqB,CAAC,KAAmB;IACvD,MAAM,MAAM,GAAmC,EAAE,CAAC;IAClD,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACvC,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;QACtB,MAAM,CAAC,IAAI,CAAC;YACV,GAAG;YACH;gBACE,WAAW,EAAE,CAAC,CAAC,WAAW;gBAC1B,iBAAiB,EAAE,CAAC,CAAC,iBAAiB;gBACtC,sBAAsB,EAAE,CAAC,CAAC,sBAAsB;gBAChD,QAAQ,EAAE;oBACR,GAAG,CAAC,CAAC,QAAQ;oBACb,KAAK,EACH,CAAC,CAAC,QAAQ,CAAC,KAAK,IAAI,IAAI;wBACtB,CAAC,CAAC,IAAI;wBACN,CAAC,CAAC;4BACE,KAAK,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK;4BAC7B,GAAG,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG;4BACzB,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;4BACrB,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;4BACtD,cAAc,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc;yBAChD;iBACR;gBACD,aAAa,EAAE,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACzC,KAAK,EAAE,CAAC,CAAC,KAAK;oBACd,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;oBACvC,cAAc,EAAE,CAAC,CAAC,cAAc;iBACjC,CAAC,CAAC;gBACH,WAAW,EAAE,CAAC,CAAC,WAAW;gBAC1B,OAAO,EAAE;oBACP,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;wBACxC,MAAM,EAAE,CAAC,CAAC,MAAM;wBAChB,UAAU,EAAE,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC;wBAC3C,WAAW,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI;wBACpE,kBAAkB,EAAE,CAAC,CAAC,kBAAkB;qBACzC,CAAC,CAAC;iBACJ;gBACD,KAAK,EAAE;oBACL,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU;oBACjC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;wBACxC,WAAW,EAAE,CAAC,CAAC,WAAW;wBAC1B,cAAc,EAAE,CAAC,CAAC,cAAc;wBAChC,SAAS,EAAE,CAAC,CAAC,SAAS;wBACtB,aAAa,EAAE,CAAC,CAAC,aAAa;wBAC9B,KAAK,EAAE,CAAC,CAAC,KAAK;wBACd,SAAS,EAAE,CAAC,CAAC,SAAS;wBACtB,cAAc,EAAE,CAAC,CAAC,cAAc;wBAChC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC;wBACjC,WAAW,EAAE,CAAC,CAAC,WAAW;qBAC3B,CAAC,CAAC;iBACJ;aACF;SACF,CAAC,CAAC;IACL,CAAC;IACD,MAAM,GAAG,GAAgB;QACvB,OAAO,EAAE,CAAC;QACV,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,OAAO,EAAE,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QACrC,UAAU,EAAE,CAAC,GAAG,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACrD,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,gBAAgB,EAAE,CAAC,CAAC,gBAAgB,CAAC,QAAQ,CAAC,QAAQ,CAAC;YACvD,aAAa,EAAE,CAAC,CAAC,aAAa;YAC9B,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,QAAQ,CAAC,QAAQ,CAAC;YAC5C,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,WAAW,EAAE,CAAC,CAAC,WAAW;SAC3B,CAAC,CAAC;QACH,MAAM;KACP,CAAC;IACF,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;AAC7B,CAAC;AAED,6CAA6C;AAC7C,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAChD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAgB,CAAC;IAC5C,IAAI,GAAG,CAAC,OAAO,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,cAAc,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IACpE,MAAM,KAAK,GAAG,kBAAkB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAChD,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;IAC1B,KAAK,CAAC,aAAa,GAAG,GAAG,CAAC,aAAa,CAAC;IACxC,KAAK,CAAC,SAAS,GAAG,GAAG,CAAC,SAAS,CAAC;IAChC,KAAK,CAAC,SAAS,GAAG,GAAG,CAAC,SAAS,CAAC;IAChC,KAAK,CAAC,YAAY,GAAG,GAAG,CAAC,YAAY,CAAC;IACtC,KAAK,CAAC,OAAO,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACrC,KAAK,CAAC,UAAU,GAAG,IAAI,GAAG,CACxB,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QACxB,CAAC,CAAC,SAAS;QACX;YACE,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,gBAAgB,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,EAAE,QAAQ,CAAC;YAC3D,aAAa,EAAE,CAAC,CAAC,aAAa;YAC9B,UAAU,EAAE,CAAC,CAAC,UAAU,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS;YAClF,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,WAAW,EAAE,CAAC,CAAC,WAAW;SAC3B;KACF,CAAC,CACH,CAAC;IACF,KAAK,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;QAClC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE;YACpB,MAAM,EAAE;gBACN,WAAW,EAAE,CAAC,CAAC,WAAW;gBAC1B,iBAAiB,EAAE,CAAC,CAAC,iBAAiB;gBACtC,sBAAsB,EAAE,CAAC,CAAC,sBAAsB;gBAChD,QAAQ,EAAE;oBACR,GAAG,CAAC,CAAC,QAAQ;oBACb,KAAK,EACH,CAAC,CAAC,QAAQ,CAAC,KAAK,IAAI,IAAI;wBACtB,CAAC,CAAC,IAAI;wBACN,CAAC,CAAC;4BACE,KAAK,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK;4BAC7B,GAAG,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG;4BACzB,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;4BACrB,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,CAAC;4BAC1D,cAAc,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc;yBAChD;iBACR;gBACD,aAAa,EAAE,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACzC,KAAK,EAAE,CAAC,CAAC,KAAK;oBACd,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC;oBAC3C,cAAc,EAAE,CAAC,CAAC,cAAc;iBACjC,CAAC,CAAC;gBACH,WAAW,EAAE,CAAC,CAAC,WAAW;aAC3B;YACD,OAAO,EAAE;gBACP,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACrC,MAAM,EAAE,CAAC,CAAC,MAAM;oBAChB,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,EAAE,QAAQ,CAAC;oBAC/C,WAAW,EAAE,CAAC,CAAC,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI;oBAChF,kBAAkB,EAAE,CAAC,CAAC,kBAAkB;iBACzC,CAAC,CAAC;aACJ;YACD,KAAK,EAAE;gBACL,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,UAAU;gBAC9B,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACrC,WAAW,EAAE,CAAC,CAAC,WAAW;oBAC1B,cAAc,EAAE,CAAC,CAAC,cAAc;oBAChC,SAAS,EAAE,CAAC,CAAC,SAAS;oBACtB,aAAa,EAAE,CAAC,CAAC,aAAa;oBAC9B,KAAK,EAAE,CAAC,CAAC,KAAK;oBACd,SAAS,EAAE,CAAC,CAAC,SAAS;oBACtB,cAAc,EAAE,CAAC,CAAC,cAAc;oBAChC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC;oBACrC,WAAW,EAAE,CAAC,CAAC,WAAW;iBAC3B,CAAC,CAAC;aACJ;SACF,CAAC,CAAC;IACL,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}