feat: sync full workspace including web modules, docs, and configurations to Gitea

Optimized the root .gitignore to exclude virtual environments, node modules,
and temp folders to ensure clean and lightweight version tracking.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
王冕
2026-06-09 18:12:25 +08:00
parent 351688006e
commit a27e3b8e43
1510 changed files with 162044 additions and 1517 deletions

View File

@@ -0,0 +1,213 @@
const PROJECT_BLOCK_SPLIT_REGEX = /(?=\[\[projects\]\])/;
const PROJECT_NAME_REGEX = /name\s*=\s*"([^"]+)"/;
const PROJECT_AGENT_TYPE_REGEX = /\[projects\.agent\]\s*\ntype\s*=\s*"([^"]+)"/;
const PROJECT_WORK_DIR_REGEX = /\[projects\.agent\.options\][\s\S]*?work_dir\s*=\s*"([^"]*)"/;
const WEIXIN_OPTIONS_SECTION_REGEX = /(\[\[projects\.platforms\]\]\s*\ntype\s*=\s*"weixin"\s*\n\s*\n\[projects\.platforms\.options\]\s*\n)([\s\S]*?)(?=\n\[\[projects\]\]|$)/;
const OPTION_LINE_REGEX = /^([a-zA-Z0-9_]+)\s*=\s*"((?:[^"\\]|\\.)*)"$/gm;
export interface AxhubWeixinState<TAgent extends string = string> {
version: 1;
configuredAgents: TAgent[];
activeAgent: TAgent;
workDir: string;
weixinOptions: Record<string, string>;
}
interface ParsedProjectBlock {
name: string | null;
agentType: string | null;
workDir: string | null;
weixinOptions: Record<string, string> | null;
}
function unescapeTomlString(value: string): string {
return value
.replace(/\\\\/g, '\\')
.replace(/\\"/g, '"')
.replace(/\\n/g, '\n')
.replace(/\\r/g, '\r')
.replace(/\\t/g, '\t');
}
function escapeTomlString(value: string): string {
return value
.replace(/\\/g, '\\\\')
.replace(/"/g, '\\"')
.replace(/\n/g, '\\n')
.replace(/\r/g, '\\r')
.replace(/\t/g, '\\t');
}
function parseTomlOptionsBody(body: string): Record<string, string> {
const options: Record<string, string> = {};
for (const match of body.matchAll(OPTION_LINE_REGEX)) {
options[match[1]] = unescapeTomlString(match[2]);
}
return options;
}
function parseProjectBlocks(content: string): ParsedProjectBlock[] {
return content
.split(PROJECT_BLOCK_SPLIT_REGEX)
.filter((block) => block.includes('[[projects]]'))
.map((block) => {
const weixinMatch = block.match(WEIXIN_OPTIONS_SECTION_REGEX);
return {
name: block.match(PROJECT_NAME_REGEX)?.[1] || null,
agentType: block.match(PROJECT_AGENT_TYPE_REGEX)?.[1] || null,
workDir: block.match(PROJECT_WORK_DIR_REGEX)?.[1] || null,
weixinOptions: weixinMatch ? parseTomlOptionsBody(weixinMatch[2]) : null,
};
});
}
function getPreferredOptionKeys(options: Record<string, string>): string[] {
const preferred = ['token', 'base_url', 'account_id', 'allow_from', 'admin_from'];
const remaining = Object.keys(options)
.filter((key) => !preferred.includes(key))
.sort();
return [...preferred.filter((key) => key in options), ...remaining];
}
function serializeTomlOptions(options: Record<string, string>): string {
return getPreferredOptionKeys(options)
.map((key) => `${key} = "${escapeTomlString(options[key])}"`)
.join('\n');
}
function buildHeader(): string {
return `# Auto-generated by Axhub Make — cc-connect WeChat integration
# language = "zh"
[log]
level = "info"
`;
}
export function findActiveAgentFromConfig<TAgent extends string>(params: {
content: string;
supportedAgents: TAgent[];
blockedUserId: string;
}): TAgent | null {
const { content, supportedAgents, blockedUserId } = params;
const supportedAgentSet = new Set<string>(supportedAgents);
for (const project of parseProjectBlocks(content)) {
if (!project.agentType || !supportedAgentSet.has(project.agentType)) continue;
const allowFrom = project.weixinOptions?.allow_from;
if (allowFrom && allowFrom !== blockedUserId && allowFrom.includes('@im.wechat')) {
return project.agentType as TAgent;
}
}
return null;
}
export function createAxhubWeixinStateFromConfig<TAgent extends string>(params: {
content: string;
supportedAgents: TAgent[];
blockedUserId: string;
preferredActiveAgent?: TAgent | null;
recoveredAllowFrom?: string | null;
}): AxhubWeixinState<TAgent> | null {
const {
content,
supportedAgents,
blockedUserId,
preferredActiveAgent = null,
recoveredAllowFrom = null,
} = params;
const supportedAgentSet = new Set<string>(supportedAgents);
const projects = parseProjectBlocks(content).filter((project) => {
return (
!!project.agentType &&
supportedAgentSet.has(project.agentType) &&
!!project.weixinOptions?.token
);
});
if (projects.length === 0) {
return null;
}
const configuredAgents = supportedAgents.filter((agent) => {
return projects.some((project) => project.agentType === agent);
});
if (configuredAgents.length === 0) {
return null;
}
const activeAgentFromConfig = findActiveAgentFromConfig({
content,
supportedAgents: configuredAgents,
blockedUserId,
});
const activeAgent = activeAgentFromConfig
|| (preferredActiveAgent && configuredAgents.includes(preferredActiveAgent) ? preferredActiveAgent : null)
|| configuredAgents[0];
const activeProject = projects.find((project) => project.agentType === activeAgent) || projects[0];
const allowFrom = activeProject.weixinOptions?.allow_from
&& activeProject.weixinOptions.allow_from !== blockedUserId
&& activeProject.weixinOptions.allow_from.includes('@im.wechat')
? activeProject.weixinOptions.allow_from
: recoveredAllowFrom;
if (!allowFrom) {
return null;
}
return {
version: 1,
configuredAgents,
activeAgent,
workDir: activeProject.workDir || '',
weixinOptions: {
...(activeProject.weixinOptions || {}),
allow_from: allowFrom,
},
};
}
export function generateSingleAgentConfigToml<TAgent extends string>(params: {
agent: TAgent;
workDir: string;
weixinOptions: Record<string, string>;
}): string {
const { agent, workDir, weixinOptions } = params;
return `${buildHeader()}[[projects]]
name = "axhub-${escapeTomlString(agent)}"
[projects.agent]
type = "${escapeTomlString(agent)}"
[projects.agent.options]
work_dir = "${escapeTomlString(workDir)}"
mode = "yolo"
[[projects.platforms]]
type = "weixin"
[projects.platforms.options]
${serializeTomlOptions(weixinOptions)}
`;
}
export function generateWeixinSetupConfigToml<TAgent extends string>(params: {
agent: TAgent;
workDir: string;
}): string {
const { agent, workDir } = params;
return generateSingleAgentConfigToml({
agent,
workDir,
weixinOptions: {
token: '',
},
});
}