@apmantza/greedysearch-pi 1.6.2 → 1.6.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apmantza/greedysearch-pi",
3
- "version": "1.6.2",
3
+ "version": "1.6.4",
4
4
  "description": "Pi extension: multi-engine AI search (Perplexity, Bing Copilot, Google AI) via browser automation — NO API KEYS needed. Extracts answers with sources, optional Gemini synthesis. Grounded AI answers from real browser interactions.",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -11,6 +11,13 @@
11
11
  "url": "git+https://github.com/apmantza/GreedySearch-pi.git"
12
12
  },
13
13
  "license": "MIT",
14
+ "files": [
15
+ "index.ts",
16
+ "src/",
17
+ "skills/",
18
+ "CHANGELOG.md",
19
+ "README.md"
20
+ ],
14
21
  "pi": {
15
22
  "extensions": [
16
23
  "./index.ts"
@@ -1,207 +1,207 @@
1
- /**
2
- * Search results formatters
3
- * Extracted from index.ts
4
- */
5
-
6
- import { formatEngineName, humanizeSourceType } from "../utils/helpers.js";
7
- import { renderSynthesis } from "./synthesis.js";
8
- import { formatSourceLine, renderSourceEvidence } from "./sources.js";
9
-
10
- /**
11
- * Format search results based on engine type
12
- */
13
- export function formatResults(
14
- engine: string,
15
- data: Record<string, unknown>,
16
- ): string {
17
- const lines: string[] = [];
18
-
19
- if (engine === "all") {
20
- return formatAllEnginesResult(data, lines);
21
- }
22
-
23
- return formatSingleEngineResult(data, lines);
24
- }
25
-
26
- /**
27
- * Format multi-engine results with synthesis
28
- */
29
- function formatAllEnginesResult(
30
- data: Record<string, unknown>,
31
- lines: string[],
32
- ): string {
33
- const synthesis = data._synthesis as Record<string, unknown> | undefined;
34
- const dedupedSources = data._sources as
35
- | Array<Record<string, unknown>>
36
- | undefined;
37
-
38
- // If we have a synthesis answer, render it
39
- if (synthesis?.answer) {
40
- renderSynthesis(lines, synthesis, dedupedSources || [], 6);
41
- lines.push("*Synthesized from Perplexity, Bing Copilot, and Google AI*\n");
42
- return lines.join("\n").trim();
43
- }
44
-
45
- // Fallback: render individual engine results
46
- for (const [eng, result] of Object.entries(data)) {
47
- if (eng.startsWith("_")) continue;
48
- lines.push(`\n## ${formatEngineName(eng)}`);
49
- formatEngineResult(result as Record<string, unknown>, lines, 3);
50
- }
51
-
52
- return lines.join("\n").trim();
53
- }
54
-
55
- /**
56
- * Format single engine result
57
- */
58
- function formatSingleEngineResult(
59
- data: Record<string, unknown>,
60
- lines: string[],
61
- ): string {
62
- formatEngineResult(data, lines, 5);
63
- return lines.join("\n").trim();
64
- }
65
-
66
- /**
67
- * Format a single engine's result (answer + sources)
68
- */
69
- function formatEngineResult(
70
- data: Record<string, unknown>,
71
- lines: string[],
72
- maxSources: number,
73
- ): void {
74
- if (data.error) {
75
- lines.push(`Error: ${data.error}`);
76
- return;
77
- }
78
-
79
- if (data.answer) {
80
- lines.push(String(data.answer));
81
- }
82
-
83
- const sources = data.sources as Array<Record<string, string>> | undefined;
84
- if (Array.isArray(sources) && sources.length > 0) {
85
- lines.push("\nSources:");
86
- for (const s of sources.slice(0, maxSources)) {
87
- lines.push(`- [${s.title || s.url}](${s.url})`);
88
- }
89
- }
90
- }
91
-
92
- /**
93
- * Format deep research results with confidence metrics
94
- */
95
- export function formatDeepResearch(data: Record<string, unknown>): string {
96
- const lines: string[] = [];
97
- const confidence = data._confidence as Record<string, unknown> | undefined;
98
- const dedupedSources = data._sources as
99
- | Array<Record<string, unknown>>
100
- | undefined;
101
- const synthesis = data._synthesis as Record<string, unknown> | undefined;
102
-
103
- lines.push("# Deep Research Report\n");
104
-
105
- if (confidence) {
106
- formatConfidenceSection(lines, confidence);
107
- }
108
-
109
- if (synthesis?.answer) {
110
- renderSynthesis(lines, synthesis, dedupedSources || [], 8);
111
- }
112
-
113
- formatEnginePerspectives(lines, data);
114
- formatSourceRegistry(lines, dedupedSources || []);
115
-
116
- return lines.join("\n").trim();
117
- }
118
-
119
- /**
120
- * Format confidence section with metrics
121
- */
122
- function formatConfidenceSection(
123
- lines: string[],
124
- confidence: Record<string, unknown>,
125
- ): void {
126
- const enginesResponded = (confidence.enginesResponded as string[]) || [];
127
- const enginesFailed = (confidence.enginesFailed as string[]) || [];
128
- const agreementLevel = String(confidence.agreementLevel || "mixed");
129
- const firstPartySourceCount = Number(confidence.firstPartySourceCount || 0);
130
- const sourceTypeBreakdown = confidence.sourceTypeBreakdown as
131
- | Record<string, number>
132
- | undefined;
133
-
134
- lines.push("## Confidence\n");
135
- lines.push(`- Agreement: ${formatEngineName(agreementLevel)}`);
136
- lines.push(
137
- `- Engines responded: ${enginesResponded.map(formatEngineName).join(", ") || "none"}`,
138
- );
139
-
140
- if (enginesFailed.length > 0) {
141
- lines.push(
142
- `- Engines failed: ${enginesFailed.map(formatEngineName).join(", ")}`,
143
- );
144
- }
145
-
146
- lines.push(
147
- `- Top source consensus: ${confidence.topSourceConsensus || 0}/3 engines`,
148
- );
149
- lines.push(`- Total unique sources: ${confidence.sourcesCount || 0}`);
150
- lines.push(`- Official sources: ${confidence.officialSourceCount || 0}`);
151
- lines.push(`- First-party sources: ${firstPartySourceCount}`);
152
- lines.push(
153
- `- Fetch success rate: ${confidence.fetchedSourceSuccessRate || 0}`,
154
- );
155
-
156
- if (sourceTypeBreakdown && Object.keys(sourceTypeBreakdown).length > 0) {
157
- lines.push(
158
- `- Source mix: ${Object.entries(sourceTypeBreakdown)
159
- .map(([type, count]) => `${humanizeSourceType(type)} ${count}`)
160
- .join(", ")}`,
161
- );
162
- }
163
-
164
- lines.push("");
165
- }
166
-
167
- /**
168
- * Format engine perspectives section
169
- */
170
- function formatEnginePerspectives(
171
- lines: string[],
172
- data: Record<string, unknown>,
173
- ): void {
174
- lines.push("## Engine Perspectives\n");
175
-
176
- for (const engine of ["perplexity", "bing", "google"]) {
177
- const r = data[engine] as Record<string, unknown> | undefined;
178
- if (!r) continue;
179
-
180
- lines.push(`### ${formatEngineName(engine)}`);
181
-
182
- if (r.error) {
183
- lines.push(`⚠️ Error: ${r.error}`);
184
- } else if (r.answer) {
185
- lines.push(String(r.answer).slice(0, 2000));
186
- }
187
-
188
- lines.push("");
189
- }
190
- }
191
-
192
- /**
193
- * Format source registry section
194
- */
195
- function formatSourceRegistry(
196
- lines: string[],
197
- sources: Array<Record<string, unknown>>,
198
- ): void {
199
- if (sources.length === 0) return;
200
-
201
- lines.push("## Source Registry\n");
202
- for (const source of sources) {
203
- lines.push(formatSourceLine(source));
204
- renderSourceEvidence(lines, source);
205
- }
206
- lines.push("");
207
- }
1
+ /**
2
+ * Search results formatters
3
+ * Extracted from index.ts
4
+ */
5
+
6
+ import { formatEngineName, humanizeSourceType } from "../utils/helpers.js";
7
+ import { renderSynthesis } from "./synthesis.js";
8
+ import { formatSourceLine, renderSourceEvidence } from "./sources.js";
9
+
10
+ /**
11
+ * Format search results based on engine type
12
+ */
13
+ export function formatResults(
14
+ engine: string,
15
+ data: Record<string, unknown>,
16
+ ): string {
17
+ const lines: string[] = [];
18
+
19
+ if (engine === "all") {
20
+ return formatAllEnginesResult(data, lines);
21
+ }
22
+
23
+ return formatSingleEngineResult(data, lines);
24
+ }
25
+
26
+ /**
27
+ * Format multi-engine results with synthesis
28
+ */
29
+ function formatAllEnginesResult(
30
+ data: Record<string, unknown>,
31
+ lines: string[],
32
+ ): string {
33
+ const synthesis = data._synthesis as Record<string, unknown> | undefined;
34
+ const dedupedSources = data._sources as
35
+ | Array<Record<string, unknown>>
36
+ | undefined;
37
+
38
+ // If we have a synthesis answer, render it
39
+ if (synthesis?.answer) {
40
+ renderSynthesis(lines, synthesis, dedupedSources || [], 6);
41
+ lines.push("*Synthesized from Perplexity, Bing Copilot, and Google AI*\n");
42
+ return lines.join("\n").trim();
43
+ }
44
+
45
+ // Fallback: render individual engine results
46
+ for (const [eng, result] of Object.entries(data)) {
47
+ if (eng.startsWith("_")) continue;
48
+ lines.push(`\n## ${formatEngineName(eng)}`);
49
+ formatEngineResult(result as Record<string, unknown>, lines, 3);
50
+ }
51
+
52
+ return lines.join("\n").trim();
53
+ }
54
+
55
+ /**
56
+ * Format single engine result
57
+ */
58
+ function formatSingleEngineResult(
59
+ data: Record<string, unknown>,
60
+ lines: string[],
61
+ ): string {
62
+ formatEngineResult(data, lines, 5);
63
+ return lines.join("\n").trim();
64
+ }
65
+
66
+ /**
67
+ * Format a single engine's result (answer + sources)
68
+ */
69
+ function formatEngineResult(
70
+ data: Record<string, unknown>,
71
+ lines: string[],
72
+ maxSources: number,
73
+ ): void {
74
+ if (data.error) {
75
+ lines.push(`Error: ${data.error}`);
76
+ return;
77
+ }
78
+
79
+ if (data.answer) {
80
+ lines.push(String(data.answer));
81
+ }
82
+
83
+ const sources = data.sources as Array<Record<string, string>> | undefined;
84
+ if (Array.isArray(sources) && sources.length > 0) {
85
+ lines.push("\nSources:");
86
+ for (const s of sources.slice(0, maxSources)) {
87
+ lines.push(`- [${s.title || s.url}](${s.url})`);
88
+ }
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Format deep research results with confidence metrics
94
+ */
95
+ export function formatDeepResearch(data: Record<string, unknown>): string {
96
+ const lines: string[] = [];
97
+ const confidence = data._confidence as Record<string, unknown> | undefined;
98
+ const dedupedSources = data._sources as
99
+ | Array<Record<string, unknown>>
100
+ | undefined;
101
+ const synthesis = data._synthesis as Record<string, unknown> | undefined;
102
+
103
+ lines.push("# Deep Research Report\n");
104
+
105
+ if (confidence) {
106
+ formatConfidenceSection(lines, confidence);
107
+ }
108
+
109
+ if (synthesis?.answer) {
110
+ renderSynthesis(lines, synthesis, dedupedSources || [], 8);
111
+ }
112
+
113
+ formatEnginePerspectives(lines, data);
114
+ formatSourceRegistry(lines, dedupedSources || []);
115
+
116
+ return lines.join("\n").trim();
117
+ }
118
+
119
+ /**
120
+ * Format confidence section with metrics
121
+ */
122
+ function formatConfidenceSection(
123
+ lines: string[],
124
+ confidence: Record<string, unknown>,
125
+ ): void {
126
+ const enginesResponded = (confidence.enginesResponded as string[]) || [];
127
+ const enginesFailed = (confidence.enginesFailed as string[]) || [];
128
+ const agreementLevel = String(confidence.agreementLevel || "mixed");
129
+ const firstPartySourceCount = Number(confidence.firstPartySourceCount || 0);
130
+ const sourceTypeBreakdown = confidence.sourceTypeBreakdown as
131
+ | Record<string, number>
132
+ | undefined;
133
+
134
+ lines.push("## Confidence\n");
135
+ lines.push(`- Agreement: ${formatEngineName(agreementLevel)}`);
136
+ lines.push(
137
+ `- Engines responded: ${enginesResponded.map(formatEngineName).join(", ") || "none"}`,
138
+ );
139
+
140
+ if (enginesFailed.length > 0) {
141
+ lines.push(
142
+ `- Engines failed: ${enginesFailed.map(formatEngineName).join(", ")}`,
143
+ );
144
+ }
145
+
146
+ lines.push(
147
+ `- Top source consensus: ${confidence.topSourceConsensus || 0}/3 engines`,
148
+ );
149
+ lines.push(`- Total unique sources: ${confidence.sourcesCount || 0}`);
150
+ lines.push(`- Official sources: ${confidence.officialSourceCount || 0}`);
151
+ lines.push(`- First-party sources: ${firstPartySourceCount}`);
152
+ lines.push(
153
+ `- Fetch success rate: ${confidence.fetchedSourceSuccessRate || 0}`,
154
+ );
155
+
156
+ if (sourceTypeBreakdown && Object.keys(sourceTypeBreakdown).length > 0) {
157
+ lines.push(
158
+ `- Source mix: ${Object.entries(sourceTypeBreakdown)
159
+ .map(([type, count]) => `${humanizeSourceType(type)} ${count}`)
160
+ .join(", ")}`,
161
+ );
162
+ }
163
+
164
+ lines.push("");
165
+ }
166
+
167
+ /**
168
+ * Format engine perspectives section
169
+ */
170
+ function formatEnginePerspectives(
171
+ lines: string[],
172
+ data: Record<string, unknown>,
173
+ ): void {
174
+ lines.push("## Engine Perspectives\n");
175
+
176
+ for (const engine of ["perplexity", "bing", "google"]) {
177
+ const r = data[engine] as Record<string, unknown> | undefined;
178
+ if (!r) continue;
179
+
180
+ lines.push(`### ${formatEngineName(engine)}`);
181
+
182
+ if (r.error) {
183
+ lines.push(`⚠️ Error: ${r.error}`);
184
+ } else if (r.answer) {
185
+ lines.push(String(r.answer).slice(0, 2000));
186
+ }
187
+
188
+ lines.push("");
189
+ }
190
+ }
191
+
192
+ /**
193
+ * Format source registry section
194
+ */
195
+ function formatSourceRegistry(
196
+ lines: string[],
197
+ sources: Array<Record<string, unknown>>,
198
+ ): void {
199
+ if (sources.length === 0) return;
200
+
201
+ lines.push("## Source Registry\n");
202
+ for (const source of sources) {
203
+ lines.push(formatSourceLine(source));
204
+ renderSourceEvidence(lines, source);
205
+ }
206
+ lines.push("");
207
+ }