diff --git a/typescript/packages/linkheap/main.ts b/typescript/packages/linkheap/main.ts
index bea73c554..fbf887651 100644
--- a/typescript/packages/linkheap/main.ts
+++ b/typescript/packages/linkheap/main.ts
@@ -96,13 +96,13 @@ async function saveLink(
if (comment) {
console.log(`Comment: ${comment}`);
}
-
- // Fetch and analyze the link in the background
- analyzeLink(url);
} catch (error) {
db.query("ROLLBACK");
- console.error(`Error saving link: ${error.message}`);
+ throw new Error(`Error saving link: ${error.message}`);
}
+
+ // FIXME(ja): should we rollback if this fails?
+ await analyzeLink(url);
}
export function grabJson(txt: string) {
@@ -240,6 +240,7 @@ no yapping, just output the JSON
const structured = grabJson(message);
// Update the database
+ // FIXME(ja): this will silently fail if the URL is not found
db.query(
`UPDATE links SET
title = ?, description = ?, tags = ?, category = ?,
@@ -262,75 +263,53 @@ no yapping, just output the JSON
console.log(`Updated metadata for: ${url}`);
} catch (error) {
- console.error(`Error analyzing link: ${error.message}`);
+ throw new Error(`Error analyzing link: ${error.message}`);
}
}
-async function listLinks(collection?: string) {
- if (!collection) {
- // List all collections
- const collections = db.query(`
- SELECT c.name, COUNT(lc.link_id) as link_count
+async function listCollections() {
+ const collections = db.query<[string]>(`
+ SELECT json_object(
+ 'name', c.name,
+ 'link_count', COUNT(lc.link_id)
+ ) as json
FROM collections c
LEFT JOIN link_collections lc ON c.id = lc.collection_id
GROUP BY c.id
ORDER BY c.name
- `);
+ `).map(([collection]) => JSON.parse(collection));
- console.log("Collections:");
- for (const [name, linkCount] of collections) {
- console.log(` ${name} (${linkCount} links)`);
- }
- console.log(
- "\nUse 'list
-
`;
}
@@ -426,8 +382,7 @@ async function viewCollection(collection: string, comment?: string) {
console.log(`View saved to: ${filePath}`);
- // Open the HTML file in the default web browser
- await open(filePath);
+ return filePath;
} catch (error) {
console.error(`Error viewing collection: ${error.message}`);
}
@@ -440,58 +395,17 @@ async function imagineCollection(collection: string, userComment?: string) {
await ensureDir(viewsDir);
// Fetch links for the given collection
- const links = db.query(
- `
- SELECT l.*
- FROM links l
- JOIN link_collections lc ON l.id = lc.link_id
- JOIN collections c ON lc.collection_id = c.id
- WHERE c.name = ?
- ORDER BY l.created_at DESC
- `,
- [collection],
- );
+ const links = await listLinks(collection);
if (links.length === 0) {
console.log(`No links found in collection: ${collection}`);
return;
}
- // Prepare data for LLM query
- const linksData = links.map(
- ([
- id,
- url,
- comment,
- title,
- description,
- tags,
- category,
- summary,
- image_url,
- favicon_url,
- screenshot_path,
- created_at,
- json,
- ]) => ({
- url,
- comment,
- title,
- description,
- tags,
- category,
- image_url,
- favicon_url,
- screenshot_path,
- created_at,
- json,
- }),
- );
-
const prompt = `
Take this collections of links and imagine an interactive webpage. The collection is named "${collection}" and contains ${links.length} links. Here's the data:
-${JSON.stringify(linksData, null, 2).slice(0, 50000)}
+${JSON.stringify(links, null, 2).slice(0, 50000)}
Create a complete HTML page that inspired by this collection. Try to synthesize the broader themes of this collection and capture them in the artifact.
@@ -535,10 +449,9 @@ Provide the entire HTML code for the page, including any embedded CSS and JavaSc
console.log(`Imagined view saved to: ${filePath}`);
- // Open the HTML file in the default web browser
- await open(filePath);
+ return filePath;
} catch (error) {
- console.error(`Error imagining collection: ${error.message}`);
+ throw new Error(`Error imagining collection: ${error.message}`);
}
}
@@ -558,69 +471,109 @@ async function main() {
const args = line.trim().split(" ");
const command = args.shift()?.toLowerCase();
- switch (command) {
- case "save":
- if (args.length === 0) {
- console.log("Please provide a URL to save.");
- } else {
- const url = args.shift()!;
- const commentIndex = args.indexOf("--comment");
- let collections: string[] = [];
- let comment: string = "";
-
- if (commentIndex !== -1) {
- collections = args.slice(0, commentIndex);
- comment = args.slice(commentIndex + 1).join(" ");
+ try {
+ switch (command) {
+ case "save":
+ if (args.length === 0) {
+ console.log("Please provide a URL to save.");
} else {
- collections = args;
+ const url = args.shift()!;
+ const commentIndex = args.indexOf("--comment");
+ let collections: string[] = [];
+ let comment: string = "";
+
+ if (commentIndex !== -1) {
+ collections = args.slice(0, commentIndex);
+ comment = args.slice(commentIndex + 1).join(" ");
+ } else {
+ collections = args;
+ }
+
+ await saveLink(url, collections, comment);
}
-
- await saveLink(url, collections, comment);
- }
- break;
- case "list":
- await listLinks(args[0]);
- break;
- case "view":
- if (args.length === 0) {
- console.log("Please provide a collection name to view.");
- } else {
- const collection = args.shift()!;
- const comment = args.join(" ");
- await viewCollection(collection, comment);
- }
- break;
- case "imagine":
- if (args.length === 0) {
- console.log("Please provide a collection name to imagine.");
- } else {
- const collection = args.shift()!;
- const comment = args.join(" ");
- await imagineCollection(collection, comment);
- }
- break;
- case "refresh":
- if (args.length === 0) {
- console.log("Please provide a URL to refresh.");
- } else {
- const url = args[0];
- await analyzeLink(url);
- }
- break;
-
- case "exit":
- console.log("Goodbye!");
- Deno.exit(0);
- default:
- console.log("Unknown command. Available commands:");
- console.log(
- " save ${title || "N/A"}
- ${url}
- ${category || "N/A"}
- ${linkComment || "N/A"}
- ${summary || "N/A"}
- ${tags || "N/A"}
- ${screenshot_path ? `
- ` : "N/A"}
${image_url ? `
+ ` : "N/A"}
${link.title || "N/A"}
+ ${link.url}
+ ${link.category || "N/A"}
+ ${link.comment || "N/A"}
+ ${link.summary || "N/A"}
+ ${link.tags || "N/A"}
+ ${link.screenshot_path ? `
+ ` : "N/A"}
${link.image_url ? `
` : "N/A"}