xhs-operator 1.0.0-beta.1
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 +100 -0
- package/dist/actions/account.d.ts +59 -0
- package/dist/actions/account.d.ts.map +1 -0
- package/dist/actions/account.js +142 -0
- package/dist/actions/account.js.map +1 -0
- package/dist/actions/interact.d.ts +37 -0
- package/dist/actions/interact.d.ts.map +1 -0
- package/dist/actions/interact.js +205 -0
- package/dist/actions/interact.js.map +1 -0
- package/dist/actions/publish.d.ts +18 -0
- package/dist/actions/publish.d.ts.map +1 -0
- package/dist/actions/publish.js +135 -0
- package/dist/actions/publish.js.map +1 -0
- package/dist/actions/scrape.d.ts +21 -0
- package/dist/actions/scrape.d.ts.map +1 -0
- package/dist/actions/scrape.js +145 -0
- package/dist/actions/scrape.js.map +1 -0
- package/dist/agents/copywriter.d.ts +21 -0
- package/dist/agents/copywriter.d.ts.map +1 -0
- package/dist/agents/copywriter.js +115 -0
- package/dist/agents/copywriter.js.map +1 -0
- package/dist/agents/image-composer.d.ts +26 -0
- package/dist/agents/image-composer.d.ts.map +1 -0
- package/dist/agents/image-composer.js +103 -0
- package/dist/agents/image-composer.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +204 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin.d.ts +61 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +182 -0
- package/dist/plugin.js.map +1 -0
- package/dist/risk/behavior-humanizer.d.ts +30 -0
- package/dist/risk/behavior-humanizer.d.ts.map +1 -0
- package/dist/risk/behavior-humanizer.js +105 -0
- package/dist/risk/behavior-humanizer.js.map +1 -0
- package/dist/risk/fingerprint-guard.d.ts +23 -0
- package/dist/risk/fingerprint-guard.d.ts.map +1 -0
- package/dist/risk/fingerprint-guard.js +127 -0
- package/dist/risk/fingerprint-guard.js.map +1 -0
- package/dist/risk/rate-guard.d.ts +33 -0
- package/dist/risk/rate-guard.d.ts.map +1 -0
- package/dist/risk/rate-guard.js +104 -0
- package/dist/risk/rate-guard.js.map +1 -0
- package/dist/runtime/standalone.d.ts +15 -0
- package/dist/runtime/standalone.d.ts.map +1 -0
- package/dist/runtime/standalone.js +199 -0
- package/dist/runtime/standalone.js.map +1 -0
- package/dist/scheduler.d.ts +42 -0
- package/dist/scheduler.d.ts.map +1 -0
- package/dist/scheduler.js +139 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/storage/database.d.ts +23 -0
- package/dist/storage/database.d.ts.map +1 -0
- package/dist/storage/database.js +142 -0
- package/dist/storage/database.js.map +1 -0
- package/dist/storage/kv-store.d.ts +13 -0
- package/dist/storage/kv-store.d.ts.map +1 -0
- package/dist/storage/kv-store.js +60 -0
- package/dist/storage/kv-store.js.map +1 -0
- package/dist/types/index.d.ts +320 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/helpers.d.ts +63 -0
- package/dist/utils/helpers.d.ts.map +1 -0
- package/dist/utils/helpers.js +115 -0
- package/dist/utils/helpers.js.map +1 -0
- package/dist/workflows/content-campaign.d.ts +58 -0
- package/dist/workflows/content-campaign.d.ts.map +1 -0
- package/dist/workflows/content-campaign.js +155 -0
- package/dist/workflows/content-campaign.js.map +1 -0
- package/dist/workflows/daily-operate.d.ts +36 -0
- package/dist/workflows/daily-operate.d.ts.map +1 -0
- package/dist/workflows/daily-operate.js +222 -0
- package/dist/workflows/daily-operate.js.map +1 -0
- package/manifest.json +29 -0
- package/package.json +66 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// Publish Action — Note publishing to XHS Creator Center
|
|
3
|
+
// ============================================================
|
|
4
|
+
import { BehaviorHumanizer } from '../risk/behavior-humanizer.js';
|
|
5
|
+
import { QuotaExceededError } from '../risk/rate-guard.js';
|
|
6
|
+
import { randomBetween } from '../utils/helpers.js';
|
|
7
|
+
const CREATOR_PUBLISH_URL = 'https://creator.xiaohongshu.com/publish/publish';
|
|
8
|
+
export class PublishAction {
|
|
9
|
+
runtime;
|
|
10
|
+
fingerprintGuard;
|
|
11
|
+
rateGuard;
|
|
12
|
+
humanizer;
|
|
13
|
+
constructor(runtime, fingerprintGuard, rateGuard) {
|
|
14
|
+
this.runtime = runtime;
|
|
15
|
+
this.fingerprintGuard = fingerprintGuard;
|
|
16
|
+
this.rateGuard = rateGuard;
|
|
17
|
+
this.humanizer = new BehaviorHumanizer();
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Publish a note with images to XHS.
|
|
21
|
+
*/
|
|
22
|
+
async publishNote(account, note, images) {
|
|
23
|
+
// Check publish quota
|
|
24
|
+
const quota = this.rateGuard.checkQuota(account.id, 'publish');
|
|
25
|
+
if (!quota.allowed) {
|
|
26
|
+
throw new QuotaExceededError(quota.resetAt);
|
|
27
|
+
}
|
|
28
|
+
const page = await this.runtime.browser.newPage({
|
|
29
|
+
cookieFile: account.sessionFile,
|
|
30
|
+
proxy: account.proxy,
|
|
31
|
+
});
|
|
32
|
+
try {
|
|
33
|
+
// Apply fingerprint
|
|
34
|
+
await this.fingerprintGuard.applyFingerprint(page, account.id);
|
|
35
|
+
// Navigate to creator center
|
|
36
|
+
await page.navigate(CREATOR_PUBLISH_URL);
|
|
37
|
+
await this.humanizer.waitRandom(2000, 4000);
|
|
38
|
+
// Upload images
|
|
39
|
+
await this.uploadImages(page, images);
|
|
40
|
+
// Fill title
|
|
41
|
+
await this.humanizer.typeHuman(page, '#title-input', note.title, {
|
|
42
|
+
wpm: randomBetween(60, 120),
|
|
43
|
+
});
|
|
44
|
+
await this.humanizer.waitRandom(500, 1000);
|
|
45
|
+
// Fill body
|
|
46
|
+
await this.humanizer.typeHuman(page, '#content-textarea', note.body, {
|
|
47
|
+
wpm: randomBetween(50, 100),
|
|
48
|
+
});
|
|
49
|
+
await this.humanizer.waitRandom(800, 1500);
|
|
50
|
+
// Add hashtags
|
|
51
|
+
for (const tag of note.hashtags) {
|
|
52
|
+
await this.addHashtag(page, tag);
|
|
53
|
+
await this.humanizer.waitRandom(300, 800);
|
|
54
|
+
}
|
|
55
|
+
// Preview and submit
|
|
56
|
+
await this.humanizer.waitRandom(1000, 2000);
|
|
57
|
+
await this.humanizer.clickNatural(page, '[data-testid="publish-btn"]');
|
|
58
|
+
// Wait for publish confirmation
|
|
59
|
+
const result = await this.waitForPublishSuccess(page);
|
|
60
|
+
// Record action
|
|
61
|
+
this.rateGuard.recordAction(account.id, 'publish', result.noteId);
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
this.rateGuard.recordFailure(account.id);
|
|
66
|
+
return {
|
|
67
|
+
success: false,
|
|
68
|
+
error: error instanceof Error ? error.message : String(error),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
await page.close();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async uploadImages(page, images) {
|
|
76
|
+
for (const [idx, _img] of images.entries()) {
|
|
77
|
+
// Find upload input and trigger file selection
|
|
78
|
+
// In a real implementation, this would use the file chooser API
|
|
79
|
+
await page.waitForSelector('input[type="file"]', { timeout: 10000 });
|
|
80
|
+
// Simulated: openclaw browser API handles file buffer upload
|
|
81
|
+
await page.evaluate(`
|
|
82
|
+
document.querySelector('input[type="file"]').dispatchEvent(new Event('change'));
|
|
83
|
+
`);
|
|
84
|
+
if (idx < images.length - 1) {
|
|
85
|
+
await this.humanizer.waitRandom(800, 1500);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Wait for upload completion
|
|
89
|
+
await this.humanizer.waitRandom(2000, 4000);
|
|
90
|
+
}
|
|
91
|
+
async addHashtag(page, tag) {
|
|
92
|
+
// Type # to trigger hashtag picker
|
|
93
|
+
await page.keyboard.type('#');
|
|
94
|
+
await this.humanizer.waitRandom(200, 500);
|
|
95
|
+
// Type tag name
|
|
96
|
+
for (const char of tag) {
|
|
97
|
+
await page.keyboard.type(char);
|
|
98
|
+
await this.humanizer.waitRandom(50, 150);
|
|
99
|
+
}
|
|
100
|
+
await this.humanizer.waitRandom(500, 1000);
|
|
101
|
+
// Select first suggestion
|
|
102
|
+
const suggestion = await page.$('.hashtag-suggestion-item');
|
|
103
|
+
if (suggestion) {
|
|
104
|
+
await suggestion.click();
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
await page.keyboard.press('Enter');
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
async waitForPublishSuccess(page, timeoutMs = 30000) {
|
|
111
|
+
const start = Date.now();
|
|
112
|
+
while (Date.now() - start < timeoutMs) {
|
|
113
|
+
const url = page.url();
|
|
114
|
+
// Check for success redirect
|
|
115
|
+
if (url.includes('/publish/success') || url.includes('noteId=')) {
|
|
116
|
+
const noteIdMatch = url.match(/noteId=([a-f0-9]+)/);
|
|
117
|
+
return {
|
|
118
|
+
success: true,
|
|
119
|
+
noteId: noteIdMatch?.[1],
|
|
120
|
+
url: noteIdMatch ? `https://www.xiaohongshu.com/explore/${noteIdMatch[1]}` : undefined,
|
|
121
|
+
publishedAt: new Date(),
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
// Check for error messages
|
|
125
|
+
const errorEl = await page.$('.publish-error, .error-message');
|
|
126
|
+
if (errorEl) {
|
|
127
|
+
const errorText = await errorEl.textContent();
|
|
128
|
+
return { success: false, error: errorText || 'Unknown publish error' };
|
|
129
|
+
}
|
|
130
|
+
await this.humanizer.waitRandom(500, 1000);
|
|
131
|
+
}
|
|
132
|
+
return { success: false, error: 'Publish timeout' };
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=publish.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish.js","sourceRoot":"","sources":["../../src/actions/publish.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { OpenClawRuntime, Account, AccountMetrics, NoteMetric } from '../types/index.js';
|
|
2
|
+
import { FingerprintGuard } from '../risk/fingerprint-guard.js';
|
|
3
|
+
export declare class ScrapeAction {
|
|
4
|
+
private runtime;
|
|
5
|
+
private fingerprintGuard;
|
|
6
|
+
private humanizer;
|
|
7
|
+
constructor(runtime: OpenClawRuntime, fingerprintGuard: FingerprintGuard);
|
|
8
|
+
/**
|
|
9
|
+
* Scrape complete account metrics from the Creator Center.
|
|
10
|
+
*/
|
|
11
|
+
scrapeAccountMetrics(account: Account): Promise<AccountMetrics>;
|
|
12
|
+
/**
|
|
13
|
+
* Scrape a single note's detailed metrics.
|
|
14
|
+
*/
|
|
15
|
+
scrapeNoteDetail(account: Account, noteId: string): Promise<NoteMetric | null>;
|
|
16
|
+
private scrapeOverview;
|
|
17
|
+
private scrapeNotesList;
|
|
18
|
+
private extractNoteMetricFromCard;
|
|
19
|
+
private scrapeNoteMetric;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=scrape.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scrape.d.ts","sourceRoot":"","sources":["../../src/actions/scrape.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,eAAe,EACf,OAAO,EACP,cAAc,EACd,UAAU,EAEX,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAMhE,qBAAa,YAAY;IAIrB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,gBAAgB;IAJ1B,OAAO,CAAC,SAAS,CAAoB;gBAG3B,OAAO,EAAE,eAAe,EACxB,gBAAgB,EAAE,gBAAgB;IAK5C;;OAEG;IACG,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC;IAgCrE;;OAEG;IACG,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;YAiBtE,cAAc;YAiBd,eAAe;YAsBf,yBAAyB;YAyBzB,gBAAgB;CA0B/B"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// Scrape Action — Data collection from XHS Creator Center
|
|
3
|
+
// ============================================================
|
|
4
|
+
import { BehaviorHumanizer } from '../risk/behavior-humanizer.js';
|
|
5
|
+
import { sanitizePageContent } from '../utils/helpers.js';
|
|
6
|
+
const CREATOR_HOME_URL = 'https://creator.xiaohongshu.com/creator/home';
|
|
7
|
+
const CREATOR_NOTES_URL = 'https://creator.xiaohongshu.com/creator/notes';
|
|
8
|
+
export class ScrapeAction {
|
|
9
|
+
runtime;
|
|
10
|
+
fingerprintGuard;
|
|
11
|
+
humanizer;
|
|
12
|
+
constructor(runtime, fingerprintGuard) {
|
|
13
|
+
this.runtime = runtime;
|
|
14
|
+
this.fingerprintGuard = fingerprintGuard;
|
|
15
|
+
this.humanizer = new BehaviorHumanizer();
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Scrape complete account metrics from the Creator Center.
|
|
19
|
+
*/
|
|
20
|
+
async scrapeAccountMetrics(account) {
|
|
21
|
+
const page = await this.runtime.browser.newPage({
|
|
22
|
+
cookieFile: account.sessionFile,
|
|
23
|
+
proxy: account.proxy,
|
|
24
|
+
});
|
|
25
|
+
try {
|
|
26
|
+
await this.fingerprintGuard.applyFingerprint(page, account.id);
|
|
27
|
+
// Navigate to creator home
|
|
28
|
+
await page.navigate(CREATOR_HOME_URL);
|
|
29
|
+
await this.humanizer.waitRandom(2000, 4000);
|
|
30
|
+
// Scrape overview metrics
|
|
31
|
+
const overview = await this.scrapeOverview(page);
|
|
32
|
+
// Navigate to notes list
|
|
33
|
+
await page.navigate(CREATOR_NOTES_URL);
|
|
34
|
+
await this.humanizer.waitRandom(2000, 4000);
|
|
35
|
+
// Scrape individual note metrics
|
|
36
|
+
const notes = await this.scrapeNotesList(page);
|
|
37
|
+
return {
|
|
38
|
+
...overview,
|
|
39
|
+
notes,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
await page.close();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Scrape a single note's detailed metrics.
|
|
48
|
+
*/
|
|
49
|
+
async scrapeNoteDetail(account, noteId) {
|
|
50
|
+
const page = await this.runtime.browser.newPage({
|
|
51
|
+
cookieFile: account.sessionFile,
|
|
52
|
+
proxy: account.proxy,
|
|
53
|
+
});
|
|
54
|
+
try {
|
|
55
|
+
await this.fingerprintGuard.applyFingerprint(page, account.id);
|
|
56
|
+
await page.navigate(`https://creator.xiaohongshu.com/creator/notes/${noteId}`);
|
|
57
|
+
await this.humanizer.waitRandom(2000, 4000);
|
|
58
|
+
return this.scrapeNoteMetric(page, noteId);
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
await page.close();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async scrapeOverview(page) {
|
|
65
|
+
// Try to extract from the page DOM
|
|
66
|
+
const extractNumber = async (selector) => {
|
|
67
|
+
const el = await page.$(selector);
|
|
68
|
+
if (!el)
|
|
69
|
+
return 0;
|
|
70
|
+
const text = sanitizePageContent((await el.textContent()) || '0');
|
|
71
|
+
return parseInt(text.replace(/[^0-9]/g, ''), 10) || 0;
|
|
72
|
+
};
|
|
73
|
+
return {
|
|
74
|
+
fans: await extractNumber('.fans-count, [data-type="fans"]'),
|
|
75
|
+
follows: await extractNumber('.follows-count, [data-type="follows"]'),
|
|
76
|
+
likes: await extractNumber('.likes-count, [data-type="likes"]'),
|
|
77
|
+
collects: await extractNumber('.collects-count, [data-type="collects"]'),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
async scrapeNotesList(page) {
|
|
81
|
+
const notes = [];
|
|
82
|
+
// Scroll to load notes
|
|
83
|
+
for (let i = 0; i < 3; i++) {
|
|
84
|
+
const cards = await page.$$('.note-item, [data-type="note-row"]');
|
|
85
|
+
for (const card of cards) {
|
|
86
|
+
const noteId = await card.getAttribute('data-note-id');
|
|
87
|
+
if (!noteId || notes.some((n) => n.noteId === noteId))
|
|
88
|
+
continue;
|
|
89
|
+
const metric = await this.extractNoteMetricFromCard(card, noteId);
|
|
90
|
+
if (metric)
|
|
91
|
+
notes.push(metric);
|
|
92
|
+
}
|
|
93
|
+
// Scroll for more
|
|
94
|
+
await this.humanizer.browseRandomly(page, 2);
|
|
95
|
+
}
|
|
96
|
+
return notes;
|
|
97
|
+
}
|
|
98
|
+
async extractNoteMetricFromCard(card, noteId) {
|
|
99
|
+
try {
|
|
100
|
+
const rawText = sanitizePageContent((await card.textContent()) || '');
|
|
101
|
+
// Parse numbers from the card text (simplified extraction)
|
|
102
|
+
const numbers = rawText.match(/\d+/g)?.map(Number) || [];
|
|
103
|
+
return {
|
|
104
|
+
noteId,
|
|
105
|
+
title: rawText.slice(0, 50),
|
|
106
|
+
views: numbers[0] || 0,
|
|
107
|
+
likes: numbers[1] || 0,
|
|
108
|
+
comments: numbers[2] || 0,
|
|
109
|
+
collects: numbers[3] || 0,
|
|
110
|
+
publishedAt: new Date(),
|
|
111
|
+
ctr: numbers[0] && numbers[4] ? numbers[0] / numbers[4] : 0,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
async scrapeNoteMetric(page, noteId) {
|
|
119
|
+
try {
|
|
120
|
+
const extractNumber = async (selector) => {
|
|
121
|
+
const el = await page.$(selector);
|
|
122
|
+
if (!el)
|
|
123
|
+
return 0;
|
|
124
|
+
const text = sanitizePageContent((await el.textContent()) || '0');
|
|
125
|
+
return parseInt(text.replace(/[^0-9]/g, ''), 10) || 0;
|
|
126
|
+
};
|
|
127
|
+
const titleEl = await page.$('.note-title, h1');
|
|
128
|
+
const title = sanitizePageContent((await titleEl?.textContent()) || '');
|
|
129
|
+
return {
|
|
130
|
+
noteId,
|
|
131
|
+
title,
|
|
132
|
+
views: await extractNumber('.views-count, [data-type="views"]'),
|
|
133
|
+
likes: await extractNumber('.likes-count, [data-type="likes"]'),
|
|
134
|
+
comments: await extractNumber('.comments-count, [data-type="comments"]'),
|
|
135
|
+
collects: await extractNumber('.collects-count, [data-type="collects"]'),
|
|
136
|
+
publishedAt: new Date(),
|
|
137
|
+
ctr: 0,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=scrape.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scrape.js","sourceRoot":"","sources":["../../src/actions/scrape.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { OpenClawRuntime, NoteGenerateRequest, NoteContent, NoteMetric } from '../types/index.js';
|
|
2
|
+
export declare class Copywriter {
|
|
3
|
+
private runtime;
|
|
4
|
+
constructor(runtime: OpenClawRuntime);
|
|
5
|
+
/**
|
|
6
|
+
* Generate a complete XHS note (title, body, hashtags, cover text).
|
|
7
|
+
*/
|
|
8
|
+
generateNote(req: NoteGenerateRequest): Promise<NoteContent>;
|
|
9
|
+
/**
|
|
10
|
+
* Generate a personalized comment for an interaction task.
|
|
11
|
+
*/
|
|
12
|
+
generateComment(noteTitle: string, noteExcerpt: string): Promise<string>;
|
|
13
|
+
/**
|
|
14
|
+
* Analyze past note performance to suggest the best topic.
|
|
15
|
+
*/
|
|
16
|
+
analyzeTopPerformingTopics(notes: NoteMetric[]): Promise<string>;
|
|
17
|
+
private buildSystemPrompt;
|
|
18
|
+
private buildContentPrompt;
|
|
19
|
+
private parseNoteContent;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=copywriter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copywriter.d.ts","sourceRoot":"","sources":["../../src/agents/copywriter.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,eAAe,EACf,mBAAmB,EACnB,WAAW,EAGX,UAAU,EACX,MAAM,mBAAmB,CAAC;AAgB3B,qBAAa,UAAU;IACT,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,eAAe;IAE5C;;OAEG;IACG,YAAY,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,WAAW,CAAC;IAclE;;OAEG;IACG,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAoB9E;;OAEG;IACG,0BAA0B,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAqBtE,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,kBAAkB;IAa1B,OAAO,CAAC,gBAAgB;CAmBzB"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// Copywriter Agent — AI-powered content generation for XHS
|
|
3
|
+
// ============================================================
|
|
4
|
+
import { sanitizePageContent } from '../utils/helpers.js';
|
|
5
|
+
const STYLE_PROMPTS = {
|
|
6
|
+
lifestyle: `你是小红书生活方式博主。标题要有场景感+情绪词,正文结构:HOOK开头 → 故事 → 产品/体验 → CTA互动引导。结尾用评论区提问引发互动。`,
|
|
7
|
+
tutorial: `你是小红书教程类博主。标题用数字列表+结果导向,正文结构:痛点引入 → 分步骤教程 → Tips补充。结尾提醒收藏备用。`,
|
|
8
|
+
review: `你是小红书测评博主。标题用对比型/结论先行,正文结构:开箱体验 → 详细测评 → 优缺点总结。结尾引导点赞收藏。`,
|
|
9
|
+
vlog: `你是小红书vlog博主。标题用地点/事件型,正文按时间线叙事。结尾引导关注看后续。`,
|
|
10
|
+
};
|
|
11
|
+
const TONE_MODIFIERS = {
|
|
12
|
+
casual: '语气轻松活泼,像朋友聊天一样自然。适当使用口语化表达。',
|
|
13
|
+
professional: '语气专业可信,数据支撑观点。保持权威但不生硬。',
|
|
14
|
+
trendy: '紧跟潮流热梗,使用当下流行语和网络用语。活泼有趣。',
|
|
15
|
+
};
|
|
16
|
+
export class Copywriter {
|
|
17
|
+
runtime;
|
|
18
|
+
constructor(runtime) {
|
|
19
|
+
this.runtime = runtime;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Generate a complete XHS note (title, body, hashtags, cover text).
|
|
23
|
+
*/
|
|
24
|
+
async generateNote(req) {
|
|
25
|
+
const systemPrompt = this.buildSystemPrompt(req.style, req.tone);
|
|
26
|
+
const userPrompt = this.buildContentPrompt(req);
|
|
27
|
+
const result = await this.runtime.ai.completion({
|
|
28
|
+
model: 'claude-sonnet-4-20250514',
|
|
29
|
+
system: systemPrompt,
|
|
30
|
+
prompt: userPrompt,
|
|
31
|
+
responseFormat: 'json',
|
|
32
|
+
});
|
|
33
|
+
return this.parseNoteContent(result);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Generate a personalized comment for an interaction task.
|
|
37
|
+
*/
|
|
38
|
+
async generateComment(noteTitle, noteExcerpt) {
|
|
39
|
+
const sanitizedTitle = sanitizePageContent(noteTitle);
|
|
40
|
+
const sanitizedExcerpt = sanitizePageContent(noteExcerpt);
|
|
41
|
+
const result = await this.runtime.ai.completion({
|
|
42
|
+
model: 'claude-sonnet-4-20250514',
|
|
43
|
+
system: `你是一个真实的小红书用户。根据笔记内容生成一条自然、真诚的评论。
|
|
44
|
+
要求:
|
|
45
|
+
- 10-50字之间
|
|
46
|
+
- 表达真实感受或提问
|
|
47
|
+
- 不要用模板化语言
|
|
48
|
+
- 可以适当用emoji但不要过多
|
|
49
|
+
- 不要用"博主"这样的称呼`,
|
|
50
|
+
prompt: `笔记标题:${sanitizedTitle}\n笔记内容摘要:${sanitizedExcerpt}\n\n请生成一条评论:`,
|
|
51
|
+
responseFormat: 'text',
|
|
52
|
+
});
|
|
53
|
+
return result.trim();
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Analyze past note performance to suggest the best topic.
|
|
57
|
+
*/
|
|
58
|
+
async analyzeTopPerformingTopics(notes) {
|
|
59
|
+
if (notes.length === 0)
|
|
60
|
+
return '日常分享';
|
|
61
|
+
// Sort by engagement (likes + comments + collects)
|
|
62
|
+
const sorted = [...notes].sort((a, b) => (b.likes + b.comments + b.collects) - (a.likes + a.comments + a.collects));
|
|
63
|
+
const topNotes = sorted.slice(0, 5);
|
|
64
|
+
const titles = topNotes.map((n) => n.title).join('\n');
|
|
65
|
+
const result = await this.runtime.ai.completion({
|
|
66
|
+
model: 'claude-sonnet-4-20250514',
|
|
67
|
+
system: '你是数据分析师,根据历史高互动笔记标题分析内容方向。',
|
|
68
|
+
prompt: `以下是近期互动最高的笔记标题:\n${titles}\n\n请推荐一个今天适合发布的话题方向(只输出话题关键词,不要其他内容):`,
|
|
69
|
+
responseFormat: 'text',
|
|
70
|
+
});
|
|
71
|
+
return result.trim();
|
|
72
|
+
}
|
|
73
|
+
buildSystemPrompt(style, tone) {
|
|
74
|
+
return `${STYLE_PROMPTS[style]}\n${TONE_MODIFIERS[tone]}\n\n请以JSON格式返回,包含以下字段:
|
|
75
|
+
{
|
|
76
|
+
"title": "笔记标题(≤20字,含关键词)",
|
|
77
|
+
"body": "笔记正文",
|
|
78
|
+
"hashtags": ["话题标签1", "话题标签2", ...],
|
|
79
|
+
"coverText": "封面文字(≤10字)"
|
|
80
|
+
}`;
|
|
81
|
+
}
|
|
82
|
+
buildContentPrompt(req) {
|
|
83
|
+
const parts = [
|
|
84
|
+
`主题:${req.topic}`,
|
|
85
|
+
`关键词:${req.keywords.join('、')}`,
|
|
86
|
+
`字数范围:${req.wordCount[0]}-${req.wordCount[1]}字`,
|
|
87
|
+
];
|
|
88
|
+
if (req.includeEmoji)
|
|
89
|
+
parts.push('正文中适当使用emoji');
|
|
90
|
+
if (req.includeHashtags)
|
|
91
|
+
parts.push('生成3-5个相关话题标签');
|
|
92
|
+
return parts.join('\n');
|
|
93
|
+
}
|
|
94
|
+
parseNoteContent(raw) {
|
|
95
|
+
try {
|
|
96
|
+
const parsed = JSON.parse(raw);
|
|
97
|
+
return {
|
|
98
|
+
title: String(parsed.title || '').slice(0, 20),
|
|
99
|
+
body: String(parsed.body || ''),
|
|
100
|
+
hashtags: Array.isArray(parsed.hashtags) ? parsed.hashtags.map(String) : [],
|
|
101
|
+
coverText: String(parsed.coverText || '').slice(0, 10),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
// Fallback: treat the whole response as the body
|
|
106
|
+
return {
|
|
107
|
+
title: raw.slice(0, 20),
|
|
108
|
+
body: raw,
|
|
109
|
+
hashtags: [],
|
|
110
|
+
coverText: '',
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=copywriter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copywriter.js","sourceRoot":"","sources":["../../src/agents/copywriter.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,2DAA2D;AAC3D,+DAA+D;AAU/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE1D,MAAM,aAAa,GAA8B;IAC/C,SAAS,EAAE,0EAA0E;IACrF,QAAQ,EAAE,8DAA8D;IACxE,MAAM,EAAE,0DAA0D;IAClE,IAAI,EAAE,2CAA2C;CAClD,CAAC;AAEF,MAAM,cAAc,GAA6B;IAC/C,MAAM,EAAE,6BAA6B;IACrC,YAAY,EAAE,yBAAyB;IACvC,MAAM,EAAE,2BAA2B;CACpC,CAAC;AAEF,MAAM,OAAO,UAAU;IACD;IAApB,YAAoB,OAAwB;QAAxB,YAAO,GAAP,OAAO,CAAiB;IAAG,CAAC;IAEhD;;OAEG;IACH,KAAK,CAAC,YAAY,CAAC,GAAwB;QACzC,MAAM,YAAY,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QACjE,MAAM,UAAU,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC;QAEhD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC;YAC9C,KAAK,EAAE,0BAA0B;YACjC,MAAM,EAAE,YAAY;YACpB,MAAM,EAAE,UAAU;YAClB,cAAc,EAAE,MAAM;SACvB,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe,CAAC,SAAiB,EAAE,WAAmB;QAC1D,MAAM,cAAc,GAAG,mBAAmB,CAAC,SAAS,CAAC,CAAC;QACtD,MAAM,gBAAgB,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC;QAE1D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC;YAC9C,KAAK,EAAE,0BAA0B;YACjC,MAAM,EAAE;;;;;;eAMC;YACT,MAAM,EAAE,QAAQ,cAAc,YAAY,gBAAgB,cAAc;YACxE,cAAc,EAAE,MAAM;SACvB,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,0BAA0B,CAAC,KAAmB;QAClD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,MAAM,CAAC;QAEtC,mDAAmD;QACnD,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAC5B,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CACpF,CAAC;QAEF,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEvD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC;YAC9C,KAAK,EAAE,0BAA0B;YACjC,MAAM,EAAE,4BAA4B;YACpC,MAAM,EAAE,oBAAoB,MAAM,wCAAwC;YAC1E,cAAc,EAAE,MAAM;SACvB,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;IACvB,CAAC;IAEO,iBAAiB,CAAC,KAAgB,EAAE,IAAc;QACxD,OAAO,GAAG,aAAa,CAAC,KAAK,CAAC,KAAK,cAAc,CAAC,IAAI,CAAC;;;;;;EAMzD,CAAC;IACD,CAAC;IAEO,kBAAkB,CAAC,GAAwB;QACjD,MAAM,KAAK,GAAG;YACZ,MAAM,GAAG,CAAC,KAAK,EAAE;YACjB,OAAO,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;YAC/B,QAAQ,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG;SAChD,CAAC;QAEF,IAAI,GAAG,CAAC,YAAY;YAAE,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACjD,IAAI,GAAG,CAAC,eAAe;YAAE,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAEpD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAEO,gBAAgB,CAAC,GAAW;QAClC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC/B,OAAO;gBACL,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;gBAC9C,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;gBAC/B,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE;gBAC3E,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;aACvD,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,iDAAiD;YACjD,OAAO;gBACL,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;gBACvB,IAAI,EAAE,GAAG;gBACT,QAAQ,EAAE,EAAE;gBACZ,SAAS,EAAE,EAAE;aACd,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { OpenClawRuntime, NoteContent, ImageComposerConfig } from '../types/index.js';
|
|
2
|
+
export declare class ImageComposer {
|
|
3
|
+
private runtime;
|
|
4
|
+
constructor(runtime: OpenClawRuntime);
|
|
5
|
+
/**
|
|
6
|
+
* Compose a cover image for a note.
|
|
7
|
+
*/
|
|
8
|
+
composeCoverImage(content: NoteContent, config: ImageComposerConfig): Promise<Buffer>;
|
|
9
|
+
/**
|
|
10
|
+
* Generate an AI image based on note content.
|
|
11
|
+
*/
|
|
12
|
+
generateAIImage(content: NoteContent): Promise<Buffer>;
|
|
13
|
+
/**
|
|
14
|
+
* Fetch base image from configured source.
|
|
15
|
+
*/
|
|
16
|
+
private fetchBaseImage;
|
|
17
|
+
/**
|
|
18
|
+
* Overlay text on the image using Sharp.
|
|
19
|
+
*/
|
|
20
|
+
private overlayText;
|
|
21
|
+
/**
|
|
22
|
+
* Add a subtle brand watermark.
|
|
23
|
+
*/
|
|
24
|
+
private addWatermark;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=image-composer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-composer.d.ts","sourceRoot":"","sources":["../../src/agents/image-composer.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,eAAe,EACf,WAAW,EACX,mBAAmB,EAEpB,MAAM,mBAAmB,CAAC;AAE3B,qBAAa,aAAa;IACZ,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,eAAe;IAE5C;;OAEG;IACG,iBAAiB,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC;IAe3F;;OAEG;IACG,eAAe,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAS5D;;OAEG;YACW,cAAc;IAK5B;;OAEG;YACW,WAAW;IA0CzB;;OAEG;YACW,YAAY;CAiB3B"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// Image Composer — Cover image generation and composition
|
|
3
|
+
// ============================================================
|
|
4
|
+
export class ImageComposer {
|
|
5
|
+
runtime;
|
|
6
|
+
constructor(runtime) {
|
|
7
|
+
this.runtime = runtime;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Compose a cover image for a note.
|
|
11
|
+
*/
|
|
12
|
+
async composeCoverImage(content, config) {
|
|
13
|
+
// Step 1: Get base image
|
|
14
|
+
const baseImage = await this.fetchBaseImage(content, config);
|
|
15
|
+
// Step 2: Overlay text (cover text)
|
|
16
|
+
const composed = await this.overlayText(baseImage, content.coverText, config);
|
|
17
|
+
// Step 3: Add watermark if brand colors are configured
|
|
18
|
+
if (config.brandColors.length > 0) {
|
|
19
|
+
return this.addWatermark(composed, config);
|
|
20
|
+
}
|
|
21
|
+
return composed;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Generate an AI image based on note content.
|
|
25
|
+
*/
|
|
26
|
+
async generateAIImage(content) {
|
|
27
|
+
const prompt = `小红书风格封面图,主题:${content.title},风格清新自然,高质量`;
|
|
28
|
+
return this.runtime.ai.imageGeneration({
|
|
29
|
+
prompt,
|
|
30
|
+
size: '1080x1440', // 3:4 ratio for XHS
|
|
31
|
+
style: 'natural',
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Fetch base image from configured source.
|
|
36
|
+
*/
|
|
37
|
+
async fetchBaseImage(content, config) {
|
|
38
|
+
// Default: generate with AI
|
|
39
|
+
return this.generateAIImage(content);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Overlay text on the image using Sharp.
|
|
43
|
+
*/
|
|
44
|
+
async overlayText(imageBuffer, text, config) {
|
|
45
|
+
// Dynamic import for sharp (heavy dependency)
|
|
46
|
+
const sharp = (await import('sharp')).default;
|
|
47
|
+
if (!text || !config.textOverlay)
|
|
48
|
+
return imageBuffer;
|
|
49
|
+
const { position, textColor, backgroundColor, padding } = config.textOverlay;
|
|
50
|
+
const fontSize = config.coverTemplate?.fontSize ?? 48;
|
|
51
|
+
// Create text SVG overlay
|
|
52
|
+
const svgWidth = 1080;
|
|
53
|
+
const svgHeight = 200;
|
|
54
|
+
const y = position === 'top' ? padding : position === 'center' ? 600 : 1200;
|
|
55
|
+
const bgRect = backgroundColor
|
|
56
|
+
? `<rect x="0" y="0" width="${svgWidth}" height="${svgHeight}" fill="${backgroundColor}" opacity="0.7"/>`
|
|
57
|
+
: '';
|
|
58
|
+
const svg = `
|
|
59
|
+
<svg width="${svgWidth}" height="${svgHeight}">
|
|
60
|
+
${bgRect}
|
|
61
|
+
<text x="${svgWidth / 2}" y="${svgHeight / 2 + fontSize / 3}"
|
|
62
|
+
font-size="${fontSize}" fill="${textColor}"
|
|
63
|
+
text-anchor="middle" font-family="sans-serif" font-weight="bold">
|
|
64
|
+
${escapeXml(text)}
|
|
65
|
+
</text>
|
|
66
|
+
</svg>
|
|
67
|
+
`;
|
|
68
|
+
return sharp(imageBuffer)
|
|
69
|
+
.composite([{
|
|
70
|
+
input: Buffer.from(svg),
|
|
71
|
+
top: y,
|
|
72
|
+
left: 0,
|
|
73
|
+
}])
|
|
74
|
+
.toBuffer();
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Add a subtle brand watermark.
|
|
78
|
+
*/
|
|
79
|
+
async addWatermark(imageBuffer, config) {
|
|
80
|
+
const sharp = (await import('sharp')).default;
|
|
81
|
+
const color = config.brandColors[0] || '#ffffff';
|
|
82
|
+
const svg = `
|
|
83
|
+
<svg width="200" height="40">
|
|
84
|
+
<rect x="0" y="0" width="200" height="40" fill="${color}" opacity="0.3" rx="8"/>
|
|
85
|
+
</svg>
|
|
86
|
+
`;
|
|
87
|
+
return sharp(imageBuffer)
|
|
88
|
+
.composite([{
|
|
89
|
+
input: Buffer.from(svg),
|
|
90
|
+
gravity: 'southeast',
|
|
91
|
+
}])
|
|
92
|
+
.toBuffer();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function escapeXml(text) {
|
|
96
|
+
return text
|
|
97
|
+
.replace(/&/g, '&')
|
|
98
|
+
.replace(/</g, '<')
|
|
99
|
+
.replace(/>/g, '>')
|
|
100
|
+
.replace(/"/g, '"')
|
|
101
|
+
.replace(/'/g, ''');
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=image-composer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-composer.js","sourceRoot":"","sources":["../../src/agents/image-composer.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|