@telepat/ideon 0.1.25 → 0.1.27
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/ideon.js
CHANGED
|
@@ -12,7 +12,8 @@ import { access, mkdir, writeFile } from "fs/promises";
|
|
|
12
12
|
import os from "os";
|
|
13
13
|
import path from "path";
|
|
14
14
|
function resolveOutputPaths() {
|
|
15
|
-
const
|
|
15
|
+
const ideonHome = process.env.IDEON_HOME || os.homedir();
|
|
16
|
+
const base = path.join(ideonHome, ".ideon", "output");
|
|
16
17
|
return {
|
|
17
18
|
markdownOutputDir: base,
|
|
18
19
|
assetOutputDir: path.join(base, "assets")
|
|
@@ -1423,7 +1424,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
1423
1424
|
// package.json
|
|
1424
1425
|
var package_default = {
|
|
1425
1426
|
name: "@telepat/ideon",
|
|
1426
|
-
version: "0.1.
|
|
1427
|
+
version: "0.1.27",
|
|
1427
1428
|
description: "CLI for generating rich articles and images from ideas.",
|
|
1428
1429
|
type: "module",
|
|
1429
1430
|
repository: {
|
|
@@ -1623,7 +1624,7 @@ function assertNoLegacyXMode(contentTargets, sourceLabel) {
|
|
|
1623
1624
|
}
|
|
1624
1625
|
|
|
1625
1626
|
// src/pipeline/runner.ts
|
|
1626
|
-
import { mkdir as mkdir6, stat as stat2 } from "fs/promises";
|
|
1627
|
+
import { mkdir as mkdir6, readFile as readFile6, stat as stat2 } from "fs/promises";
|
|
1627
1628
|
import { randomUUID } from "crypto";
|
|
1628
1629
|
import path9 from "path";
|
|
1629
1630
|
|
|
@@ -2380,7 +2381,7 @@ function buildLongFormPlanJsonSchema(targetLengthWords) {
|
|
|
2380
2381
|
required: ["description", "anchorAfterSection"],
|
|
2381
2382
|
properties: {
|
|
2382
2383
|
description: { type: "string" },
|
|
2383
|
-
anchorAfterSection: { type: "number", minimum:
|
|
2384
|
+
anchorAfterSection: { type: "number", minimum: 1 }
|
|
2384
2385
|
}
|
|
2385
2386
|
}
|
|
2386
2387
|
}
|
|
@@ -2446,7 +2447,7 @@ function buildLongFormPlanMessages(idea, options) {
|
|
|
2446
2447
|
"- Each section description should name the mechanism, evidence type, or practical action that makes the section useful.",
|
|
2447
2448
|
"- Sections are primary-only structure and must not be treated as requirements for non-primary channels.",
|
|
2448
2449
|
`- Include a cover image description and ${imageCounts.min} to ${imageCounts.max} inline image descriptions.`,
|
|
2449
|
-
"- Each inline image must specify which section it follows (anchorAfterSection, starting at
|
|
2450
|
+
"- Each inline image must specify which section it follows (anchorAfterSection, starting at 1). Choose sections where visual reinforcement adds the most value.",
|
|
2450
2451
|
"- Image descriptions should capture the general concept and mood \u2014 the exact text-to-image prompt will be refined later using the actual section content.",
|
|
2451
2452
|
"- Image descriptions must be concrete and contextual, not generic stock-photo phrasing.",
|
|
2452
2453
|
"",
|
|
@@ -2468,7 +2469,7 @@ function buildLongFormPlanMessages(idea, options) {
|
|
|
2468
2469
|
"- outroBrief: string",
|
|
2469
2470
|
`- sections: array of ${sectionCounts.label} objects, each with title and description strings`,
|
|
2470
2471
|
"- coverImageDescription: string",
|
|
2471
|
-
`- inlineImages: array of ${imageCounts.min} to ${imageCounts.max} objects, each with a description string and an anchorAfterSection number (starting at
|
|
2472
|
+
`- inlineImages: array of ${imageCounts.min} to ${imageCounts.max} objects, each with a description string and an anchorAfterSection number (starting at 1).`,
|
|
2472
2473
|
"",
|
|
2473
2474
|
"Do not omit any required fields. Return strict JSON only."
|
|
2474
2475
|
].join("\n")
|
|
@@ -2530,7 +2531,7 @@ var articleSectionPlanSchema = z5.object({
|
|
|
2530
2531
|
});
|
|
2531
2532
|
var inlineImagePlanSchema = z5.object({
|
|
2532
2533
|
description: z5.string().min(1),
|
|
2533
|
-
anchorAfterSection: z5.number().int().min(
|
|
2534
|
+
anchorAfterSection: z5.number().int().min(1)
|
|
2534
2535
|
});
|
|
2535
2536
|
var primaryPlanSchema = z5.object({
|
|
2536
2537
|
contentType: z5.string().min(1).default("article"),
|
|
@@ -2619,7 +2620,7 @@ async function planPrimaryContent({
|
|
|
2619
2620
|
keywords: longPlan.keywords.slice(0, 8),
|
|
2620
2621
|
inlineImages: longPlan.inlineImages.slice(0, 3).map((img) => ({
|
|
2621
2622
|
...img,
|
|
2622
|
-
anchorAfterSection: Math.max(
|
|
2623
|
+
anchorAfterSection: Math.max(1, Math.min(sectionCount, img.anchorAfterSection))
|
|
2623
2624
|
}))
|
|
2624
2625
|
};
|
|
2625
2626
|
}
|
|
@@ -3276,7 +3277,7 @@ function buildImageSlots(plan, sections, options) {
|
|
|
3276
3277
|
kind: "inline",
|
|
3277
3278
|
prompt: "",
|
|
3278
3279
|
description: img.description,
|
|
3279
|
-
anchorAfterSection: Math.max(
|
|
3280
|
+
anchorAfterSection: Math.max(1, Math.min(sectionCount, img.anchorAfterSection))
|
|
3280
3281
|
});
|
|
3281
3282
|
}
|
|
3282
3283
|
return slots;
|
|
@@ -5137,15 +5138,47 @@ async function runPipelineShell(input, options = {}) {
|
|
|
5137
5138
|
markStageStarted(stageTracking, "links");
|
|
5138
5139
|
options.onUpdate?.(cloneStages(stages));
|
|
5139
5140
|
if (!shouldEnrichLinks) {
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5141
|
+
const customLinkActions = pipelineCustomLinkRaws.length > 0 || pipelineUnlinks.length > 0;
|
|
5142
|
+
if (customLinkActions && eligibleOutputsForLinks.length > 0) {
|
|
5143
|
+
for (const output of eligibleOutputsForLinks) {
|
|
5144
|
+
const existingLinks = await readExistingLinks(resolveLinksPath(output.markdownPath));
|
|
5145
|
+
const mergedCustomLinks = resolvePipelineCustomLinks(
|
|
5146
|
+
existingLinks?.customLinks ?? [],
|
|
5147
|
+
pipelineCustomLinkRaws,
|
|
5148
|
+
pipelineUnlinks
|
|
5149
|
+
);
|
|
5150
|
+
const generatedLinks = existingLinks?.links ?? [];
|
|
5151
|
+
await writeLinksFile(output.markdownPath, {
|
|
5152
|
+
version: 2,
|
|
5153
|
+
customLinks: mergedCustomLinks,
|
|
5154
|
+
links: generatedLinks
|
|
5155
|
+
});
|
|
5156
|
+
}
|
|
5157
|
+
markStageCompleted(stageTracking, "links");
|
|
5158
|
+
stages[6] = {
|
|
5159
|
+
...stages[6],
|
|
5160
|
+
status: "succeeded",
|
|
5161
|
+
detail: "Updated custom links without generating new links.",
|
|
5162
|
+
summary: `${eligibleOutputsForLinks.length} files updated`,
|
|
5163
|
+
items: (stages[6].items ?? []).map((stageItem) => ({
|
|
5164
|
+
...stageItem,
|
|
5165
|
+
status: "succeeded",
|
|
5166
|
+
detail: "Saved custom links sidecar."
|
|
5167
|
+
})),
|
|
5168
|
+
stageAnalytics: snapshotStageAnalytics(stageTracking, "links")
|
|
5169
|
+
};
|
|
5170
|
+
options.onUpdate?.(cloneStages(stages));
|
|
5171
|
+
} else {
|
|
5172
|
+
markStageCompleted(stageTracking, "links");
|
|
5173
|
+
stages[6] = {
|
|
5174
|
+
...stages[6],
|
|
5175
|
+
status: "succeeded",
|
|
5176
|
+
detail: "Skipped link enrichment (enable with --enrich-links).",
|
|
5177
|
+
summary: "Link enrichment disabled for this run",
|
|
5178
|
+
stageAnalytics: snapshotStageAnalytics(stageTracking, "links")
|
|
5179
|
+
};
|
|
5180
|
+
options.onUpdate?.(cloneStages(stages));
|
|
5181
|
+
}
|
|
5149
5182
|
} else if (eligibleOutputsForLinks.length === 0) {
|
|
5150
5183
|
markStageCompleted(stageTracking, "links");
|
|
5151
5184
|
stages[6] = {
|
|
@@ -5803,9 +5836,61 @@ function parsePipelineCustomLinks(rawLinks, unlinks) {
|
|
|
5803
5836
|
}
|
|
5804
5837
|
return Array.from(result.values());
|
|
5805
5838
|
}
|
|
5839
|
+
function resolvePipelineCustomLinks(existing, rawLinks, unlinks) {
|
|
5840
|
+
const result = new Map(
|
|
5841
|
+
existing.map((entry) => [entry.expression.trim().toLowerCase(), entry])
|
|
5842
|
+
);
|
|
5843
|
+
for (const raw of rawLinks) {
|
|
5844
|
+
const separatorIndex = raw.indexOf("->");
|
|
5845
|
+
if (separatorIndex < 0) {
|
|
5846
|
+
continue;
|
|
5847
|
+
}
|
|
5848
|
+
const expression = raw.slice(0, separatorIndex).trim();
|
|
5849
|
+
const url = raw.slice(separatorIndex + 2).trim();
|
|
5850
|
+
if (expression && url) {
|
|
5851
|
+
result.set(expression.toLowerCase(), { expression, url, title: null });
|
|
5852
|
+
}
|
|
5853
|
+
}
|
|
5854
|
+
for (const expr of unlinks) {
|
|
5855
|
+
result.delete(expr.trim().toLowerCase());
|
|
5856
|
+
}
|
|
5857
|
+
return Array.from(result.values());
|
|
5858
|
+
}
|
|
5859
|
+
async function readExistingLinks(linksPath) {
|
|
5860
|
+
try {
|
|
5861
|
+
const raw = await readFile6(linksPath, "utf8");
|
|
5862
|
+
const parsed = JSON.parse(raw);
|
|
5863
|
+
const links = Array.isArray(parsed.links) ? parsed.links.filter((entry) => isValidLinkEntry(entry)).map((entry) => ({
|
|
5864
|
+
expression: entry.expression.trim(),
|
|
5865
|
+
url: entry.url.trim(),
|
|
5866
|
+
title: typeof entry.title === "string" ? entry.title : null
|
|
5867
|
+
})) : null;
|
|
5868
|
+
if (!links) {
|
|
5869
|
+
throw new Error(`Invalid links sidecar format at ${linksPath}. Expected { version, links[] }.`);
|
|
5870
|
+
}
|
|
5871
|
+
const customLinks = Array.isArray(parsed.customLinks) ? parsed.customLinks.filter((entry) => isValidLinkEntry(entry)).map((entry) => ({
|
|
5872
|
+
expression: entry.expression.trim(),
|
|
5873
|
+
url: entry.url.trim(),
|
|
5874
|
+
title: typeof entry.title === "string" ? entry.title : null
|
|
5875
|
+
})) : [];
|
|
5876
|
+
return {
|
|
5877
|
+
version: typeof parsed.version === "number" ? parsed.version : 2,
|
|
5878
|
+
customLinks,
|
|
5879
|
+
links
|
|
5880
|
+
};
|
|
5881
|
+
} catch (error) {
|
|
5882
|
+
if (error.code === "ENOENT") {
|
|
5883
|
+
return null;
|
|
5884
|
+
}
|
|
5885
|
+
throw error;
|
|
5886
|
+
}
|
|
5887
|
+
}
|
|
5888
|
+
function isValidLinkEntry(entry) {
|
|
5889
|
+
return typeof entry === "object" && entry !== null && typeof entry.expression === "string" && typeof entry.url === "string";
|
|
5890
|
+
}
|
|
5806
5891
|
|
|
5807
5892
|
// src/cli/commands/links.ts
|
|
5808
|
-
import { readFile as
|
|
5893
|
+
import { readFile as readFile7, stat as stat3 } from "fs/promises";
|
|
5809
5894
|
import path10 from "path";
|
|
5810
5895
|
async function runLinksCommand(options, dependencies = {}) {
|
|
5811
5896
|
const slug = normalizeSlug2(options.slug);
|
|
@@ -5828,7 +5913,7 @@ async function runLinksCommand(options, dependencies = {}) {
|
|
|
5828
5913
|
}
|
|
5829
5914
|
const openRouter = new OpenRouterClient(openRouterApiKey);
|
|
5830
5915
|
const linksPath = resolveLinksPath(markdownPath);
|
|
5831
|
-
const existing = await
|
|
5916
|
+
const existing = await readExistingLinks2(linksPath);
|
|
5832
5917
|
const updatedCustomLinks = resolveCustomLinks(existing?.customLinks ?? [], options.links ?? [], options.unlinks ?? []);
|
|
5833
5918
|
const effectiveMaxLinks = options.maxLinks;
|
|
5834
5919
|
const linksResult = await enrichLinks({
|
|
@@ -5923,7 +6008,7 @@ async function newestPath(paths) {
|
|
|
5923
6008
|
return latestPath;
|
|
5924
6009
|
}
|
|
5925
6010
|
async function readFrontmatter(markdownPath) {
|
|
5926
|
-
const markdown = await
|
|
6011
|
+
const markdown = await readFile7(markdownPath, "utf8");
|
|
5927
6012
|
return parseFrontmatter(markdown);
|
|
5928
6013
|
}
|
|
5929
6014
|
function parseFrontmatter(markdown) {
|
|
@@ -5967,11 +6052,11 @@ async function isReadableFile(filePath) {
|
|
|
5967
6052
|
return false;
|
|
5968
6053
|
}
|
|
5969
6054
|
}
|
|
5970
|
-
async function
|
|
6055
|
+
async function readExistingLinks2(linksPath) {
|
|
5971
6056
|
try {
|
|
5972
|
-
const raw = await
|
|
6057
|
+
const raw = await readFile7(linksPath, "utf8");
|
|
5973
6058
|
const parsed = JSON.parse(raw);
|
|
5974
|
-
const links = Array.isArray(parsed.links) ? parsed.links.filter((entry) =>
|
|
6059
|
+
const links = Array.isArray(parsed.links) ? parsed.links.filter((entry) => isValidLinkEntry2(entry)).map((entry) => ({
|
|
5975
6060
|
expression: entry.expression.trim(),
|
|
5976
6061
|
url: entry.url.trim(),
|
|
5977
6062
|
title: typeof entry.title === "string" ? entry.title : null
|
|
@@ -5979,7 +6064,7 @@ async function readExistingLinks(linksPath) {
|
|
|
5979
6064
|
if (!links) {
|
|
5980
6065
|
throw new ReportedError(`Invalid links sidecar format at ${linksPath}. Expected { version, links[] }.`);
|
|
5981
6066
|
}
|
|
5982
|
-
const customLinks = Array.isArray(parsed.customLinks) ? parsed.customLinks.filter((entry) =>
|
|
6067
|
+
const customLinks = Array.isArray(parsed.customLinks) ? parsed.customLinks.filter((entry) => isValidLinkEntry2(entry)).map((entry) => ({
|
|
5983
6068
|
expression: entry.expression.trim(),
|
|
5984
6069
|
url: entry.url.trim(),
|
|
5985
6070
|
title: typeof entry.title === "string" ? entry.title : null
|
|
@@ -6013,7 +6098,7 @@ function mergeLinks(existingLinks, generatedLinks) {
|
|
|
6013
6098
|
}
|
|
6014
6099
|
return merged;
|
|
6015
6100
|
}
|
|
6016
|
-
function
|
|
6101
|
+
function isValidLinkEntry2(value2) {
|
|
6017
6102
|
if (typeof value2 !== "object" || value2 === null) {
|
|
6018
6103
|
return false;
|
|
6019
6104
|
}
|
|
@@ -6067,7 +6152,7 @@ function resolveCustomLinks(existing, addRaw, removeExpressions) {
|
|
|
6067
6152
|
}
|
|
6068
6153
|
|
|
6069
6154
|
// src/cli/commands/export.ts
|
|
6070
|
-
import { copyFile as copyFile2, mkdir as mkdir7, readFile as
|
|
6155
|
+
import { copyFile as copyFile2, mkdir as mkdir7, readFile as readFile9, stat as stat5, writeFile as writeFile6 } from "fs/promises";
|
|
6071
6156
|
import path12 from "path";
|
|
6072
6157
|
|
|
6073
6158
|
// src/output/enrichMarkdownWithLinks.ts
|
|
@@ -6124,7 +6209,7 @@ function escapeRegExp(value2) {
|
|
|
6124
6209
|
}
|
|
6125
6210
|
|
|
6126
6211
|
// src/server/previewHelpers.ts
|
|
6127
|
-
import { readdir, stat as stat4, readFile as
|
|
6212
|
+
import { readdir, stat as stat4, readFile as readFile8 } from "fs/promises";
|
|
6128
6213
|
import path11 from "path";
|
|
6129
6214
|
var DEFAULT_PORT = 4173;
|
|
6130
6215
|
var CONTENT_TYPE_ORDER = ["article", "blog-post", "x-thread", "x-post", "linkedin-post", "reddit-post", "newsletter"];
|
|
@@ -6226,7 +6311,7 @@ function extractCoverImageUrl(markdown) {
|
|
|
6226
6311
|
return match?.[1] ?? null;
|
|
6227
6312
|
}
|
|
6228
6313
|
async function extractArticleMetadata(markdownPath) {
|
|
6229
|
-
const markdown = await
|
|
6314
|
+
const markdown = await readFile8(markdownPath, "utf8");
|
|
6230
6315
|
const fileStat = await stat4(markdownPath);
|
|
6231
6316
|
const slug = extractFrontmatterSlug(markdown) ?? path11.basename(markdownPath, ".md");
|
|
6232
6317
|
const title = extractHeadingTitle(stripFrontmatter2(markdown)) ?? slug;
|
|
@@ -6243,7 +6328,7 @@ async function extractArticleMetadata(markdownPath) {
|
|
|
6243
6328
|
}
|
|
6244
6329
|
async function listAllGenerations(markdownOutputDir) {
|
|
6245
6330
|
const markdownFiles = await findMarkdownFiles(markdownOutputDir);
|
|
6246
|
-
const
|
|
6331
|
+
const outputMap = /* @__PURE__ */ new Map();
|
|
6247
6332
|
for (const filePath of markdownFiles) {
|
|
6248
6333
|
try {
|
|
6249
6334
|
const metadata = await extractArticleMetadata(filePath);
|
|
@@ -6261,15 +6346,23 @@ async function listAllGenerations(markdownOutputDir) {
|
|
|
6261
6346
|
contentTypeLabel: toContentTypeLabel(identity.contentType),
|
|
6262
6347
|
index: identity.index
|
|
6263
6348
|
};
|
|
6264
|
-
const
|
|
6265
|
-
|
|
6266
|
-
|
|
6267
|
-
|
|
6268
|
-
grouped.set(identity.generationId, [output]);
|
|
6349
|
+
const outputKey = `${output.generationId}:${output.contentType}:${output.index}`;
|
|
6350
|
+
const existing = outputMap.get(outputKey);
|
|
6351
|
+
if (!existing || output.mtime > existing.mtime) {
|
|
6352
|
+
outputMap.set(outputKey, output);
|
|
6269
6353
|
}
|
|
6270
6354
|
} catch {
|
|
6271
6355
|
}
|
|
6272
6356
|
}
|
|
6357
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
6358
|
+
for (const output of outputMap.values()) {
|
|
6359
|
+
const existing = grouped.get(output.generationId);
|
|
6360
|
+
if (existing) {
|
|
6361
|
+
existing.push(output);
|
|
6362
|
+
} else {
|
|
6363
|
+
grouped.set(output.generationId, [output]);
|
|
6364
|
+
}
|
|
6365
|
+
}
|
|
6273
6366
|
const generations = [];
|
|
6274
6367
|
for (const [id, outputs] of grouped.entries()) {
|
|
6275
6368
|
outputs.sort((a, b) => compareContentTypes(a.contentType, b.contentType) || a.index - b.index || b.mtime - a.mtime);
|
|
@@ -6375,7 +6468,7 @@ async function resolvePrimaryContentType(outputs) {
|
|
|
6375
6468
|
}
|
|
6376
6469
|
const jobPath = path11.join(generationDir, "job.json");
|
|
6377
6470
|
try {
|
|
6378
|
-
const raw = await
|
|
6471
|
+
const raw = await readFile8(jobPath, "utf8");
|
|
6379
6472
|
const parsed = JSON.parse(raw);
|
|
6380
6473
|
const targets = Array.isArray(parsed.contentTargets) ? parsed.contentTargets : Array.isArray(parsed.settings?.contentTargets) ? parsed.settings.contentTargets : [];
|
|
6381
6474
|
const primary = targets.find((target) => target?.role === "primary" && typeof target.contentType === "string");
|
|
@@ -6416,7 +6509,7 @@ async function runOutputCommand(options, dependencies = {}) {
|
|
|
6416
6509
|
);
|
|
6417
6510
|
}
|
|
6418
6511
|
const sourceMarkdownPath = articleOutput.sourcePath;
|
|
6419
|
-
const sourceMarkdown = await
|
|
6512
|
+
const sourceMarkdown = await readFile9(sourceMarkdownPath, "utf8");
|
|
6420
6513
|
const slug = extractFrontmatterSlug2(sourceMarkdown) ?? path12.basename(sourceMarkdownPath, ".md");
|
|
6421
6514
|
const exportFilename = `${slug}.md`;
|
|
6422
6515
|
const destinationDir = await resolveDestinationDir(options.destinationPath, cwd2);
|
|
@@ -6483,7 +6576,7 @@ async function loadLinks(markdownPath) {
|
|
|
6483
6576
|
const linksPath = resolveLinksPath(markdownPath);
|
|
6484
6577
|
let raw;
|
|
6485
6578
|
try {
|
|
6486
|
-
raw = await
|
|
6579
|
+
raw = await readFile9(linksPath, "utf8");
|
|
6487
6580
|
} catch {
|
|
6488
6581
|
return [];
|
|
6489
6582
|
}
|
|
@@ -7405,7 +7498,7 @@ import { spawn } from "child_process";
|
|
|
7405
7498
|
// src/server/previewServer.ts
|
|
7406
7499
|
import { execFile } from "child_process";
|
|
7407
7500
|
import { promisify } from "util";
|
|
7408
|
-
import { readFile as
|
|
7501
|
+
import { readFile as readFile10, stat as stat6 } from "fs/promises";
|
|
7409
7502
|
import { watch as fsWatch } from "fs";
|
|
7410
7503
|
import path13 from "path";
|
|
7411
7504
|
import { fileURLToPath } from "url";
|
|
@@ -7422,7 +7515,7 @@ async function startPreviewServer(options) {
|
|
|
7422
7515
|
const app = express();
|
|
7423
7516
|
const previewClientDir = await resolvePreviewClientBuildDir();
|
|
7424
7517
|
app.disable("x-powered-by");
|
|
7425
|
-
app.use("/assets", express.static(options.assetDir));
|
|
7518
|
+
app.use("/assets", express.static(options.assetDir, { dotfiles: "allow" }));
|
|
7426
7519
|
if (previewClientDir) {
|
|
7427
7520
|
app.use(express.static(previewClientDir, { index: false }));
|
|
7428
7521
|
}
|
|
@@ -7456,7 +7549,7 @@ async function startPreviewServer(options) {
|
|
|
7456
7549
|
const assetPathParam = req.params.assetPath;
|
|
7457
7550
|
const rawAssetPath = Array.isArray(assetPathParam) ? assetPathParam.join("/") : assetPathParam ?? "";
|
|
7458
7551
|
const resolvedAssetPath = await resolveGenerationAssetPath(generationId, rawAssetPath, options.markdownOutputDir);
|
|
7459
|
-
res.sendFile(resolvedAssetPath);
|
|
7552
|
+
res.sendFile(resolvedAssetPath, { dotfiles: "allow" });
|
|
7460
7553
|
} catch (error) {
|
|
7461
7554
|
const message = error instanceof Error ? error.message : "Unknown error loading generation asset";
|
|
7462
7555
|
const status = error instanceof MissingArticleError ? 404 : 400;
|
|
@@ -7505,7 +7598,7 @@ async function startPreviewServer(options) {
|
|
|
7505
7598
|
if (options.watch) {
|
|
7506
7599
|
let html2;
|
|
7507
7600
|
try {
|
|
7508
|
-
html2 = await
|
|
7601
|
+
html2 = await readFile10(path13.join(previewClientDir, "index.html"), "utf8");
|
|
7509
7602
|
} catch {
|
|
7510
7603
|
res.status(200).type("html").send(
|
|
7511
7604
|
`<!doctype html><html><head><meta charset="utf-8"><title>Rebuilding\u2026</title><style>body{margin:0;display:flex;align-items:center;justify-content:center;height:100vh;font-family:sans-serif;background:#101820;color:#e0eaf0}p{font-size:15px;opacity:.7}</style></head><body><p>Rebuilding\u2026</p><script>const s=new EventSource('/api/__reload');s.onmessage=function(){location.reload()};</script></body></html>`
|
|
@@ -7569,7 +7662,7 @@ async function getArticleContent(generationId, markdownOutputDir) {
|
|
|
7569
7662
|
generation.outputs.map(async (output) => {
|
|
7570
7663
|
let markdown = "";
|
|
7571
7664
|
try {
|
|
7572
|
-
markdown = await
|
|
7665
|
+
markdown = await readFile10(output.sourcePath, "utf8");
|
|
7573
7666
|
} catch (error) {
|
|
7574
7667
|
if (isMissingFileError(error)) {
|
|
7575
7668
|
throw new MissingArticleError(`Generation "${generationId}" no longer exists.`);
|
|
@@ -7633,7 +7726,7 @@ async function renderArticleHtml(markdown, generationId, sourcePath) {
|
|
|
7633
7726
|
async function loadSavedLinks(markdownPath) {
|
|
7634
7727
|
const linksPath = resolveLinksPath(markdownPath);
|
|
7635
7728
|
try {
|
|
7636
|
-
const raw = await
|
|
7729
|
+
const raw = await readFile10(linksPath, "utf8");
|
|
7637
7730
|
const parsed = JSON.parse(raw);
|
|
7638
7731
|
if (!Array.isArray(parsed.links)) {
|
|
7639
7732
|
return [];
|
|
@@ -7659,7 +7752,7 @@ async function loadSavedLinks(markdownPath) {
|
|
|
7659
7752
|
async function loadSavedInteractions(generationDir) {
|
|
7660
7753
|
const interactionsPath = path13.join(generationDir, "model.interactions.json");
|
|
7661
7754
|
try {
|
|
7662
|
-
const raw = await
|
|
7755
|
+
const raw = await readFile10(interactionsPath, "utf8");
|
|
7663
7756
|
const parsed = JSON.parse(raw);
|
|
7664
7757
|
const llmCalls = Array.isArray(parsed.llmCalls) ? parsed.llmCalls.filter(isPreviewLlmInteraction) : [];
|
|
7665
7758
|
const t2iCalls = Array.isArray(parsed.t2iCalls) ? parsed.t2iCalls.filter(isPreviewT2IInteraction) : [];
|
|
@@ -7677,7 +7770,7 @@ async function loadSavedInteractions(generationDir) {
|
|
|
7677
7770
|
async function loadSavedAnalyticsSummary(generationDir) {
|
|
7678
7771
|
const analyticsPath = path13.join(generationDir, "generation.analytics.json");
|
|
7679
7772
|
try {
|
|
7680
|
-
const raw = await
|
|
7773
|
+
const raw = await readFile10(analyticsPath, "utf8");
|
|
7681
7774
|
const parsed = JSON.parse(raw);
|
|
7682
7775
|
const summary = parsed.summary;
|
|
7683
7776
|
if (!summary || typeof summary !== "object") {
|
|
@@ -7701,7 +7794,7 @@ async function loadSavedAnalyticsSummary(generationDir) {
|
|
|
7701
7794
|
async function loadSavedMetaJson(generationDir) {
|
|
7702
7795
|
const metaJsonPath = path13.join(generationDir, "meta.json");
|
|
7703
7796
|
try {
|
|
7704
|
-
const raw = await
|
|
7797
|
+
const raw = await readFile10(metaJsonPath, "utf8");
|
|
7705
7798
|
return JSON.parse(raw);
|
|
7706
7799
|
} catch {
|
|
7707
7800
|
return null;
|