seshat-scribe 0.9.2 → 3.0.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.
- package/README.md +47 -58
- package/dist/commands/check-due.d.ts +15 -0
- package/dist/commands/check-due.d.ts.map +1 -0
- package/dist/commands/check-due.js +53 -0
- package/dist/commands/check-due.js.map +1 -0
- package/dist/commands/generate.d.ts +4 -1
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/generate.js +120 -97
- package/dist/commands/generate.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +73 -338
- package/dist/commands/init.js.map +1 -1
- package/dist/config.d.ts +21 -179
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +43 -112
- package/dist/config.js.map +1 -1
- package/dist/core/analyzer.d.ts +1 -1
- package/dist/core/analyzer.d.ts.map +1 -1
- package/dist/core/analyzer.js +2 -115
- package/dist/core/analyzer.js.map +1 -1
- package/dist/core/artist.d.ts +1 -2
- package/dist/core/artist.d.ts.map +1 -1
- package/dist/core/artist.js +2 -5
- package/dist/core/artist.js.map +1 -1
- package/dist/core/planner.d.ts +2 -2
- package/dist/core/sanity.d.ts +36 -1
- package/dist/core/sanity.d.ts.map +1 -1
- package/dist/core/sanity.js +78 -2
- package/dist/core/sanity.js.map +1 -1
- package/dist/core/scheduler.d.ts +45 -0
- package/dist/core/scheduler.d.ts.map +1 -0
- package/dist/core/scheduler.js +136 -0
- package/dist/core/scheduler.js.map +1 -0
- package/dist/index.js +26 -3
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +52 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/package.json +7 -8
- package/dist/core/writer.d.ts +0 -7
- package/dist/core/writer.d.ts.map +0 -1
- package/dist/core/writer.js +0 -126
- package/dist/core/writer.js.map +0 -1
- package/dist/lib/detection.d.ts +0 -13
- package/dist/lib/detection.d.ts.map +0 -1
- package/dist/lib/detection.js +0 -158
- package/dist/lib/detection.js.map +0 -1
- package/dist/lib/frontmatter.d.ts +0 -28
- package/dist/lib/frontmatter.d.ts.map +0 -1
- package/dist/lib/frontmatter.js +0 -114
- package/dist/lib/frontmatter.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artist.d.ts","sourceRoot":"","sources":["../../src/core/artist.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"artist.d.ts","sourceRoot":"","sources":["../../src/core/artist.ts"],"names":[],"mappings":"AAoBA;;GAEG;AACH,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,CAwDjB"}
|
package/dist/core/artist.js
CHANGED
|
@@ -17,11 +17,8 @@ const STYLE_OVERLAYS = [
|
|
|
17
17
|
/**
|
|
18
18
|
* Generate an image using Gemini's Imagen 4.0 model
|
|
19
19
|
*/
|
|
20
|
-
export async function generateImage(
|
|
21
|
-
|
|
22
|
-
throw new Error('assetsDir is required for image generation');
|
|
23
|
-
}
|
|
24
|
-
const assetsPath = path.resolve(process.cwd(), config.assetsDir);
|
|
20
|
+
export async function generateImage(imagePrompt, slug, assetsDir) {
|
|
21
|
+
const assetsPath = path.resolve(process.cwd(), assetsDir);
|
|
25
22
|
const imagePath = path.join(assetsPath, `${slug}.png`);
|
|
26
23
|
// Ensure the assets directory exists
|
|
27
24
|
await fs.mkdir(assetsPath, { recursive: true });
|
package/dist/core/artist.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artist.js","sourceRoot":"","sources":["../../src/core/artist.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,aAAa,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAC1F,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"artist.js","sourceRoot":"","sources":["../../src/core/artist.ts"],"names":[],"mappings":"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"}
|
package/dist/core/planner.d.ts
CHANGED
|
@@ -11,15 +11,15 @@ export declare const BlogPlanSchema: z.ZodObject<{
|
|
|
11
11
|
tags: z.ZodArray<z.ZodString, "many">;
|
|
12
12
|
imagePrompt: z.ZodString;
|
|
13
13
|
}, "strip", z.ZodTypeAny, {
|
|
14
|
-
description: string;
|
|
15
14
|
title: string;
|
|
16
15
|
slug: string;
|
|
16
|
+
description: string;
|
|
17
17
|
tags: string[];
|
|
18
18
|
imagePrompt: string;
|
|
19
19
|
}, {
|
|
20
|
-
description: string;
|
|
21
20
|
title: string;
|
|
22
21
|
slug: string;
|
|
22
|
+
description: string;
|
|
23
23
|
tags: string[];
|
|
24
24
|
imagePrompt: string;
|
|
25
25
|
}>;
|
package/dist/core/sanity.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type SanityClient } from '@sanity/client';
|
|
2
2
|
import type { SeshatConfig } from '../config.js';
|
|
3
3
|
import type { BlogPlan } from './planner.js';
|
|
4
|
+
import type { ContentTopicDocument, SanityConnectionConfig } from '../types.js';
|
|
4
5
|
/**
|
|
5
6
|
* Get or create a Sanity client instance
|
|
6
7
|
*/
|
|
@@ -10,7 +11,7 @@ export declare function getSanityClient(config: SeshatConfig, options?: {
|
|
|
10
11
|
/**
|
|
11
12
|
* Upload an image file to Sanity assets
|
|
12
13
|
*/
|
|
13
|
-
export declare function uploadImageToSanity(client: SanityClient, imagePath: string
|
|
14
|
+
export declare function uploadImageToSanity(client: SanityClient, imagePath: string): Promise<{
|
|
14
15
|
_type: 'image';
|
|
15
16
|
asset: {
|
|
16
17
|
_type: 'reference';
|
|
@@ -34,4 +35,38 @@ export declare function uploadToSanity(config: SeshatConfig, plan: BlogPlan, por
|
|
|
34
35
|
documentId: string;
|
|
35
36
|
slug: string;
|
|
36
37
|
}>;
|
|
38
|
+
/**
|
|
39
|
+
* Create a Sanity client from connection config
|
|
40
|
+
*/
|
|
41
|
+
export declare function createSanityClientFromConfig(config: SanityConnectionConfig, options?: {
|
|
42
|
+
readOnly?: boolean;
|
|
43
|
+
}): SanityClient;
|
|
44
|
+
/**
|
|
45
|
+
* Fetch a single content topic from Sanity
|
|
46
|
+
* @param client - Sanity client instance
|
|
47
|
+
* @param topicId - Content topic document ID
|
|
48
|
+
* @returns Content topic document
|
|
49
|
+
*/
|
|
50
|
+
export declare function fetchContentTopic(client: SanityClient, topicId: string): Promise<ContentTopicDocument>;
|
|
51
|
+
/**
|
|
52
|
+
* Fetch all active content topics from Sanity
|
|
53
|
+
* @param client - Sanity client instance
|
|
54
|
+
* @returns Array of active content topic documents
|
|
55
|
+
*/
|
|
56
|
+
export declare function fetchActiveTopics(client: SanityClient): Promise<ContentTopicDocument[]>;
|
|
57
|
+
/**
|
|
58
|
+
* Update a content topic after successful generation
|
|
59
|
+
* @param client - Sanity client instance
|
|
60
|
+
* @param topicId - Content topic document ID
|
|
61
|
+
* @param postId - ID of the newly generated post
|
|
62
|
+
* @param nextRunTime - Calculated next run time
|
|
63
|
+
*/
|
|
64
|
+
export declare function updateTopicAfterGeneration(client: SanityClient, topicId: string, postId: string, nextRunTime: Date): Promise<void>;
|
|
65
|
+
/**
|
|
66
|
+
* Update a content topic with error information
|
|
67
|
+
* @param client - Sanity client instance
|
|
68
|
+
* @param topicId - Content topic document ID
|
|
69
|
+
* @param errorMessage - Error message to store
|
|
70
|
+
*/
|
|
71
|
+
export declare function updateTopicError(client: SanityClient, topicId: string, errorMessage: string): Promise<void>;
|
|
37
72
|
//# sourceMappingURL=sanity.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sanity.d.ts","sourceRoot":"","sources":["../../src/core/sanity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"sanity.d.ts","sourceRoot":"","sources":["../../src/core/sanity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,KAAK,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAEhF;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,YAAY,CAoBxG;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,YAAY,EACpB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE;QAAE,KAAK,EAAE,WAAW,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC,CAe1E;AAGD;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,QAAQ,EACd,gBAAgB,EAAE,GAAG,EAAE,EACvB,QAAQ,EAAE;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE;QAAE,KAAK,EAAE,WAAW,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GAAG,IAAI,EAChF,QAAQ,EAAE,IAAI,EACd,YAAY,GAAE,MAAe,GAC5B,OAAO,CAAC,GAAG,CAAC,CAqBd;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,QAAQ,EACd,gBAAgB,EAAE,GAAG,EAAE,EACvB,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,QAAQ,EAAE,IAAI,GACb,OAAO,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAwB/C;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,sBAAsB,EAC9B,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAO,GACnC,YAAY,CAcd;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,oBAAoB,CAAC,CAW/B;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAGjC;AAED;;;;;;GAMG;AACH,wBAAsB,0BAA0B,CAC9C,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,IAAI,GAChB,OAAO,CAAC,IAAI,CAAC,CAcf;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CAOf"}
|
package/dist/core/sanity.js
CHANGED
|
@@ -24,7 +24,7 @@ export function getSanityClient(config, options = {}) {
|
|
|
24
24
|
/**
|
|
25
25
|
* Upload an image file to Sanity assets
|
|
26
26
|
*/
|
|
27
|
-
export async function uploadImageToSanity(client, imagePath
|
|
27
|
+
export async function uploadImageToSanity(client, imagePath) {
|
|
28
28
|
const imageBuffer = await fs.readFile(imagePath);
|
|
29
29
|
// Upload to Sanity assets
|
|
30
30
|
const asset = await client.assets.upload('image', imageBuffer, {
|
|
@@ -69,7 +69,7 @@ export async function uploadToSanity(config, plan, portableTextBody, imagePath,
|
|
|
69
69
|
// Upload the image if provided
|
|
70
70
|
let imageRef = null;
|
|
71
71
|
if (imagePath) {
|
|
72
|
-
imageRef = await uploadImageToSanity(client, imagePath
|
|
72
|
+
imageRef = await uploadImageToSanity(client, imagePath);
|
|
73
73
|
}
|
|
74
74
|
// Create the post document
|
|
75
75
|
const documentType = config.sanity?.documentType || 'post';
|
|
@@ -79,4 +79,80 @@ export async function uploadToSanity(config, plan, portableTextBody, imagePath,
|
|
|
79
79
|
slug: plan.slug,
|
|
80
80
|
};
|
|
81
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* Create a Sanity client from connection config
|
|
84
|
+
*/
|
|
85
|
+
export function createSanityClientFromConfig(config, options = {}) {
|
|
86
|
+
const token = process.env.SANITY_WRITE_TOKEN;
|
|
87
|
+
if (!options.readOnly && !token) {
|
|
88
|
+
throw new Error('SANITY_WRITE_TOKEN environment variable is required for Sanity writes');
|
|
89
|
+
}
|
|
90
|
+
return createClient({
|
|
91
|
+
projectId: config.projectId,
|
|
92
|
+
dataset: config.dataset,
|
|
93
|
+
apiVersion: config.apiVersion || '2024-01-01',
|
|
94
|
+
token: token || undefined,
|
|
95
|
+
useCdn: options.readOnly,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Fetch a single content topic from Sanity
|
|
100
|
+
* @param client - Sanity client instance
|
|
101
|
+
* @param topicId - Content topic document ID
|
|
102
|
+
* @returns Content topic document
|
|
103
|
+
*/
|
|
104
|
+
export async function fetchContentTopic(client, topicId) {
|
|
105
|
+
const query = `*[_type == "contentTopic" && _id == $topicId][0]`;
|
|
106
|
+
const params = { topicId };
|
|
107
|
+
const topic = await client.fetch(query, params);
|
|
108
|
+
if (!topic) {
|
|
109
|
+
throw new Error(`Content topic not found: ${topicId}`);
|
|
110
|
+
}
|
|
111
|
+
return topic;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Fetch all active content topics from Sanity
|
|
115
|
+
* @param client - Sanity client instance
|
|
116
|
+
* @returns Array of active content topic documents
|
|
117
|
+
*/
|
|
118
|
+
export async function fetchActiveTopics(client) {
|
|
119
|
+
const query = `*[_type == "contentTopic" && active == true] | order(name asc)`;
|
|
120
|
+
return await client.fetch(query);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Update a content topic after successful generation
|
|
124
|
+
* @param client - Sanity client instance
|
|
125
|
+
* @param topicId - Content topic document ID
|
|
126
|
+
* @param postId - ID of the newly generated post
|
|
127
|
+
* @param nextRunTime - Calculated next run time
|
|
128
|
+
*/
|
|
129
|
+
export async function updateTopicAfterGeneration(client, topicId, postId, nextRunTime) {
|
|
130
|
+
await client
|
|
131
|
+
.patch(topicId)
|
|
132
|
+
.set({
|
|
133
|
+
lastGeneratedAt: new Date().toISOString(),
|
|
134
|
+
nextRunTime: nextRunTime.toISOString(),
|
|
135
|
+
lastGeneratedPostId: {
|
|
136
|
+
_type: 'reference',
|
|
137
|
+
_ref: postId,
|
|
138
|
+
},
|
|
139
|
+
})
|
|
140
|
+
.inc({ totalGenerated: 1 })
|
|
141
|
+
.unset(['lastError']) // Clear any previous errors
|
|
142
|
+
.commit();
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Update a content topic with error information
|
|
146
|
+
* @param client - Sanity client instance
|
|
147
|
+
* @param topicId - Content topic document ID
|
|
148
|
+
* @param errorMessage - Error message to store
|
|
149
|
+
*/
|
|
150
|
+
export async function updateTopicError(client, topicId, errorMessage) {
|
|
151
|
+
await client
|
|
152
|
+
.patch(topicId)
|
|
153
|
+
.set({
|
|
154
|
+
lastError: `${new Date().toISOString()}: ${errorMessage}`,
|
|
155
|
+
})
|
|
156
|
+
.commit();
|
|
157
|
+
}
|
|
82
158
|
//# sourceMappingURL=sanity.js.map
|
package/dist/core/sanity.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sanity.js","sourceRoot":"","sources":["../../src/core/sanity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAqB,MAAM,gBAAgB,CAAC;AACjE,OAAO,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"sanity.js","sourceRoot":"","sources":["../../src/core/sanity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAqB,MAAM,gBAAgB,CAAC;AACjE,OAAO,EAAE,MAAM,aAAa,CAAC;AAK7B;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,MAAoB,EAAE,UAAkC,EAAE;IACxF,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACrD,CAAC;IAED,4DAA4D;IAC5D,0CAA0C;IAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;IAE7C,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,CAAC,KAAK,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,wEAAwE,CAAC,CAAC;IAC5F,CAAC;IAED,OAAO,YAAY,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS;QAClC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO;QAC9B,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU,IAAI,YAAY;QACpD,KAAK,EAAE,KAAK,IAAI,SAAS;QACzB,MAAM,EAAE,OAAO,CAAC,QAAQ,EAAE,8BAA8B;KACzD,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAAoB,EACpB,SAAiB;IAEjB,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IAEjD,0BAA0B;IAC1B,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,WAAW,EAAE;QAC7D,QAAQ,EAAE,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,WAAW;KACpD,CAAC,CAAC;IAEH,OAAO;QACL,KAAK,EAAE,OAAO;QACd,KAAK,EAAE;YACL,KAAK,EAAE,WAAW;YAClB,IAAI,EAAE,KAAK,CAAC,GAAG;SAChB;KACF,CAAC;AACJ,CAAC;AAGD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,MAAoB,EACpB,IAAc,EACd,gBAAuB,EACvB,QAAgF,EAChF,QAAc,EACd,eAAuB,MAAM;IAE7B,MAAM,GAAG,GAAQ;QACf,KAAK,EAAE,YAAY;QACnB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,IAAI,EAAE;YACJ,KAAK,EAAE,MAAM;YACb,OAAO,EAAE,IAAI,CAAC,IAAI;SACnB;QACD,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,IAAI,EAAE,QAAQ,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,oBAAoB;QAChE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,SAAS;QAC9B,IAAI,EAAE,gBAAgB;KACvB,CAAC;IAEF,6CAA6C;IAC7C,IAAI,QAAQ,EAAE,CAAC;QACb,GAAG,CAAC,KAAK,GAAG,QAAQ,CAAC;QACrB,GAAG,CAAC,QAAQ,GAAG,oBAAoB,IAAI,CAAC,KAAK,EAAE,CAAC;IAClD,CAAC;IAED,OAAO,MAAM,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAoB,EACpB,IAAc,EACd,gBAAuB,EACvB,SAAwB,EACxB,QAAc;IAEd,MAAM,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAEvC,+BAA+B;IAC/B,IAAI,QAAQ,GAA2E,IAAI,CAAC;IAC5F,IAAI,SAAS,EAAE,CAAC;QACd,QAAQ,GAAG,MAAM,mBAAmB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAC1D,CAAC;IAED,2BAA2B;IAC3B,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,YAAY,IAAI,MAAM,CAAC;IAC3D,MAAM,MAAM,GAAG,MAAM,gBAAgB,CACnC,MAAM,EACN,IAAI,EACJ,gBAAgB,EAChB,QAAQ,EACR,QAAQ,EACR,YAAY,CACb,CAAC;IAEF,OAAO;QACL,UAAU,EAAE,MAAM,CAAC,GAAG;QACtB,IAAI,EAAE,IAAI,CAAC,IAAI;KAChB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,4BAA4B,CAC1C,MAA8B,EAC9B,UAAkC,EAAE;IAEpC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;IAE7C,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,CAAC,KAAK,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAC;IAC3F,CAAC;IAED,OAAO,YAAY,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,YAAY;QAC7C,KAAK,EAAE,KAAK,IAAI,SAAS;QACzB,MAAM,EAAE,OAAO,CAAC,QAAQ;KACzB,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAAoB,EACpB,OAAe;IAEf,MAAM,KAAK,GAAG,kDAAkD,CAAC;IACjE,MAAM,MAAM,GAAG,EAAE,OAAO,EAAE,CAAC;IAE3B,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,KAAK,CAAuB,KAAK,EAAE,MAAM,CAAC,CAAC;IAEtE,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,4BAA4B,OAAO,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAAoB;IAEpB,MAAM,KAAK,GAAG,gEAAgE,CAAC;IAC/E,OAAO,MAAM,MAAM,CAAC,KAAK,CAAyB,KAAK,CAAC,CAAC;AAC3D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,MAAoB,EACpB,OAAe,EACf,MAAc,EACd,WAAiB;IAEjB,MAAM,MAAM;SACT,KAAK,CAAC,OAAO,CAAC;SACd,GAAG,CAAC;QACH,eAAe,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACzC,WAAW,EAAE,WAAW,CAAC,WAAW,EAAE;QACtC,mBAAmB,EAAE;YACnB,KAAK,EAAE,WAAW;YAClB,IAAI,EAAE,MAAM;SACb;KACF,CAAC;SACD,GAAG,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,CAAC;SAC1B,KAAK,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,4BAA4B;SACjD,MAAM,EAAE,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,MAAoB,EACpB,OAAe,EACf,YAAoB;IAEpB,MAAM,MAAM;SACT,KAAK,CAAC,OAAO,CAAC;SACd,GAAG,CAAC;QACH,SAAS,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,YAAY,EAAE;KAC1D,CAAC;SACD,MAAM,EAAE,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scheduler module for parsing cron expressions and determining topic due status
|
|
3
|
+
*/
|
|
4
|
+
import type { ContentTopicDocument, ScheduleInfo } from '../types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Parse a cron expression and return the parser instance
|
|
7
|
+
* @param expression - Cron expression (e.g., "0 9 * * 1" for Mondays at 9 AM)
|
|
8
|
+
* @returns Cron parser instance
|
|
9
|
+
* @throws Error if expression is invalid
|
|
10
|
+
*/
|
|
11
|
+
export declare function parseCron(expression: string): import("cron-parser").CronExpression<false>;
|
|
12
|
+
/**
|
|
13
|
+
* Calculate the next run time from a given starting point
|
|
14
|
+
* @param cronExpression - Cron expression
|
|
15
|
+
* @param from - Starting date (defaults to now)
|
|
16
|
+
* @returns Next scheduled run time
|
|
17
|
+
*/
|
|
18
|
+
export declare function calculateNextRun(cronExpression: string, from?: Date): Date;
|
|
19
|
+
/**
|
|
20
|
+
* Determine if a topic is due for generation based on its schedule
|
|
21
|
+
*
|
|
22
|
+
* Logic:
|
|
23
|
+
* - If never generated (lastGenerated is null), topic is due
|
|
24
|
+
* - Calculate next run time from last generation
|
|
25
|
+
* - If next run time is in the past or now, topic is due
|
|
26
|
+
*
|
|
27
|
+
* @param cronSchedule - Cron expression for the topic
|
|
28
|
+
* @param lastGenerated - Last generation timestamp (null if never generated)
|
|
29
|
+
* @param now - Current time (defaults to now, useful for testing)
|
|
30
|
+
* @returns true if topic should generate now
|
|
31
|
+
*/
|
|
32
|
+
export declare function isTopicDue(cronSchedule: string, lastGenerated: Date | null, now?: Date): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Get comprehensive schedule information for a topic
|
|
35
|
+
* @param topic - Content topic document from Sanity
|
|
36
|
+
* @returns Schedule information including due status
|
|
37
|
+
*/
|
|
38
|
+
export declare function getTopicScheduleInfo(topic: ContentTopicDocument): ScheduleInfo;
|
|
39
|
+
/**
|
|
40
|
+
* Format a cron expression into human-readable text
|
|
41
|
+
* @param cronExpression - Cron expression to describe
|
|
42
|
+
* @returns Human-readable description (e.g., "Every day at 9:00 AM")
|
|
43
|
+
*/
|
|
44
|
+
export declare function describeCronSchedule(cronExpression: string): string;
|
|
45
|
+
//# sourceMappingURL=scheduler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../src/core/scheduler.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEtE;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,+CAU3C;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,GAAE,IAAiB,GAAG,IAAI,CAMtF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CACxB,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,IAAI,GAAG,IAAI,EAC1B,GAAG,GAAE,IAAiB,GACrB,OAAO,CAiBT;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,oBAAoB,GAAG,YAAY,CA2B9E;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAoCnE"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scheduler module for parsing cron expressions and determining topic due status
|
|
3
|
+
*/
|
|
4
|
+
import { parseExpression } from 'cron-parser';
|
|
5
|
+
/**
|
|
6
|
+
* Parse a cron expression and return the parser instance
|
|
7
|
+
* @param expression - Cron expression (e.g., "0 9 * * 1" for Mondays at 9 AM)
|
|
8
|
+
* @returns Cron parser instance
|
|
9
|
+
* @throws Error if expression is invalid
|
|
10
|
+
*/
|
|
11
|
+
export function parseCron(expression) {
|
|
12
|
+
try {
|
|
13
|
+
return parseExpression(expression, {
|
|
14
|
+
utc: true, // Always use UTC for consistency
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
throw new Error(`Invalid cron expression "${expression}": ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Calculate the next run time from a given starting point
|
|
23
|
+
* @param cronExpression - Cron expression
|
|
24
|
+
* @param from - Starting date (defaults to now)
|
|
25
|
+
* @returns Next scheduled run time
|
|
26
|
+
*/
|
|
27
|
+
export function calculateNextRun(cronExpression, from = new Date()) {
|
|
28
|
+
const interval = parseExpression(cronExpression, {
|
|
29
|
+
currentDate: from,
|
|
30
|
+
utc: true,
|
|
31
|
+
});
|
|
32
|
+
return interval.next().toDate();
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Determine if a topic is due for generation based on its schedule
|
|
36
|
+
*
|
|
37
|
+
* Logic:
|
|
38
|
+
* - If never generated (lastGenerated is null), topic is due
|
|
39
|
+
* - Calculate next run time from last generation
|
|
40
|
+
* - If next run time is in the past or now, topic is due
|
|
41
|
+
*
|
|
42
|
+
* @param cronSchedule - Cron expression for the topic
|
|
43
|
+
* @param lastGenerated - Last generation timestamp (null if never generated)
|
|
44
|
+
* @param now - Current time (defaults to now, useful for testing)
|
|
45
|
+
* @returns true if topic should generate now
|
|
46
|
+
*/
|
|
47
|
+
export function isTopicDue(cronSchedule, lastGenerated, now = new Date()) {
|
|
48
|
+
// If never generated, it's due
|
|
49
|
+
if (!lastGenerated) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
// Calculate when the next run should have been, based on last generation
|
|
54
|
+
const nextRun = calculateNextRun(cronSchedule, lastGenerated);
|
|
55
|
+
// If next run time is in the past or now, it's due
|
|
56
|
+
return nextRun <= now;
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
// If cron expression is invalid, log warning but don't throw
|
|
60
|
+
console.warn(`Invalid cron schedule for topic: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Get comprehensive schedule information for a topic
|
|
66
|
+
* @param topic - Content topic document from Sanity
|
|
67
|
+
* @returns Schedule information including due status
|
|
68
|
+
*/
|
|
69
|
+
export function getTopicScheduleInfo(topic) {
|
|
70
|
+
const lastRun = topic.lastGeneratedAt ? new Date(topic.lastGeneratedAt) : null;
|
|
71
|
+
let nextRun = null;
|
|
72
|
+
let isDue = false;
|
|
73
|
+
if (topic.active) {
|
|
74
|
+
try {
|
|
75
|
+
if (lastRun) {
|
|
76
|
+
nextRun = calculateNextRun(topic.cronSchedule, lastRun);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
// If never run, next run is "now" (first available time)
|
|
80
|
+
nextRun = calculateNextRun(topic.cronSchedule, new Date());
|
|
81
|
+
}
|
|
82
|
+
isDue = isTopicDue(topic.cronSchedule, lastRun);
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
// Invalid cron, schedule info unavailable
|
|
86
|
+
console.warn(`Cannot calculate schedule for topic ${topic.name}: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
isActive: topic.active,
|
|
91
|
+
lastRun,
|
|
92
|
+
nextRun,
|
|
93
|
+
isDue,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Format a cron expression into human-readable text
|
|
98
|
+
* @param cronExpression - Cron expression to describe
|
|
99
|
+
* @returns Human-readable description (e.g., "Every day at 9:00 AM")
|
|
100
|
+
*/
|
|
101
|
+
export function describeCronSchedule(cronExpression) {
|
|
102
|
+
try {
|
|
103
|
+
const interval = parseCron(cronExpression);
|
|
104
|
+
// Get next few occurrences to infer pattern
|
|
105
|
+
const next1 = interval.next().toDate();
|
|
106
|
+
const next2 = interval.next().toDate();
|
|
107
|
+
const next3 = interval.next().toDate();
|
|
108
|
+
const timeDiff1 = next2.getTime() - next1.getTime();
|
|
109
|
+
const timeDiff2 = next3.getTime() - next2.getTime();
|
|
110
|
+
// Check if intervals are consistent
|
|
111
|
+
if (Math.abs(timeDiff1 - timeDiff2) < 1000) {
|
|
112
|
+
const hours = Math.floor(timeDiff1 / (1000 * 60 * 60));
|
|
113
|
+
const days = Math.floor(hours / 24);
|
|
114
|
+
const timeStr = next1.toISOString().slice(11, 16);
|
|
115
|
+
if (days === 1) {
|
|
116
|
+
return `Every day at ${timeStr} UTC`;
|
|
117
|
+
}
|
|
118
|
+
else if (days === 7) {
|
|
119
|
+
const dayName = next1.toLocaleDateString('en-US', { weekday: 'long', timeZone: 'UTC' });
|
|
120
|
+
return `Every ${dayName} at ${timeStr} UTC`;
|
|
121
|
+
}
|
|
122
|
+
else if (hours < 24) {
|
|
123
|
+
return `Every ${hours} hour${hours > 1 ? 's' : ''}`;
|
|
124
|
+
}
|
|
125
|
+
else if (days > 1 && days < 7) {
|
|
126
|
+
return `Every ${days} days at ${timeStr} UTC`;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// Fallback to showing next run time
|
|
130
|
+
return `Next: ${next1.toISOString().replace('T', ' ').slice(0, 16)} UTC`;
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
return `Invalid schedule: ${cronExpression}`;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=scheduler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/core/scheduler.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -4,13 +4,14 @@ import { printHeader } from './lib/output.js';
|
|
|
4
4
|
import { init } from './commands/init.js';
|
|
5
5
|
import { generate } from './commands/generate.js';
|
|
6
6
|
import { setupWorkflow } from './commands/setup-workflow.js';
|
|
7
|
+
import { checkDueTopics } from './commands/check-due.js';
|
|
7
8
|
const program = new Command();
|
|
8
9
|
// Print the Seshat header
|
|
9
10
|
printHeader();
|
|
10
11
|
program
|
|
11
12
|
.name('seshat')
|
|
12
|
-
.description('
|
|
13
|
-
.version('
|
|
13
|
+
.description('AI-powered content generation for Sanity CMS')
|
|
14
|
+
.version('2.0.0');
|
|
14
15
|
program
|
|
15
16
|
.command('init')
|
|
16
17
|
.description('Initialize Seshat configuration in the current directory')
|
|
@@ -27,7 +28,10 @@ program
|
|
|
27
28
|
.command('write')
|
|
28
29
|
.description('Generate a new blog post with AI')
|
|
29
30
|
.option('--dry-run', 'Preview the content without saving files')
|
|
30
|
-
.option('-t, --topic <topic>', 'Override the topic from config for this post')
|
|
31
|
+
.option('-t, --topic <topic>', 'Override the topic from config for this post (file-based config only)')
|
|
32
|
+
.option('--topic-id <id>', 'Sanity contentTopic document ID to generate from')
|
|
33
|
+
.option('--sanity-project <projectId>', 'Sanity project ID (required with --topic-id)')
|
|
34
|
+
.option('--sanity-dataset <dataset>', 'Sanity dataset name (required with --topic-id)')
|
|
31
35
|
.action(async (options) => {
|
|
32
36
|
try {
|
|
33
37
|
await generate(options);
|
|
@@ -37,6 +41,25 @@ program
|
|
|
37
41
|
process.exit(1);
|
|
38
42
|
}
|
|
39
43
|
});
|
|
44
|
+
program
|
|
45
|
+
.command('check-due')
|
|
46
|
+
.description('Check which content topics are due for generation based on their schedules')
|
|
47
|
+
.requiredOption('--sanity-project <projectId>', 'Sanity project ID')
|
|
48
|
+
.requiredOption('--sanity-dataset <dataset>', 'Sanity dataset name')
|
|
49
|
+
.option('--json', 'Output topic IDs as JSON array (for GitHub Actions)')
|
|
50
|
+
.action(async (options) => {
|
|
51
|
+
try {
|
|
52
|
+
const dueTopics = await checkDueTopics(options);
|
|
53
|
+
// If JSON output requested, print the array
|
|
54
|
+
if (options.json) {
|
|
55
|
+
console.log(JSON.stringify(dueTopics));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
console.error('Error:', err instanceof Error ? err.message : 'Unknown error');
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
40
63
|
program
|
|
41
64
|
.command('setup-workflow')
|
|
42
65
|
.description('Create or update .github/workflows/seshat.yml from seshat.config.json (uses schedule or default daily 9 UTC)')
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript type definitions for Seshat
|
|
3
|
+
*/
|
|
4
|
+
import type { GenerationConfig } from './config.js';
|
|
5
|
+
/**
|
|
6
|
+
* Content Topic document type from Sanity
|
|
7
|
+
* Represents a topic configuration for scheduled content generation
|
|
8
|
+
*/
|
|
9
|
+
export interface ContentTopicDocument {
|
|
10
|
+
_id: string;
|
|
11
|
+
_type: 'contentTopic';
|
|
12
|
+
_createdAt: string;
|
|
13
|
+
_updatedAt: string;
|
|
14
|
+
_rev: string;
|
|
15
|
+
name: string;
|
|
16
|
+
description?: string;
|
|
17
|
+
active: boolean;
|
|
18
|
+
topic: string;
|
|
19
|
+
tone: string;
|
|
20
|
+
cronSchedule: string;
|
|
21
|
+
nextRunTime?: string;
|
|
22
|
+
lastGeneratedAt?: string;
|
|
23
|
+
generation?: GenerationConfig;
|
|
24
|
+
sanityOverride?: {
|
|
25
|
+
documentType?: string;
|
|
26
|
+
imageFormat?: 'png' | 'jpg' | 'svg';
|
|
27
|
+
};
|
|
28
|
+
totalGenerated: number;
|
|
29
|
+
lastError?: string;
|
|
30
|
+
lastGeneratedPostId?: {
|
|
31
|
+
_type: 'reference';
|
|
32
|
+
_ref: string;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Schedule information for a topic
|
|
37
|
+
*/
|
|
38
|
+
export interface ScheduleInfo {
|
|
39
|
+
isActive: boolean;
|
|
40
|
+
lastRun: Date | null;
|
|
41
|
+
nextRun: Date | null;
|
|
42
|
+
isDue: boolean;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Configuration for Sanity connection
|
|
46
|
+
*/
|
|
47
|
+
export interface SanityConnectionConfig {
|
|
48
|
+
projectId: string;
|
|
49
|
+
dataset: string;
|
|
50
|
+
apiVersion?: string;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAgB,MAAM,aAAa,CAAC;AAElE;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,cAAc,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IAGb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;IAGhB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IAGb,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IAGzB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAG9B,cAAc,CAAC,EAAE;QACf,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,WAAW,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;KACrC,CAAC;IAGF,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mBAAmB,CAAC,EAAE;QACpB,KAAK,EAAE,WAAW,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,IAAI,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,IAAI,GAAG,IAAI,CAAC;IACrB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "seshat-scribe",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
|
+
"description": "AI-powered blog content generation for Sanity CMS using Google Gemini",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"bin": {
|
|
@@ -22,13 +22,12 @@
|
|
|
22
22
|
"ai",
|
|
23
23
|
"gemini",
|
|
24
24
|
"automation",
|
|
25
|
-
"mdx",
|
|
26
25
|
"content-generation",
|
|
27
26
|
"cli",
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
27
|
+
"sanity",
|
|
28
|
+
"cms",
|
|
29
|
+
"headless-cms",
|
|
30
|
+
"static-site"
|
|
32
31
|
],
|
|
33
32
|
"author": "Loke",
|
|
34
33
|
"repository": {
|
|
@@ -51,8 +50,8 @@
|
|
|
51
50
|
"@sanity/client": "^7.14.0",
|
|
52
51
|
"chalk": "^5.3.0",
|
|
53
52
|
"commander": "^12.1.0",
|
|
53
|
+
"cron-parser": "^4.9.0",
|
|
54
54
|
"dotenv": "^16.4.7",
|
|
55
|
-
"gray-matter": "^4.0.3",
|
|
56
55
|
"ora": "^8.1.1",
|
|
57
56
|
"zod": "^3.24.1"
|
|
58
57
|
},
|
package/dist/core/writer.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { BlogPlan } from './planner.js';
|
|
2
|
-
import type { SeshatConfig } from '../config.js';
|
|
3
|
-
/**
|
|
4
|
-
* Use Gemini to write a complete MDX blog post
|
|
5
|
-
*/
|
|
6
|
-
export declare function writeBlogPost(config: SeshatConfig, plan: BlogPlan, postDate?: Date, imagePath?: string | null): Promise<string>;
|
|
7
|
-
//# sourceMappingURL=writer.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"writer.d.ts","sourceRoot":"","sources":["../../src/core/writer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAmBjD;;GAEG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,QAAQ,EACd,QAAQ,GAAE,IAAiB,EAC3B,SAAS,GAAE,MAAM,GAAG,IAA0B,GAC7C,OAAO,CAAC,MAAM,CAAC,CAoHjB"}
|