@vncsleal/quillby 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.
Files changed (61) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +140 -0
  3. package/bin/quillby-mcp +12 -0
  4. package/config/context.json +1 -0
  5. package/config/memory.json +1 -0
  6. package/config/rss_sources.txt +2 -0
  7. package/dist/agent.d.ts +21 -0
  8. package/dist/agent.js +61 -0
  9. package/dist/agent.js.map +1 -0
  10. package/dist/agents/compose.d.ts +2 -0
  11. package/dist/agents/compose.js +40 -0
  12. package/dist/agents/compose.js.map +1 -0
  13. package/dist/agents/discover.d.ts +15 -0
  14. package/dist/agents/discover.js +39 -0
  15. package/dist/agents/discover.js.map +1 -0
  16. package/dist/agents/harvest.d.ts +31 -0
  17. package/dist/agents/harvest.js +100 -0
  18. package/dist/agents/harvest.js.map +1 -0
  19. package/dist/agents/onboard.d.ts +14 -0
  20. package/dist/agents/onboard.js +88 -0
  21. package/dist/agents/onboard.js.map +1 -0
  22. package/dist/agents/seeds.d.ts +34 -0
  23. package/dist/agents/seeds.js +64 -0
  24. package/dist/agents/seeds.js.map +1 -0
  25. package/dist/cli.d.ts +44 -0
  26. package/dist/cli.js +233 -0
  27. package/dist/cli.js.map +1 -0
  28. package/dist/config.d.ts +22 -0
  29. package/dist/config.js +44 -0
  30. package/dist/config.js.map +1 -0
  31. package/dist/extractors/content.d.ts +13 -0
  32. package/dist/extractors/content.js +93 -0
  33. package/dist/extractors/content.js.map +1 -0
  34. package/dist/extractors/reddit.d.ts +7 -0
  35. package/dist/extractors/reddit.js +69 -0
  36. package/dist/extractors/reddit.js.map +1 -0
  37. package/dist/extractors/rss.d.ts +4 -0
  38. package/dist/extractors/rss.js +58 -0
  39. package/dist/extractors/rss.js.map +1 -0
  40. package/dist/index.d.ts +1 -0
  41. package/dist/index.js +139 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/init.d.ts +1 -0
  44. package/dist/init.js +192 -0
  45. package/dist/init.js.map +1 -0
  46. package/dist/llm.d.ts +2 -0
  47. package/dist/llm.js +11 -0
  48. package/dist/llm.js.map +1 -0
  49. package/dist/mcp/server.d.ts +1 -0
  50. package/dist/mcp/server.js +1278 -0
  51. package/dist/mcp/server.js.map +1 -0
  52. package/dist/output/feedback.d.ts +51 -0
  53. package/dist/output/feedback.js +78 -0
  54. package/dist/output/feedback.js.map +1 -0
  55. package/dist/output/structures.d.ts +5 -0
  56. package/dist/output/structures.js +121 -0
  57. package/dist/output/structures.js.map +1 -0
  58. package/dist/types.d.ts +305 -0
  59. package/dist/types.js +74 -0
  60. package/dist/types.js.map +1 -0
  61. package/package.json +63 -0
@@ -0,0 +1,69 @@
1
+ import * as https from "https";
2
+ const ITEMS_PER_SOURCE = 25;
3
+ function get(url) {
4
+ return new Promise((resolve) => {
5
+ https
6
+ .get(url, {
7
+ headers: {
8
+ "User-Agent": "quillby-mcp/1.0 (content research tool)",
9
+ Accept: "application/json",
10
+ },
11
+ }, (res) => {
12
+ // Reddit may redirect to old.reddit.com — follow
13
+ if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
14
+ get(res.headers.location).then(resolve);
15
+ return;
16
+ }
17
+ let data = "";
18
+ res.on("data", (c) => (data += c));
19
+ res.on("end", () => {
20
+ try {
21
+ resolve(JSON.parse(data));
22
+ }
23
+ catch {
24
+ resolve(null);
25
+ }
26
+ });
27
+ res.on("error", () => resolve(null));
28
+ })
29
+ .on("error", () => resolve(null));
30
+ });
31
+ }
32
+ /**
33
+ * Fetch hot posts from a subreddit.
34
+ * @param subreddit subreddit name without r/ prefix (e.g. "marketing")
35
+ * @param sort "hot" | "new" | "top" | "rising"
36
+ */
37
+ export async function fetchReddit(subreddit, sort = "hot", log = () => { }) {
38
+ const url = `https://www.reddit.com/r/${subreddit}/${sort}.json?limit=${ITEMS_PER_SOURCE}&raw_json=1`;
39
+ log(`Reddit r/${subreddit}/${sort}: fetching...`);
40
+ const listing = await get(url);
41
+ if (!listing?.data?.children) {
42
+ log(`Reddit r/${subreddit}: no data (may be private or non-existent)`);
43
+ return [];
44
+ }
45
+ const results = [];
46
+ for (const post of listing.data.children) {
47
+ const d = post.data;
48
+ if (!d.title)
49
+ continue;
50
+ // For link posts: use the external URL. For text posts: use the reddit permalink.
51
+ const link = d.is_self
52
+ ? `https://www.reddit.com${d.permalink}`
53
+ : (d.url ?? `https://www.reddit.com${d.permalink}`);
54
+ const snippet = d.is_self && d.selftext
55
+ ? d.selftext.slice(0, 500).replace(/\s+/g, " ").trim()
56
+ : `r/${d.subreddit} · ${d.score} upvotes · ${d.num_comments} comments · by u/${d.author}`;
57
+ results.push({
58
+ id: `reddit-${d.id}`,
59
+ source: d.subreddit_name_prefixed,
60
+ title: d.title,
61
+ link,
62
+ snippet,
63
+ publishedAt: new Date(d.created_utc * 1000).toISOString(),
64
+ });
65
+ }
66
+ log(`Reddit r/${subreddit}: ${results.length} posts ready`);
67
+ return results;
68
+ }
69
+ //# sourceMappingURL=reddit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reddit.js","sourceRoot":"","sources":["../../src/extractors/reddit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { RssItem } from "../types.js";
2
+ export declare function getSeenUrls(): Set<string>;
3
+ export declare function saveSeenUrls(urls: Set<string>): void;
4
+ export declare function fetchFeeds(sources: string[], log?: (msg: string) => void): Promise<RssItem[]>;
@@ -0,0 +1,58 @@
1
+ import * as fs from "fs";
2
+ import Parser from "rss-parser";
3
+ import { CONFIG } from "../config.js";
4
+ const parser = new Parser({
5
+ timeout: CONFIG.RSS.TIMEOUT,
6
+ requestOptions: { rejectUnauthorized: false },
7
+ headers: {
8
+ "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
9
+ },
10
+ });
11
+ export function getSeenUrls() {
12
+ try {
13
+ if (fs.existsSync(CONFIG.FILES.CACHE)) {
14
+ return new Set(JSON.parse(fs.readFileSync(CONFIG.FILES.CACHE, "utf-8")));
15
+ }
16
+ }
17
+ catch {
18
+ // Ignore malformed cache.
19
+ }
20
+ return new Set();
21
+ }
22
+ export function saveSeenUrls(urls) {
23
+ fs.writeFileSync(CONFIG.FILES.CACHE, JSON.stringify([...urls], null, 2));
24
+ }
25
+ export async function fetchFeeds(sources, log = () => { }) {
26
+ const seen = getSeenUrls();
27
+ const allItems = [];
28
+ let processed = 0;
29
+ for (let index = 0; index < sources.length; index += CONFIG.RSS.CONCURRENCY) {
30
+ const batch = sources.slice(index, index + CONFIG.RSS.CONCURRENCY);
31
+ const batchResults = await Promise.all(batch.map(async (url) => {
32
+ try {
33
+ const feed = await parser.parseURL(url);
34
+ return feed.items
35
+ .filter((item) => item.link && !seen.has(item.link))
36
+ .slice(0, CONFIG.RSS.ITEMS_PER_FEED)
37
+ .map((item, itemIndex) => ({
38
+ id: `${url}-${itemIndex}`,
39
+ source: typeof feed.title === "string" ? feed.title : url,
40
+ title: typeof item.title === "string" ? item.title : "Untitled",
41
+ link: item.link,
42
+ snippet: (typeof item.contentSnippet === "string" ? item.contentSnippet :
43
+ typeof item.content === "string" ? item.content :
44
+ "").slice(0, 500).replace(/\s+/g, " ").trim(),
45
+ publishedAt: item.pubDate || item.isoDate || undefined,
46
+ }));
47
+ }
48
+ catch {
49
+ return [];
50
+ }
51
+ }));
52
+ batchResults.forEach((items) => allItems.push(...items));
53
+ processed += batch.length;
54
+ log(`Feeds processed: ${processed}/${sources.length} (${allItems.length} new items so far)`);
55
+ }
56
+ return allItems;
57
+ }
58
+ //# sourceMappingURL=rss.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rss.js","sourceRoot":"","sources":["../../src/extractors/rss.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ import "dotenv/config";
package/dist/index.js ADDED
@@ -0,0 +1,139 @@
1
+ import "dotenv/config";
2
+ import { CONFIG, readTextFile } from "./config";
3
+ import { harvest } from "./agents/harvest";
4
+ import { compose } from "./agents/compose";
5
+ import { loadLatestHarvest, saveComposeOutput, saveHarvestOutput } from "./output/structures";
6
+ import * as cli from "./cli";
7
+ import { runInit } from "./init";
8
+ function parseArgs(argv) {
9
+ const commandToken = argv[0] && !argv[0].startsWith("--") ? argv[0] : "harvest";
10
+ const command = commandToken === "compose" ? "compose" :
11
+ commandToken === "board" ? "board" :
12
+ commandToken === "init" ? "init" :
13
+ commandToken === "help" ? "help" : "harvest";
14
+ const rawFlags = commandToken === command ? argv.slice(1) : argv;
15
+ const flags = {};
16
+ for (let i = 0; i < rawFlags.length; i++) {
17
+ const token = rawFlags[i];
18
+ if (!token.startsWith("--"))
19
+ continue;
20
+ const key = token.slice(2);
21
+ const next = rawFlags[i + 1];
22
+ if (!next || next.startsWith("--")) {
23
+ flags[key] = "true";
24
+ continue;
25
+ }
26
+ flags[key] = next;
27
+ i++;
28
+ }
29
+ return { command, flags };
30
+ }
31
+ function printHelp() {
32
+ console.log(`
33
+ GRIST Commands
34
+ --------------
35
+ npm run harvest
36
+ Agent reads your feeds, fetches interesting articles, builds structure cards
37
+
38
+ npm run board
39
+ Show latest structure cards
40
+
41
+ npm run compose -- --card 1 --platform LinkedIn
42
+ Draft a post from a structure card
43
+
44
+ npm run init
45
+ Interactive setup: creates context.md and seeds rss_sources.txt
46
+
47
+ Compose flags:
48
+ --take <text> override which take to use
49
+ --insight <text> override which insight to drive
50
+ --angle <text> override content angle
51
+
52
+ Typical flow:
53
+ npm run harvest → npm run board → npm run compose -- --card 1 --platform LinkedIn
54
+ `);
55
+ }
56
+ function runBoard() {
57
+ const bundle = loadLatestHarvest();
58
+ cli.printStageStart("Structure Board");
59
+ cli.printMessage(`${bundle.cards.length} cards — ${bundle.dateLabel}`, "muted");
60
+ bundle.cards.forEach((card) => {
61
+ console.log("");
62
+ console.log(` [${card.id}] ${card.title}`);
63
+ console.log(` ${card.source}`);
64
+ if (card.takeOptions[0])
65
+ console.log(` ↳ ${card.takeOptions[0]}`);
66
+ });
67
+ console.log("");
68
+ cli.printMessage("Compose: npm run compose -- --card <id> --platform LinkedIn", "muted");
69
+ }
70
+ async function runHarvest() {
71
+ cli.printHeader("GRIST", "Guided Research & Insight Synthesis Tool");
72
+ const context = readTextFile(CONFIG.FILES.CONTEXT);
73
+ const sources = readTextFile(CONFIG.FILES.SOURCES)
74
+ .split("\n")
75
+ .map((s) => s.trim())
76
+ .filter((s) => s && !s.startsWith("#"));
77
+ if (sources.length === 0) {
78
+ cli.printError("No RSS sources found in config/rss_sources.txt");
79
+ process.exit(1);
80
+ }
81
+ cli.printMessage(`${sources.length} sources configured`, "muted");
82
+ const { cards, seenUrls } = await harvest(context, sources);
83
+ const outputDir = saveHarvestOutput(cards, seenUrls);
84
+ if (cards.length === 0) {
85
+ cli.printMessage("No cards built — nothing new or relevant today", "muted");
86
+ return;
87
+ }
88
+ cli.printStageStart("Done");
89
+ cli.printMessage(`Output saved to: ${outputDir}`, "muted");
90
+ cli.printMessage("Next: npm run board", "muted");
91
+ }
92
+ async function runCompose(flags) {
93
+ const cardId = parseInt(flags.card || "0");
94
+ const platform = flags.platform || "LinkedIn";
95
+ if (!cardId) {
96
+ console.error(" Usage: npm run compose -- --card <id> --platform LinkedIn");
97
+ process.exit(1);
98
+ }
99
+ const bundle = loadLatestHarvest();
100
+ const card = bundle.cards.find((c) => c.id === cardId);
101
+ if (!card) {
102
+ console.error(` Card ${cardId} not found. Run: npm run board`);
103
+ process.exit(1);
104
+ }
105
+ const context = readTextFile(CONFIG.FILES.CONTEXT);
106
+ const draft = await compose(card, platform, context, {
107
+ take: flags.take,
108
+ insight: flags.insight,
109
+ angle: flags.angle,
110
+ });
111
+ const filePath = saveComposeOutput(draft, platform, cardId);
112
+ console.log("\n" + draft + "\n");
113
+ cli.printMessage(`Saved: ${filePath}`, "muted");
114
+ }
115
+ async function main() {
116
+ const { command, flags } = parseArgs(process.argv.slice(2));
117
+ switch (command) {
118
+ case "harvest":
119
+ await runHarvest();
120
+ break;
121
+ case "compose":
122
+ await runCompose(flags);
123
+ break;
124
+ case "board":
125
+ runBoard();
126
+ break;
127
+ case "init":
128
+ await runInit(flags);
129
+ break;
130
+ case "help":
131
+ printHelp();
132
+ break;
133
+ }
134
+ }
135
+ main().catch((err) => {
136
+ console.error(`\n Error: ${err.message || String(err)}`);
137
+ process.exit(1);
138
+ });
139
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/init.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare function runInit(_flags?: Record<string, string>): Promise<void>;
package/dist/init.js ADDED
@@ -0,0 +1,192 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ import * as readline from "readline";
4
+ import OpenAI from "openai";
5
+ import { CONFIG } from "./config";
6
+ import { fetchURL, extractTextFromHTML } from "./extractors/content";
7
+ import * as cli from "./cli";
8
+ function resolveWorkspacePath(relativePath) {
9
+ return path.join(process.cwd(), relativePath);
10
+ }
11
+ function createRL() {
12
+ return readline.createInterface({ input: process.stdin, output: process.stdout });
13
+ }
14
+ function ask(rl, question) {
15
+ return new Promise((resolve) => rl.question(`\n ${question}\n > `, (answer) => resolve(answer.trim())));
16
+ }
17
+ function confirm(rl, question) {
18
+ return new Promise((resolve) => rl.question(`\n ${question} (y/n) `, (answer) => resolve(answer.trim().toLowerCase() === "y")));
19
+ }
20
+ function copyTemplate(target, example) {
21
+ const targetPath = resolveWorkspacePath(target);
22
+ const examplePath = resolveWorkspacePath(example);
23
+ if (!fs.existsSync(examplePath) || fs.existsSync(targetPath)) {
24
+ return "skipped";
25
+ }
26
+ fs.mkdirSync(path.dirname(targetPath), { recursive: true });
27
+ fs.copyFileSync(examplePath, targetPath);
28
+ return "created";
29
+ }
30
+ function hasOpenAIKey() {
31
+ return Boolean(process.env.OPENAI_API_KEY);
32
+ }
33
+ async function callOpenAI(systemPrompt, userMessage, model) {
34
+ const client = new OpenAI();
35
+ const response = await client.chat.completions.create({
36
+ model,
37
+ messages: [
38
+ { role: "system", content: systemPrompt },
39
+ { role: "user", content: userMessage },
40
+ ],
41
+ temperature: 0.35,
42
+ });
43
+ return response.choices[0]?.message?.content?.trim() ?? "";
44
+ }
45
+ async function fetchWritingSamples(urls) {
46
+ const samples = [];
47
+ for (const url of urls) {
48
+ cli.startSpinner(`Fetching ${url}`);
49
+ try {
50
+ const html = await fetchURL(url);
51
+ const text = extractTextFromHTML(html).slice(0, 3000);
52
+ if (text.length > 200) {
53
+ samples.push(`--- Sample from ${url} ---\n${text}`);
54
+ }
55
+ }
56
+ catch {
57
+ // Best-effort only.
58
+ }
59
+ finally {
60
+ cli.stopSpinner();
61
+ }
62
+ }
63
+ return samples.join("\n\n");
64
+ }
65
+ async function generateContextMd(answers, writingSamples) {
66
+ const systemPrompt = [
67
+ "You generate a detailed identity and voice context file for a content pipeline.",
68
+ "Output plain markdown only.",
69
+ "Be specific about writing voice, signature patterns, and banned constructions.",
70
+ "If writing samples are provided, they are the ground truth for voice.",
71
+ "Do not invent tools, experience, or interests the user did not explicitly mention.",
72
+ ].join("\n");
73
+ const userMessage = [
74
+ "Build a comprehensive context.md for this person.",
75
+ "",
76
+ "USER ANSWERS:",
77
+ Object.entries(answers).map(([key, value]) => `${key}: ${value}`).join("\n"),
78
+ "",
79
+ writingSamples
80
+ ? `WRITING SAMPLES:\n${writingSamples}`
81
+ : "No writing samples provided.",
82
+ "",
83
+ "REQUIRED SECTIONS:",
84
+ "# Identity & Voice",
85
+ "## Who I Am",
86
+ "## Core Beliefs",
87
+ "## What I've Built",
88
+ "## Stack I Use Daily",
89
+ "## Content Themes",
90
+ "## Writing Style",
91
+ "## Signature Patterns",
92
+ "## BANNED",
93
+ "",
94
+ "Output only the markdown content.",
95
+ ].join("\n");
96
+ return callOpenAI(systemPrompt, userMessage, CONFIG.LLM.MODELS.ADVANCED);
97
+ }
98
+ async function generateRssSeed(stack, topics) {
99
+ const systemPrompt = [
100
+ "You suggest RSS feed URLs for a person based on their stack and interests.",
101
+ "Return only plain text: one URL per line.",
102
+ "Add a short inline comment after each URL with #.",
103
+ "No markdown, no preamble.",
104
+ "Aim for 10 to 14 high-quality feeds.",
105
+ ].join("\n");
106
+ const userMessage = [
107
+ `Stack: ${stack}`,
108
+ `Topics of interest: ${topics}`,
109
+ "",
110
+ "Suggest RSS feeds.",
111
+ ].join("\n");
112
+ return callOpenAI(systemPrompt, userMessage, CONFIG.LLM.MODELS.STANDARD);
113
+ }
114
+ export async function runInit(_flags) {
115
+ const contextPath = resolveWorkspacePath(CONFIG.FILES.CONTEXT);
116
+ const sourcesPath = resolveWorkspacePath(CONFIG.FILES.SOURCES);
117
+ if (!hasOpenAIKey()) {
118
+ cli.printStageStart("No OPENAI_API_KEY found");
119
+ const contextStatus = copyTemplate(CONFIG.FILES.CONTEXT, "config/context.example.md");
120
+ const sourcesStatus = copyTemplate(CONFIG.FILES.SOURCES, "config/rss_sources.example.txt");
121
+ cli.printResult("context.md", contextStatus === "created" ? 1 : 0, 1, contextStatus);
122
+ cli.printResult("rss_sources.txt", sourcesStatus === "created" ? 1 : 0, 1, sourcesStatus);
123
+ cli.printMessage("Set OPENAI_API_KEY and re-run npm run init for AI-assisted setup.", "muted");
124
+ return;
125
+ }
126
+ const rl = createRL();
127
+ let rlClosed = false;
128
+ try {
129
+ if (fs.existsSync(contextPath)) {
130
+ cli.printMessage("context.md already exists.", "muted");
131
+ const rebuild = await confirm(rl, "Start a fresh interview and rebuild context.md?");
132
+ if (!rebuild) {
133
+ cli.printMessage("Nothing changed.", "muted");
134
+ rl.close();
135
+ rlClosed = true;
136
+ return;
137
+ }
138
+ }
139
+ cli.printStageStart("Interview");
140
+ cli.printMessage("Specific answers produce much better voice matching.", "muted");
141
+ const name = await ask(rl, "Your name and what you build (one sentence):");
142
+ const stack = await ask(rl, "Your daily stack, limited to what you actually ship with:");
143
+ const alwaysRead = await ask(rl, "Topics you always read:");
144
+ const alwaysSkip = await ask(rl, "Topics you always skip:");
145
+ const tone = await ask(rl, "Your writing tone in one sentence:");
146
+ cli.printMessage("Paste 1-3 writing sample URLs if you have them.", "muted");
147
+ const url1 = await ask(rl, "URL 1 (or Enter to skip):");
148
+ const url2 = url1 ? await ask(rl, "URL 2 (or Enter to skip):") : "";
149
+ const url3 = url2 ? await ask(rl, "URL 3 (or Enter to skip):") : "";
150
+ rl.close();
151
+ rlClosed = true;
152
+ const sampleUrls = [url1, url2, url3].filter(Boolean);
153
+ let writingSamples = "";
154
+ if (sampleUrls.length > 0) {
155
+ cli.printStageStart("Fetching writing samples");
156
+ writingSamples = await fetchWritingSamples(sampleUrls);
157
+ cli.printResult("Samples", writingSamples ? sampleUrls.length : 0, sampleUrls.length);
158
+ }
159
+ cli.printStageStart("Generating context.md");
160
+ cli.startSpinner("Building your identity and voice profile...");
161
+ const contextMd = await generateContextMd({
162
+ name,
163
+ stack,
164
+ "always-read": alwaysRead,
165
+ "always-skip": alwaysSkip,
166
+ tone,
167
+ }, writingSamples);
168
+ cli.stopSpinner();
169
+ fs.mkdirSync(path.dirname(contextPath), { recursive: true });
170
+ fs.writeFileSync(contextPath, contextMd + "\n");
171
+ cli.printResult("context.md written", 1, 1);
172
+ if (!fs.existsSync(sourcesPath)) {
173
+ cli.printStageStart("Generating RSS starter list");
174
+ cli.startSpinner("Suggesting feeds based on your stack and interests...");
175
+ const rssSeed = await generateRssSeed(stack, alwaysRead);
176
+ cli.stopSpinner();
177
+ fs.mkdirSync(path.dirname(sourcesPath), { recursive: true });
178
+ fs.writeFileSync(sourcesPath, rssSeed + "\n");
179
+ cli.printResult("rss_sources.txt written", 1, 1);
180
+ }
181
+ else {
182
+ cli.printMessage("rss_sources.txt already exists, skipped.", "muted");
183
+ }
184
+ cli.printMessage("Run npm run harvest next.", "success");
185
+ }
186
+ finally {
187
+ if (!rlClosed) {
188
+ rl.close();
189
+ }
190
+ }
191
+ }
192
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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"}
package/dist/llm.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ /** Run async tasks with a concurrency limit. */
2
+ export declare function mapWithConcurrency<T, R>(items: T[], fn: (item: T, index: number) => Promise<R>, concurrency: number): Promise<R[]>;
package/dist/llm.js ADDED
@@ -0,0 +1,11 @@
1
+ /** Run async tasks with a concurrency limit. */
2
+ export async function mapWithConcurrency(items, fn, concurrency) {
3
+ const results = [];
4
+ for (let i = 0; i < items.length; i += concurrency) {
5
+ const batch = items.slice(i, i + concurrency);
6
+ const batchResults = await Promise.all(batch.map((item, j) => fn(item, i + j)));
7
+ results.push(...batchResults);
8
+ }
9
+ return results;
10
+ }
11
+ //# sourceMappingURL=llm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm.js","sourceRoot":"","sources":["../src/llm.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,KAAU,EACV,EAA0C,EAC1C,WAAmB;IAEnB,MAAM,OAAO,GAAQ,EAAE,CAAC;IACxB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,WAAW,EAAE,CAAC;QACnD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC;QAC9C,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAChF,OAAO,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1 @@
1
+ import "dotenv/config";