agentel 0.2.3 → 0.2.5
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 +4 -4
- package/docs/code-reference.md +3 -3
- package/docs/history-source-handling.md +88 -39
- package/docs/release.md +1 -2
- package/package.json +1 -2
- package/src/cli.js +58 -16
- package/src/config.js +4 -1
- package/src/doctor.js +13 -2
- package/src/importers/providers.js +26 -2
- package/src/importers.js +534 -67
- package/src/parser-versions.js +5 -0
- package/src/search.js +55 -26
- package/src/sources.js +7 -3
- package/agentlog-spec.md +0 -558
package/src/parser-versions.js
CHANGED
|
@@ -21,6 +21,11 @@ const PARSER_VERSION_SUFFIXES = {
|
|
|
21
21
|
"devin-cli-history": 0,
|
|
22
22
|
"gemini-cli-history": 0,
|
|
23
23
|
"cline-task-history": 0,
|
|
24
|
+
"opencode-cli-history": 0,
|
|
25
|
+
"opencode-cli-sqlite-history": 0,
|
|
26
|
+
"opencode-desktop-history": 0,
|
|
27
|
+
"opencode-desktop-sqlite-history": 0,
|
|
28
|
+
"opencode-web-sqlite-history": 0,
|
|
24
29
|
"opencode-history": 0,
|
|
25
30
|
"opencode-sqlite-history": 0,
|
|
26
31
|
"aider-chat-history": 0,
|
package/src/search.js
CHANGED
|
@@ -17,6 +17,8 @@ const SQLITE_BUILD_BATCH_SIZE = 100;
|
|
|
17
17
|
const RIPGREP_SEARCH_TIMEOUT_MS = 8000;
|
|
18
18
|
const RIPGREP_BATCH_FILE_COUNT = 200;
|
|
19
19
|
const MARKDOWN_MATCHES_PER_FILE = 3;
|
|
20
|
+
const FTS_SEARCH_BATCH_SIZE = 250;
|
|
21
|
+
const FTS_MAX_SCAN_ROWS = 5000;
|
|
20
22
|
const _indexCache = {
|
|
21
23
|
path: "",
|
|
22
24
|
mtimeMs: 0,
|
|
@@ -671,33 +673,29 @@ function searchFtsSessions(query, queryTokens, context, env = process.env) {
|
|
|
671
673
|
if (!ftsIndexAvailable(env, { noStaleCheck: Boolean(context.options.noRebuild || context.options.allowStaleFts) })) return null;
|
|
672
674
|
const matchQuery = ftsMatchQuery(query);
|
|
673
675
|
if (!matchQuery) return [];
|
|
674
|
-
const candidateLimit = Math.max(context.limit * 8, 80);
|
|
675
|
-
const rows = sqliteJson(
|
|
676
|
-
ftsPath,
|
|
677
|
-
[
|
|
678
|
-
"SELECT",
|
|
679
|
-
" d.doc_id, d.session_id, d.provider, d.source_type, d.repo_canonical, d.repo_display,",
|
|
680
|
-
" d.scope_canonical, d.cwd, d.title, d.started_at, d.occurred_at, d.role,",
|
|
681
|
-
" d.event_id, d.event_kind, d.message_index, d.path, d.matched_text,",
|
|
682
|
-
" snippet(docs_fts, 0, '', '', '...', 32) AS excerpt,",
|
|
683
|
-
" bm25(docs_fts) AS rank",
|
|
684
|
-
"FROM docs_fts",
|
|
685
|
-
"JOIN docs d ON d.rowid = docs_fts.rowid",
|
|
686
|
-
`WHERE docs_fts MATCH ${sqliteString(matchQuery)}`,
|
|
687
|
-
"ORDER BY rank ASC, d.occurred_at DESC, d.started_at DESC",
|
|
688
|
-
`LIMIT ${candidateLimit};`
|
|
689
|
-
].join("\n")
|
|
690
|
-
);
|
|
691
|
-
if (!rows) return null;
|
|
692
676
|
const bySession = new Map();
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
677
|
+
const batchSize = Math.max(context.limit * 20, FTS_SEARCH_BATCH_SIZE);
|
|
678
|
+
const maxScanRows = Math.max(batchSize, Math.min(FTS_MAX_SCAN_ROWS, context.limit * 500));
|
|
679
|
+
let offset = 0;
|
|
680
|
+
while (offset < maxScanRows && bySession.size < context.limit) {
|
|
681
|
+
const rows = ftsSearchRows(ftsPath, matchQuery, {
|
|
682
|
+
limit: Math.min(batchSize, maxScanRows - offset),
|
|
683
|
+
offset,
|
|
684
|
+
context
|
|
685
|
+
});
|
|
686
|
+
if (!rows) return null;
|
|
687
|
+
if (!rows.length) break;
|
|
688
|
+
offset += rows.length;
|
|
689
|
+
for (const row of rows) {
|
|
690
|
+
const doc = ftsRowToDoc(row);
|
|
691
|
+
if (!matchesSessionFilter(doc, { ...context.filter, includeWebChats: context.includeWebChats, since: context.since })) continue;
|
|
692
|
+
if (!context.options.repo && context.repo && doc.repoCanonical === context.repo) {
|
|
693
|
+
row.rank = Number(row.rank || 0) - 0.05;
|
|
694
|
+
}
|
|
695
|
+
if (!bySession.has(doc.sessionId)) bySession.set(doc.sessionId, { doc, row });
|
|
696
|
+
if (bySession.size >= context.limit) break;
|
|
698
697
|
}
|
|
699
|
-
if (
|
|
700
|
-
if (bySession.size >= context.limit) break;
|
|
698
|
+
if (rows.length < batchSize) break;
|
|
701
699
|
}
|
|
702
700
|
return [...bySession.values()].slice(0, context.limit).map(({ doc, row }) => ({
|
|
703
701
|
session_id: doc.sessionId,
|
|
@@ -720,6 +718,34 @@ function searchFtsSessions(query, queryTokens, context, env = process.env) {
|
|
|
720
718
|
}));
|
|
721
719
|
}
|
|
722
720
|
|
|
721
|
+
function ftsSearchRows(ftsPath, matchQuery, options) {
|
|
722
|
+
const clauses = [`docs_fts MATCH ${sqliteString(matchQuery)}`];
|
|
723
|
+
const filter = options.context?.filter || {};
|
|
724
|
+
if (filter.provider) clauses.push(`d.provider = ${sqliteString(filter.provider)}`);
|
|
725
|
+
const sourceTypes = filter.sourceTypes?.length ? filter.sourceTypes : filter.sourceType ? [filter.sourceType] : [];
|
|
726
|
+
if (sourceTypes.length) clauses.push(`d.source_type IN (${sourceTypes.map(sqliteString).join(", ")})`);
|
|
727
|
+
if (options.context?.since) {
|
|
728
|
+
const since = sqliteString(options.context.since.toISOString());
|
|
729
|
+
clauses.push(`(d.started_at >= ${since} OR (d.started_at = '' AND d.occurred_at >= ${since}))`);
|
|
730
|
+
}
|
|
731
|
+
return sqliteJson(
|
|
732
|
+
ftsPath,
|
|
733
|
+
[
|
|
734
|
+
"SELECT",
|
|
735
|
+
" d.doc_id, d.session_id, d.provider, d.source_type, d.repo_canonical, d.repo_display,",
|
|
736
|
+
" d.scope_canonical, d.cwd, d.title, d.started_at, d.occurred_at, d.role,",
|
|
737
|
+
" d.event_id, d.event_kind, d.message_index, d.path, d.matched_text,",
|
|
738
|
+
" snippet(docs_fts, 0, '', '', '...', 32) AS excerpt,",
|
|
739
|
+
" bm25(docs_fts) AS rank",
|
|
740
|
+
"FROM docs_fts",
|
|
741
|
+
"JOIN docs d ON d.rowid = docs_fts.rowid",
|
|
742
|
+
`WHERE ${clauses.join(" AND ")}`,
|
|
743
|
+
"ORDER BY rank ASC, d.occurred_at DESC, d.started_at DESC",
|
|
744
|
+
`LIMIT ${Math.max(1, Number(options.limit) || FTS_SEARCH_BATCH_SIZE)} OFFSET ${Math.max(0, Number(options.offset) || 0)};`
|
|
745
|
+
].join("\n")
|
|
746
|
+
);
|
|
747
|
+
}
|
|
748
|
+
|
|
723
749
|
function ftsRowToDoc(row) {
|
|
724
750
|
return {
|
|
725
751
|
id: row.doc_id || "",
|
|
@@ -1079,7 +1105,10 @@ function normalizeProviderFilter(value) {
|
|
|
1079
1105
|
codex_desktop: { provider: "codex", sourceType: "codex-desktop-history", sourceTypes: ["codex-desktop-history"] },
|
|
1080
1106
|
cursor: { provider: "cursor" },
|
|
1081
1107
|
cline: { provider: "cline", sourceType: "cline-task-history", sourceTypes: ["cline-task-history"] },
|
|
1082
|
-
opencode: { provider: "opencode", sourceTypes: ["opencode-history", "opencode-sqlite-history"] },
|
|
1108
|
+
opencode: { provider: "opencode", sourceTypes: ["opencode-cli-history", "opencode-cli-sqlite-history", "opencode-desktop-history", "opencode-desktop-sqlite-history", "opencode-web-sqlite-history", "opencode-history", "opencode-sqlite-history"] },
|
|
1109
|
+
opencode_cli: { provider: "opencode", sourceType: "opencode-cli-history", sourceTypes: ["opencode-cli-history", "opencode-cli-sqlite-history"] },
|
|
1110
|
+
opencode_desktop: { provider: "opencode", sourceType: "opencode-desktop-history", sourceTypes: ["opencode-desktop-history", "opencode-desktop-sqlite-history"] },
|
|
1111
|
+
opencode_web: { provider: "opencode", sourceType: "opencode-web-sqlite-history", sourceTypes: ["opencode-web-sqlite-history"] },
|
|
1083
1112
|
aider: { provider: "aider", sourceType: "aider-chat-history", sourceTypes: ["aider-chat-history"] },
|
|
1084
1113
|
devin: { provider: "devin" },
|
|
1085
1114
|
devin_cli: { provider: "devin", sourceType: "devin-cli-history", sourceTypes: ["devin-cli-history"] },
|
package/src/sources.js
CHANGED
|
@@ -37,7 +37,9 @@ const SOURCE_GROUPS = [
|
|
|
37
37
|
sources: [
|
|
38
38
|
{ source: "cursor", provider: "cursor", label: "Cursor" },
|
|
39
39
|
{ source: "cline", provider: "cline", sourceType: "cline-task-history", label: "Cline" },
|
|
40
|
-
{ source: "opencode", provider: "opencode", sourceType: "opencode-history", label: "OpenCode" },
|
|
40
|
+
{ source: "opencode-cli", provider: "opencode", sourceType: "opencode-cli-history", label: "OpenCode CLI" },
|
|
41
|
+
{ source: "opencode-desktop", provider: "opencode", sourceType: "opencode-desktop-history", label: "OpenCode Desktop" },
|
|
42
|
+
{ source: "opencode-web", provider: "opencode", sourceType: "opencode-web-sqlite-history", label: "OpenCode Web" },
|
|
41
43
|
{ source: "aider", provider: "aider", sourceType: "aider-chat-history", label: "Aider" }
|
|
42
44
|
]
|
|
43
45
|
}
|
|
@@ -61,7 +63,9 @@ const IMPORT_SOURCE_ORDER = [
|
|
|
61
63
|
"devin-cli",
|
|
62
64
|
"cursor",
|
|
63
65
|
"cline",
|
|
64
|
-
"opencode",
|
|
66
|
+
"opencode-cli",
|
|
67
|
+
"opencode-desktop",
|
|
68
|
+
"opencode-web",
|
|
65
69
|
"aider"
|
|
66
70
|
];
|
|
67
71
|
|
|
@@ -72,7 +76,7 @@ function enabledImportSources(sources) {
|
|
|
72
76
|
}
|
|
73
77
|
|
|
74
78
|
function sourceLabel(source) {
|
|
75
|
-
return HISTORY_PROVIDER_OPTIONS.find((item) => item.source === source)?.label || source;
|
|
79
|
+
return HISTORY_PROVIDER_OPTIONS.find((item) => item.source === source)?.label || { opencode: "OpenCode" }[source] || source;
|
|
76
80
|
}
|
|
77
81
|
|
|
78
82
|
module.exports = {
|