@aigne/afs-persona 1.11.0-beta.10
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/LICENSE.md +26 -0
- package/dist/_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.cjs +11 -0
- package/dist/_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.mjs +10 -0
- package/dist/db.cjs +206 -0
- package/dist/db.d.cts +93 -0
- package/dist/db.d.cts.map +1 -0
- package/dist/db.d.mts +93 -0
- package/dist/db.d.mts.map +1 -0
- package/dist/db.mjs +207 -0
- package/dist/db.mjs.map +1 -0
- package/dist/index.cjs +987 -0
- package/dist/index.d.cts +121 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +121 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +987 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["parseYaml","stringifyYaml"],"sources":["../src/index.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"node:fs\";\nimport { readdir } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport {\n type ActionCatalog,\n type ActionDefinition,\n Actions,\n type AFSAccessMode,\n AFSBaseProvider,\n type AFSEntry,\n type AFSExecResult,\n type AFSListResult,\n type AFSModuleLoadParams,\n type AFSRoot,\n type AFSStatResult,\n type CapabilitiesManifest,\n Explain,\n List,\n Meta,\n type ProviderManifest,\n type ProviderTreeSchema,\n Read,\n type RouteContext,\n Stat,\n} from \"@aigne/afs\";\nimport { zodParse } from \"@aigne/afs/utils/zod\";\nimport { joinURL } from \"ufo\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { z } from \"zod\";\nimport { type InteractionRow, PersonaDB } from \"./db.js\";\n\ninterface SessionStep {\n name: string;\n platform: string;\n topic?: string;\n angle?: string | null;\n budget?: { max_rounds?: number };\n}\n\nconst personaOptionsSchema = z.object({\n name: z.string().optional(),\n description: z.string().optional(),\n accessMode: z.enum([\"readonly\", \"readwrite\"]).optional(),\n dataDir: z.string().describe(\"Root data directory for persona storage\"),\n database: z.string().optional().describe(\"SQLite database path (defaults to dataDir/persona.db)\"),\n model: z.string().optional().describe(\"Default LLM model path for ASH agent-run\"),\n ashPath: z.string().optional().describe(\"ASH provider mount path\"),\n tickInterval: z.number().positive().optional().describe(\"Tick interval in milliseconds\"),\n safety: z\n .object({\n blocked_keywords: z.array(z.string()).optional(),\n review_mode: z.enum([\"auto\", \"manual\"]).optional(),\n })\n .optional(),\n});\n\nexport type AFSPersonaOptions = z.infer<typeof personaOptionsSchema>;\n\n// Character name validation: no path traversal, special chars, max 64 chars\nconst INVALID_NAME_PATTERN = /[/\\\\]/;\nconst MAX_NAME_LENGTH = 64;\n\nfunction validateCharacterName(name: unknown): { valid: true } | { valid: false; reason: string } {\n if (typeof name !== \"string\" || name.length === 0) {\n return { valid: false, reason: \"Character name must be a non-empty string\" };\n }\n if (name === \".\" || name === \"..\") {\n return { valid: false, reason: \"Character name cannot be . or ..\" };\n }\n if (name.includes(\"..\")) {\n return { valid: false, reason: \"Character name cannot contain path traversal\" };\n }\n if (INVALID_NAME_PATTERN.test(name)) {\n return { valid: false, reason: \"Character name cannot contain / or \\\\\" };\n }\n if (name.length > MAX_NAME_LENGTH) {\n return { valid: false, reason: `Character name cannot exceed ${MAX_NAME_LENGTH} characters` };\n }\n return { valid: true };\n}\n\nconst WORKSPACE_TOML_TEMPLATE = `[[mounts]]\npath = \"/profile\"\nuri = \"json://./profile.yaml\"\naccess_mode = \"readwrite\"\n\n[[mounts]]\npath = \"/browser\"\nuri = \"mcp+stdio://npx @anthropic-ai/mcp-server-playwright\"\n[mounts.options]\nuserDataDir = \"./browser\"\n\n[[mounts]]\npath = \"/data\"\nuri = \"fs://./data\"\naccess_mode = \"readwrite\"\n`;\n\nexport class AFSPersonaProvider extends AFSBaseProvider {\n override readonly name: string;\n override readonly description?: string;\n override readonly accessMode: AFSAccessMode;\n\n private readonly dataDir: string;\n private readonly database: string;\n private readonly model: string;\n private readonly ashPath: string;\n private readonly tickInterval: number;\n private readonly safety: { blocked_keywords?: string[]; review_mode?: string };\n\n private afs?: AFSRoot;\n private db?: PersonaDB;\n private tickTimer?: ReturnType<typeof setTimeout>;\n private destroyed = false;\n\n constructor(options: AFSPersonaOptions) {\n super();\n\n const validated = personaOptionsSchema.parse(options);\n\n this.name = validated.name || \"persona\";\n this.description = validated.description || \"Virtual persona management\";\n this.accessMode = validated.accessMode || \"readwrite\";\n this.dataDir = resolve(validated.dataDir);\n this.database = validated.database || resolve(this.dataDir, \"persona.db\");\n this.model = validated.model || \"/modules/aignehub/defaults/chat\";\n this.ashPath = validated.ashPath || \"/modules/ash\";\n this.tickInterval = validated.tickInterval || 5 * 60 * 1000;\n this.safety = validated.safety || {};\n\n // Ensure dataDir exists\n if (!existsSync(this.dataDir)) {\n mkdirSync(this.dataDir, { recursive: true });\n }\n }\n\n static schema() {\n return personaOptionsSchema;\n }\n\n static checkKeywords(\n content: string,\n keywords: string[],\n ): { blocked: boolean; keyword?: string } {\n if (!content || keywords.length === 0) return { blocked: false };\n const lowerContent = content.toLowerCase();\n for (const keyword of keywords) {\n if (lowerContent.includes(keyword.toLowerCase())) {\n return { blocked: true, keyword };\n }\n }\n return { blocked: false };\n }\n\n loadBlockedKeywords(): string[] {\n const entries = this.safety.blocked_keywords || [];\n const keywords: string[] = [];\n for (const entry of entries) {\n const resolved = resolve(this.dataDir, entry);\n // Security: must be within dataDir\n if (!resolved.startsWith(`${this.dataDir}/`) && resolved !== this.dataDir) {\n continue;\n }\n if (!existsSync(resolved)) continue;\n const content = readFileSync(resolved, \"utf-8\");\n for (const line of content.split(\"\\n\")) {\n const trimmed = line.trim();\n if (trimmed) keywords.push(trimmed);\n }\n }\n return keywords;\n }\n\n static manifest(): ProviderManifest {\n return {\n name: \"persona\",\n description:\n \"Virtual persona manager — creates isolated character workspaces, drives session-based social media interaction via ASH agent-run.\",\n uriTemplate: \"persona://{dataDir}\",\n category: \"agent\",\n schema: z.object({\n dataDir: z.string(),\n database: z.string().optional(),\n model: z.string().optional(),\n ashPath: z.string().optional(),\n tickInterval: z.number().optional(),\n }),\n tags: [\"persona\", \"social\", \"agent\", \"automation\"],\n capabilityTags: [\"read-write\"],\n security: {\n riskLevel: \"external\",\n resourceAccess: [\"internet\", \"process-spawn\"],\n requires: [\"sqlite\"],\n dataSensitivity: [\"personal-data\"],\n notes: [\"Automates social media interactions via Playwright browser\"],\n },\n };\n }\n\n static treeSchema(): ProviderTreeSchema {\n return {\n operations: [\"list\", \"read\", \"exec\", \"stat\", \"explain\"],\n tree: {\n \"/\": {\n kind: \"persona:root\",\n operations: [\"list\", \"read\"],\n actions: [\"create-character\", \"delete-character\", \"tick\", \"dispatch-task\"],\n },\n \"/characters\": { kind: \"persona:collection\", operations: [\"list\"] },\n \"/characters/{name}\": {\n kind: \"persona:character\",\n operations: [\"list\", \"read\", \"exec\"],\n actions: [\"session\", \"post\", \"reply\", \"pause\", \"resume\"],\n },\n },\n bestFor: [\"persona management\", \"social media automation\", \"character orchestration\"],\n notFor: [\"file storage\", \"databases\"],\n };\n }\n\n static async load({ basePath, config }: AFSModuleLoadParams = {}): Promise<AFSPersonaProvider> {\n const options = zodParse(personaOptionsSchema, config, { prefix: basePath });\n return new AFSPersonaProvider(options);\n }\n\n // ========== Lifecycle ==========\n\n onMount(afs: AFSRoot, _mountPath?: string) {\n this.afs = afs;\n this.scheduleNextTick();\n }\n\n // ========== Helpers ==========\n\n private get charactersDir(): string {\n return resolve(this.dataDir, \"characters\");\n }\n\n private async getCharacterNames(): Promise<string[]> {\n if (!existsSync(this.charactersDir)) {\n return [];\n }\n const entries = await readdir(this.charactersDir, { withFileTypes: true });\n return entries.filter((e) => e.isDirectory()).map((e) => e.name);\n }\n\n private characterDir(name: string): string {\n return resolve(this.charactersDir, name);\n }\n\n private characterProfilePath(name: string): string {\n return resolve(this.characterDir(name), \"profile.yaml\");\n }\n\n private readCharacterProfile(name: string): Record<string, unknown> | null {\n const profilePath = this.characterProfilePath(name);\n if (!existsSync(profilePath)) return null;\n const content = readFileSync(profilePath, \"utf-8\");\n return parseYaml(content) as Record<string, unknown>;\n }\n\n private writeCharacterProfile(name: string, profile: Record<string, unknown>): void {\n const profilePath = this.characterProfilePath(name);\n writeFileSync(profilePath, stringifyYaml(profile), \"utf-8\");\n }\n\n private getDB(): PersonaDB {\n if (!this.db) {\n this.db = new PersonaDB(this.database);\n }\n return this.db;\n }\n\n private scheduleNextTick() {\n if (this.destroyed) return;\n this.tickTimer = setTimeout(async () => {\n try {\n await this.runTick();\n } catch {\n // Swallow error to prevent tick loop from stopping\n }\n this.scheduleNextTick();\n }, this.tickInterval);\n }\n\n private shouldStartSession(gap: number[], offlineMinutes: number): boolean {\n const gapMin = gap[0] ?? 30;\n const gapMax = gap[1] ?? 240;\n\n // Beyond or at max gap: always start\n if (offlineMinutes >= gapMax) return true;\n\n // Below min gap: too early, skip\n if (offlineMinutes < gapMin) return false;\n\n // Degenerate case (gapMin === gapMax handled by >= above)\n if (gapMax <= gapMin) return true;\n\n // Between gapMin and gapMax: probability increases linearly\n const probability = (offlineMinutes - gapMin) / (gapMax - gapMin);\n return Math.random() < probability;\n }\n\n private async runTick(\n characterFilter?: string,\n ): Promise<{ sessions_started: number; stale_recovered: number }> {\n const db = this.getDB();\n\n // Step 1: Stale session recovery\n const stale_recovered = db.markStaleSessions(60);\n\n // Step 2: Get character list\n const characterNames = characterFilter ? [characterFilter] : await this.getCharacterNames();\n\n // Step 3: Process each character sequentially\n let sessions_started = 0;\n\n for (const name of characterNames) {\n const profile = this.readCharacterProfile(name);\n if (!profile) continue;\n\n // Skip paused characters\n if (profile.status === \"paused\") continue;\n\n // Skip characters with running sessions\n const running = db.getRunningSession(name);\n if (running) continue;\n\n // Get last completed session for gap calculation\n const lastDone = db.getLastDoneSession(name);\n let offlineMinutes: number;\n\n if (!lastDone || !lastDone.ended_at) {\n // No completed session → treat as first time → always start\n offlineMinutes = Number.POSITIVE_INFINITY;\n } else {\n const endedAt = new Date(lastDone.ended_at).getTime();\n offlineMinutes = (Date.now() - endedAt) / (60 * 1000);\n }\n\n // Gap-based scheduling decision\n const gap = Array.isArray(profile.gap) ? (profile.gap as number[]) : [30, 240];\n if (!this.shouldStartSession(gap, offlineMinutes)) continue;\n\n // Mock session: create and immediately complete (Phase 3 behavior)\n const sessionId = db.insertSession(name);\n db.updateSession(sessionId, {\n status: \"done\",\n ended_at: new Date().toISOString(),\n });\n sessions_started++;\n }\n\n return { sessions_started, stale_recovered };\n }\n\n // ========== Session Runner ==========\n\n private async runSessionSteps(\n name: string,\n profile: Record<string, unknown>,\n _sessionId: number,\n ): Promise<Record<string, unknown>> {\n const db = this.getDB();\n const platforms = (profile.platforms as string[]) || [];\n const model = (profile.model as string) || this.model;\n const recentInteractions = db.getRecentInteractions(name, 10);\n\n let steps_completed = 0;\n let interactions_saved = 0;\n\n for (const platform of platforms) {\n const steps = this.buildStepsForPlatform(name, platform);\n\n for (const step of steps) {\n const result = await this.executeStep(\n name,\n profile,\n platform,\n step,\n model,\n recentInteractions,\n );\n\n // Save trace regardless of outcome\n if (result.trace) {\n try {\n db.insertInteraction({\n character: name,\n platform,\n type: step.name,\n content: null,\n metadata: {\n step: step.name,\n trace_rounds: Array.isArray(result.trace) ? result.trace.length : 0,\n status: result.status,\n },\n });\n interactions_saved++;\n } catch {\n // saveTrace failure should not affect other traces\n }\n }\n\n if (result.status === \"error\") {\n throw new Error(`Step '${step.name}' failed`);\n }\n\n // budget_exhausted → counted as attempted but not completed\n if (result.status !== \"budget_exhausted\") {\n steps_completed++;\n }\n }\n }\n\n return { steps_completed, interactions_saved };\n }\n\n private buildStepsForPlatform(name: string, platform: string): SessionStep[] {\n const db = this.getDB();\n const steps: SessionStep[] = [\n { name: \"notifications\", platform, budget: { max_rounds: 15 } },\n { name: \"browse\", platform, budget: { max_rounds: 25 } },\n ];\n\n // Probabilistic original post (~30% chance)\n if (Math.random() < 0.3) {\n steps.push({ name: \"post\", platform, budget: { max_rounds: 20 } });\n }\n\n // Seeded topics (pending only; expired excluded by query filter)\n const seededTopics = db.getSeededTopics(name, \"pending\");\n for (const topic of seededTopics) {\n const claimed = db.claimSeededTopic(topic.id, topic.task_id);\n if (claimed) {\n steps.push({\n name: \"seeded_topic\",\n platform,\n topic: topic.topic,\n angle: topic.angle,\n budget: { max_rounds: 20 },\n });\n }\n }\n\n return steps;\n }\n\n private async executeStep(\n name: string,\n profile: Record<string, unknown>,\n platform: string,\n step: SessionStep,\n model: string,\n recentInteractions: InteractionRow[],\n ): Promise<{ status: string; trace?: unknown[]; error?: string }> {\n const system = this.buildSystemPrompt(name, profile, platform, recentInteractions);\n const tools = this.buildToolsWhitelist(name);\n const task = this.buildStepTask(step, name, platform);\n\n try {\n const result = await this.afs!.exec!(\n joinURL(this.ashPath, \".actions/agent-run\"),\n {\n task,\n model,\n system,\n tools,\n budget: step.budget,\n },\n {},\n );\n\n if (!result.success) {\n return { status: \"error\", error: result.error?.message };\n }\n\n const data = result.data || {};\n const trace = data.trace as unknown[] | undefined;\n\n if (data.status === \"error\") {\n return { status: \"error\", error: String(data.message || \"Unknown error\"), trace };\n }\n if (data.status === \"budget_exhausted\") {\n return { status: \"budget_exhausted\", trace };\n }\n\n return { status: \"completed\", trace };\n } catch (e) {\n return { status: \"error\", error: e instanceof Error ? e.message : \"Unknown error\" };\n }\n }\n\n private buildSystemPrompt(\n name: string,\n profile: Record<string, unknown>,\n platform: string,\n recentInteractions: InteractionRow[],\n ): string {\n const personality = (profile.personality as Record<string, string>) || {};\n const interests = (profile.interests as Array<{ topic: string }>) || [];\n\n const parts: string[] = [];\n parts.push(`你是 ${name}。${personality.tone || \"neutral\"}。`);\n parts.push(\n `兴趣:${interests.map((i) => i.topic).join(\", \") || \"广泛\"}。风格:${personality.style || \"简洁\"}。语言:${personality.language || \"en\"}。`,\n );\n\n if (recentInteractions.length > 0) {\n parts.push(\"最近发过的内容:\");\n for (const interaction of recentInteractions.slice(0, 5)) {\n parts.push(`- [${interaction.type}] ${interaction.content || \"(no content)\"}`);\n }\n }\n\n parts.push(`当前平台:${platform}`);\n return parts.join(\"\\n\");\n }\n\n private buildToolsWhitelist(characterName: string): object[] {\n return [\n {\n path: `/modules/persona/characters/${characterName}/browser/tools/*`,\n ops: [\"exec\"],\n },\n {\n path: `/modules/persona/characters/${characterName}/browser/tools`,\n ops: [\"list\"],\n },\n {\n path: `/modules/persona/characters/${characterName}/profile/**`,\n ops: [\"read\", \"list\"],\n maxDepth: 3,\n },\n {\n path: `/modules/persona/characters/${characterName}/data/**`,\n ops: [\"read\", \"write\", \"list\"],\n maxDepth: 3,\n },\n ];\n }\n\n private buildStepTask(step: SessionStep, name: string, platform: string): string {\n switch (step.name) {\n case \"notifications\":\n return `Check notifications on ${platform} and reply to any mentions or messages as ${name}.`;\n case \"browse\":\n return `Browse the ${platform} feed, engage with interesting posts that match your interests.`;\n case \"post\":\n return `Create an original post on ${platform} about something you find interesting, in character as ${name}.`;\n case \"seeded_topic\":\n return `Create a post on ${platform} about: ${step.topic}. ${step.angle ? `Angle: ${step.angle}.` : \"\"} Make it natural and in-character as ${name}.`;\n default:\n return `Perform ${step.name} on ${platform} as ${name}.`;\n }\n }\n\n private buildActionEntry(name: string, description: string, basePath = \"/\"): AFSEntry {\n return {\n id: name,\n path: joinURL(basePath, \".actions\", name),\n summary: name,\n meta: {\n kind: \"afs:executable\",\n name,\n description,\n },\n actions: [{ name, description }],\n };\n }\n\n // ========== List Operations ==========\n\n @List(\"/\")\n async listRoot(_ctx: RouteContext): Promise<AFSListResult> {\n const characterNames = await this.getCharacterNames();\n return {\n data: [\n {\n id: \"persona:characters\",\n path: \"/characters\",\n meta: {\n kind: \"persona:collection\",\n childrenCount: characterNames.length,\n },\n },\n ],\n };\n }\n\n @List(\"/characters\")\n async listCharacters(_ctx: RouteContext): Promise<AFSListResult> {\n const characterNames = await this.getCharacterNames();\n const entries: AFSEntry[] = characterNames.map((name) => ({\n id: `persona:character:${name}`,\n path: joinURL(\"/characters\", name),\n meta: {\n kind: \"persona:character\",\n childrenCount: -1,\n },\n }));\n return { data: entries };\n }\n\n // ========== Read Operations ==========\n\n @Read(\"/\")\n async readRoot(_ctx: RouteContext): Promise<AFSEntry> {\n const characterNames = await this.getCharacterNames();\n return {\n id: \"persona:root\",\n path: \"/\",\n content: {\n type: \"persona-provider\",\n characterCount: characterNames.length,\n },\n meta: {\n kind: \"persona:root\",\n childrenCount: 1,\n },\n };\n }\n\n @Read(\"/characters\")\n async readCharacters(_ctx: RouteContext): Promise<AFSEntry> {\n const characterNames = await this.getCharacterNames();\n return {\n id: \"persona:characters\",\n path: \"/characters\",\n content: {\n type: \"directory\",\n count: characterNames.length,\n },\n meta: {\n kind: \"persona:collection\",\n childrenCount: characterNames.length,\n },\n };\n }\n\n @Read(\"/characters/:name\")\n async readCharacter(ctx: RouteContext): Promise<AFSEntry> {\n const name = ctx.params?.name as string;\n const profile = this.readCharacterProfile(name);\n if (!profile) {\n throw new Error(`Character not found: ${name}`);\n }\n return {\n id: `persona:character:${name}`,\n path: joinURL(\"/characters\", name),\n content: profile,\n meta: {\n kind: \"persona:character\",\n childrenCount: -1,\n },\n };\n }\n\n // ========== Meta Operations ==========\n\n @Meta(\"/\")\n async metaRoot(_ctx: RouteContext): Promise<AFSEntry> {\n const characterNames = await this.getCharacterNames();\n return {\n id: \"persona:root\",\n path: \"/.meta\",\n content: {\n characterCount: characterNames.length,\n provider: \"persona\",\n },\n meta: {\n kind: \"persona:root\",\n childrenCount: 1,\n },\n };\n }\n\n @Meta(\"/characters\")\n async metaCharacters(_ctx: RouteContext): Promise<AFSEntry> {\n const characterNames = await this.getCharacterNames();\n return {\n id: \"persona:characters\",\n path: \"/characters/.meta\",\n content: {\n type: \"collection\",\n count: characterNames.length,\n },\n meta: {\n kind: \"persona:collection\",\n childrenCount: characterNames.length,\n },\n };\n }\n\n // ========== Capabilities ==========\n\n @Read(\"/.meta/.capabilities\")\n async readCapabilities(_ctx: RouteContext): Promise<AFSEntry> {\n const rootActions: ActionDefinition[] = [\n {\n name: \"create-character\",\n description: \"Create a new character workspace\",\n inputSchema: {\n type: \"object\",\n properties: {\n name: { type: \"string\", description: \"Character name\" },\n profile: { type: \"object\", description: \"Character profile data\" },\n },\n required: [\"name\", \"profile\"],\n },\n },\n {\n name: \"delete-character\",\n description: \"Remove a character and optionally archive\",\n inputSchema: {\n type: \"object\",\n properties: {\n name: { type: \"string\" },\n archive: { type: \"boolean\" },\n },\n required: [\"name\"],\n },\n },\n {\n name: \"tick\",\n description: \"Check and run due sessions\",\n inputSchema: {\n type: \"object\",\n properties: {\n character: { type: \"string\", description: \"Optional: tick single character\" },\n },\n },\n },\n {\n name: \"dispatch-task\",\n description: \"Seed topic into characters' feeds\",\n inputSchema: {\n type: \"object\",\n properties: {\n topic: { type: \"string\" },\n goal: { type: \"string\" },\n },\n required: [\"topic\", \"goal\"],\n },\n },\n ];\n\n const actionCatalogs: ActionCatalog[] = [\n {\n kind: \"persona:root\",\n description: \"Root-level persona management actions\",\n catalog: rootActions,\n discovery: {\n pathTemplate: \"/.actions\",\n note: \"Root actions for persona management\",\n },\n },\n ];\n\n const manifest: CapabilitiesManifest = {\n schemaVersion: 1,\n provider: \"persona\",\n description:\n \"Virtual persona management — character lifecycle, session scheduling, social media automation\",\n tools: [],\n actions: actionCatalogs,\n operations: {\n list: true,\n read: true,\n write: false,\n delete: false,\n search: false,\n exec: true,\n stat: true,\n explain: true,\n },\n };\n\n return {\n id: \"/.meta/.capabilities\",\n path: \"/.meta/.capabilities\",\n content: manifest,\n meta: { kind: \"afs:capabilities\" },\n };\n }\n\n // ========== Stat Operations ==========\n\n @Stat(\"/\")\n async statRoot(_ctx: RouteContext): Promise<AFSStatResult> {\n return {\n data: {\n id: \"persona:root\",\n path: \"/\",\n meta: {\n kind: \"persona:root\",\n childrenCount: 1,\n },\n },\n };\n }\n\n @Stat(\"/characters\")\n async statCharacters(_ctx: RouteContext): Promise<AFSStatResult> {\n const characterNames = await this.getCharacterNames();\n return {\n data: {\n id: \"persona:characters\",\n path: \"/characters\",\n meta: {\n kind: \"persona:collection\",\n childrenCount: characterNames.length,\n },\n },\n };\n }\n\n // ========== Explain Operations ==========\n\n @Explain(\"/\")\n async explainRoot(_ctx: RouteContext) {\n return {\n format: \"markdown\" as const,\n content: [\n \"# Persona Provider\",\n \"\",\n \"Manages virtual characters that autonomously interact on social platforms.\",\n \"\",\n \"## Actions\",\n \"- `create-character` — Create a new character workspace\",\n \"- `delete-character` — Remove a character and optionally archive\",\n \"- `tick` — Check and run due sessions\",\n \"- `dispatch-task` — Seed topic into characters' feeds\",\n \"\",\n \"## Structure\",\n \"- `/characters/` — Character workspaces\",\n ].join(\"\\n\"),\n };\n }\n\n // ========== Root Actions ==========\n\n @Actions(\"/\")\n async listRootActions(_ctx: RouteContext): Promise<AFSListResult> {\n return {\n data: [\n this.buildActionEntry(\"create-character\", \"Create a new character workspace\"),\n this.buildActionEntry(\"delete-character\", \"Remove a character and optionally archive\"),\n this.buildActionEntry(\"tick\", \"Check and run due sessions\"),\n this.buildActionEntry(\"dispatch-task\", \"Seed topic into characters' feeds\"),\n ],\n };\n }\n\n @Actions.Exec(\"/\", \"create-character\")\n async execCreateCharacter(\n _ctx: RouteContext,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const nameResult = validateCharacterName(args.name);\n if (!nameResult.valid) {\n return { success: false, error: { code: \"INVALID_NAME\", message: nameResult.reason } };\n }\n\n const name = args.name as string;\n const charDir = this.characterDir(name);\n\n if (existsSync(charDir)) {\n return {\n success: false,\n error: { code: \"ALREADY_EXISTS\", message: `Character '${name}' already exists` },\n };\n }\n\n // Create directory structure\n mkdirSync(charDir, { recursive: true });\n mkdirSync(resolve(charDir, \"browser\"), { recursive: true });\n mkdirSync(resolve(charDir, \"data\"), { recursive: true });\n\n // Build profile with defaults\n const profileInput = (args.profile as Record<string, unknown>) || {};\n const profile: Record<string, unknown> = {\n name,\n description: profileInput.description || \"\",\n model: profileInput.model || undefined,\n timezone: profileInput.timezone || \"UTC\",\n gap: profileInput.gap || [30, 240],\n platforms: profileInput.platforms || [\"x\"],\n interests: profileInput.interests || [],\n personality: profileInput.personality || {\n tone: \"neutral\",\n style: \"concise\",\n language: \"en\",\n },\n reply_policy: profileInput.reply_policy || { enabled: true, max_daily: 10 },\n status: \"active\",\n };\n\n // Write profile.yaml\n this.writeCharacterProfile(name, profile);\n\n // Write .afs-workspace.toml\n writeFileSync(resolve(charDir, \".afs-workspace.toml\"), WORKSPACE_TOML_TEMPLATE, \"utf-8\");\n\n return {\n success: true,\n data: { name, path: joinURL(\"/characters\", name) },\n };\n }\n\n @Actions.Exec(\"/\", \"delete-character\")\n async execDeleteCharacter(\n _ctx: RouteContext,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const nameResult = validateCharacterName(args.name);\n if (!nameResult.valid) {\n return { success: false, error: { code: \"INVALID_NAME\", message: nameResult.reason } };\n }\n\n const name = args.name as string;\n const charDir = this.characterDir(name);\n\n if (!existsSync(charDir)) {\n return {\n success: false,\n error: { code: \"NOT_FOUND\", message: `Character '${name}' not found` },\n };\n }\n\n if (args.archive) {\n // Move to archive/\n const archiveDir = resolve(this.dataDir, \"archive\");\n if (!existsSync(archiveDir)) {\n mkdirSync(archiveDir, { recursive: true });\n }\n renameSync(charDir, resolve(archiveDir, name));\n } else {\n rmSync(charDir, { recursive: true, force: true });\n }\n\n return { success: true };\n }\n\n @Actions.Exec(\"/\", \"tick\")\n async execTick(_ctx: RouteContext, args: Record<string, unknown>): Promise<AFSExecResult> {\n const characterFilter = args.character as string | undefined;\n\n // Validate character exists if specified\n if (characterFilter) {\n const profile = this.readCharacterProfile(characterFilter);\n if (!profile) {\n return {\n success: false,\n error: { code: \"NOT_FOUND\", message: `Character '${characterFilter}' not found` },\n };\n }\n }\n\n try {\n const result = await this.runTick(characterFilter);\n return { success: true, data: result };\n } catch (e) {\n return {\n success: false,\n error: { code: \"TICK_ERROR\", message: e instanceof Error ? e.message : \"Unknown error\" },\n };\n }\n }\n\n @Actions.Exec(\"/\", \"dispatch-task\")\n async execDispatchTask(\n _ctx: RouteContext,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const topic = args.topic as string | undefined;\n if (!topic) {\n return {\n success: false,\n error: { code: \"INVALID_INPUT\", message: \"topic is required\" },\n };\n }\n\n const goal = args.goal as string | undefined;\n const selectCount = args.select_count as number | undefined;\n const material = args.material as Record<string, unknown> | undefined;\n\n // Get all active characters and their interests\n const characterNames = await this.getCharacterNames();\n const activeChars: Array<{\n name: string;\n interests: Array<{ topic: string; weight: number }>;\n }> = [];\n\n for (const name of characterNames) {\n const profile = this.readCharacterProfile(name);\n if (!profile || profile.status === \"paused\") continue;\n const interests = (profile.interests as Array<{ topic: string; weight: number }>) || [];\n activeChars.push({ name, interests });\n }\n\n // Filter by interest matching (dispatch topic contains interest topic)\n const topicLower = topic.toLowerCase();\n const matched = activeChars.filter((char) =>\n char.interests.some((i) => topicLower.includes(i.topic.toLowerCase())),\n );\n\n // Apply select_count limit\n let selected = matched;\n if (selectCount !== undefined && selectCount < matched.length) {\n selected = [...matched].sort(() => Math.random() - 0.5).slice(0, selectCount);\n }\n\n if (selected.length === 0) {\n return {\n success: true,\n data: {\n assigned: [],\n angles: {},\n warning: \"No characters matched the given topic\",\n },\n };\n }\n\n // Generate task_id\n const taskId = `task-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n\n // Generate angles per character based on their matching interest\n const angles: Record<string, string> = {};\n for (const char of selected) {\n const matchingInterest = char.interests.find((i) =>\n topicLower.includes(i.topic.toLowerCase()),\n );\n angles[char.name] = `From ${matchingInterest?.topic || \"general\"} perspective on ${topic}`;\n }\n\n const db = this.getDB();\n const assigned = selected.map((c) => c.name);\n\n // Insert task record\n db.insertTask({\n id: taskId,\n topic,\n goal: goal ?? null,\n material: material ?? null,\n assignments: Object.fromEntries(assigned.map((n) => [n, angles[n]!])),\n });\n\n // Insert seeded_topics for each assigned character\n for (const name of assigned) {\n db.insertSeededTopic({\n character: name,\n task_id: taskId,\n topic,\n angle: angles[name],\n });\n }\n\n return {\n success: true,\n data: { task_id: taskId, assigned, angles },\n };\n }\n\n // ========== Per-Character Actions ==========\n\n @Actions(\"/characters/:name\")\n async listCharacterActions(ctx: RouteContext): Promise<AFSListResult> {\n const name = ctx.params?.name as string;\n const basePath = joinURL(\"/characters\", name);\n return {\n data: [\n this.buildActionEntry(\"session\", \"Run one browsing session\", basePath),\n this.buildActionEntry(\"post\", \"Manual post trigger\", basePath),\n this.buildActionEntry(\"reply\", \"Manual reply trigger\", basePath),\n this.buildActionEntry(\"pause\", \"Pause character scheduling\", basePath),\n this.buildActionEntry(\"resume\", \"Resume character scheduling\", basePath),\n ],\n };\n }\n\n @Actions.Exec(\"/characters/:name\", \"pause\")\n async execPause(ctx: RouteContext, _args: Record<string, unknown>): Promise<AFSExecResult> {\n const name = ctx.params?.name as string;\n const profile = this.readCharacterProfile(name);\n if (!profile) {\n return {\n success: false,\n error: { code: \"NOT_FOUND\", message: `Character '${name}' not found` },\n };\n }\n\n profile.status = \"paused\";\n this.writeCharacterProfile(name, profile);\n return { success: true, data: { name, status: \"paused\" } };\n }\n\n @Actions.Exec(\"/characters/:name\", \"resume\")\n async execResume(ctx: RouteContext, _args: Record<string, unknown>): Promise<AFSExecResult> {\n const name = ctx.params?.name as string;\n const profile = this.readCharacterProfile(name);\n if (!profile) {\n return {\n success: false,\n error: { code: \"NOT_FOUND\", message: `Character '${name}' not found` },\n };\n }\n\n profile.status = \"active\";\n this.writeCharacterProfile(name, profile);\n return { success: true, data: { name, status: \"active\" } };\n }\n\n @Actions.Exec(\"/characters/:name\", \"session\")\n async execSession(ctx: RouteContext, _args: Record<string, unknown>): Promise<AFSExecResult> {\n const name = ctx.params?.name as string;\n const profile = this.readCharacterProfile(name);\n if (!profile) {\n return {\n success: false,\n error: { code: \"NOT_FOUND\", message: `Character '${name}' not found` },\n };\n }\n\n if (!this.afs) {\n return {\n success: false,\n error: { code: \"NOT_MOUNTED\", message: \"Provider not mounted to AFS\" },\n };\n }\n\n const db = this.getDB();\n const sessionId = db.insertSession(name);\n\n try {\n const result = await this.runSessionSteps(name, profile, sessionId);\n db.updateSession(sessionId, { status: \"done\", ended_at: new Date().toISOString() });\n return { success: true, data: result };\n } catch {\n db.updateSession(sessionId, { status: \"failed\", ended_at: new Date().toISOString() });\n return {\n success: false,\n error: { code: \"SESSION_FAILED\", message: `Session failed for character '${name}'` },\n };\n }\n }\n\n @Actions.Exec(\"/characters/:name\", \"post\")\n async execPost(_ctx: RouteContext, _args: Record<string, unknown>): Promise<AFSExecResult> {\n // Phase 4: full implementation\n return { success: false, error: { code: \"NOT_IMPLEMENTED\", message: \"Not implemented yet\" } };\n }\n\n @Actions.Exec(\"/characters/:name\", \"reply\")\n async execReply(_ctx: RouteContext, _args: Record<string, unknown>): Promise<AFSExecResult> {\n // Phase 4: full implementation\n return { success: false, error: { code: \"NOT_IMPLEMENTED\", message: \"Not implemented yet\" } };\n }\n\n // ========== Cleanup ==========\n\n destroy() {\n this.destroyed = true;\n if (this.tickTimer) {\n clearTimeout(this.tickTimer);\n this.tickTimer = undefined;\n }\n if (this.db) {\n this.db.close();\n this.db = undefined;\n }\n }\n}\n\nexport type AFSPersonaProviderClass = typeof AFSPersonaProvider;\n\nexport type { InteractionRow, SeededTopicRow, SessionRow, TaskRow } from \"./db.js\";\nexport { PersonaDB } from \"./db.js\";\n"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aigne/afs-persona",
|
|
3
|
+
"version": "1.11.0-beta.10",
|
|
4
|
+
"description": "AIGNE AFS module for managing virtual personas on social platforms",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public"
|
|
8
|
+
},
|
|
9
|
+
"author": "Arcblock <blocklet@arcblock.io> https://github.com/arcblock",
|
|
10
|
+
"homepage": "https://github.com/arcblock/afs",
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/arcblock/afs"
|
|
14
|
+
},
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/arcblock/afs/issues"
|
|
17
|
+
},
|
|
18
|
+
"type": "module",
|
|
19
|
+
"main": "./dist/index.cjs",
|
|
20
|
+
"module": "./dist/index.mjs",
|
|
21
|
+
"types": "./dist/index.d.cts",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"require": "./dist/index.cjs",
|
|
25
|
+
"import": "./dist/index.mjs"
|
|
26
|
+
},
|
|
27
|
+
"./*": "./*"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist",
|
|
31
|
+
"LICENSE",
|
|
32
|
+
"README.md",
|
|
33
|
+
"CHANGELOG.md"
|
|
34
|
+
],
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"ufo": "^1.6.3",
|
|
37
|
+
"yaml": "^2.8.1",
|
|
38
|
+
"zod": "^4.0.0",
|
|
39
|
+
"@aigne/afs": "^1.11.0-beta.11"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/bun": "^1.3.6",
|
|
43
|
+
"npm-run-all": "^4.1.5",
|
|
44
|
+
"rimraf": "^6.1.2",
|
|
45
|
+
"tsdown": "0.20.0-beta.3",
|
|
46
|
+
"typescript": "5.9.2",
|
|
47
|
+
"@aigne/typescript-config": "0.0.0",
|
|
48
|
+
"@aigne/scripts": "0.0.0",
|
|
49
|
+
"@aigne/afs-testing": "1.11.0-beta.11"
|
|
50
|
+
},
|
|
51
|
+
"scripts": {
|
|
52
|
+
"build": "tsdown",
|
|
53
|
+
"check-types": "tsc --noEmit",
|
|
54
|
+
"clean": "rimraf dist coverage",
|
|
55
|
+
"test": "bun test",
|
|
56
|
+
"test:coverage": "bun test --coverage --coverage-reporter=lcov --coverage-reporter=text"
|
|
57
|
+
}
|
|
58
|
+
}
|