mindkeeper-openclaw 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/dist/cli.d.ts +5 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +37 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/llm-provider.d.ts +13 -0
- package/dist/llm-provider.d.ts.map +1 -0
- package/dist/llm-provider.js +286 -0
- package/dist/llm-provider.js.map +1 -0
- package/dist/service.d.ts +16 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +29 -0
- package/dist/service.js.map +1 -0
- package/dist/tools.d.ts +13 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +156 -0
- package/dist/tools.js.map +1 -0
- package/openclaw.plugin.json +72 -0
- package/package.json +57 -0
- package/skills/mindkeeper/SKILL.md +45 -0
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE;IAAE,WAAW,CAAC,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAAA;CAAE,EAClE,KAAK,EAAE,KAAK,GACX,IAAI,CAyCN"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export function registerVaultCli(api, vault) {
|
|
2
|
+
if (!api.registerCli)
|
|
3
|
+
return;
|
|
4
|
+
api.registerCli((program) => {
|
|
5
|
+
const cmd = program;
|
|
6
|
+
const vaultCmd = cmd.command("mind");
|
|
7
|
+
addSubcommand(vaultCmd, "status", "Show vault status", async () => {
|
|
8
|
+
const status = await vault.status();
|
|
9
|
+
console.log(`Workspace: ${status.workDir}`);
|
|
10
|
+
console.log(`Pending changes: ${status.pendingChanges.length}`);
|
|
11
|
+
console.log(`Named snapshots: ${status.snapshots.length}`);
|
|
12
|
+
});
|
|
13
|
+
addSubcommand(vaultCmd, "history [file]", "View change history", async (...args) => {
|
|
14
|
+
const file = args[0];
|
|
15
|
+
const commits = await vault.history({ file, limit: 20 });
|
|
16
|
+
if (commits.length === 0) {
|
|
17
|
+
console.log("No history found.");
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
for (const c of commits) {
|
|
21
|
+
const date = c.date.toISOString().replace("T", " ").slice(0, 19);
|
|
22
|
+
console.log(`${c.oid.slice(0, 8)} ${date} ${c.message}`);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
addSubcommand(vaultCmd, "snapshot [name]", "Create a named snapshot", async (...args) => {
|
|
26
|
+
const name = args[0];
|
|
27
|
+
const commit = await vault.snapshot({ name });
|
|
28
|
+
console.log(`Snapshot created: ${commit.oid.slice(0, 8)} ${commit.message}`);
|
|
29
|
+
if (name)
|
|
30
|
+
console.log(`Tagged as: ${name}`);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function addSubcommand(parent, name, description, handler) {
|
|
35
|
+
parent.command(name).description(description).action(handler);
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,gBAAgB,CAC9B,GAAkE,EAClE,KAAY;IAEZ,IAAI,CAAC,GAAG,CAAC,WAAW;QAAE,OAAO;IAE7B,GAAG,CAAC,WAAW,CAAC,CAAC,OAAgB,EAAE,EAAE;QACnC,MAAM,GAAG,GAAG,OAEX,CAAC;QAEF,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACrC,aAAa,CAAC,QAAQ,EAAE,QAAQ,EAAE,mBAAmB,EAAE,KAAK,IAAI,EAAE;YAChE,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE,CAAC;YACpC,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;YAC5C,OAAO,CAAC,GAAG,CAAC,oBAAoB,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC;YAChE,OAAO,CAAC,GAAG,CAAC,oBAAoB,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;QAC7D,CAAC,CAAC,CAAC;QAEH,aAAa,CAAC,QAAQ,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,KAAK,EAAE,GAAG,IAAe,EAAE,EAAE;YAC5F,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAuB,CAAC;YAC3C,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;YACzD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;gBACjC,OAAO;YACT,CAAC;YACD,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;gBACxB,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACjE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;YAC7D,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,aAAa,CACX,QAAQ,EACR,iBAAiB,EACjB,yBAAyB,EACzB,KAAK,EAAE,GAAG,IAAe,EAAE,EAAE;YAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAuB,CAAC;YAC3C,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;YAC9C,OAAO,CAAC,GAAG,CAAC,qBAAqB,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;YAC7E,IAAI,IAAI;gBAAE,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC;QAC9C,CAAC,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAQD,SAAS,aAAa,CACpB,MAAsB,EACtB,IAAY,EACZ,WAAmB,EACnB,OAA8C;IAE9C,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAChE,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenClaw Plugin entry point.
|
|
3
|
+
* Called by OpenClaw's plugin loader with the Plugin API.
|
|
4
|
+
*/
|
|
5
|
+
export default function mindkeeperPlugin(api: OpenClawPluginApi): Promise<void>;
|
|
6
|
+
/**
|
|
7
|
+
* Minimal type definition for OpenClaw Plugin API.
|
|
8
|
+
* Only the methods mindkeeper uses are declared here.
|
|
9
|
+
* In a real build, this would import from openclaw/plugin-sdk.
|
|
10
|
+
*/
|
|
11
|
+
interface OpenClawPluginApi {
|
|
12
|
+
config?: unknown;
|
|
13
|
+
pluginConfig?: Record<string, unknown>;
|
|
14
|
+
getWorkspaceDir?(): string;
|
|
15
|
+
registerTool?(tool: PluginTool, opts?: Record<string, unknown>): void;
|
|
16
|
+
registerCli?(registrar: (program: unknown) => void): void;
|
|
17
|
+
registerService?(service: PluginService): void;
|
|
18
|
+
registerHook?(events: string[], handler: (...args: unknown[]) => void): void;
|
|
19
|
+
log?: {
|
|
20
|
+
info?(...args: unknown[]): void;
|
|
21
|
+
warn?(...args: unknown[]): void;
|
|
22
|
+
error?(...args: unknown[]): void;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
interface PluginTool {
|
|
26
|
+
name: string;
|
|
27
|
+
description: string;
|
|
28
|
+
parameters: Record<string, unknown>;
|
|
29
|
+
handler(args: Record<string, unknown>): Promise<unknown>;
|
|
30
|
+
}
|
|
31
|
+
interface PluginService {
|
|
32
|
+
name: string;
|
|
33
|
+
start(): Promise<void>;
|
|
34
|
+
stop(): Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
export {};
|
|
37
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,wBAA8B,gBAAgB,CAAC,GAAG,EAAE,iBAAiB,iBAyBpE;AAED;;;;GAIG;AACH,UAAU,iBAAiB;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,eAAe,CAAC,IAAI,MAAM,CAAC;IAC3B,YAAY,CAAC,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACtE,WAAW,CAAC,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC;IAC1D,eAAe,CAAC,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAAC;IAC/C,YAAY,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI,CAAC;IAC7E,GAAG,CAAC,EAAE;QACJ,IAAI,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;QAChC,IAAI,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;QAChC,KAAK,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;KAClC,CAAC;CACH;AAED,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1D;AAED,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Vault } from "mindkeeper";
|
|
2
|
+
import { registerVaultTools } from "./tools.js";
|
|
3
|
+
import { registerVaultCli } from "./cli.js";
|
|
4
|
+
import { createWatcherService } from "./service.js";
|
|
5
|
+
import { createOpenClawLlmProvider } from "./llm-provider.js";
|
|
6
|
+
/**
|
|
7
|
+
* OpenClaw Plugin entry point.
|
|
8
|
+
* Called by OpenClaw's plugin loader with the Plugin API.
|
|
9
|
+
*/
|
|
10
|
+
export default async function mindkeeperPlugin(api) {
|
|
11
|
+
const workspaceDir = api.getWorkspaceDir?.() ?? process.env.OPENCLAW_WORKSPACE;
|
|
12
|
+
if (!workspaceDir) {
|
|
13
|
+
api.log?.warn?.("[mindkeeper] No workspace directory found. Plugin disabled.");
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const llmProvider = await createOpenClawLlmProvider({
|
|
17
|
+
config: api.config,
|
|
18
|
+
pluginConfig: api.pluginConfig,
|
|
19
|
+
log: api.log,
|
|
20
|
+
});
|
|
21
|
+
const vault = new Vault({
|
|
22
|
+
workDir: workspaceDir,
|
|
23
|
+
llmProvider: llmProvider ?? undefined,
|
|
24
|
+
});
|
|
25
|
+
registerVaultTools(api, vault);
|
|
26
|
+
registerVaultCli(api, vault);
|
|
27
|
+
const watcherService = createWatcherService(vault, api);
|
|
28
|
+
api.registerService?.(watcherService);
|
|
29
|
+
api.log?.info?.("[mindkeeper] Plugin loaded.");
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAgB,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAE9D;;;GAGG;AACH,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,gBAAgB,CAAC,GAAsB;IACnE,MAAM,YAAY,GAAG,GAAG,CAAC,eAAe,EAAE,EAAE,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;IAC/E,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,6DAA6D,CAAC,CAAC;QAC/E,OAAO;IACT,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,yBAAyB,CAAC;QAClD,MAAM,EAAE,GAAG,CAAC,MAA6C;QACzD,YAAY,EAAE,GAAG,CAAC,YAAY;QAC9B,GAAG,EAAE,GAAG,CAAC,GAAG;KACb,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC;QACtB,OAAO,EAAE,YAAY;QACrB,WAAW,EAAE,WAAW,IAAI,SAAS;KACtC,CAAC,CAAC;IAEH,kBAAkB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC/B,gBAAgB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAE7B,MAAM,cAAc,GAAG,oBAAoB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACxD,GAAG,CAAC,eAAe,EAAE,CAAC,cAAc,CAAC,CAAC;IAEtC,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,6BAA6B,CAAC,CAAC;AACjD,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { LlmProvider } from "mindkeeper";
|
|
2
|
+
interface PluginApi {
|
|
3
|
+
config?: Record<string, unknown>;
|
|
4
|
+
pluginConfig?: Record<string, unknown>;
|
|
5
|
+
log?: {
|
|
6
|
+
info?(...args: unknown[]): void;
|
|
7
|
+
warn?(...args: unknown[]): void;
|
|
8
|
+
error?(...args: unknown[]): void;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export declare function createOpenClawLlmProvider(api: PluginApi): Promise<LlmProvider | null>;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=llm-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-provider.d.ts","sourceRoot":"","sources":["../src/llm-provider.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAc,MAAM,YAAY,CAAC;AA8B1D,UAAU,SAAS;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,GAAG,CAAC,EAAE;QACJ,IAAI,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;QAChC,IAAI,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;QAChC,KAAK,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;KAClC,CAAC;CACH;AAMD,wBAAsB,yBAAyB,CAC7C,GAAG,EAAE,SAAS,GACb,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CA6C7B"}
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import fsPromises from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
const SYSTEM_PROMPT = "You are a version control assistant for AI agent configuration files " +
|
|
5
|
+
"(personality, rules, memory, skills). Given the diffs, write a single-line " +
|
|
6
|
+
"commit message (max 72 chars). Describe WHAT changed semantically, not " +
|
|
7
|
+
"technically. No quotes, no conventional-commit prefix. Return ONLY the message.";
|
|
8
|
+
const LLM_TIMEOUT_MS = 15_000;
|
|
9
|
+
const MAX_DIFF_CHARS = 4_000;
|
|
10
|
+
const MAX_TOKENS = 100;
|
|
11
|
+
// --------------------------------------------------------------------------
|
|
12
|
+
// Public entry
|
|
13
|
+
// --------------------------------------------------------------------------
|
|
14
|
+
export async function createOpenClawLlmProvider(api) {
|
|
15
|
+
const modelSpec = resolveModelFromConfig(api.config);
|
|
16
|
+
if (!modelSpec) {
|
|
17
|
+
api.log?.warn?.("[mindkeeper] No default model configured in OpenClaw — LLM commit messages disabled.");
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
// OAuth-based providers don't carry an extractable API key
|
|
21
|
+
if (isOAuthProvider(modelSpec.provider)) {
|
|
22
|
+
api.log?.warn?.(`[mindkeeper] Provider "${modelSpec.provider}" uses OAuth — LLM commit messages not supported, falling back to template.`);
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
const apiKey = await resolveApiKey(modelSpec.provider);
|
|
26
|
+
if (!apiKey) {
|
|
27
|
+
api.log?.warn?.(`[mindkeeper] No API key found for provider "${modelSpec.provider}" — LLM commit messages disabled.`);
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
api.log?.info?.(`[mindkeeper] LLM commit messages enabled (${modelSpec.provider}/${modelSpec.model}).`);
|
|
31
|
+
return {
|
|
32
|
+
async generateCommitMessage(diffs) {
|
|
33
|
+
const diffText = diffs
|
|
34
|
+
.map((d) => `--- ${d.file} ---\n${d.unified}`)
|
|
35
|
+
.join("\n")
|
|
36
|
+
.slice(0, MAX_DIFF_CHARS);
|
|
37
|
+
return callLlm({
|
|
38
|
+
provider: modelSpec.provider,
|
|
39
|
+
model: modelSpec.model,
|
|
40
|
+
apiKey,
|
|
41
|
+
userPrompt: diffText,
|
|
42
|
+
baseUrl: modelSpec.baseUrl,
|
|
43
|
+
});
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function isOAuthProvider(provider) {
|
|
48
|
+
const normalized = normalizeProvider(provider);
|
|
49
|
+
return normalized.includes("portal") || normalized.includes("oauth");
|
|
50
|
+
}
|
|
51
|
+
// --------------------------------------------------------------------------
|
|
52
|
+
// Model resolution
|
|
53
|
+
// --------------------------------------------------------------------------
|
|
54
|
+
function resolveModelFromConfig(config) {
|
|
55
|
+
const agents = config?.agents;
|
|
56
|
+
const defaults = agents?.defaults;
|
|
57
|
+
const raw = defaults?.model;
|
|
58
|
+
let spec;
|
|
59
|
+
if (typeof raw === "string") {
|
|
60
|
+
spec = raw.trim();
|
|
61
|
+
}
|
|
62
|
+
else if (raw && typeof raw === "object") {
|
|
63
|
+
const primary = raw.primary;
|
|
64
|
+
if (typeof primary === "string")
|
|
65
|
+
spec = primary.trim();
|
|
66
|
+
}
|
|
67
|
+
if (!spec?.includes("/"))
|
|
68
|
+
return null;
|
|
69
|
+
const slashIdx = spec.indexOf("/");
|
|
70
|
+
const provider = spec.slice(0, slashIdx);
|
|
71
|
+
const model = spec.slice(slashIdx + 1);
|
|
72
|
+
// Read baseUrl from models.providers[provider] if configured by the user
|
|
73
|
+
const providers = config?.models
|
|
74
|
+
?.providers;
|
|
75
|
+
const providerCfg = providers?.[provider];
|
|
76
|
+
const baseUrl = typeof providerCfg?.baseUrl === "string" ? providerCfg.baseUrl.trim() : undefined;
|
|
77
|
+
return { provider, model, baseUrl };
|
|
78
|
+
}
|
|
79
|
+
// --------------------------------------------------------------------------
|
|
80
|
+
// API key resolution (3-tier)
|
|
81
|
+
// --------------------------------------------------------------------------
|
|
82
|
+
async function resolveApiKey(provider) {
|
|
83
|
+
// Tier 1 & 2: auth-profiles.json (key field + keyRef env resolution)
|
|
84
|
+
const profileKey = await readAuthProfileKey(provider);
|
|
85
|
+
if (profileKey)
|
|
86
|
+
return profileKey;
|
|
87
|
+
// Tier 3: environment variables
|
|
88
|
+
return readEnvApiKey(provider);
|
|
89
|
+
}
|
|
90
|
+
async function readAuthProfileKey(provider) {
|
|
91
|
+
const candidates = buildAuthProfilePaths();
|
|
92
|
+
for (const filepath of candidates) {
|
|
93
|
+
try {
|
|
94
|
+
const content = await fsPromises.readFile(filepath, "utf-8");
|
|
95
|
+
const store = JSON.parse(content);
|
|
96
|
+
if (!store.profiles || typeof store.profiles !== "object")
|
|
97
|
+
continue;
|
|
98
|
+
const normalized = normalizeProvider(provider);
|
|
99
|
+
for (const credential of Object.values(store.profiles)) {
|
|
100
|
+
if (normalizeProvider(credential.provider) !== normalized)
|
|
101
|
+
continue;
|
|
102
|
+
// Tier 1: plain-text key in file
|
|
103
|
+
if (credential.type === "api_key" && credential.key) {
|
|
104
|
+
return credential.key;
|
|
105
|
+
}
|
|
106
|
+
if (credential.type === "token" && credential.token) {
|
|
107
|
+
return credential.token;
|
|
108
|
+
}
|
|
109
|
+
// Tier 2: keyRef / tokenRef with source=env
|
|
110
|
+
const ref = credential.keyRef ?? credential.tokenRef;
|
|
111
|
+
if (ref?.source === "env" && ref.key) {
|
|
112
|
+
const envVal = process.env[ref.key];
|
|
113
|
+
if (envVal)
|
|
114
|
+
return envVal;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
function buildAuthProfilePaths() {
|
|
125
|
+
const home = os.homedir();
|
|
126
|
+
const paths = [];
|
|
127
|
+
const envHome = process.env.OPENCLAW_HOME;
|
|
128
|
+
if (envHome) {
|
|
129
|
+
paths.push(path.join(envHome, "auth-profiles.json"));
|
|
130
|
+
}
|
|
131
|
+
paths.push(path.join(home, ".openclaw", "auth-profiles.json"), path.join(home, ".config", "openclaw", "auth-profiles.json"));
|
|
132
|
+
return paths;
|
|
133
|
+
}
|
|
134
|
+
function readEnvApiKey(provider) {
|
|
135
|
+
const normalized = normalizeProvider(provider);
|
|
136
|
+
const map = {
|
|
137
|
+
// International
|
|
138
|
+
anthropic: ["ANTHROPIC_API_KEY"],
|
|
139
|
+
openai: ["OPENAI_API_KEY"],
|
|
140
|
+
openaicodex: ["OPENAI_API_KEY"],
|
|
141
|
+
openrouter: ["OPENROUTER_API_KEY"],
|
|
142
|
+
google: ["GEMINI_API_KEY", "GOOGLE_API_KEY", "GOOGLE_GENERATIVE_AI_API_KEY"],
|
|
143
|
+
groq: ["GROQ_API_KEY"],
|
|
144
|
+
mistral: ["MISTRAL_API_KEY"],
|
|
145
|
+
deepseek: ["DEEPSEEK_API_KEY"],
|
|
146
|
+
xai: ["XAI_API_KEY"],
|
|
147
|
+
together: ["TOGETHER_API_KEY"],
|
|
148
|
+
venice: ["VENICE_API_KEY"],
|
|
149
|
+
// Chinese providers
|
|
150
|
+
moonshot: ["MOONSHOT_API_KEY"], // Kimi (international)
|
|
151
|
+
moonshotcn: ["MOONSHOT_API_KEY"], // Kimi (CN endpoint)
|
|
152
|
+
minimax: ["MINIMAX_API_KEY"],
|
|
153
|
+
minimaxcn: ["MINIMAX_API_KEY"],
|
|
154
|
+
zai: ["ZAI_API_KEY", "Z_AI_API_KEY"], // Zhipu ZAI
|
|
155
|
+
qianfan: ["QIANFAN_API_KEY"], // Baidu Qianfan
|
|
156
|
+
volcengine: ["VOLCANO_ENGINE_API_KEY"], // ByteDance Volcano (Doubao)
|
|
157
|
+
byteplus: ["BYTEPLUS_API_KEY"],
|
|
158
|
+
dashscope: ["DASHSCOPE_API_KEY"], // Alibaba DashScope (Qwen API)
|
|
159
|
+
xiaomi: ["XIAOMI_API_KEY"],
|
|
160
|
+
kilocode: ["KILOCODE_API_KEY"],
|
|
161
|
+
litellm: ["LITELLM_API_KEY"],
|
|
162
|
+
};
|
|
163
|
+
const envKeys = map[normalized] ??
|
|
164
|
+
[`${provider.toUpperCase().replace(/-/g, "_")}_API_KEY`];
|
|
165
|
+
for (const envKey of envKeys) {
|
|
166
|
+
const val = process.env[envKey];
|
|
167
|
+
if (val)
|
|
168
|
+
return val;
|
|
169
|
+
}
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
function normalizeProvider(provider) {
|
|
173
|
+
return provider.toLowerCase().replace(/-/g, "").replace(/_/g, "");
|
|
174
|
+
}
|
|
175
|
+
// --------------------------------------------------------------------------
|
|
176
|
+
// LLM HTTP calls
|
|
177
|
+
// --------------------------------------------------------------------------
|
|
178
|
+
async function callLlm(params) {
|
|
179
|
+
const normalized = normalizeProvider(params.provider);
|
|
180
|
+
if (normalized === "anthropic") {
|
|
181
|
+
return callAnthropic(params);
|
|
182
|
+
}
|
|
183
|
+
if (normalized === "google") {
|
|
184
|
+
return callGoogle(params);
|
|
185
|
+
}
|
|
186
|
+
// Default: OpenAI-compatible (covers all Chinese providers)
|
|
187
|
+
return callOpenAiCompatible(params);
|
|
188
|
+
}
|
|
189
|
+
async function callAnthropic(params) {
|
|
190
|
+
const res = await fetch("https://api.anthropic.com/v1/messages", {
|
|
191
|
+
method: "POST",
|
|
192
|
+
headers: {
|
|
193
|
+
"x-api-key": params.apiKey,
|
|
194
|
+
"content-type": "application/json",
|
|
195
|
+
"anthropic-version": "2023-06-01",
|
|
196
|
+
},
|
|
197
|
+
body: JSON.stringify({
|
|
198
|
+
model: params.model,
|
|
199
|
+
max_tokens: MAX_TOKENS,
|
|
200
|
+
system: SYSTEM_PROMPT,
|
|
201
|
+
messages: [{ role: "user", content: params.userPrompt }],
|
|
202
|
+
}),
|
|
203
|
+
signal: AbortSignal.timeout(LLM_TIMEOUT_MS),
|
|
204
|
+
});
|
|
205
|
+
if (!res.ok) {
|
|
206
|
+
throw new Error(`Anthropic API ${res.status}: ${await res.text().catch(() => "")}`);
|
|
207
|
+
}
|
|
208
|
+
const data = (await res.json());
|
|
209
|
+
return data.content?.[0]?.text?.trim() ?? "";
|
|
210
|
+
}
|
|
211
|
+
async function callOpenAiCompatible(params) {
|
|
212
|
+
const baseUrl = resolveOpenAiBaseUrl(params.provider, params.baseUrl);
|
|
213
|
+
const res = await fetch(`${baseUrl}/chat/completions`, {
|
|
214
|
+
method: "POST",
|
|
215
|
+
headers: {
|
|
216
|
+
Authorization: `Bearer ${params.apiKey}`,
|
|
217
|
+
"Content-Type": "application/json",
|
|
218
|
+
},
|
|
219
|
+
body: JSON.stringify({
|
|
220
|
+
model: params.model,
|
|
221
|
+
max_tokens: MAX_TOKENS,
|
|
222
|
+
messages: [
|
|
223
|
+
{ role: "system", content: SYSTEM_PROMPT },
|
|
224
|
+
{ role: "user", content: params.userPrompt },
|
|
225
|
+
],
|
|
226
|
+
}),
|
|
227
|
+
signal: AbortSignal.timeout(LLM_TIMEOUT_MS),
|
|
228
|
+
});
|
|
229
|
+
if (!res.ok) {
|
|
230
|
+
throw new Error(`OpenAI-compatible API ${res.status}: ${await res.text().catch(() => "")}`);
|
|
231
|
+
}
|
|
232
|
+
const data = (await res.json());
|
|
233
|
+
return data.choices?.[0]?.message?.content?.trim() ?? "";
|
|
234
|
+
}
|
|
235
|
+
async function callGoogle(params) {
|
|
236
|
+
const url = `https://generativelanguage.googleapis.com/v1beta/models/${params.model}:generateContent?key=${params.apiKey}`;
|
|
237
|
+
const res = await fetch(url, {
|
|
238
|
+
method: "POST",
|
|
239
|
+
headers: { "Content-Type": "application/json" },
|
|
240
|
+
body: JSON.stringify({
|
|
241
|
+
system_instruction: { parts: [{ text: SYSTEM_PROMPT }] },
|
|
242
|
+
contents: [{ parts: [{ text: params.userPrompt }] }],
|
|
243
|
+
generationConfig: { maxOutputTokens: MAX_TOKENS },
|
|
244
|
+
}),
|
|
245
|
+
signal: AbortSignal.timeout(LLM_TIMEOUT_MS),
|
|
246
|
+
});
|
|
247
|
+
if (!res.ok) {
|
|
248
|
+
throw new Error(`Google AI API ${res.status}: ${await res.text().catch(() => "")}`);
|
|
249
|
+
}
|
|
250
|
+
const data = (await res.json());
|
|
251
|
+
return data.candidates?.[0]?.content?.parts?.[0]?.text?.trim() ?? "";
|
|
252
|
+
}
|
|
253
|
+
function resolveOpenAiBaseUrl(provider, configuredBaseUrl) {
|
|
254
|
+
// Highest priority: baseUrl explicitly set in OpenClaw's models.providers config
|
|
255
|
+
if (configuredBaseUrl)
|
|
256
|
+
return configuredBaseUrl.replace(/\/$/, "");
|
|
257
|
+
const normalized = normalizeProvider(provider);
|
|
258
|
+
const map = {
|
|
259
|
+
// International
|
|
260
|
+
openai: "https://api.openai.com/v1",
|
|
261
|
+
openaicodex: "https://api.openai.com/v1",
|
|
262
|
+
openrouter: "https://openrouter.ai/api/v1",
|
|
263
|
+
groq: "https://api.groq.com/openai/v1",
|
|
264
|
+
mistral: "https://api.mistral.ai/v1",
|
|
265
|
+
deepseek: "https://api.deepseek.com/v1",
|
|
266
|
+
xai: "https://api.x.ai/v1",
|
|
267
|
+
together: "https://api.together.xyz/v1",
|
|
268
|
+
venice: "https://api.venice.ai/api/v1",
|
|
269
|
+
kilocode: "https://api.kilo.ai/api/gateway",
|
|
270
|
+
litellm: "http://127.0.0.1:4000", // self-hosted default
|
|
271
|
+
// Chinese providers
|
|
272
|
+
moonshot: "https://api.moonshot.ai/v1", // Kimi (international)
|
|
273
|
+
moonshotcn: "https://api.moonshot.cn/v1", // Kimi (CN)
|
|
274
|
+
minimax: "https://api.minimax.io/v1", // MiniMax (international)
|
|
275
|
+
minimaxcn: "https://api.minimaxi.com/v1", // MiniMax (CN)
|
|
276
|
+
zai: "https://api.z.ai/v1", // Zhipu ZAI (international)
|
|
277
|
+
zaicn: "https://open.bigmodel.cn/api/paas/v4", // Zhipu (CN)
|
|
278
|
+
qianfan: "https://qianfan.baidubce.com/v2", // Baidu Qianfan
|
|
279
|
+
volcengine: "https://ark.cn-beijing.volces.com/api/v3", // Volcano (Doubao)
|
|
280
|
+
byteplus: "https://api.byteplus.com/v1",
|
|
281
|
+
dashscope: "https://dashscope.aliyuncs.com/compatible-mode/v1", // Alibaba DashScope
|
|
282
|
+
xiaomi: "https://api.xiaomi.com/v1",
|
|
283
|
+
};
|
|
284
|
+
return map[normalized] ?? `https://api.${provider}.com/v1`;
|
|
285
|
+
}
|
|
286
|
+
//# sourceMappingURL=llm-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-provider.js","sourceRoot":"","sources":["../src/llm-provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Vault } from "mindkeeper";
|
|
2
|
+
interface PluginService {
|
|
3
|
+
name: string;
|
|
4
|
+
start(): Promise<void>;
|
|
5
|
+
stop(): Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
interface PluginApi {
|
|
8
|
+
log?: {
|
|
9
|
+
info?(...args: unknown[]): void;
|
|
10
|
+
warn?(...args: unknown[]): void;
|
|
11
|
+
error?(...args: unknown[]): void;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export declare function createWatcherService(vault: Vault, api: PluginApi): PluginService;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAgB,MAAM,YAAY,CAAC;AAEjD,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED,UAAU,SAAS;IACjB,GAAG,CAAC,EAAE;QACJ,IAAI,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;QAChC,IAAI,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;QAChC,KAAK,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;KAClC,CAAC;CACH;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,GAAG,aAAa,CAmChF"}
|
package/dist/service.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { VaultWatcher } from "mindkeeper";
|
|
2
|
+
export function createWatcherService(vault, api) {
|
|
3
|
+
let watcher = null;
|
|
4
|
+
return {
|
|
5
|
+
name: "mindkeeper-watcher",
|
|
6
|
+
async start() {
|
|
7
|
+
await vault.init();
|
|
8
|
+
watcher = new VaultWatcher({
|
|
9
|
+
vault,
|
|
10
|
+
onSnapshot: (commit) => {
|
|
11
|
+
api.log?.info?.(`[mindkeeper] Auto-snapshot ${commit.oid.slice(0, 8)}: ${commit.message}`);
|
|
12
|
+
},
|
|
13
|
+
onError: (err) => {
|
|
14
|
+
api.log?.error?.(`[mindkeeper] Watcher error: ${err.message}`);
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
await watcher.start();
|
|
18
|
+
api.log?.info?.(`[mindkeeper] Watching ${vault.workDir} (debounce: ${vault.getConfig().snapshot.debounceMs}ms)`);
|
|
19
|
+
},
|
|
20
|
+
async stop() {
|
|
21
|
+
if (watcher) {
|
|
22
|
+
await watcher.stop();
|
|
23
|
+
watcher = null;
|
|
24
|
+
api.log?.info?.("[mindkeeper] Watcher stopped.");
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,YAAY,EAAE,MAAM,YAAY,CAAC;AAgBjD,MAAM,UAAU,oBAAoB,CAAC,KAAY,EAAE,GAAc;IAC/D,IAAI,OAAO,GAAwB,IAAI,CAAC;IAExC,OAAO;QACL,IAAI,EAAE,oBAAoB;QAE1B,KAAK,CAAC,KAAK;YACT,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;YAEnB,OAAO,GAAG,IAAI,YAAY,CAAC;gBACzB,KAAK;gBACL,UAAU,EAAE,CAAC,MAAM,EAAE,EAAE;oBACrB,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,CACb,8BAA8B,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,OAAO,EAAE,CAC1E,CAAC;gBACJ,CAAC;gBACD,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;oBACf,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,+BAA+B,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;gBACjE,CAAC;aACF,CAAC,CAAC;YAEH,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;YACtB,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,CACb,yBAAyB,KAAK,CAAC,OAAO,eAAe,KAAK,CAAC,SAAS,EAAE,CAAC,QAAQ,CAAC,UAAU,KAAK,CAChG,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,IAAI;YACR,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;gBACrB,OAAO,GAAG,IAAI,CAAC;gBACf,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,+BAA+B,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/tools.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Vault } from "mindkeeper";
|
|
2
|
+
type RegisterTool = (tool: PluginTool, opts?: Record<string, unknown>) => void;
|
|
3
|
+
interface PluginTool {
|
|
4
|
+
name: string;
|
|
5
|
+
description: string;
|
|
6
|
+
parameters: Record<string, unknown>;
|
|
7
|
+
handler(args: Record<string, unknown>): Promise<unknown>;
|
|
8
|
+
}
|
|
9
|
+
export declare function registerVaultTools(api: {
|
|
10
|
+
registerTool?: RegisterTool;
|
|
11
|
+
}, vault: Vault): void;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAuC,MAAM,YAAY,CAAC;AAE7E,KAAK,YAAY,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;AAE/E,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1D;AAED,wBAAgB,kBAAkB,CAChC,GAAG,EAAE;IAAE,YAAY,CAAC,EAAE,YAAY,CAAA;CAAE,EACpC,KAAK,EAAE,KAAK,GACX,IAAI,CAmIN"}
|
package/dist/tools.js
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
export function registerVaultTools(api, vault) {
|
|
2
|
+
if (!api.registerTool)
|
|
3
|
+
return;
|
|
4
|
+
api.registerTool({
|
|
5
|
+
name: "mind_history",
|
|
6
|
+
description: "View version history of agent context files. " +
|
|
7
|
+
"Optionally filter by a specific file. Returns commit hashes, dates, and messages.",
|
|
8
|
+
parameters: {
|
|
9
|
+
type: "object",
|
|
10
|
+
properties: {
|
|
11
|
+
file: {
|
|
12
|
+
type: "string",
|
|
13
|
+
description: "File path to filter history (e.g. 'SOUL.md'). Omit for all files.",
|
|
14
|
+
},
|
|
15
|
+
limit: {
|
|
16
|
+
type: "number",
|
|
17
|
+
description: "Maximum number of entries to return (default: 10).",
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
handler: async (args) => {
|
|
22
|
+
const commits = await vault.history({
|
|
23
|
+
file: args.file,
|
|
24
|
+
limit: args.limit ?? 10,
|
|
25
|
+
});
|
|
26
|
+
return formatHistoryResult(commits);
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
api.registerTool({
|
|
30
|
+
name: "mind_diff",
|
|
31
|
+
description: "Compare two versions of an agent context file. " +
|
|
32
|
+
"Shows additions, deletions, and a unified diff.",
|
|
33
|
+
parameters: {
|
|
34
|
+
type: "object",
|
|
35
|
+
properties: {
|
|
36
|
+
file: { type: "string", description: "File path to compare (e.g. 'SOUL.md')." },
|
|
37
|
+
from: { type: "string", description: "Source commit hash." },
|
|
38
|
+
to: { type: "string", description: "Target commit hash (defaults to HEAD)." },
|
|
39
|
+
},
|
|
40
|
+
required: ["file", "from"],
|
|
41
|
+
},
|
|
42
|
+
handler: async (args) => {
|
|
43
|
+
const result = await vault.diff({
|
|
44
|
+
file: args.file,
|
|
45
|
+
from: args.from,
|
|
46
|
+
to: args.to,
|
|
47
|
+
});
|
|
48
|
+
return formatDiffResult(result);
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
api.registerTool({
|
|
52
|
+
name: "mind_rollback",
|
|
53
|
+
description: "Rollback an agent context file to a previous version. " +
|
|
54
|
+
"First call with preview=true to see the diff, then call again without preview to execute.",
|
|
55
|
+
parameters: {
|
|
56
|
+
type: "object",
|
|
57
|
+
properties: {
|
|
58
|
+
file: { type: "string", description: "File path to rollback (e.g. 'SOUL.md')." },
|
|
59
|
+
to: { type: "string", description: "Commit hash to rollback to." },
|
|
60
|
+
preview: {
|
|
61
|
+
type: "boolean",
|
|
62
|
+
description: "If true, show diff preview without executing rollback. Default: true.",
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
required: ["file", "to"],
|
|
66
|
+
},
|
|
67
|
+
handler: async (args) => {
|
|
68
|
+
const file = args.file;
|
|
69
|
+
const to = args.to;
|
|
70
|
+
const preview = args.preview ?? true;
|
|
71
|
+
if (preview) {
|
|
72
|
+
const diff = await vault.diff({ file, from: to, to: "HEAD" });
|
|
73
|
+
return {
|
|
74
|
+
preview: true,
|
|
75
|
+
diff: formatDiffResult(diff),
|
|
76
|
+
instruction: "Show this diff to the user. If they confirm, call mind_rollback again with preview=false.",
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const commit = await vault.rollback({ file, to });
|
|
80
|
+
return {
|
|
81
|
+
preview: false,
|
|
82
|
+
success: true,
|
|
83
|
+
commit: { oid: commit.oid.slice(0, 8), message: commit.message },
|
|
84
|
+
note: "Tell the user to run /new to apply the changes to the current session.",
|
|
85
|
+
};
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
api.registerTool({
|
|
89
|
+
name: "mind_snapshot",
|
|
90
|
+
description: "Create a named checkpoint of the current state of all agent context files. " +
|
|
91
|
+
"Useful before making significant changes.",
|
|
92
|
+
parameters: {
|
|
93
|
+
type: "object",
|
|
94
|
+
properties: {
|
|
95
|
+
name: { type: "string", description: "Snapshot name (e.g. 'personality-v2')." },
|
|
96
|
+
message: { type: "string", description: "Optional description of this snapshot." },
|
|
97
|
+
},
|
|
98
|
+
required: ["name"],
|
|
99
|
+
},
|
|
100
|
+
handler: async (args) => {
|
|
101
|
+
const commit = await vault.snapshot({
|
|
102
|
+
name: args.name,
|
|
103
|
+
message: args.message,
|
|
104
|
+
});
|
|
105
|
+
return {
|
|
106
|
+
success: true,
|
|
107
|
+
snapshot: args.name,
|
|
108
|
+
commit: { oid: commit.oid.slice(0, 8), message: commit.message },
|
|
109
|
+
};
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
api.registerTool({
|
|
113
|
+
name: "mind_status",
|
|
114
|
+
description: "Show the current status of the context vault: tracked files, pending changes, and named snapshots.",
|
|
115
|
+
parameters: { type: "object", properties: {} },
|
|
116
|
+
handler: async () => {
|
|
117
|
+
const status = await vault.status();
|
|
118
|
+
return formatStatusResult(status);
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
function formatHistoryResult(commits) {
|
|
123
|
+
return {
|
|
124
|
+
count: commits.length,
|
|
125
|
+
entries: commits.map((c) => ({
|
|
126
|
+
oid: c.oid.slice(0, 8),
|
|
127
|
+
date: c.date.toISOString().replace("T", " ").slice(0, 19),
|
|
128
|
+
message: c.message,
|
|
129
|
+
})),
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
function formatDiffResult(result) {
|
|
133
|
+
return {
|
|
134
|
+
file: result.file,
|
|
135
|
+
from: result.fromVersion,
|
|
136
|
+
to: result.toVersion,
|
|
137
|
+
additions: result.additions,
|
|
138
|
+
deletions: result.deletions,
|
|
139
|
+
unified: result.unified,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
function formatStatusResult(status) {
|
|
143
|
+
return {
|
|
144
|
+
initialized: status.initialized,
|
|
145
|
+
workDir: status.workDir,
|
|
146
|
+
pendingChanges: status.pendingChanges.map((e) => ({
|
|
147
|
+
file: e.filepath,
|
|
148
|
+
status: e.status,
|
|
149
|
+
})),
|
|
150
|
+
snapshots: status.snapshots.map((s) => ({
|
|
151
|
+
name: s.name,
|
|
152
|
+
oid: s.oid.slice(0, 8),
|
|
153
|
+
})),
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "mindkeeper",
|
|
3
|
+
"name": "Mindkeeper",
|
|
4
|
+
"description": "Time machine for your AI's brain. Auto-snapshots every change to agent context files (AGENTS.md, SOUL.md, MEMORY.md, skills, etc.) with full history, visual diffs, and one-command rollback.",
|
|
5
|
+
"configSchema": {
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"properties": {
|
|
9
|
+
"tracking": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"additionalProperties": false,
|
|
12
|
+
"properties": {
|
|
13
|
+
"include": {
|
|
14
|
+
"type": "array",
|
|
15
|
+
"items": { "type": "string" },
|
|
16
|
+
"description": "Glob patterns for files to track"
|
|
17
|
+
},
|
|
18
|
+
"exclude": {
|
|
19
|
+
"type": "array",
|
|
20
|
+
"items": { "type": "string" },
|
|
21
|
+
"description": "Glob patterns for files to exclude"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"snapshot": {
|
|
26
|
+
"type": "object",
|
|
27
|
+
"additionalProperties": false,
|
|
28
|
+
"properties": {
|
|
29
|
+
"debounceMs": {
|
|
30
|
+
"type": "number",
|
|
31
|
+
"description": "Debounce interval for auto-snapshots (ms)",
|
|
32
|
+
"default": 30000
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"commitMessage": {
|
|
37
|
+
"type": "object",
|
|
38
|
+
"additionalProperties": false,
|
|
39
|
+
"properties": {
|
|
40
|
+
"mode": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"enum": ["template", "llm"],
|
|
43
|
+
"default": "template",
|
|
44
|
+
"description": "How to generate commit messages: 'template' (fast, no API call) or 'llm' (uses your configured model)"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"uiHints": {
|
|
51
|
+
"tracking.include": {
|
|
52
|
+
"label": "Tracked file patterns",
|
|
53
|
+
"placeholder": "AGENTS.md, memory/**/*.md, skills/**/*.md"
|
|
54
|
+
},
|
|
55
|
+
"tracking.exclude": {
|
|
56
|
+
"label": "Excluded file patterns",
|
|
57
|
+
"placeholder": "BOOTSTRAP.md, canvas/**"
|
|
58
|
+
},
|
|
59
|
+
"snapshot.debounceMs": {
|
|
60
|
+
"label": "Auto-snapshot interval (ms)",
|
|
61
|
+
"placeholder": "30000"
|
|
62
|
+
},
|
|
63
|
+
"commitMessage.mode": {
|
|
64
|
+
"label": "Commit message mode"
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
"install": {
|
|
68
|
+
"npmSpec": "mindkeeper-openclaw",
|
|
69
|
+
"defaultChoice": "npm"
|
|
70
|
+
},
|
|
71
|
+
"skills": ["skills"]
|
|
72
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mindkeeper-openclaw",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "OpenClaw plugin for mindkeeper: auto-snapshot, diff, and rollback for agent context files",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"openclaw",
|
|
7
|
+
"openclaw-plugin",
|
|
8
|
+
"mindkeeper",
|
|
9
|
+
"agent",
|
|
10
|
+
"version-control",
|
|
11
|
+
"snapshot",
|
|
12
|
+
"rollback"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://github.com/seekcontext/mindkeeper#readme",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/seekcontext/mindkeeper/issues"
|
|
17
|
+
},
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "https://github.com/seekcontext/mindkeeper.git",
|
|
21
|
+
"directory": "packages/openclaw"
|
|
22
|
+
},
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"type": "module",
|
|
25
|
+
"exports": {
|
|
26
|
+
".": {
|
|
27
|
+
"import": "./dist/index.js",
|
|
28
|
+
"types": "./dist/index.d.ts"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist",
|
|
33
|
+
"skills",
|
|
34
|
+
"openclaw.plugin.json"
|
|
35
|
+
],
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsc",
|
|
38
|
+
"clean": "rm -rf dist",
|
|
39
|
+
"prepublishOnly": "pnpm run clean && pnpm run build"
|
|
40
|
+
},
|
|
41
|
+
"openclaw": {
|
|
42
|
+
"extensions": ["./dist/index.js"]
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"mindkeeper": "workspace:*"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"typescript": "^5.7.0",
|
|
49
|
+
"@types/node": "^22.0.0"
|
|
50
|
+
},
|
|
51
|
+
"engines": {
|
|
52
|
+
"node": ">=22.0.0"
|
|
53
|
+
},
|
|
54
|
+
"publishConfig": {
|
|
55
|
+
"access": "public"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mindkeeper
|
|
3
|
+
description: Version control for agent context files — view history, compare versions, and rollback changes
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
metadata:
|
|
6
|
+
openclaw:
|
|
7
|
+
requires:
|
|
8
|
+
config: ["workspace.dir"]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Mindkeeper — Version Control for Agent Context
|
|
12
|
+
|
|
13
|
+
Use the vault tools when the user asks about changes, history, or versions of their agent context files (AGENTS.md, SOUL.md, USER.md, IDENTITY.md, TOOLS.md, MEMORY.md, memory/, skills/).
|
|
14
|
+
|
|
15
|
+
## Available Tools
|
|
16
|
+
|
|
17
|
+
- **mind_history** — View change history of context files
|
|
18
|
+
- **mind_diff** — Compare two versions of a file
|
|
19
|
+
- **mind_rollback** — Restore a file to a previous version (always preview first)
|
|
20
|
+
- **mind_snapshot** — Create a named checkpoint before major changes
|
|
21
|
+
- **mind_status** — Show current tracking status
|
|
22
|
+
|
|
23
|
+
## When to Use
|
|
24
|
+
|
|
25
|
+
Use these tools when the user:
|
|
26
|
+
- Asks what changed in their agent configuration ("what changed in SOUL.md?")
|
|
27
|
+
- Wants to compare versions ("show me the diff from last week")
|
|
28
|
+
- Wants to undo a change ("rollback AGENTS.md to yesterday")
|
|
29
|
+
- Wants to save a checkpoint ("save a snapshot called stable-v1")
|
|
30
|
+
- Asks about the state of their agent context files
|
|
31
|
+
|
|
32
|
+
## Rollback Procedure
|
|
33
|
+
|
|
34
|
+
Always follow this sequence for rollbacks:
|
|
35
|
+
1. Call `mind_history` to find the target version
|
|
36
|
+
2. Call `mind_rollback` with `preview=true` to show the user what will change
|
|
37
|
+
3. Only after user confirms, call `mind_rollback` with `preview=false`
|
|
38
|
+
4. After successful rollback, tell the user to run `/new` to apply changes
|
|
39
|
+
|
|
40
|
+
## Important Notes
|
|
41
|
+
|
|
42
|
+
- Rollback only affects the specified file, not all files
|
|
43
|
+
- Every rollback is recorded as a new commit (can be undone)
|
|
44
|
+
- Auto-snapshots happen in the background; the user does not need to manually save
|
|
45
|
+
- Named snapshots (via mind_snapshot) are useful before significant personality or rule changes
|