openalmanac 0.2.13 → 0.2.15
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/dist/server.js +6 -0
- package/dist/tools/articles.js +35 -5
- package/dist/tools/research.js +41 -0
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -47,6 +47,12 @@ export function createServer() {
|
|
|
47
47
|
"read_webpage(url=profile_url) to get their full profile with a high-resolution photo, then " +
|
|
48
48
|
"create_stub with the image_url from the  line in the scraped markdown. " +
|
|
49
49
|
"For topics/orgs/events: use descriptive kebab-case slugs (e.g. 'reinforcement-learning', 'openai').\n\n" +
|
|
50
|
+
"## Images\n\n" +
|
|
51
|
+
"Use search_images to find images for articles. Syntax: `` where position " +
|
|
52
|
+
"is 'right' (default), 'left', or 'center'. The caption (alt text) is displayed below the image — " +
|
|
53
|
+
"make it descriptive. Use 1-3 images per major section. " +
|
|
54
|
+
"For the infobox hero image, set infobox.header.image_url in frontmatter. " +
|
|
55
|
+
"External image URLs are auto-persisted on push — no extra steps needed.\n\n" +
|
|
50
56
|
"After creating an article, always share the exact URL from the push response with the user. " +
|
|
51
57
|
"This URL includes a celebration page for the newly created article.\n\n" +
|
|
52
58
|
"After pushing an article, call search_communities to find relevant communities. " +
|
package/dist/tools/articles.js
CHANGED
|
@@ -82,6 +82,32 @@ Include an infobox for any article about a person, place, organization, event, o
|
|
|
82
82
|
- Every source in the sources list must be referenced at least once in the body
|
|
83
83
|
- Every [N] marker must have a matching source
|
|
84
84
|
|
|
85
|
+
## Images
|
|
86
|
+
|
|
87
|
+
Use search_images to find relevant images. Images render as figures with visible captions.
|
|
88
|
+
|
|
89
|
+
**Syntax:** \`\`
|
|
90
|
+
|
|
91
|
+
Positions: \`"right"\` (default if omitted), \`"left"\`, \`"center"\`
|
|
92
|
+
|
|
93
|
+
\`\`\`markdown
|
|
94
|
+

|
|
95
|
+
|
|
96
|
+
The early life of Alan Turing began...
|
|
97
|
+
|
|
98
|
+

|
|
99
|
+
\`\`\`
|
|
100
|
+
|
|
101
|
+
**Caption rules:**
|
|
102
|
+
- Every image MUST have a descriptive caption — it is displayed below the image
|
|
103
|
+
- Describe what the image shows: "Alan Turing in 1930, aged 18" not "Photo"
|
|
104
|
+
- Include dates, context, or attribution when relevant
|
|
105
|
+
|
|
106
|
+
**Placement:** 1-3 images per major section, spread throughout. First image near the top.
|
|
107
|
+
For the infobox hero image, use \`infobox.header.image_url\` in frontmatter instead.
|
|
108
|
+
|
|
109
|
+
External image URLs are auto-persisted on push — no extra steps needed.
|
|
110
|
+
|
|
85
111
|
## Writing quality
|
|
86
112
|
|
|
87
113
|
- Every sentence should contain a specific fact the reader didn't know
|
|
@@ -230,9 +256,10 @@ export function registerArticleTools(server) {
|
|
|
230
256
|
"validates locally (frontmatter, citations, sources), then pushes via the API. Requires login.",
|
|
231
257
|
parameters: z.object({
|
|
232
258
|
slug: z.string().describe("Article slug matching the filename (without .md)"),
|
|
233
|
-
|
|
259
|
+
change_title: z.string().optional().describe("Short title for the change (e.g. 'Added early life section')"),
|
|
260
|
+
change_description: z.string().optional().describe("Longer description of what changed and why"),
|
|
234
261
|
}),
|
|
235
|
-
async execute({ slug,
|
|
262
|
+
async execute({ slug, change_title, change_description }) {
|
|
236
263
|
const filePath = join(ARTICLES_DIR, `${slug}.md`);
|
|
237
264
|
let raw;
|
|
238
265
|
try {
|
|
@@ -247,11 +274,14 @@ export function registerArticleTools(server) {
|
|
|
247
274
|
const lines = errors.map((e) => ` ${e.field}: ${e.message}`);
|
|
248
275
|
throw new Error(`Validation failed (${errors.length} error${errors.length > 1 ? "s" : ""}):\n${lines.join("\n")}\n\nFix the file and try again.`);
|
|
249
276
|
}
|
|
250
|
-
// Inject
|
|
277
|
+
// Inject change_title/change_description into frontmatter if provided
|
|
251
278
|
let body = raw;
|
|
252
|
-
if (
|
|
279
|
+
if (change_title || change_description) {
|
|
253
280
|
const { frontmatter, content } = parseFrontmatter(raw);
|
|
254
|
-
|
|
281
|
+
if (change_title)
|
|
282
|
+
frontmatter.change_title = change_title;
|
|
283
|
+
if (change_description)
|
|
284
|
+
frontmatter.change_description = change_description;
|
|
255
285
|
const newFrontmatter = yamlStringify(frontmatter);
|
|
256
286
|
body = `---\n${newFrontmatter}---\n${content}`;
|
|
257
287
|
}
|
package/dist/tools/research.js
CHANGED
|
@@ -40,4 +40,45 @@ export function registerResearchTools(server) {
|
|
|
40
40
|
return JSON.stringify(data, null, 2);
|
|
41
41
|
},
|
|
42
42
|
});
|
|
43
|
+
server.addTool({
|
|
44
|
+
name: "search_images",
|
|
45
|
+
description: "Search for images to include in articles. Returns image URLs, titles, dimensions, and licensing info. " +
|
|
46
|
+
"Two sources: 'wikimedia' (free, open-licensed images from Wikimedia Commons — preferred) and 'google' (broader web images via Google). " +
|
|
47
|
+
"Use descriptive search terms. Pick images based on their title and description. " +
|
|
48
|
+
"External image URLs are automatically persisted when you push the article — no extra steps needed.\n\n" +
|
|
49
|
+
"## Using images in articles\n\n" +
|
|
50
|
+
"Images render as figures with visible captions. The alt text becomes the caption — make it descriptive.\n\n" +
|
|
51
|
+
"**Syntax:** ``\n\n" +
|
|
52
|
+
"Position options (in the title/quotes):\n" +
|
|
53
|
+
"- `\"right\"` — float right (DEFAULT if omitted)\n" +
|
|
54
|
+
"- `\"left\"` — float left\n" +
|
|
55
|
+
"- `\"center\"` — full-width, centered\n\n" +
|
|
56
|
+
"**Examples:**\n" +
|
|
57
|
+
"- `` — floats right (default)\n" +
|
|
58
|
+
"- `` — floats left\n" +
|
|
59
|
+
"- `` — full-width\n\n" +
|
|
60
|
+
"**Caption rules:**\n" +
|
|
61
|
+
"- Every image MUST have a descriptive caption — it is displayed below the image\n" +
|
|
62
|
+
"- Describe what the image shows: 'Alan Turing in 1930, aged 18' not 'Photo'\n" +
|
|
63
|
+
"- Include date, context, or attribution when relevant\n" +
|
|
64
|
+
"- Bad: `` — Good: ``\n\n" +
|
|
65
|
+
"**Placement rules:**\n" +
|
|
66
|
+
"- Place 1-3 images per major section — don't overload\n" +
|
|
67
|
+
"- First image should appear near the top, illustrating the article's subject\n" +
|
|
68
|
+
"- Spread images throughout, not clustered together\n" +
|
|
69
|
+
"- For the infobox hero image, set `infobox.header.image_url` in frontmatter instead\n\n" +
|
|
70
|
+
"Requires login. Rate limit: 10/min.",
|
|
71
|
+
parameters: z.object({
|
|
72
|
+
query: z.string().describe("Descriptive search terms for the image (e.g. 'Apollo 11 moon landing photograph')"),
|
|
73
|
+
source: z.enum(["wikimedia", "google"]).default("wikimedia").describe("Image source: 'wikimedia' (free, open-licensed — preferred) or 'google' (broader coverage)"),
|
|
74
|
+
limit: z.number().default(10).describe("Max results (1-30, default 10)"),
|
|
75
|
+
}),
|
|
76
|
+
async execute({ query, source, limit }) {
|
|
77
|
+
const resp = await request("GET", "/api/research/images", {
|
|
78
|
+
auth: true,
|
|
79
|
+
params: { query, source, limit },
|
|
80
|
+
});
|
|
81
|
+
return JSON.stringify(await resp.json(), null, 2);
|
|
82
|
+
},
|
|
83
|
+
});
|
|
43
84
|
}
|