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.
@@ -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
- for (const row of rows) {
694
- const doc = ftsRowToDoc(row);
695
- if (!matchesSessionFilter(doc, { ...context.filter, includeWebChats: context.includeWebChats, since: context.since })) continue;
696
- if (!context.options.repo && context.repo && doc.repoCanonical === context.repo) {
697
- row.rank = Number(row.rank || 0) - 0.05;
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 (!bySession.has(doc.sessionId)) bySession.set(doc.sessionId, { doc, row });
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 = {