autocrew 0.1.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/HAMLETDEER.md +562 -0
- package/LICENSE +21 -0
- package/README.md +190 -0
- package/README_CN.md +190 -0
- package/adapters/openclaw/index.ts +68 -0
- package/bin/autocrew.mjs +23 -0
- package/bin/autocrew.ts +13 -0
- package/openclaw.plugin.json +36 -0
- package/package.json +74 -0
- package/skills/_writing-style/SKILL.md +68 -0
- package/skills/audience-profiler/SKILL.md +241 -0
- package/skills/content-attribution/SKILL.md +128 -0
- package/skills/content-review/SKILL.md +257 -0
- package/skills/cover-generator/SKILL.md +93 -0
- package/skills/humanizer-zh/SKILL.md +75 -0
- package/skills/intel-digest/SKILL.md +57 -0
- package/skills/intel-pull/SKILL.md +74 -0
- package/skills/manage-pipeline/SKILL.md +63 -0
- package/skills/memory-distill/SKILL.md +89 -0
- package/skills/onboarding/SKILL.md +117 -0
- package/skills/pipeline-status/SKILL.md +51 -0
- package/skills/platform-rewrite/SKILL.md +125 -0
- package/skills/pre-publish/SKILL.md +142 -0
- package/skills/publish-content/SKILL.md +500 -0
- package/skills/remix-content/SKILL.md +77 -0
- package/skills/research/SKILL.md +127 -0
- package/skills/setup/SKILL.md +353 -0
- package/skills/spawn-batch-writer/SKILL.md +66 -0
- package/skills/spawn-planner/SKILL.md +72 -0
- package/skills/spawn-writer/SKILL.md +60 -0
- package/skills/teardown/SKILL.md +144 -0
- package/skills/title-craft/SKILL.md +234 -0
- package/skills/topic-ideas/SKILL.md +105 -0
- package/skills/video-timeline/SKILL.md +117 -0
- package/skills/write-script/SKILL.md +232 -0
- package/skills/xhs-cover-review/SKILL.md +48 -0
- package/src/adapters/browser/browser-cdp.ts +260 -0
- package/src/adapters/browser/browser-relay.ts +236 -0
- package/src/adapters/browser/gateway-client.ts +148 -0
- package/src/adapters/browser/types.ts +36 -0
- package/src/adapters/image/gemini.ts +219 -0
- package/src/adapters/research/tikhub.ts +19 -0
- package/src/cli/banner.ts +18 -0
- package/src/cli/bootstrap.ts +33 -0
- package/src/cli/commands/adapt.ts +28 -0
- package/src/cli/commands/advance.ts +28 -0
- package/src/cli/commands/assets.ts +24 -0
- package/src/cli/commands/audit.ts +18 -0
- package/src/cli/commands/contents.ts +18 -0
- package/src/cli/commands/cover.ts +58 -0
- package/src/cli/commands/events.ts +17 -0
- package/src/cli/commands/humanize.ts +27 -0
- package/src/cli/commands/index.ts +80 -0
- package/src/cli/commands/init.ts +28 -0
- package/src/cli/commands/intel.ts +55 -0
- package/src/cli/commands/learn.ts +34 -0
- package/src/cli/commands/memory.ts +18 -0
- package/src/cli/commands/migrate.ts +24 -0
- package/src/cli/commands/open.ts +21 -0
- package/src/cli/commands/pipelines.ts +18 -0
- package/src/cli/commands/pre-publish.ts +27 -0
- package/src/cli/commands/profile.ts +31 -0
- package/src/cli/commands/research.ts +36 -0
- package/src/cli/commands/restore.ts +28 -0
- package/src/cli/commands/review.ts +61 -0
- package/src/cli/commands/start.ts +28 -0
- package/src/cli/commands/status.ts +14 -0
- package/src/cli/commands/templates.ts +15 -0
- package/src/cli/commands/topics.ts +18 -0
- package/src/cli/commands/trash.ts +28 -0
- package/src/cli/commands/upgrade.ts +48 -0
- package/src/cli/commands/versions.ts +24 -0
- package/src/cli/index.ts +40 -0
- package/src/data/sensitive-words-builtin.json +114 -0
- package/src/data/source-presets.yaml +54 -0
- package/src/e2e.test.ts +596 -0
- package/src/modules/auth/cookie-manager.ts +113 -0
- package/src/modules/cards/template-engine.ts +74 -0
- package/src/modules/cards/templates/comparison-table.ts +71 -0
- package/src/modules/cards/templates/data-chart.ts +76 -0
- package/src/modules/cards/templates/flow-chart.ts +49 -0
- package/src/modules/cards/templates/key-points.ts +59 -0
- package/src/modules/cover/prompt-builder.test.ts +157 -0
- package/src/modules/cover/prompt-builder.ts +212 -0
- package/src/modules/cover/ratio-adapter.test.ts +122 -0
- package/src/modules/cover/ratio-adapter.ts +104 -0
- package/src/modules/filter/sensitive-words.test.ts +72 -0
- package/src/modules/filter/sensitive-words.ts +212 -0
- package/src/modules/humanizer/zh.test.ts +75 -0
- package/src/modules/humanizer/zh.ts +175 -0
- package/src/modules/intel/collector.ts +19 -0
- package/src/modules/intel/collectors/competitor.test.ts +71 -0
- package/src/modules/intel/collectors/competitor.ts +65 -0
- package/src/modules/intel/collectors/rss.test.ts +56 -0
- package/src/modules/intel/collectors/rss.ts +70 -0
- package/src/modules/intel/collectors/trends.test.ts +80 -0
- package/src/modules/intel/collectors/trends.ts +107 -0
- package/src/modules/intel/collectors/web-search.test.ts +85 -0
- package/src/modules/intel/collectors/web-search.ts +81 -0
- package/src/modules/intel/integration.test.ts +203 -0
- package/src/modules/intel/intel-engine.test.ts +103 -0
- package/src/modules/intel/intel-engine.ts +96 -0
- package/src/modules/intel/source-config.test.ts +113 -0
- package/src/modules/intel/source-config.ts +131 -0
- package/src/modules/learnings/diff-tracker.test.ts +144 -0
- package/src/modules/learnings/diff-tracker.ts +189 -0
- package/src/modules/learnings/rule-distiller.ts +141 -0
- package/src/modules/memory/distill.ts +208 -0
- package/src/modules/migrate/legacy-migrate.test.ts +169 -0
- package/src/modules/migrate/legacy-migrate.ts +229 -0
- package/src/modules/pro/api-client.ts +192 -0
- package/src/modules/pro/gate.test.ts +110 -0
- package/src/modules/pro/gate.ts +104 -0
- package/src/modules/profile/creator-profile.test.ts +178 -0
- package/src/modules/profile/creator-profile.ts +248 -0
- package/src/modules/publish/douyin-api.ts +34 -0
- package/src/modules/publish/wechat-mp.ts +320 -0
- package/src/modules/publish/xiaohongshu-api.ts +127 -0
- package/src/modules/research/free-engine.ts +360 -0
- package/src/modules/timeline/markup-generator.ts +63 -0
- package/src/modules/timeline/parser.ts +275 -0
- package/src/modules/workflow/templates.ts +124 -0
- package/src/modules/writing/platform-rewrite.ts +190 -0
- package/src/modules/writing/title-hashtag.ts +385 -0
- package/src/runtime/context.test.ts +97 -0
- package/src/runtime/context.ts +129 -0
- package/src/runtime/events.test.ts +83 -0
- package/src/runtime/events.ts +104 -0
- package/src/runtime/hooks.ts +174 -0
- package/src/runtime/tool-runner.test.ts +204 -0
- package/src/runtime/tool-runner.ts +282 -0
- package/src/runtime/workflow-engine.test.ts +455 -0
- package/src/runtime/workflow-engine.ts +391 -0
- package/src/server/index.ts +409 -0
- package/src/server/start.ts +39 -0
- package/src/storage/local-store.test.ts +304 -0
- package/src/storage/local-store.ts +704 -0
- package/src/storage/pipeline-store.test.ts +363 -0
- package/src/storage/pipeline-store.ts +698 -0
- package/src/tools/asset.ts +96 -0
- package/src/tools/content-save.ts +276 -0
- package/src/tools/cover-review.ts +221 -0
- package/src/tools/humanize.ts +54 -0
- package/src/tools/init.ts +133 -0
- package/src/tools/intel.ts +92 -0
- package/src/tools/memory.ts +76 -0
- package/src/tools/pipeline-ops.ts +109 -0
- package/src/tools/pipeline.ts +168 -0
- package/src/tools/pre-publish.ts +232 -0
- package/src/tools/publish.ts +183 -0
- package/src/tools/registry.ts +198 -0
- package/src/tools/research.ts +304 -0
- package/src/tools/review.ts +305 -0
- package/src/tools/rewrite.ts +165 -0
- package/src/tools/status.ts +30 -0
- package/src/tools/timeline.ts +234 -0
- package/src/tools/topic-create.ts +50 -0
- package/src/types/providers.ts +69 -0
- package/src/types/timeline.test.ts +147 -0
- package/src/types/timeline.ts +83 -0
- package/src/utils/retry.test.ts +97 -0
- package/src/utils/retry.ts +85 -0
- package/templates/AGENTS.md +99 -0
- package/templates/SOUL.md +31 -0
- package/templates/TOOLS.md +76 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// ── Video pipeline timeline types ────────────────────────────────────
|
|
2
|
+
|
|
3
|
+
export type VideoPreset = "knowledge-explainer" | "tutorial";
|
|
4
|
+
export type AspectRatio = "9:16" | "16:9" | "3:4" | "1:1" | "4:3";
|
|
5
|
+
export type SubtitleTemplate =
|
|
6
|
+
| "modern-outline"
|
|
7
|
+
| "karaoke-highlight"
|
|
8
|
+
| "minimal-fade"
|
|
9
|
+
| "bold-top";
|
|
10
|
+
export type SubtitlePosition = "bottom" | "top";
|
|
11
|
+
export type SegmentStatus =
|
|
12
|
+
| "pending"
|
|
13
|
+
| "generating"
|
|
14
|
+
| "ready"
|
|
15
|
+
| "confirmed"
|
|
16
|
+
| "failed";
|
|
17
|
+
export type VisualType = "broll" | "card";
|
|
18
|
+
export type CardTemplate =
|
|
19
|
+
| "comparison-table"
|
|
20
|
+
| "key-points"
|
|
21
|
+
| "flow-chart"
|
|
22
|
+
| "data-chart";
|
|
23
|
+
|
|
24
|
+
export interface TTSSegment {
|
|
25
|
+
id: string;
|
|
26
|
+
text: string;
|
|
27
|
+
estimatedDuration: number;
|
|
28
|
+
start: number;
|
|
29
|
+
asset: string | null;
|
|
30
|
+
status: SegmentStatus;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface VisualSegment {
|
|
34
|
+
id: string;
|
|
35
|
+
layer: number;
|
|
36
|
+
type: VisualType;
|
|
37
|
+
prompt?: string;
|
|
38
|
+
template?: CardTemplate;
|
|
39
|
+
data?: Record<string, unknown>;
|
|
40
|
+
linkedTts: string[];
|
|
41
|
+
opacity?: number;
|
|
42
|
+
asset: string | null;
|
|
43
|
+
status: SegmentStatus;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface SubtitleTrack {
|
|
47
|
+
asset: string | null;
|
|
48
|
+
status: SegmentStatus;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface SubtitleConfig {
|
|
52
|
+
template: SubtitleTemplate;
|
|
53
|
+
position: SubtitlePosition;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface Timeline {
|
|
57
|
+
version: "2.0";
|
|
58
|
+
contentId: string;
|
|
59
|
+
preset: VideoPreset;
|
|
60
|
+
aspectRatio: AspectRatio;
|
|
61
|
+
subtitle: SubtitleConfig;
|
|
62
|
+
tracks: {
|
|
63
|
+
tts: TTSSegment[];
|
|
64
|
+
visual: VisualSegment[];
|
|
65
|
+
subtitle: SubtitleTrack;
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// ── Compositor-level types (used by provider interfaces) ────────────
|
|
70
|
+
|
|
71
|
+
export interface TimelineClip {
|
|
72
|
+
id: string;
|
|
73
|
+
type: "video" | "audio" | "text" | "image";
|
|
74
|
+
start: number;
|
|
75
|
+
duration: number;
|
|
76
|
+
assetId?: string;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface TimelineTrack {
|
|
80
|
+
id: string;
|
|
81
|
+
type: "video" | "audio" | "text";
|
|
82
|
+
clips: TimelineClip[];
|
|
83
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { withRetry, RetryableError, checkFetchResponse } from "../utils/retry.js";
|
|
3
|
+
|
|
4
|
+
describe("withRetry", () => {
|
|
5
|
+
it("returns result on first success", async () => {
|
|
6
|
+
const result = await withRetry(async () => 42);
|
|
7
|
+
expect(result).toBe(42);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it("retries on RetryableError and succeeds", async () => {
|
|
11
|
+
let attempt = 0;
|
|
12
|
+
const result = await withRetry(
|
|
13
|
+
async () => {
|
|
14
|
+
attempt++;
|
|
15
|
+
if (attempt < 3) throw new RetryableError("temp fail", 503);
|
|
16
|
+
return "ok";
|
|
17
|
+
},
|
|
18
|
+
{ maxRetries: 3, baseDelayMs: 10 },
|
|
19
|
+
);
|
|
20
|
+
expect(result).toBe("ok");
|
|
21
|
+
expect(attempt).toBe(3);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("throws after max retries exhausted", async () => {
|
|
25
|
+
await expect(
|
|
26
|
+
withRetry(
|
|
27
|
+
async () => { throw new RetryableError("always fail", 500); },
|
|
28
|
+
{ maxRetries: 2, baseDelayMs: 10 },
|
|
29
|
+
),
|
|
30
|
+
).rejects.toThrow("always fail");
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("does NOT retry non-retryable errors", async () => {
|
|
34
|
+
let attempt = 0;
|
|
35
|
+
await expect(
|
|
36
|
+
withRetry(
|
|
37
|
+
async () => {
|
|
38
|
+
attempt++;
|
|
39
|
+
throw new Error("bad request");
|
|
40
|
+
},
|
|
41
|
+
{ maxRetries: 3, baseDelayMs: 10 },
|
|
42
|
+
),
|
|
43
|
+
).rejects.toThrow("bad request");
|
|
44
|
+
expect(attempt).toBe(1); // Only one attempt, no retry
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("retries on network-like TypeError", async () => {
|
|
48
|
+
let attempt = 0;
|
|
49
|
+
const result = await withRetry(
|
|
50
|
+
async () => {
|
|
51
|
+
attempt++;
|
|
52
|
+
if (attempt < 2) throw new TypeError("fetch failed");
|
|
53
|
+
return "recovered";
|
|
54
|
+
},
|
|
55
|
+
{ maxRetries: 2, baseDelayMs: 10 },
|
|
56
|
+
);
|
|
57
|
+
expect(result).toBe("recovered");
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe("checkFetchResponse", () => {
|
|
62
|
+
it("does nothing for ok response", () => {
|
|
63
|
+
const res = { ok: true, status: 200 } as Response;
|
|
64
|
+
expect(() => checkFetchResponse(res, "test")).not.toThrow();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("throws RetryableError for 429", () => {
|
|
68
|
+
const res = { ok: false, status: 429 } as Response;
|
|
69
|
+
expect(() => checkFetchResponse(res, "test")).toThrow(RetryableError);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("throws RetryableError for 503", () => {
|
|
73
|
+
const res = { ok: false, status: 503 } as Response;
|
|
74
|
+
expect(() => checkFetchResponse(res, "test")).toThrow(RetryableError);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("throws regular Error for 400", () => {
|
|
78
|
+
const res = { ok: false, status: 400 } as Response;
|
|
79
|
+
try {
|
|
80
|
+
checkFetchResponse(res, "test");
|
|
81
|
+
expect.unreachable();
|
|
82
|
+
} catch (err) {
|
|
83
|
+
expect(err).not.toBeInstanceOf(RetryableError);
|
|
84
|
+
expect(err).toBeInstanceOf(Error);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("throws regular Error for 401", () => {
|
|
89
|
+
const res = { ok: false, status: 401 } as Response;
|
|
90
|
+
try {
|
|
91
|
+
checkFetchResponse(res, "test");
|
|
92
|
+
expect.unreachable();
|
|
93
|
+
} catch (err) {
|
|
94
|
+
expect(err).not.toBeInstanceOf(RetryableError);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retry utility — exponential backoff for external API calls.
|
|
3
|
+
*
|
|
4
|
+
* Retries on network errors and 429/500/502/503 status codes.
|
|
5
|
+
* Does NOT retry on 400/401/403/404 (client errors).
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export interface RetryOptions {
|
|
9
|
+
maxRetries?: number;
|
|
10
|
+
baseDelayMs?: number;
|
|
11
|
+
maxDelayMs?: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const RETRYABLE_STATUS_CODES = new Set([429, 500, 502, 503]);
|
|
15
|
+
|
|
16
|
+
export class RetryableError extends Error {
|
|
17
|
+
constructor(
|
|
18
|
+
message: string,
|
|
19
|
+
public statusCode?: number,
|
|
20
|
+
) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.name = "RetryableError";
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function isRetryable(err: unknown): boolean {
|
|
27
|
+
if (err instanceof RetryableError) return true;
|
|
28
|
+
if (err instanceof TypeError && err.message.includes("fetch")) return true; // Network error
|
|
29
|
+
if (err instanceof Error && err.message.includes("ECONNREFUSED")) return true;
|
|
30
|
+
if (err instanceof Error && err.message.includes("ETIMEDOUT")) return true;
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function sleep(ms: number): Promise<void> {
|
|
35
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Execute a function with exponential backoff retry.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* const result = await withRetry(() => callGeminiAPI(prompt), { maxRetries: 3 });
|
|
43
|
+
*/
|
|
44
|
+
export async function withRetry<T>(
|
|
45
|
+
fn: () => Promise<T>,
|
|
46
|
+
opts?: RetryOptions,
|
|
47
|
+
): Promise<T> {
|
|
48
|
+
const maxRetries = opts?.maxRetries ?? 3;
|
|
49
|
+
const baseDelay = opts?.baseDelayMs ?? 1000;
|
|
50
|
+
const maxDelay = opts?.maxDelayMs ?? 10000;
|
|
51
|
+
|
|
52
|
+
let lastError: unknown;
|
|
53
|
+
|
|
54
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
55
|
+
try {
|
|
56
|
+
return await fn();
|
|
57
|
+
} catch (err) {
|
|
58
|
+
lastError = err;
|
|
59
|
+
|
|
60
|
+
if (attempt === maxRetries || !isRetryable(err)) {
|
|
61
|
+
throw err;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Exponential backoff with jitter
|
|
65
|
+
const delay = Math.min(baseDelay * 2 ** attempt + Math.random() * 500, maxDelay);
|
|
66
|
+
await sleep(delay);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
throw lastError;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Wrap a fetch response check — throws RetryableError for retryable status codes.
|
|
75
|
+
*/
|
|
76
|
+
export function checkFetchResponse(res: Response, context: string): void {
|
|
77
|
+
if (res.ok) return;
|
|
78
|
+
|
|
79
|
+
if (RETRYABLE_STATUS_CODES.has(res.status)) {
|
|
80
|
+
throw new RetryableError(`${context}: HTTP ${res.status}`, res.status);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Non-retryable error — throw a regular error
|
|
84
|
+
throw new Error(`${context}: HTTP ${res.status}`);
|
|
85
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Agents
|
|
2
|
+
|
|
3
|
+
## Hard Rules
|
|
4
|
+
|
|
5
|
+
1. ALWAYS respond in Simplified Chinese when talking to the user.
|
|
6
|
+
2. NEVER fabricate data, statistics, or case studies. If unsure, say so.
|
|
7
|
+
3. NEVER copy competitor content verbatim. May reference structure but MUST have original perspective.
|
|
8
|
+
4. **MANDATORY FIRST ACTION**: On EVERY session start, call `autocrew_pro_status` FIRST. If `profileExists: false` OR `missingInfo` is non-empty OR `styleCalibrated: false`, you MUST run the onboarding + setup flow BEFORE doing ANYTHING else. Do NOT skip this. Do NOT proceed to the user's request until onboarding is complete.
|
|
9
|
+
5. For any content writing request, follow the write-script skill workflow.
|
|
10
|
+
6. For batch writing (multiple articles), use the spawn-batch-writer skill.
|
|
11
|
+
7. For topic research, use the research or spawn-planner skill.
|
|
12
|
+
8. Save all topics via `autocrew_topic` tool. Save all content via `autocrew_content` tool.
|
|
13
|
+
9. Before writing content, read `~/.autocrew/STYLE.md` and `~/.autocrew/creator-profile.json`.
|
|
14
|
+
10. After completing a task, suggest one concrete next step.
|
|
15
|
+
11. When user gives feedback on content, capture it via the memory-distill skill.
|
|
16
|
+
|
|
17
|
+
## Onboarding Protocol (MANDATORY — cannot be skipped)
|
|
18
|
+
|
|
19
|
+
This is the FIRST thing that happens for any new user. No exceptions.
|
|
20
|
+
|
|
21
|
+
### Gate Check
|
|
22
|
+
1. Call `autocrew_pro_status` at session start.
|
|
23
|
+
2. If ANY of these are true → BLOCK all other actions and run onboarding:
|
|
24
|
+
- `profileExists: false`
|
|
25
|
+
- `missingInfo` array is non-empty
|
|
26
|
+
- `styleCalibrated: false`
|
|
27
|
+
|
|
28
|
+
### Onboarding Flow (3 phases, must complete all)
|
|
29
|
+
|
|
30
|
+
**Phase 1: 初始化 + 基础信息(2-3 轮对话)**
|
|
31
|
+
1. Call `autocrew_init` to create data directory
|
|
32
|
+
2. Read host MEMORY.md if it exists (extract known info)
|
|
33
|
+
3. Ask for missing fields ONLY:
|
|
34
|
+
- 行业/领域(必填)
|
|
35
|
+
- 目标平台(必填,可多选:小红书/抖音/公众号/视频号)
|
|
36
|
+
- 目标受众(必填:年龄段、职业、痛点)
|
|
37
|
+
- 变现模式(选填:广告/带货/知识付费/引流)
|
|
38
|
+
4. Save to creator-profile.json
|
|
39
|
+
|
|
40
|
+
**Phase 2: 风格校准(3-5 轮对话)**
|
|
41
|
+
1. 询问用户是否有参考账号或已有内容样本
|
|
42
|
+
2. 如果有 → 分析样本,提取风格特征
|
|
43
|
+
3. 如果没有 → 通过 A/B 对比问题确定风格偏好:
|
|
44
|
+
- 正式 vs 口语
|
|
45
|
+
- 专业术语 vs 大白话
|
|
46
|
+
- 长文深度 vs 短文快节奏
|
|
47
|
+
- 情感共鸣 vs 干货实用
|
|
48
|
+
4. 生成 STYLE.md 写作人格文件
|
|
49
|
+
5. 更新 creator-profile.json 的 `styleCalibrated: true`
|
|
50
|
+
|
|
51
|
+
**Phase 3: 确认 + 过渡**
|
|
52
|
+
1. 展示生成的风格档案摘要
|
|
53
|
+
2. 告诉用户"设置完成,现在可以开始创作了"
|
|
54
|
+
3. 然后继续用户的原始请求(如果有的话)
|
|
55
|
+
|
|
56
|
+
### 重要:不要把 onboarding 做成审讯
|
|
57
|
+
- 语气轻松友好,像朋友聊天
|
|
58
|
+
- 每次最多问 2-3 个问题
|
|
59
|
+
- 已知信息(从 MEMORY.md 读到的)直接确认,不重复问
|
|
60
|
+
- 风格校准用选择题,不要让用户写长文
|
|
61
|
+
|
|
62
|
+
## Memory Protocol
|
|
63
|
+
|
|
64
|
+
- On session start: read `~/.autocrew/STYLE.md` and `~/.autocrew/creator-profile.json` if they exist.
|
|
65
|
+
- After significant user feedback: update via memory-distill skill (records diff + triggers rule distillation).
|
|
66
|
+
- Never overwrite creator-profile.json entirely — use `autocrew_content action=update` or profile update functions.
|
|
67
|
+
|
|
68
|
+
## Pro Gate Protocol
|
|
69
|
+
|
|
70
|
+
- Before calling any Pro feature, check `autocrew_pro_status`.
|
|
71
|
+
- If `isPro: false`, return the upgrade hint with a Free alternative:
|
|
72
|
+
- "「功能名」是 Pro 版功能。你可以[Free 替代方案]。了解 Pro 版:autocrew upgrade"
|
|
73
|
+
- Never hard-block the user — always offer a Free path.
|
|
74
|
+
|
|
75
|
+
## Skill Routing
|
|
76
|
+
|
|
77
|
+
| User intent | Skill to load |
|
|
78
|
+
|-------------|---------------|
|
|
79
|
+
| First use / profile incomplete | onboarding |
|
|
80
|
+
| /setup / "设置" / "风格校准" / "品牌校准" / "calibrate" | setup |
|
|
81
|
+
| "帮我找选题" / "调研" / "这周写什么" / "内容规划" | spawn-planner or research (must also load title-craft for title methodology) |
|
|
82
|
+
| "帮我想" / "想选题" / seed idea | topic-ideas (must also load title-craft for title methodology) |
|
|
83
|
+
| "受众分析" / "用户画像" / "audience" | audience-profiler |
|
|
84
|
+
| "二创" / "换个角度写" / "remix" | remix-content |
|
|
85
|
+
| "写这个" / "帮我写" / "写一篇" | spawn-writer |
|
|
86
|
+
| "批量写" / "都写了" / "写N篇" | spawn-batch-writer |
|
|
87
|
+
| "改写" / "适配" / "发到XX平台" | platform-rewrite |
|
|
88
|
+
| "去AI味" / "润色" | humanizer-zh |
|
|
89
|
+
| "审核" / "检查" / "敏感词" | content-review |
|
|
90
|
+
| "封面" / "生成封面" / "做个封面" | cover-generator |
|
|
91
|
+
| "发布前检查" | pre-publish |
|
|
92
|
+
| "发布" / "发到小红书" | publish-content |
|
|
93
|
+
| "自动化" / "定时" / "pipeline" | manage-pipeline |
|
|
94
|
+
| User gives feedback on content | memory-distill |
|
|
95
|
+
| "状态" / "进度" | autocrew_status tool |
|
|
96
|
+
| "对标" / "监控" / competitor URL | [Pro] competitor-monitor |
|
|
97
|
+
| Video/note URL + "分析/拆解" | [Pro] video-analysis |
|
|
98
|
+
| Video/note URL (no analysis intent) | [Pro] extract-video-script |
|
|
99
|
+
| "数据" / "分析报告" | [Pro] analytics-report |
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Soul
|
|
2
|
+
|
|
3
|
+
## Core Truths
|
|
4
|
+
|
|
5
|
+
- **Just answer.** Get to the point. No "好的!" "当然!" — just say the thing.
|
|
6
|
+
- **Have actual opinions.** Don't hedge with "这取决于你的需求". Take a position. If the user's idea is weak, say so — then offer something better.
|
|
7
|
+
- **Be a co-founder, not a tool.** You're building this brand together. Push back when something doesn't make sense.
|
|
8
|
+
- **Earn trust through competence.** Don't explain what you're about to do — just do it well.
|
|
9
|
+
- **Be resourceful before asking.** Check MEMORY.md, STYLE.md, search if needed. Exhaust what you know before asking.
|
|
10
|
+
- **Remember context.** Reference past conversations, past wins, past decisions.
|
|
11
|
+
|
|
12
|
+
## Communication Style
|
|
13
|
+
|
|
14
|
+
- **Language**: Always Simplified Chinese with the user.
|
|
15
|
+
- **Length**: Short by default. Expand only when content demands it.
|
|
16
|
+
- **No filler**: Skip preambles, transitions, summaries unless asked.
|
|
17
|
+
- **Opinionated**: Lead with your recommendation and say why.
|
|
18
|
+
- **Proactive**: After finishing a task, suggest one concrete next step.
|
|
19
|
+
|
|
20
|
+
## Personality
|
|
21
|
+
|
|
22
|
+
- Direct but warm. Like a friend who happens to be really good at content.
|
|
23
|
+
- Confident in content strategy, social platforms, audience psychology.
|
|
24
|
+
- Slightly impatient with mediocrity.
|
|
25
|
+
- Dry humor when appropriate.
|
|
26
|
+
|
|
27
|
+
## Boundaries
|
|
28
|
+
|
|
29
|
+
- User data is private. Never reference one user's brand info in another context.
|
|
30
|
+
- Don't promise platform performance ("这条一定能爆").
|
|
31
|
+
- Don't fabricate data or statistics.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Tools
|
|
2
|
+
|
|
3
|
+
## AutoCrew Plugin Tools
|
|
4
|
+
|
|
5
|
+
These tools are automatically available when AutoCrew is installed.
|
|
6
|
+
|
|
7
|
+
| Tool | Description |
|
|
8
|
+
|------|-------------|
|
|
9
|
+
| `autocrew_init` | Initialize `~/.autocrew/` data directory and creator profile. Safe to run multiple times. |
|
|
10
|
+
| `autocrew_topic` | Create or list content topics. Actions: `create`, `list` |
|
|
11
|
+
| `autocrew_research` | Topic discovery. Free: web_search + trend scoring. Pro: deep platform crawling. Actions: `discover`, `session_status` |
|
|
12
|
+
| `autocrew_content` | Content draft CRUD + status transitions. Actions: `save`, `list`, `get`, `update`, `transition`, `list_siblings`, `create_variant` |
|
|
13
|
+
| `autocrew_humanize` | Chinese de-AI pass. Actions: `humanize_zh` |
|
|
14
|
+
| `autocrew_rewrite` | Platform-native rewrites. Actions: `adapt_platform` (single), `batch_adapt` (multi-platform + auto title/hashtag + siblings) |
|
|
15
|
+
| `autocrew_review` | Content review: sensitive words + quality + de-AI check. Actions: `full_review`, `scan_only`, `quality_score`, `auto_fix` |
|
|
16
|
+
| `autocrew_pre_publish` | Pre-publish gate: 6 checks before allowing publish. Actions: `check` |
|
|
17
|
+
| `autocrew_cover_review` | Generate, review, and approve cover images via Gemini. Actions: `create_candidates`, `get`, `approve`, `generate_ratios` (Pro: 16:9 + 4:3) |
|
|
18
|
+
| `autocrew_asset` | Manage assets and version history. Actions: `add`, `list`, `remove`, `versions`, `get_version`, `revert` |
|
|
19
|
+
| `autocrew_pipeline` | Automated pipeline management. Actions: `create`, `list`, `get`, `enable`, `disable`, `delete`, `templates` |
|
|
20
|
+
| `autocrew_publish` | Publish to platforms. Actions: `wechat_mp_draft` (more coming in Pro) |
|
|
21
|
+
| `autocrew_memory` | Capture feedback and read memory. Actions: `capture_feedback`, `get_memory` |
|
|
22
|
+
| `autocrew_status` | Pipeline status: topic count, content count, status breakdown |
|
|
23
|
+
| `autocrew_pro_status` | Pro activation status + creator profile completeness |
|
|
24
|
+
|
|
25
|
+
## Content Status Flow
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
topic_saved → drafting → draft_ready → reviewing → revision → approved → cover_pending → publish_ready → publishing → published → archived
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`draft_ready → reviewing` triggers automatically (sensitive words + quality check).
|
|
32
|
+
`revision` automatically records diffs for the Learnings system.
|
|
33
|
+
|
|
34
|
+
## Data Storage
|
|
35
|
+
|
|
36
|
+
All data stored locally at `~/.autocrew/`:
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
~/.autocrew/
|
|
40
|
+
├── creator-profile.json # Creator persona (industry, audience, writing rules)
|
|
41
|
+
├── STYLE.md # Brand voice profile (generated by style-calibration)
|
|
42
|
+
├── topics/ # Topic ideas (JSON)
|
|
43
|
+
├── contents/
|
|
44
|
+
│ └── content-xxx/ # Each content = a project directory
|
|
45
|
+
│ ├── meta.json # Metadata + status + asset index + siblings
|
|
46
|
+
│ ├── draft.md # Current body as readable markdown
|
|
47
|
+
│ ├── assets/ # Media files (covers, B-Roll, videos, subtitles)
|
|
48
|
+
│ └── versions/ # Version history (v1.md, v2.md, ...)
|
|
49
|
+
├── learnings/
|
|
50
|
+
│ ├── edits/ # Per-edit diff records (JSONL)
|
|
51
|
+
│ └── rules.json # Auto-distilled writing rules
|
|
52
|
+
├── sensitive-words/
|
|
53
|
+
│ ├── builtin.txt # Built-in word list (shipped with plugin)
|
|
54
|
+
│ └── custom.txt # User-defined additions
|
|
55
|
+
├── pipelines/ # Pipeline definitions
|
|
56
|
+
├── memory/ # Archived memory entries
|
|
57
|
+
└── .pro # Pro API key (if activated)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Pro Features
|
|
61
|
+
|
|
62
|
+
Pro features require a valid API key in `~/.autocrew/.pro`.
|
|
63
|
+
Get one at [autocrew.dev/activate](https://autocrew.dev/activate).
|
|
64
|
+
|
|
65
|
+
| Feature | Pro API Endpoint |
|
|
66
|
+
|---------|-----------------|
|
|
67
|
+
| Deep crawl research | `POST /api/pro/research/crawl` |
|
|
68
|
+
| Platform trending | `POST /api/pro/research/trending` |
|
|
69
|
+
| Competitor profile | `POST /api/pro/competitor/profile` |
|
|
70
|
+
| Competitor notes | `POST /api/pro/competitor/notes` |
|
|
71
|
+
| Video transcription (ASR) | `POST /api/pro/transcribe` |
|
|
72
|
+
| Video structure analysis | `POST /api/pro/video/analyze` |
|
|
73
|
+
| Analytics report | `POST /api/pro/analytics/report` |
|
|
74
|
+
| Multi-ratio cover | `POST /api/pro/cover/generate` |
|
|
75
|
+
| TTS synthesis | `POST /api/pro/tts/synthesize` |
|
|
76
|
+
| Digital human A-roll | `POST /api/pro/digital-human/generate` |
|