context-mode 0.9.21 → 1.0.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.
Files changed (102) hide show
  1. package/.claude-plugin/hooks/hooks.json +46 -4
  2. package/.claude-plugin/marketplace.json +2 -2
  3. package/.claude-plugin/plugin.json +4 -4
  4. package/README.md +377 -191
  5. package/build/adapters/claude-code/config.d.ts +8 -0
  6. package/build/adapters/claude-code/config.js +8 -0
  7. package/build/adapters/claude-code/hooks.d.ts +53 -0
  8. package/build/adapters/claude-code/hooks.js +88 -0
  9. package/build/adapters/claude-code/index.d.ts +50 -0
  10. package/build/adapters/claude-code/index.js +523 -0
  11. package/build/adapters/codex/config.d.ts +8 -0
  12. package/build/adapters/codex/config.js +8 -0
  13. package/build/adapters/codex/hooks.d.ts +21 -0
  14. package/build/adapters/codex/hooks.js +27 -0
  15. package/build/adapters/codex/index.d.ts +44 -0
  16. package/build/adapters/codex/index.js +223 -0
  17. package/build/adapters/detect.d.ts +26 -0
  18. package/build/adapters/detect.js +131 -0
  19. package/build/adapters/gemini-cli/config.d.ts +8 -0
  20. package/build/adapters/gemini-cli/config.js +8 -0
  21. package/build/adapters/gemini-cli/hooks.d.ts +44 -0
  22. package/build/adapters/gemini-cli/hooks.js +64 -0
  23. package/build/adapters/gemini-cli/index.d.ts +57 -0
  24. package/build/adapters/gemini-cli/index.js +468 -0
  25. package/build/adapters/opencode/config.d.ts +8 -0
  26. package/build/adapters/opencode/config.js +8 -0
  27. package/build/adapters/opencode/hooks.d.ts +38 -0
  28. package/build/adapters/opencode/hooks.js +50 -0
  29. package/build/adapters/opencode/index.d.ts +52 -0
  30. package/build/adapters/opencode/index.js +386 -0
  31. package/build/adapters/types.d.ts +218 -0
  32. package/build/adapters/types.js +13 -0
  33. package/build/adapters/vscode-copilot/config.d.ts +8 -0
  34. package/build/adapters/vscode-copilot/config.js +8 -0
  35. package/build/adapters/vscode-copilot/hooks.d.ts +49 -0
  36. package/build/adapters/vscode-copilot/hooks.js +76 -0
  37. package/build/adapters/vscode-copilot/index.d.ts +58 -0
  38. package/build/adapters/vscode-copilot/index.js +512 -0
  39. package/build/cli.d.ts +9 -6
  40. package/build/cli.js +133 -423
  41. package/build/db-base.d.ts +84 -0
  42. package/build/db-base.js +128 -0
  43. package/build/executor.d.ts +6 -7
  44. package/build/executor.js +111 -51
  45. package/build/opencode-plugin.d.ts +37 -0
  46. package/build/opencode-plugin.js +118 -0
  47. package/build/runtime.js +1 -1
  48. package/build/server.js +436 -117
  49. package/build/session/db.d.ts +110 -0
  50. package/build/session/db.js +285 -0
  51. package/build/session/extract.d.ts +51 -0
  52. package/build/session/extract.js +407 -0
  53. package/build/session/snapshot.d.ts +70 -0
  54. package/build/session/snapshot.js +309 -0
  55. package/build/store.d.ts +4 -22
  56. package/build/store.js +67 -55
  57. package/build/truncate.d.ts +59 -0
  58. package/build/truncate.js +157 -0
  59. package/build/types.d.ts +101 -0
  60. package/build/types.js +20 -0
  61. package/configs/claude-code/CLAUDE.md +62 -0
  62. package/configs/codex/AGENTS.md +58 -0
  63. package/configs/codex/config.toml +5 -0
  64. package/configs/gemini-cli/GEMINI.md +58 -0
  65. package/configs/gemini-cli/mcp.json +7 -0
  66. package/configs/gemini-cli/settings.json +49 -0
  67. package/configs/opencode/AGENTS.md +58 -0
  68. package/configs/opencode/opencode.json +10 -0
  69. package/configs/vscode-copilot/copilot-instructions.md +58 -0
  70. package/configs/vscode-copilot/hooks.json +16 -0
  71. package/configs/vscode-copilot/mcp.json +8 -0
  72. package/hooks/core/formatters.mjs +86 -0
  73. package/hooks/core/routing.mjs +262 -0
  74. package/hooks/core/stdin.mjs +19 -0
  75. package/hooks/formatters/claude-code.mjs +57 -0
  76. package/hooks/formatters/gemini-cli.mjs +55 -0
  77. package/hooks/formatters/vscode-copilot.mjs +55 -0
  78. package/hooks/gemini-cli/aftertool.mjs +58 -0
  79. package/hooks/gemini-cli/beforetool.mjs +25 -0
  80. package/hooks/gemini-cli/precompress.mjs +51 -0
  81. package/hooks/gemini-cli/sessionstart.mjs +117 -0
  82. package/hooks/hooks.json +46 -4
  83. package/hooks/posttooluse.mjs +53 -0
  84. package/hooks/precompact.mjs +55 -0
  85. package/hooks/pretooluse.mjs +23 -266
  86. package/hooks/routing-block.mjs +19 -6
  87. package/hooks/session-directive.mjs +353 -0
  88. package/hooks/session-helpers.mjs +112 -0
  89. package/hooks/sessionstart.mjs +123 -16
  90. package/hooks/userpromptsubmit.mjs +58 -0
  91. package/hooks/vscode-copilot/posttooluse.mjs +58 -0
  92. package/hooks/vscode-copilot/precompact.mjs +51 -0
  93. package/hooks/vscode-copilot/pretooluse.mjs +25 -0
  94. package/hooks/vscode-copilot/sessionstart.mjs +115 -0
  95. package/package.json +20 -17
  96. package/skills/context-mode/SKILL.md +49 -49
  97. package/skills/{doctor → ctx-doctor}/SKILL.md +3 -3
  98. package/skills/{stats → ctx-stats}/SKILL.md +3 -3
  99. package/skills/{upgrade → ctx-upgrade}/SKILL.md +3 -3
  100. package/start.mjs +47 -0
  101. package/hooks/pretooluse.sh +0 -147
  102. package/server.bundle.mjs +0 -341
@@ -0,0 +1,407 @@
1
+ /**
2
+ * Session event extraction — pure functions, zero side effects.
3
+ * Extracts structured events from Claude Code tool calls and user messages.
4
+ *
5
+ * All 13 event categories as specified in PRD Section 3.
6
+ */
7
+ // ── Internal helpers ───────────────────────────────────────────────────────
8
+ /** Truncate a string to at most `max` characters. */
9
+ function truncate(value, max = 300) {
10
+ if (value == null)
11
+ return "";
12
+ if (value.length <= max)
13
+ return value;
14
+ return value.slice(0, max);
15
+ }
16
+ /** Serialise an unknown value to a string, then truncate. */
17
+ function truncateAny(value, max = 300) {
18
+ if (value == null)
19
+ return "";
20
+ const str = typeof value === "string" ? value : JSON.stringify(value);
21
+ return truncate(str, max);
22
+ }
23
+ // ── Category extractors ────────────────────────────────────────────────────
24
+ /**
25
+ * Category 1 & 2: rule + file
26
+ *
27
+ * CLAUDE.md / .claude/ reads → emit both a "rule" event (priority 1) AND a
28
+ * "file_read" event (priority 1) because the file is being actively accessed.
29
+ *
30
+ * Other Edit/Write/Read tool calls → emit a file_edit / file_write / file_read
31
+ * event (priority 1).
32
+ */
33
+ function extractFileAndRule(input) {
34
+ const { tool_name, tool_input, tool_response } = input;
35
+ const events = [];
36
+ if (tool_name === "Read") {
37
+ const filePath = String(tool_input["file_path"] ?? "");
38
+ // Rule detection: CLAUDE.md or anything inside a .claude/ directory
39
+ const isRuleFile = /CLAUDE\.md$|\.claude[\\/]/i.test(filePath);
40
+ if (isRuleFile) {
41
+ events.push({
42
+ type: "rule",
43
+ category: "rule",
44
+ data: truncate(filePath),
45
+ priority: 1,
46
+ });
47
+ // Capture rule content so it survives context compaction
48
+ if (tool_response && tool_response.length > 0) {
49
+ events.push({
50
+ type: "rule_content",
51
+ category: "rule",
52
+ data: truncate(tool_response, 5000),
53
+ priority: 1,
54
+ });
55
+ }
56
+ }
57
+ // Always emit file_read for any Read call
58
+ events.push({
59
+ type: "file_read",
60
+ category: "file",
61
+ data: truncate(filePath),
62
+ priority: 1,
63
+ });
64
+ return events;
65
+ }
66
+ if (tool_name === "Edit") {
67
+ const filePath = String(tool_input["file_path"] ?? "");
68
+ events.push({
69
+ type: "file",
70
+ category: "file",
71
+ data: truncate(filePath),
72
+ priority: 1,
73
+ });
74
+ return events;
75
+ }
76
+ if (tool_name === "Write") {
77
+ const filePath = String(tool_input["file_path"] ?? "");
78
+ events.push({
79
+ type: "file_write",
80
+ category: "file",
81
+ data: truncate(filePath),
82
+ priority: 1,
83
+ });
84
+ return events;
85
+ }
86
+ // Glob — file pattern exploration
87
+ if (tool_name === "Glob") {
88
+ const pattern = String(tool_input["pattern"] ?? "");
89
+ events.push({
90
+ type: "file_glob",
91
+ category: "file",
92
+ data: truncate(pattern),
93
+ priority: 3,
94
+ });
95
+ return events;
96
+ }
97
+ // Grep — code search
98
+ if (tool_name === "Grep") {
99
+ const searchPattern = String(tool_input["pattern"] ?? "");
100
+ const searchPath = String(tool_input["path"] ?? "");
101
+ events.push({
102
+ type: "file_search",
103
+ category: "file",
104
+ data: truncate(`${searchPattern} in ${searchPath}`),
105
+ priority: 3,
106
+ });
107
+ return events;
108
+ }
109
+ return events;
110
+ }
111
+ /**
112
+ * Category 4: cwd
113
+ * Matches the first `cd <path>` in a Bash command (handles quoted paths).
114
+ */
115
+ function extractCwd(input) {
116
+ if (input.tool_name !== "Bash")
117
+ return [];
118
+ const cmd = String(input.tool_input["command"] ?? "");
119
+ // Match: cd "path" | cd 'path' | cd path
120
+ const cdMatch = cmd.match(/\bcd\s+("([^"]+)"|'([^']+)'|(\S+))/);
121
+ if (!cdMatch)
122
+ return [];
123
+ const dir = cdMatch[2] ?? cdMatch[3] ?? cdMatch[4] ?? "";
124
+ return [{
125
+ type: "cwd",
126
+ category: "cwd",
127
+ data: truncate(dir),
128
+ priority: 2,
129
+ }];
130
+ }
131
+ /**
132
+ * Category 5: error
133
+ * Detects failures from bash exit codes / error patterns, or an explicit
134
+ * isError flag in tool_output.
135
+ */
136
+ function extractError(input) {
137
+ const { tool_name, tool_input, tool_response, tool_output } = input;
138
+ const response = String(tool_response ?? "");
139
+ const isErrorFlag = tool_output?.isError === true;
140
+ const isBashError = tool_name === "Bash" &&
141
+ /exit code [1-9]|error:|Error:|FAIL|failed/i.test(response);
142
+ if (!isBashError && !isErrorFlag)
143
+ return [];
144
+ return [{
145
+ type: "error_tool",
146
+ category: "error",
147
+ data: truncate(response, 300),
148
+ priority: 2,
149
+ }];
150
+ }
151
+ /**
152
+ * Category 11: git
153
+ * Matches common git operations from Bash commands.
154
+ */
155
+ const GIT_PATTERNS = [
156
+ { pattern: /\bgit\s+checkout\b/, operation: "branch" },
157
+ { pattern: /\bgit\s+commit\b/, operation: "commit" },
158
+ { pattern: /\bgit\s+merge\s+\S+/, operation: "merge" },
159
+ { pattern: /\bgit\s+rebase\b/, operation: "rebase" },
160
+ { pattern: /\bgit\s+stash\b/, operation: "stash" },
161
+ { pattern: /\bgit\s+push\b/, operation: "push" },
162
+ { pattern: /\bgit\s+pull\b/, operation: "pull" },
163
+ { pattern: /\bgit\s+log\b/, operation: "log" },
164
+ { pattern: /\bgit\s+diff\b/, operation: "diff" },
165
+ { pattern: /\bgit\s+status\b/, operation: "status" },
166
+ { pattern: /\bgit\s+branch\b/, operation: "branch" },
167
+ { pattern: /\bgit\s+reset\b/, operation: "reset" },
168
+ ];
169
+ function extractGit(input) {
170
+ if (input.tool_name !== "Bash")
171
+ return [];
172
+ const cmd = String(input.tool_input["command"] ?? "");
173
+ const match = GIT_PATTERNS.find(p => p.pattern.test(cmd));
174
+ if (!match)
175
+ return [];
176
+ return [{
177
+ type: "git",
178
+ category: "git",
179
+ data: truncate(match.operation),
180
+ priority: 2,
181
+ }];
182
+ }
183
+ /**
184
+ * Category 3: task
185
+ * TodoWrite / TaskCreate / TaskUpdate tool calls.
186
+ */
187
+ function extractTask(input) {
188
+ const TASK_TOOLS = new Set(["TodoWrite", "TaskCreate", "TaskUpdate"]);
189
+ if (!TASK_TOOLS.has(input.tool_name))
190
+ return [];
191
+ return [{
192
+ type: "task",
193
+ category: "task",
194
+ data: truncate(JSON.stringify(input.tool_input), 300),
195
+ priority: 1,
196
+ }];
197
+ }
198
+ /**
199
+ * Category 8: env
200
+ * Environment setup commands in Bash: venv, export, nvm, pyenv, conda, rbenv.
201
+ */
202
+ const ENV_PATTERNS = [
203
+ /\bsource\s+\S*activate\b/,
204
+ /\bexport\s+\w+=/,
205
+ /\bnvm\s+use\b/,
206
+ /\bpyenv\s+(shell|local|global)\b/,
207
+ /\bconda\s+activate\b/,
208
+ /\brbenv\s+(shell|local|global)\b/,
209
+ /\bnpm\s+install\b/,
210
+ /\bnpm\s+ci\b/,
211
+ /\bpip\s+install\b/,
212
+ /\bbun\s+install\b/,
213
+ /\byarn\s+(add|install)\b/,
214
+ /\bpnpm\s+(add|install)\b/,
215
+ ];
216
+ function extractEnv(input) {
217
+ if (input.tool_name !== "Bash")
218
+ return [];
219
+ const cmd = String(input.tool_input["command"] ?? "");
220
+ const isEnvCmd = ENV_PATTERNS.some(p => p.test(cmd));
221
+ if (!isEnvCmd)
222
+ return [];
223
+ return [{
224
+ type: "env",
225
+ category: "env",
226
+ data: truncate(cmd),
227
+ priority: 2,
228
+ }];
229
+ }
230
+ /**
231
+ * Category 10: skill
232
+ * Skill tool invocations.
233
+ */
234
+ function extractSkill(input) {
235
+ if (input.tool_name !== "Skill")
236
+ return [];
237
+ const skillName = String(input.tool_input["skill"] ?? "");
238
+ return [{
239
+ type: "skill",
240
+ category: "skill",
241
+ data: truncate(skillName),
242
+ priority: 3,
243
+ }];
244
+ }
245
+ /**
246
+ * Category 9: subagent
247
+ * Agent tool calls (subagent dispatches).
248
+ */
249
+ function extractSubagent(input) {
250
+ if (input.tool_name !== "Agent")
251
+ return [];
252
+ const prompt = String(input.tool_input["prompt"] ?? input.tool_input["description"] ?? "");
253
+ return [{
254
+ type: "subagent",
255
+ category: "subagent",
256
+ data: truncate(prompt, 300),
257
+ priority: 3,
258
+ }];
259
+ }
260
+ /**
261
+ * Category 14: mcp
262
+ * MCP tool calls (context7, playwright, claude-mem, ctx-stats, etc.).
263
+ */
264
+ function extractMcp(input) {
265
+ const { tool_name, tool_input } = input;
266
+ if (!tool_name.startsWith("mcp__"))
267
+ return [];
268
+ // Extract readable tool name: last segment after __
269
+ const parts = tool_name.split("__");
270
+ const toolShort = parts[parts.length - 1] || tool_name;
271
+ // Extract first string argument for context
272
+ const firstArg = Object.values(tool_input).find((v) => typeof v === "string");
273
+ const argStr = firstArg ? `: ${truncate(String(firstArg), 100)}` : "";
274
+ return [{
275
+ type: "mcp",
276
+ category: "mcp",
277
+ data: truncate(`${toolShort}${argStr}`),
278
+ priority: 3,
279
+ }];
280
+ }
281
+ // ── User-message extractors ────────────────────────────────────────────────
282
+ /**
283
+ * Category 6: decision
284
+ * User corrections / approach selections.
285
+ */
286
+ const DECISION_PATTERNS = [
287
+ /\b(don'?t|do not|never|always|instead|rather|prefer)\b/i,
288
+ /\b(use|switch to|go with|pick|choose)\s+\w+\s+(instead|over|not)\b/i,
289
+ /\b(no,?\s+(use|do|try|make))\b/i,
290
+ // Turkish patterns
291
+ /\b(hayır|hayir|evet|böyle|boyle|degil|değil|yerine|kullan)\b/i,
292
+ ];
293
+ function extractDecision(message) {
294
+ const isDecision = DECISION_PATTERNS.some(p => p.test(message));
295
+ if (!isDecision)
296
+ return [];
297
+ return [{
298
+ type: "decision",
299
+ category: "decision",
300
+ data: truncate(message, 300),
301
+ priority: 2,
302
+ }];
303
+ }
304
+ /**
305
+ * Category 7: role
306
+ * Persona / behavioral directive patterns.
307
+ */
308
+ const ROLE_PATTERNS = [
309
+ /\b(act as|you are|behave like|pretend|role of|persona)\b/i,
310
+ /\b(senior|staff|principal|lead)\s+(engineer|developer|architect)\b/i,
311
+ // Turkish patterns
312
+ /\b(gibi davran|rolünde|olarak çalış)\b/i,
313
+ ];
314
+ function extractRole(message) {
315
+ const isRole = ROLE_PATTERNS.some(p => p.test(message));
316
+ if (!isRole)
317
+ return [];
318
+ return [{
319
+ type: "role",
320
+ category: "role",
321
+ data: truncate(message, 300),
322
+ priority: 3,
323
+ }];
324
+ }
325
+ /**
326
+ * Category 13: intent
327
+ * Session mode classification from user messages.
328
+ */
329
+ const INTENT_PATTERNS = [
330
+ { mode: "investigate", pattern: /\b(why|how does|explain|understand|what is|analyze|debug|look into)\b/i },
331
+ { mode: "implement", pattern: /\b(create|add|build|implement|write|make|develop|fix)\b/i },
332
+ { mode: "discuss", pattern: /\b(think about|consider|should we|what if|pros and cons|opinion)\b/i },
333
+ { mode: "review", pattern: /\b(review|check|audit|verify|test|validate)\b/i },
334
+ ];
335
+ function extractIntent(message) {
336
+ const match = INTENT_PATTERNS.find(({ pattern }) => pattern.test(message));
337
+ if (!match)
338
+ return [];
339
+ return [{
340
+ type: "intent",
341
+ category: "intent",
342
+ data: truncate(match.mode),
343
+ priority: 4,
344
+ }];
345
+ }
346
+ /**
347
+ * Category 12: data
348
+ * Large user-pasted data references (message > 1KB).
349
+ */
350
+ function extractData(message) {
351
+ if (message.length <= 1024)
352
+ return [];
353
+ return [{
354
+ type: "data",
355
+ category: "data",
356
+ data: truncate(message, 200),
357
+ priority: 4,
358
+ }];
359
+ }
360
+ // ── Public API ─────────────────────────────────────────────────────────────
361
+ /**
362
+ * Extract session events from a PostToolUse hook input.
363
+ *
364
+ * Accepts the raw hook JSON shape (snake_case keys) as received from stdin.
365
+ * Returns an array of zero or more SessionEvents. Never throws.
366
+ */
367
+ export function extractEvents(input) {
368
+ try {
369
+ const events = [];
370
+ // File + Rule (handles Read/Edit/Write)
371
+ events.push(...extractFileAndRule(input));
372
+ // Bash-based extractors (may overlap on the same command)
373
+ events.push(...extractCwd(input));
374
+ events.push(...extractError(input));
375
+ events.push(...extractGit(input));
376
+ events.push(...extractEnv(input));
377
+ // Tool-specific extractors
378
+ events.push(...extractTask(input));
379
+ events.push(...extractSkill(input));
380
+ events.push(...extractSubagent(input));
381
+ events.push(...extractMcp(input));
382
+ return events;
383
+ }
384
+ catch {
385
+ // Graceful degradation: if extraction fails, session continues normally
386
+ return [];
387
+ }
388
+ }
389
+ /**
390
+ * Extract session events from a UserPromptSubmit hook input (user message text).
391
+ *
392
+ * Handles: decision, role, intent, data categories.
393
+ * Returns an array of zero or more SessionEvents. Never throws.
394
+ */
395
+ export function extractUserEvents(message) {
396
+ try {
397
+ const events = [];
398
+ events.push(...extractDecision(message));
399
+ events.push(...extractRole(message));
400
+ events.push(...extractIntent(message));
401
+ events.push(...extractData(message));
402
+ return events;
403
+ }
404
+ catch {
405
+ return [];
406
+ }
407
+ }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Snapshot builder — converts stored SessionEvents into an XML resume snapshot.
3
+ *
4
+ * Pure functions only. No database access, no file system, no side effects.
5
+ * The output XML is injected into Claude's context after a compact event to
6
+ * restore session awareness.
7
+ *
8
+ * Budget: default 2048 bytes, allocated by priority tier:
9
+ * P1 (file, task, rule): 50% = ~1024 bytes
10
+ * P2 (cwd, error, decision, env, git): 35% = ~716 bytes
11
+ * P3-P4 (subagent, skill, role, data, intent): 15% = ~308 bytes
12
+ */
13
+ /** Stored event as read from SessionDB. */
14
+ export interface StoredEvent {
15
+ type: string;
16
+ category: string;
17
+ data: string;
18
+ priority: number;
19
+ created_at?: string;
20
+ }
21
+ export interface BuildSnapshotOpts {
22
+ maxBytes?: number;
23
+ compactCount?: number;
24
+ }
25
+ /**
26
+ * Render <active_files> from file events.
27
+ * Deduplicates by path, counts operations, keeps the last 10 files.
28
+ */
29
+ export declare function renderActiveFiles(fileEvents: StoredEvent[]): string;
30
+ /**
31
+ * Render <task_state> from task events.
32
+ * Shows the most recent task state (last event's data).
33
+ */
34
+ export declare function renderTaskState(taskEvents: StoredEvent[]): string;
35
+ /**
36
+ * Render <rules> from rule events.
37
+ * Lists each unique rule source path + content summaries.
38
+ */
39
+ export declare function renderRules(ruleEvents: StoredEvent[]): string;
40
+ /**
41
+ * Render <decisions> from decision events.
42
+ */
43
+ export declare function renderDecisions(decisionEvents: StoredEvent[]): string;
44
+ /**
45
+ * Render <environment> from cwd, env, and git events.
46
+ */
47
+ export declare function renderEnvironment(cwdEvent: StoredEvent | undefined, envEvents: StoredEvent[], gitEvent: StoredEvent | undefined): string;
48
+ /**
49
+ * Render <errors_resolved> from error events.
50
+ */
51
+ export declare function renderErrors(errorEvents: StoredEvent[]): string;
52
+ /**
53
+ * Render <intent> from the most recent intent event.
54
+ */
55
+ export declare function renderIntent(intentEvent: StoredEvent): string;
56
+ /**
57
+ * Render <mcp_tools> from MCP tool call events.
58
+ * Deduplicates by tool name, shows usage count.
59
+ */
60
+ export declare function renderMcpTools(mcpEvents: StoredEvent[]): string;
61
+ /**
62
+ * Build a resume snapshot XML string from stored session events.
63
+ *
64
+ * Algorithm:
65
+ * 1. Group events by category
66
+ * 2. Render each section
67
+ * 3. Assemble by priority tier with budget trimming
68
+ * 4. If over maxBytes, drop lowest priority sections first
69
+ */
70
+ export declare function buildResumeSnapshot(events: StoredEvent[], opts?: BuildSnapshotOpts): string;