agentel 0.2.6 → 0.3.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/README.md +260 -79
- package/docs/code-reference.md +130 -42
- package/docs/history-source-handling.md +685 -153
- package/docs/release.md +35 -8
- package/npm-shrinkwrap.json +478 -0
- package/package.json +20 -4
- package/scripts/postinstall.js +156 -0
- package/src/archive.js +1342 -50
- package/src/canonical-events.js +346 -35
- package/src/cli.js +8835 -843
- package/src/collector.js +42 -4
- package/src/config.js +26 -4
- package/src/diffs.js +156 -0
- package/src/doctor.js +48 -5
- package/src/importers/claude.js +51 -4
- package/src/importers/copilot.js +385 -0
- package/src/importers/cursor-recovery.js +22 -0
- package/src/importers/factory.js +396 -0
- package/src/importers/gemini.js +41 -1
- package/src/importers/grok.js +367 -0
- package/src/importers/pi.js +422 -0
- package/src/importers/providers.js +64 -5
- package/src/importers.js +6429 -747
- package/src/mcp.js +1 -0
- package/src/memory-sources.js +671 -0
- package/src/memory-store.js +0 -0
- package/src/parser-versions.js +13 -0
- package/src/pricing.js +84 -0
- package/src/search.js +641 -215
- package/src/session-store.js +405 -0
- package/src/source-watch.js +293 -0
- package/src/sources.js +60 -11
- package/src/supervisor.js +197 -9
- package/src/sync.js +6 -0
- package/src/unavailable-sources.js +358 -0
- package/src/web-export-instructions.js +6 -4
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
|
|
5
|
+
const PROVIDER = "copilot";
|
|
6
|
+
|
|
7
|
+
function parseCopilotEventsFile(file, options = {}) {
|
|
8
|
+
let text;
|
|
9
|
+
try {
|
|
10
|
+
text = fs.readFileSync(file, "utf8");
|
|
11
|
+
} catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
return parseCopilotEventsText(text, options);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Copilot CLI sessions live in ~/.copilot/session-state/<uuid>/events.jsonl.
|
|
18
|
+
// Every line is {type, data, id, timestamp, parentId}. Lines can contain raw
|
|
19
|
+
// unescaped multiline tool output in older builds, so parse line-by-line and
|
|
20
|
+
// drop what does not parse.
|
|
21
|
+
function parseCopilotEventsText(text, options = {}) {
|
|
22
|
+
const lines = String(text || "").split(/\r?\n/);
|
|
23
|
+
const fallbackTime = toIso(options.fallbackTime) || new Date().toISOString();
|
|
24
|
+
const messages = [];
|
|
25
|
+
let sessionId = "";
|
|
26
|
+
let cwd = "";
|
|
27
|
+
let repository = "";
|
|
28
|
+
let branch = "";
|
|
29
|
+
let copilotVersion = "";
|
|
30
|
+
let currentModel = "";
|
|
31
|
+
let shutdown = null;
|
|
32
|
+
let taskSummary = "";
|
|
33
|
+
let index = 0;
|
|
34
|
+
for (const line of lines) {
|
|
35
|
+
if (!line.trim()) continue;
|
|
36
|
+
const event = parseJson(line);
|
|
37
|
+
if (!event || typeof event !== "object") continue;
|
|
38
|
+
const type = String(event.type || "");
|
|
39
|
+
const data = event.data && typeof event.data === "object" ? event.data : {};
|
|
40
|
+
const timestamp = toIso(event.timestamp) || offsetTimestamp(fallbackTime, index);
|
|
41
|
+
index++;
|
|
42
|
+
const base = compactObject({
|
|
43
|
+
provider: PROVIDER,
|
|
44
|
+
providerMessageId: firstString(event.id),
|
|
45
|
+
parentMessageId: firstString(event.parentId),
|
|
46
|
+
eventType: type
|
|
47
|
+
});
|
|
48
|
+
if (type === "session.start" || type === "session.resume") {
|
|
49
|
+
sessionId ||= firstString(data.sessionId);
|
|
50
|
+
const context = data.context && typeof data.context === "object" ? data.context : {};
|
|
51
|
+
cwd = firstString(context.cwd, cwd);
|
|
52
|
+
repository = firstString(context.repository, repository);
|
|
53
|
+
branch = firstString(context.branch, branch);
|
|
54
|
+
copilotVersion ||= firstString(data.copilotVersion);
|
|
55
|
+
currentModel = firstString(data.selectedModel, currentModel);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (type === "user.message") {
|
|
59
|
+
const content = firstString(data.content, data.text, data.message);
|
|
60
|
+
if (content) messages.push({ role: "user", content, timestamp, metadata: { ...base } });
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (type === "assistant.message") {
|
|
64
|
+
const content = firstString(data.content, data.text, data.message);
|
|
65
|
+
if (content) {
|
|
66
|
+
messages.push({
|
|
67
|
+
role: "assistant",
|
|
68
|
+
content,
|
|
69
|
+
timestamp,
|
|
70
|
+
metadata: compactObject({ ...base, model: firstString(data.model, currentModel) || undefined })
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (type === "tool.execution_start") {
|
|
76
|
+
const call = copilotToolCall(data);
|
|
77
|
+
if (call) {
|
|
78
|
+
messages.push({
|
|
79
|
+
role: "assistant",
|
|
80
|
+
content: "",
|
|
81
|
+
timestamp,
|
|
82
|
+
metadata: compactObject({ ...base, model: currentModel || undefined, toolCalls: [call] })
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (type === "tool.execution_complete") {
|
|
88
|
+
currentModel = firstString(data.model, currentModel);
|
|
89
|
+
const toolResult = copilotToolResult(data);
|
|
90
|
+
if (toolResult) {
|
|
91
|
+
messages.push({ role: "tool", content: toolResult.output, timestamp, metadata: { ...base, toolResult } });
|
|
92
|
+
}
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
if (type === "session.model_change") {
|
|
96
|
+
const newModel = firstString(data.newModel);
|
|
97
|
+
if (newModel) {
|
|
98
|
+
currentModel = newModel;
|
|
99
|
+
messages.push({
|
|
100
|
+
role: "system",
|
|
101
|
+
content: `Model changed to ${newModel}`,
|
|
102
|
+
timestamp,
|
|
103
|
+
metadata: { ...base, providerGenerated: true, contextKind: "model_change", model: newModel }
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
if (type === "session.compaction_complete") {
|
|
109
|
+
messages.push({
|
|
110
|
+
role: "system",
|
|
111
|
+
content: "Context compacted",
|
|
112
|
+
timestamp,
|
|
113
|
+
metadata: compactObject({
|
|
114
|
+
...base,
|
|
115
|
+
providerGenerated: true,
|
|
116
|
+
contextKind: "compaction",
|
|
117
|
+
tokensBefore: positiveNumber(data.preCompactionTokens)
|
|
118
|
+
})
|
|
119
|
+
});
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
if (type === "subagent.started" || type === "subagent.completed") {
|
|
123
|
+
const agentName = firstString(data.agentDisplayName, data.agentName);
|
|
124
|
+
messages.push({
|
|
125
|
+
role: "system",
|
|
126
|
+
content: `Subagent ${agentName || "run"} ${type === "subagent.started" ? "started" : "completed"}`,
|
|
127
|
+
timestamp,
|
|
128
|
+
metadata: compactObject({
|
|
129
|
+
...base,
|
|
130
|
+
providerGenerated: true,
|
|
131
|
+
contextKind: "subagent",
|
|
132
|
+
agentName: agentName || undefined,
|
|
133
|
+
agentDescription: firstString(data.agentDescription) || undefined,
|
|
134
|
+
toolCallId: firstString(data.toolCallId) || undefined
|
|
135
|
+
})
|
|
136
|
+
});
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (type === "session.task_complete") {
|
|
140
|
+
taskSummary = firstString(data.summary, taskSummary);
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
if (type === "session.shutdown") {
|
|
144
|
+
shutdown = data;
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (!messages.length && !sessionId) return null;
|
|
149
|
+
return {
|
|
150
|
+
sessionId,
|
|
151
|
+
cwd,
|
|
152
|
+
repository,
|
|
153
|
+
branch,
|
|
154
|
+
messages,
|
|
155
|
+
startedAt: messages[0]?.timestamp || fallbackTime,
|
|
156
|
+
endedAt: messages[messages.length - 1]?.timestamp || fallbackTime,
|
|
157
|
+
sessionSummary: copilotSessionSummary({ shutdown, taskSummary, copilotVersion, repository, branch, currentModel })
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function copilotToolCall(data) {
|
|
162
|
+
const name = firstString(data.toolName, data.name);
|
|
163
|
+
if (!name) return null;
|
|
164
|
+
// arguments is usually an object but is sometimes a JSON string.
|
|
165
|
+
let args = data.arguments;
|
|
166
|
+
if (typeof args === "string") args = parseJson(args) || { raw: args };
|
|
167
|
+
if (!args || typeof args !== "object") args = undefined;
|
|
168
|
+
const summary = summarizeToolArguments(args);
|
|
169
|
+
return compactObject({
|
|
170
|
+
id: firstString(data.toolCallId) || undefined,
|
|
171
|
+
name,
|
|
172
|
+
displayName: toolDisplayName(name),
|
|
173
|
+
rawCategory: "tool.execution_start",
|
|
174
|
+
category: copilotToolCategory(name),
|
|
175
|
+
title: toolDisplayName(name),
|
|
176
|
+
status: "tool_call",
|
|
177
|
+
argument: summary,
|
|
178
|
+
rawInputSummary: summary,
|
|
179
|
+
inputPreview: summary,
|
|
180
|
+
target: toolTarget(args) || undefined,
|
|
181
|
+
arguments: args,
|
|
182
|
+
provider: PROVIDER
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function copilotToolResult(data) {
|
|
187
|
+
const id = firstString(data.toolCallId);
|
|
188
|
+
const output = toolOutputText(data.result?.content ?? data.result);
|
|
189
|
+
if (!id && !output) return null;
|
|
190
|
+
const isError = data.success === false;
|
|
191
|
+
const lineCount = output ? output.split(/\r?\n/).length : 0;
|
|
192
|
+
return compactObject({
|
|
193
|
+
provider: PROVIDER,
|
|
194
|
+
id: id || undefined,
|
|
195
|
+
kind: "Tool result",
|
|
196
|
+
title: isError ? "Tool error" : "Tool result",
|
|
197
|
+
rawCategory: "tool.execution_complete",
|
|
198
|
+
category: "tool",
|
|
199
|
+
summary: firstLine(output),
|
|
200
|
+
output,
|
|
201
|
+
lineCount: lineCount || undefined,
|
|
202
|
+
collapsed: lineCount > 18 || undefined,
|
|
203
|
+
status: isError ? "error" : "completed"
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// session.shutdown (persisted since CLI 0.0.422 for cleanly ended sessions)
|
|
208
|
+
// carries the only token usage in the file: per-model modelMetrics plus
|
|
209
|
+
// premium-request and code-change counters.
|
|
210
|
+
function copilotSessionSummary({ shutdown, taskSummary, copilotVersion, repository, branch, currentModel }) {
|
|
211
|
+
const modelMetrics = shutdown?.modelMetrics && typeof shutdown.modelMetrics === "object" ? shutdown.modelMetrics : {};
|
|
212
|
+
const totals = { inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, cacheCreationInputTokens: 0, reasoningOutputTokens: 0 };
|
|
213
|
+
const modelUsage = [];
|
|
214
|
+
for (const [model, metrics] of Object.entries(modelMetrics)) {
|
|
215
|
+
const usage = metrics?.usage && typeof metrics.usage === "object" ? metrics.usage : {};
|
|
216
|
+
totals.inputTokens += positiveNumber(usage.inputTokens) || 0;
|
|
217
|
+
totals.outputTokens += positiveNumber(usage.outputTokens) || 0;
|
|
218
|
+
totals.cacheReadTokens += positiveNumber(usage.cacheReadTokens) || 0;
|
|
219
|
+
totals.cacheCreationInputTokens += positiveNumber(usage.cacheWriteTokens) || 0;
|
|
220
|
+
totals.reasoningOutputTokens += positiveNumber(usage.reasoningTokens) || 0;
|
|
221
|
+
modelUsage.push(compactObject({
|
|
222
|
+
model,
|
|
223
|
+
requests: positiveNumber(metrics?.requests?.count),
|
|
224
|
+
source: "copilot-session-shutdown"
|
|
225
|
+
}));
|
|
226
|
+
}
|
|
227
|
+
const usage = totals.inputTokens || totals.outputTokens || totals.cacheReadTokens
|
|
228
|
+
? compactObject({
|
|
229
|
+
inputTokens: totals.inputTokens || undefined,
|
|
230
|
+
outputTokens: totals.outputTokens || undefined,
|
|
231
|
+
cacheReadTokens: totals.cacheReadTokens || undefined,
|
|
232
|
+
cacheCreationInputTokens: totals.cacheCreationInputTokens || undefined,
|
|
233
|
+
reasoningOutputTokens: totals.reasoningOutputTokens || undefined,
|
|
234
|
+
source: "copilot-session-shutdown"
|
|
235
|
+
})
|
|
236
|
+
: undefined;
|
|
237
|
+
const codeChanges = shutdown?.codeChanges && typeof shutdown.codeChanges === "object" ? shutdown.codeChanges : null;
|
|
238
|
+
return compactObject({
|
|
239
|
+
usage,
|
|
240
|
+
modelUsage: modelUsage.length
|
|
241
|
+
? modelUsage
|
|
242
|
+
: currentModel
|
|
243
|
+
? [{ model: currentModel, source: "copilot-session-events" }]
|
|
244
|
+
: undefined,
|
|
245
|
+
copilotCli: compactObject({
|
|
246
|
+
copilotVersion: copilotVersion || undefined,
|
|
247
|
+
repository: repository || undefined,
|
|
248
|
+
branch: branch || undefined,
|
|
249
|
+
taskSummary: taskSummary ? taskSummary.slice(0, 600) : undefined,
|
|
250
|
+
premiumRequests: positiveNumber(shutdown?.totalPremiumRequests),
|
|
251
|
+
aiCredits: positiveNumber(shutdown?.totalNanoAiu) ? Number((shutdown.totalNanoAiu / 1e9).toFixed(4)) : undefined,
|
|
252
|
+
shutdownType: firstString(shutdown?.shutdownType) || undefined,
|
|
253
|
+
apiDurationMs: positiveNumber(shutdown?.totalApiDurationMs),
|
|
254
|
+
linesAdded: positiveNumber(codeChanges?.linesAdded),
|
|
255
|
+
linesRemoved: positiveNumber(codeChanges?.linesRemoved),
|
|
256
|
+
filesModified: Array.isArray(codeChanges?.filesModified) && codeChanges.filesModified.length
|
|
257
|
+
? codeChanges.filesModified.slice(0, 50)
|
|
258
|
+
: undefined
|
|
259
|
+
})
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// workspace.yaml is flat `key: value` scalars; avoid a YAML dependency.
|
|
264
|
+
function parseCopilotWorkspaceYaml(text) {
|
|
265
|
+
const result = {};
|
|
266
|
+
for (const line of String(text || "").split(/\r?\n/)) {
|
|
267
|
+
const match = line.match(/^([A-Za-z0-9_]+):\s*(.*)\s*$/);
|
|
268
|
+
if (!match) continue;
|
|
269
|
+
const value = match[2].replace(/^["']|["']$/g, "").trim();
|
|
270
|
+
if (value) result[match[1]] = value;
|
|
271
|
+
}
|
|
272
|
+
return result;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function copilotToolCategory(name) {
|
|
276
|
+
const text = String(name || "");
|
|
277
|
+
if (/report_intent/i.test(text)) return "status";
|
|
278
|
+
if (/ask_user|ask_permission/i.test(text)) return "question";
|
|
279
|
+
if (/task|agent|delegate/i.test(text)) return "task";
|
|
280
|
+
if (/bash|shell|command|exec|powershell/i.test(text)) return "shell";
|
|
281
|
+
if (/web|fetch|url|http/i.test(text)) return "web";
|
|
282
|
+
if (/edit|write|create|patch|replace/i.test(text)) return "edit";
|
|
283
|
+
if (/read|view|cat|ls|list/i.test(text)) return "read";
|
|
284
|
+
if (/grep|glob|find|search/i.test(text)) return "search";
|
|
285
|
+
if (/^mcp|__/i.test(text)) return "mcp";
|
|
286
|
+
return "tool";
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function summarizeToolArguments(value) {
|
|
290
|
+
if (value == null) return "";
|
|
291
|
+
if (typeof value === "string") return value.slice(0, 240);
|
|
292
|
+
if (typeof value !== "object") return String(value).slice(0, 240);
|
|
293
|
+
for (const key of ["intent", "command", "prompt", "query", "pattern", "path", "file_path", "url", "question"]) {
|
|
294
|
+
if (value[key]) return String(value[key]).slice(0, 240);
|
|
295
|
+
}
|
|
296
|
+
return Object.entries(value)
|
|
297
|
+
.slice(0, 3)
|
|
298
|
+
.map(([key, item]) => `${key}: ${typeof item === "string" ? item : JSON.stringify(item)}`)
|
|
299
|
+
.join(", ")
|
|
300
|
+
.slice(0, 240);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function toolOutputText(value) {
|
|
304
|
+
if (value == null) return "";
|
|
305
|
+
if (typeof value === "string") return value.trim();
|
|
306
|
+
if (Array.isArray(value)) return value.map(toolOutputText).filter(Boolean).join("\n");
|
|
307
|
+
if (typeof value === "object") {
|
|
308
|
+
const preferred = value.content ?? value.output ?? value.text ?? value.message ?? value.result;
|
|
309
|
+
if (preferred != null) return toolOutputText(preferred);
|
|
310
|
+
return JSON.stringify(value);
|
|
311
|
+
}
|
|
312
|
+
return String(value);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
function toolTarget(args) {
|
|
316
|
+
if (!args || typeof args !== "object") return "";
|
|
317
|
+
return firstString(args.path, args.file_path, args.filePath, args.file, args.directory, args.url);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function toolDisplayName(value) {
|
|
321
|
+
const text = String(value || "tool").trim();
|
|
322
|
+
return text
|
|
323
|
+
.split(/_+|(?=[A-Z])/g)
|
|
324
|
+
.filter(Boolean)
|
|
325
|
+
.map((part) => part.replace(/(^|[-\s])([a-z])/g, (_, prefix, char) => `${prefix}${char.toUpperCase()}`))
|
|
326
|
+
.join(" ");
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function firstLine(value) {
|
|
330
|
+
return String(value || "").split(/\r?\n/).find((line) => line.trim())?.trim() || "";
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
function offsetTimestamp(base, index) {
|
|
334
|
+
const date = new Date(base);
|
|
335
|
+
if (Number.isNaN(date.valueOf())) return base;
|
|
336
|
+
return new Date(date.valueOf() + index * 1000).toISOString();
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function toIso(value) {
|
|
340
|
+
if (!value) return "";
|
|
341
|
+
if (typeof value === "number") {
|
|
342
|
+
const ms = value > 1e12 ? value : value * 1000;
|
|
343
|
+
const date = new Date(ms);
|
|
344
|
+
return Number.isNaN(date.valueOf()) ? "" : date.toISOString();
|
|
345
|
+
}
|
|
346
|
+
const date = new Date(value);
|
|
347
|
+
return Number.isNaN(date.valueOf()) ? "" : date.toISOString();
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
function parseJson(text) {
|
|
351
|
+
if (typeof text !== "string" || !text.trim()) return null;
|
|
352
|
+
try {
|
|
353
|
+
return JSON.parse(text);
|
|
354
|
+
} catch {
|
|
355
|
+
return null;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
function firstString(...values) {
|
|
360
|
+
for (const value of values) {
|
|
361
|
+
if (typeof value === "string" && value.trim()) return value.trim();
|
|
362
|
+
}
|
|
363
|
+
return "";
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
function positiveNumber(value) {
|
|
367
|
+
const number = Number(value);
|
|
368
|
+
return Number.isFinite(number) && number > 0 ? number : undefined;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
function compactObject(value) {
|
|
372
|
+
if (!value || typeof value !== "object") return value;
|
|
373
|
+
const result = {};
|
|
374
|
+
for (const [key, item] of Object.entries(value)) {
|
|
375
|
+
if (item === undefined || item === null || item === "") continue;
|
|
376
|
+
result[key] = item;
|
|
377
|
+
}
|
|
378
|
+
return Object.keys(result).length ? result : undefined;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
module.exports = {
|
|
382
|
+
parseCopilotEventsFile,
|
|
383
|
+
parseCopilotEventsText,
|
|
384
|
+
parseCopilotWorkspaceYaml
|
|
385
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const CURSOR_RAW_SOURCE_TYPE = "cursor-raw-sqlite-salvage";
|
|
4
|
+
const CURSOR_SHARED_RAW_SOURCE_TYPES = new Set([
|
|
5
|
+
"cursor-workspace-sqlite",
|
|
6
|
+
"cursor-global-sqlite",
|
|
7
|
+
CURSOR_RAW_SOURCE_TYPE
|
|
8
|
+
]);
|
|
9
|
+
|
|
10
|
+
function cursorSessionUsesSharedRawFiles(sourceType) {
|
|
11
|
+
return CURSOR_SHARED_RAW_SOURCE_TYPES.has(String(sourceType || ""));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function isCursorRawRecoverySourceType(sourceType) {
|
|
15
|
+
return String(sourceType || "") === CURSOR_RAW_SOURCE_TYPE;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = {
|
|
19
|
+
CURSOR_RAW_SOURCE_TYPE,
|
|
20
|
+
cursorSessionUsesSharedRawFiles,
|
|
21
|
+
isCursorRawRecoverySourceType
|
|
22
|
+
};
|