mirror of
https://github.com/hansjone/oclaw.git
synced 2026-10-11 03:00:45 +08:00
重构主控编排与运行时预热链路,统一工作区提示词/专家调度协议并补齐 wiki 记忆注入与写回闭环。
同时收敛启动与运维脚本默认行为(含 wiki worker)、更新 Admin 可观测性与相关测试,降低首轮时延并提高运行稳定性。 Made-with: Cursor
This commit is contained in:
parent
4a23b715a2
commit
dbbe3add6a
14438 changed files with 2693620 additions and 2546 deletions
258
openclaw/extensions/memory-wiki/src/config.ts
Normal file
258
openclaw/extensions/memory-wiki/src/config.ts
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { buildPluginConfigSchema, z, type OpenClawPluginConfigSchema } from "../api.js";
|
||||
|
||||
export const WIKI_VAULT_MODES = ["isolated", "bridge", "unsafe-local"] as const;
|
||||
export const WIKI_RENDER_MODES = ["native", "obsidian"] as const;
|
||||
export const WIKI_SEARCH_BACKENDS = ["shared", "local"] as const;
|
||||
export const WIKI_SEARCH_CORPORA = ["wiki", "memory", "all"] as const;
|
||||
|
||||
export type WikiVaultMode = (typeof WIKI_VAULT_MODES)[number];
|
||||
export type WikiRenderMode = (typeof WIKI_RENDER_MODES)[number];
|
||||
export type WikiSearchBackend = (typeof WIKI_SEARCH_BACKENDS)[number];
|
||||
export type WikiSearchCorpus = (typeof WIKI_SEARCH_CORPORA)[number];
|
||||
|
||||
export type MemoryWikiPluginConfig = {
|
||||
vaultMode?: WikiVaultMode;
|
||||
vault?: {
|
||||
path?: string;
|
||||
renderMode?: WikiRenderMode;
|
||||
};
|
||||
obsidian?: {
|
||||
enabled?: boolean;
|
||||
useOfficialCli?: boolean;
|
||||
vaultName?: string;
|
||||
openAfterWrites?: boolean;
|
||||
};
|
||||
bridge?: {
|
||||
enabled?: boolean;
|
||||
readMemoryArtifacts?: boolean;
|
||||
indexDreamReports?: boolean;
|
||||
indexDailyNotes?: boolean;
|
||||
indexMemoryRoot?: boolean;
|
||||
followMemoryEvents?: boolean;
|
||||
};
|
||||
unsafeLocal?: {
|
||||
allowPrivateMemoryCoreAccess?: boolean;
|
||||
paths?: string[];
|
||||
};
|
||||
ingest?: {
|
||||
autoCompile?: boolean;
|
||||
maxConcurrentJobs?: number;
|
||||
allowUrlIngest?: boolean;
|
||||
};
|
||||
search?: {
|
||||
backend?: WikiSearchBackend;
|
||||
corpus?: WikiSearchCorpus;
|
||||
};
|
||||
context?: {
|
||||
includeCompiledDigestPrompt?: boolean;
|
||||
};
|
||||
render?: {
|
||||
preserveHumanBlocks?: boolean;
|
||||
createBacklinks?: boolean;
|
||||
createDashboards?: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
export type ResolvedMemoryWikiConfig = {
|
||||
vaultMode: WikiVaultMode;
|
||||
vault: {
|
||||
path: string;
|
||||
renderMode: WikiRenderMode;
|
||||
};
|
||||
obsidian: {
|
||||
enabled: boolean;
|
||||
useOfficialCli: boolean;
|
||||
vaultName?: string;
|
||||
openAfterWrites: boolean;
|
||||
};
|
||||
bridge: {
|
||||
enabled: boolean;
|
||||
readMemoryArtifacts: boolean;
|
||||
indexDreamReports: boolean;
|
||||
indexDailyNotes: boolean;
|
||||
indexMemoryRoot: boolean;
|
||||
followMemoryEvents: boolean;
|
||||
};
|
||||
unsafeLocal: {
|
||||
allowPrivateMemoryCoreAccess: boolean;
|
||||
paths: string[];
|
||||
};
|
||||
ingest: {
|
||||
autoCompile: boolean;
|
||||
maxConcurrentJobs: number;
|
||||
allowUrlIngest: boolean;
|
||||
};
|
||||
search: {
|
||||
backend: WikiSearchBackend;
|
||||
corpus: WikiSearchCorpus;
|
||||
};
|
||||
context: {
|
||||
includeCompiledDigestPrompt: boolean;
|
||||
};
|
||||
render: {
|
||||
preserveHumanBlocks: boolean;
|
||||
createBacklinks: boolean;
|
||||
createDashboards: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
export const DEFAULT_WIKI_VAULT_MODE: WikiVaultMode = "isolated";
|
||||
export const DEFAULT_WIKI_RENDER_MODE: WikiRenderMode = "native";
|
||||
export const DEFAULT_WIKI_SEARCH_BACKEND: WikiSearchBackend = "shared";
|
||||
export const DEFAULT_WIKI_SEARCH_CORPUS: WikiSearchCorpus = "wiki";
|
||||
|
||||
const MemoryWikiConfigSource = z.strictObject({
|
||||
vaultMode: z.enum(WIKI_VAULT_MODES).optional(),
|
||||
vault: z
|
||||
.strictObject({
|
||||
path: z.string().optional(),
|
||||
renderMode: z.enum(WIKI_RENDER_MODES).optional(),
|
||||
})
|
||||
.optional(),
|
||||
obsidian: z
|
||||
.strictObject({
|
||||
enabled: z.boolean().optional(),
|
||||
useOfficialCli: z.boolean().optional(),
|
||||
vaultName: z.string().optional(),
|
||||
openAfterWrites: z.boolean().optional(),
|
||||
})
|
||||
.optional(),
|
||||
bridge: z
|
||||
.strictObject({
|
||||
enabled: z.boolean().optional(),
|
||||
readMemoryArtifacts: z.boolean().optional(),
|
||||
indexDreamReports: z.boolean().optional(),
|
||||
indexDailyNotes: z.boolean().optional(),
|
||||
indexMemoryRoot: z.boolean().optional(),
|
||||
followMemoryEvents: z.boolean().optional(),
|
||||
})
|
||||
.optional(),
|
||||
unsafeLocal: z
|
||||
.strictObject({
|
||||
allowPrivateMemoryCoreAccess: z.boolean().optional(),
|
||||
paths: z.array(z.string()).optional(),
|
||||
})
|
||||
.optional(),
|
||||
ingest: z
|
||||
.strictObject({
|
||||
autoCompile: z.boolean().optional(),
|
||||
maxConcurrentJobs: z.number().int().min(1).optional(),
|
||||
allowUrlIngest: z.boolean().optional(),
|
||||
})
|
||||
.optional(),
|
||||
search: z
|
||||
.strictObject({
|
||||
backend: z.enum(WIKI_SEARCH_BACKENDS).optional(),
|
||||
corpus: z.enum(WIKI_SEARCH_CORPORA).optional(),
|
||||
})
|
||||
.optional(),
|
||||
context: z
|
||||
.strictObject({
|
||||
includeCompiledDigestPrompt: z.boolean().optional(),
|
||||
})
|
||||
.optional(),
|
||||
render: z
|
||||
.strictObject({
|
||||
preserveHumanBlocks: z.boolean().optional(),
|
||||
createBacklinks: z.boolean().optional(),
|
||||
createDashboards: z.boolean().optional(),
|
||||
})
|
||||
.optional(),
|
||||
});
|
||||
|
||||
const memoryWikiConfigSchemaBase = buildPluginConfigSchema(MemoryWikiConfigSource, {
|
||||
safeParse(value: unknown) {
|
||||
if (value === undefined) {
|
||||
return { success: true, data: resolveMemoryWikiConfig(undefined) };
|
||||
}
|
||||
const result = MemoryWikiConfigSource.safeParse(value);
|
||||
if (result.success) {
|
||||
return { success: true, data: resolveMemoryWikiConfig(result.data) };
|
||||
}
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
issues: result.error.issues.map((issue) => ({
|
||||
path: issue.path.filter((segment): segment is string | number => {
|
||||
const kind = typeof segment;
|
||||
return kind === "string" || kind === "number";
|
||||
}),
|
||||
message: issue.message,
|
||||
})),
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export const memoryWikiConfigSchema: OpenClawPluginConfigSchema = memoryWikiConfigSchemaBase;
|
||||
|
||||
function expandHomePath(inputPath: string, homedir: string): string {
|
||||
if (inputPath === "~") {
|
||||
return homedir;
|
||||
}
|
||||
if (inputPath.startsWith("~/")) {
|
||||
return path.join(homedir, inputPath.slice(2));
|
||||
}
|
||||
return inputPath;
|
||||
}
|
||||
|
||||
export function resolveDefaultMemoryWikiVaultPath(homedir = os.homedir()): string {
|
||||
return path.join(homedir, ".openclaw", "wiki", "main");
|
||||
}
|
||||
|
||||
export function resolveMemoryWikiConfig(
|
||||
config: MemoryWikiPluginConfig | undefined,
|
||||
options?: { homedir?: string },
|
||||
): ResolvedMemoryWikiConfig {
|
||||
const homedir = options?.homedir ?? os.homedir();
|
||||
const parsed = config ? MemoryWikiConfigSource.safeParse(config) : null;
|
||||
const safeConfig = parsed?.success ? parsed.data : (config ?? {});
|
||||
|
||||
return {
|
||||
vaultMode: safeConfig.vaultMode ?? DEFAULT_WIKI_VAULT_MODE,
|
||||
vault: {
|
||||
path: expandHomePath(
|
||||
safeConfig.vault?.path ?? resolveDefaultMemoryWikiVaultPath(homedir),
|
||||
homedir,
|
||||
),
|
||||
renderMode: safeConfig.vault?.renderMode ?? DEFAULT_WIKI_RENDER_MODE,
|
||||
},
|
||||
obsidian: {
|
||||
enabled: safeConfig.obsidian?.enabled ?? false,
|
||||
useOfficialCli: safeConfig.obsidian?.useOfficialCli ?? false,
|
||||
...(safeConfig.obsidian?.vaultName ? { vaultName: safeConfig.obsidian.vaultName } : {}),
|
||||
openAfterWrites: safeConfig.obsidian?.openAfterWrites ?? false,
|
||||
},
|
||||
bridge: {
|
||||
enabled: safeConfig.bridge?.enabled ?? false,
|
||||
readMemoryArtifacts: safeConfig.bridge?.readMemoryArtifacts ?? true,
|
||||
indexDreamReports: safeConfig.bridge?.indexDreamReports ?? true,
|
||||
indexDailyNotes: safeConfig.bridge?.indexDailyNotes ?? true,
|
||||
indexMemoryRoot: safeConfig.bridge?.indexMemoryRoot ?? true,
|
||||
followMemoryEvents: safeConfig.bridge?.followMemoryEvents ?? true,
|
||||
},
|
||||
unsafeLocal: {
|
||||
allowPrivateMemoryCoreAccess: safeConfig.unsafeLocal?.allowPrivateMemoryCoreAccess ?? false,
|
||||
paths: safeConfig.unsafeLocal?.paths ?? [],
|
||||
},
|
||||
ingest: {
|
||||
autoCompile: safeConfig.ingest?.autoCompile ?? true,
|
||||
maxConcurrentJobs: safeConfig.ingest?.maxConcurrentJobs ?? 1,
|
||||
allowUrlIngest: safeConfig.ingest?.allowUrlIngest ?? true,
|
||||
},
|
||||
search: {
|
||||
backend: safeConfig.search?.backend ?? DEFAULT_WIKI_SEARCH_BACKEND,
|
||||
corpus: safeConfig.search?.corpus ?? DEFAULT_WIKI_SEARCH_CORPUS,
|
||||
},
|
||||
context: {
|
||||
includeCompiledDigestPrompt: safeConfig.context?.includeCompiledDigestPrompt ?? false,
|
||||
},
|
||||
render: {
|
||||
preserveHumanBlocks: safeConfig.render?.preserveHumanBlocks ?? true,
|
||||
createBacklinks: safeConfig.render?.createBacklinks ?? true,
|
||||
createDashboards: safeConfig.render?.createDashboards ?? true,
|
||||
},
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue