soulmd 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.
@@ -0,0 +1,14 @@
1
+ interface CacheEntry {
2
+ name: string;
3
+ file: string;
4
+ hash: string;
5
+ cachedAt: string;
6
+ }
7
+ export declare function cacheSoul(name: string, content: string, hash: string): string;
8
+ export declare function listCached(): CacheEntry[];
9
+ export declare function getCached(name: string): {
10
+ content: string;
11
+ entry: CacheEntry;
12
+ } | null;
13
+ export {};
14
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAIA,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AA6BD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAyB7E;AAED,wBAAgB,UAAU,IAAI,UAAU,EAAE,CAEzC;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE,GAAG,IAAI,CAWrF"}
package/dist/cache.js ADDED
@@ -0,0 +1,59 @@
1
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { loadConfig } from "./config.js";
4
+ function getCacheDir() {
5
+ const config = loadConfig();
6
+ return config.cache_dir;
7
+ }
8
+ function indexPath() {
9
+ return join(getCacheDir(), "index.json");
10
+ }
11
+ function loadIndex() {
12
+ const path = indexPath();
13
+ if (!existsSync(path)) {
14
+ return { entries: [] };
15
+ }
16
+ return JSON.parse(readFileSync(path, "utf-8"));
17
+ }
18
+ function saveIndex(index) {
19
+ const dir = getCacheDir();
20
+ mkdirSync(dir, { recursive: true });
21
+ writeFileSync(indexPath(), JSON.stringify(index, null, 2), "utf-8");
22
+ }
23
+ export function cacheSoul(name, content, hash) {
24
+ const dir = getCacheDir();
25
+ mkdirSync(dir, { recursive: true });
26
+ const filename = `${name.toLowerCase().replace(/\s+/g, "-")}.soul.md`;
27
+ const filePath = join(dir, filename);
28
+ writeFileSync(filePath, content, "utf-8");
29
+ const index = loadIndex();
30
+ const existing = index.entries.findIndex((e) => e.name === name);
31
+ const entry = {
32
+ name,
33
+ file: filename,
34
+ hash,
35
+ cachedAt: new Date().toISOString(),
36
+ };
37
+ if (existing >= 0) {
38
+ index.entries[existing] = entry;
39
+ }
40
+ else {
41
+ index.entries.push(entry);
42
+ }
43
+ saveIndex(index);
44
+ return filePath;
45
+ }
46
+ export function listCached() {
47
+ return loadIndex().entries;
48
+ }
49
+ export function getCached(name) {
50
+ const index = loadIndex();
51
+ const entry = index.entries.find((e) => e.name.toLowerCase() === name.toLowerCase());
52
+ if (!entry)
53
+ return null;
54
+ const filePath = join(getCacheDir(), entry.file);
55
+ if (!existsSync(filePath))
56
+ return null;
57
+ return { content: readFileSync(filePath, "utf-8"), entry };
58
+ }
59
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export interface SoulConfig {
2
+ default_bot: string;
3
+ auth_token: string;
4
+ cache_dir: string;
5
+ swap_mode: "immediate" | "confirm";
6
+ registry_url: string;
7
+ }
8
+ export declare function loadConfig(): SoulConfig;
9
+ export declare function saveConfig(config: SoulConfig): void;
10
+ export declare function getConfigValue(key: string): string | undefined;
11
+ export declare function setConfigValue(key: string, value: string): void;
12
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,WAAW,GAAG,SAAS,CAAC;IACnC,YAAY,EAAE,MAAM,CAAC;CACtB;AAgBD,wBAAgB,UAAU,IAAI,UAAU,CAUvC;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAGnD;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAI9D;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAK/D"}
package/dist/config.js ADDED
@@ -0,0 +1,43 @@
1
+ import { readFileSync, writeFileSync, existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { homedir } from "node:os";
4
+ import { parse, stringify } from "yaml";
5
+ function defaultConfig() {
6
+ return {
7
+ default_bot: "http://localhost:4000",
8
+ auth_token: "dev-token",
9
+ cache_dir: join(homedir(), ".soul", "cache"),
10
+ swap_mode: "immediate",
11
+ registry_url: "https://api.soulmd.dev",
12
+ };
13
+ }
14
+ function configPath() {
15
+ return join(homedir(), ".soulrc.yaml");
16
+ }
17
+ export function loadConfig() {
18
+ const path = configPath();
19
+ const defaults = defaultConfig();
20
+ if (!existsSync(path)) {
21
+ saveConfig(defaults);
22
+ return { ...defaults };
23
+ }
24
+ const raw = readFileSync(path, "utf-8");
25
+ const parsed = parse(raw);
26
+ return { ...defaults, ...parsed };
27
+ }
28
+ export function saveConfig(config) {
29
+ const path = configPath();
30
+ writeFileSync(path, stringify(config), "utf-8");
31
+ }
32
+ export function getConfigValue(key) {
33
+ const config = loadConfig();
34
+ const record = config;
35
+ return record[key];
36
+ }
37
+ export function setConfigValue(key, value) {
38
+ const config = loadConfig();
39
+ const record = config;
40
+ record[key] = value;
41
+ saveConfig(config);
42
+ }
43
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAa,UAAU,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAUxC,SAAS,aAAa;IACpB,OAAO;QACL,WAAW,EAAE,uBAAuB;QACpC,UAAU,EAAE,WAAW;QACvB,SAAS,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC;QAC5C,SAAS,EAAE,WAAW;QACtB,YAAY,EAAE,wBAAwB;KACvC,CAAC;AACJ,CAAC;AAED,SAAS,UAAU;IACjB,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,cAAc,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;IAC1B,MAAM,QAAQ,GAAG,aAAa,EAAE,CAAC;IACjC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,UAAU,CAAC,QAAQ,CAAC,CAAC;QACrB,OAAO,EAAE,GAAG,QAAQ,EAAE,CAAC;IACzB,CAAC;IACD,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAwB,CAAC;IACjD,OAAO,EAAE,GAAG,QAAQ,EAAE,GAAG,MAAM,EAAE,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAkB;IAC3C,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;IAC1B,aAAa,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,MAAM,GAAG,MAA4C,CAAC;IAC5D,OAAO,MAAM,CAAC,GAAG,CAAuB,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAW,EAAE,KAAa;IACvD,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,MAAM,GAAG,MAA2C,CAAC;IAC3D,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACpB,UAAU,CAAC,MAAM,CAAC,CAAC;AACrB,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,170 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { readFileSync, existsSync } from "node:fs";
4
+ import { resolve } from "node:path";
5
+ import pc from "picocolors";
6
+ import { parseSoulFile } from "@soulmd/core";
7
+ import { getConfigValue, setConfigValue } from "./config.js";
8
+ import { listCached, getCached, cacheSoul } from "./cache.js";
9
+ import { swapSoul, rollbackSoul, hasBackup, isSwapped, readCurrentSoul, getSoulPath } from "./swap.js";
10
+ import { RegistryClient } from "./registry-client.js";
11
+ const program = new Command();
12
+ program
13
+ .name("soul")
14
+ .description("Soul.MD — Swappable bot personality files")
15
+ .version("0.1.0");
16
+ // --- config ---
17
+ const configCmd = program
18
+ .command("config")
19
+ .description("Manage CLI configuration");
20
+ configCmd
21
+ .command("get <key>")
22
+ .description("Get a config value")
23
+ .action((key) => {
24
+ const value = getConfigValue(key);
25
+ if (value === undefined) {
26
+ console.error(pc.red(`Unknown config key: ${key}`));
27
+ process.exit(1);
28
+ }
29
+ console.log(value);
30
+ });
31
+ configCmd
32
+ .command("set <key> <value>")
33
+ .description("Set a config value")
34
+ .action((key, value) => {
35
+ setConfigValue(key, value);
36
+ console.log(pc.green(`Set ${key} = ${value}`));
37
+ });
38
+ // --- status ---
39
+ program
40
+ .command("status")
41
+ .description("Show current SOUL.md status")
42
+ .action(() => {
43
+ const content = readCurrentSoul();
44
+ if (!content) {
45
+ console.log(pc.yellow(`No SOUL.md found at ${getSoulPath()}`));
46
+ return;
47
+ }
48
+ const swapped = isSwapped();
49
+ console.log(pc.bold("\nSOUL.md Status"));
50
+ console.log(`Path: ${getSoulPath()}`);
51
+ console.log(`State: ${swapped ? pc.cyan("swapped") : pc.green("original")}`);
52
+ console.log(`Backup: ${hasBackup() ? pc.green("saved") : pc.dim("none")}`);
53
+ if (swapped) {
54
+ const rawContent = content.split("\n").slice(1).join("\n");
55
+ const firstLine = rawContent.trim().split("\n")[0] ?? "";
56
+ console.log(`Preview: ${pc.cyan(firstLine)}`);
57
+ }
58
+ });
59
+ // --- swap ---
60
+ program
61
+ .command("swap <pathOrName>")
62
+ .description("Swap a soul file into ~/.openclaw/workspace/SOUL.md")
63
+ .action((pathOrName) => {
64
+ let content;
65
+ const filePath = resolve(pathOrName);
66
+ if (existsSync(filePath)) {
67
+ content = readFileSync(filePath, "utf-8");
68
+ }
69
+ else {
70
+ const cached = getCached(pathOrName);
71
+ if (cached) {
72
+ content = cached.content;
73
+ }
74
+ else {
75
+ console.error(pc.red(`File not found and not in cache: ${pathOrName}`));
76
+ process.exit(1);
77
+ }
78
+ }
79
+ const { backedUp } = swapSoul(content);
80
+ const filename = pathOrName.split("/").pop() ?? pathOrName;
81
+ console.log(pc.green(`\n✓ Swapped to ${pc.bold(filename)}`));
82
+ console.log(pc.dim(` Written to ${getSoulPath()}`));
83
+ if (backedUp) {
84
+ console.log(pc.dim(` Original SOUL.md backed up (use 'soul rollback' to restore)`));
85
+ }
86
+ });
87
+ // --- list ---
88
+ program
89
+ .command("list")
90
+ .description("List locally cached souls")
91
+ .action(() => {
92
+ const cached = listCached();
93
+ if (cached.length === 0) {
94
+ console.log(pc.yellow("No cached souls. Use 'soul swap <file>' to cache one."));
95
+ return;
96
+ }
97
+ console.log(pc.bold("\nCached Souls:"));
98
+ for (const entry of cached) {
99
+ console.log(` ${pc.cyan(entry.name)} — ${entry.hash.slice(0, 12)}... (${entry.cachedAt})`);
100
+ }
101
+ });
102
+ // --- rollback ---
103
+ program
104
+ .command("rollback")
105
+ .description("Restore the original SOUL.md")
106
+ .action(() => {
107
+ if (!hasBackup()) {
108
+ console.error(pc.red("No backup found. Nothing to rollback to."));
109
+ process.exit(1);
110
+ }
111
+ const restored = rollbackSoul();
112
+ if (restored) {
113
+ console.log(pc.green("\n✓ Restored original SOUL.md"));
114
+ console.log(pc.dim(` ${getSoulPath()}`));
115
+ }
116
+ else {
117
+ console.error(pc.red("Failed to restore backup."));
118
+ process.exit(1);
119
+ }
120
+ });
121
+ // --- pull ---
122
+ program
123
+ .command("pull <slug>")
124
+ .description("Pull a soul from the registry and cache it locally")
125
+ .action(async (slug) => {
126
+ try {
127
+ const client = new RegistryClient();
128
+ const content = await client.getContent(slug);
129
+ const soul = parseSoulFile(content);
130
+ const name = soul.frontmatter.name ?? slug;
131
+ cacheSoul(name, content, soul.hash);
132
+ console.log(pc.green(`\n✓ Pulled ${pc.bold(name)} (${slug})`));
133
+ console.log(pc.dim(` Cached locally. Use 'soul swap ${name}' to activate.`));
134
+ }
135
+ catch (err) {
136
+ console.error(pc.red(err.message));
137
+ process.exit(1);
138
+ }
139
+ });
140
+ // --- search ---
141
+ program
142
+ .command("search [query]")
143
+ .description("Search for souls in the registry")
144
+ .option("--top", "Show highest-rated souls")
145
+ .option("--popular", "Show most popular souls")
146
+ .action(async (query, opts) => {
147
+ try {
148
+ const client = new RegistryClient();
149
+ const sort = opts.top ? "top" : opts.popular ? "popular" : undefined;
150
+ const { data: results, pagination } = await client.search(query, sort);
151
+ if (results.length === 0) {
152
+ console.log(pc.yellow("No souls found."));
153
+ return;
154
+ }
155
+ console.log(pc.bold(`\n${pagination.total} soul(s) found (page ${pagination.page}/${pagination.totalPages}):\n`));
156
+ for (const soul of results) {
157
+ const rating = soul.rating_avg
158
+ ? ` ★ ${soul.rating_avg.toFixed(1)} (${soul.rating_count} ratings)`
159
+ : "";
160
+ const desc = soul.description ? pc.dim(` — ${soul.description}`) : "";
161
+ console.log(` ${pc.cyan(soul.slug)} v${soul.version} by ${soul.author}${rating}${desc}`);
162
+ }
163
+ }
164
+ catch (err) {
165
+ console.error(pc.red(err.message));
166
+ process.exit(1);
167
+ }
168
+ });
169
+ program.parse();
170
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ export interface RegistrySoul {
2
+ slug: string;
3
+ name: string;
4
+ author: string;
5
+ description: string | null;
6
+ version: string;
7
+ tags: string[];
8
+ rating_avg?: number;
9
+ rating_count?: number;
10
+ created_at: string;
11
+ updated_at: string;
12
+ }
13
+ export declare class RegistryClient {
14
+ private baseUrl;
15
+ constructor(baseUrl?: string);
16
+ search(query?: string, sort?: string, page?: number, limit?: number): Promise<{
17
+ data: RegistrySoul[];
18
+ pagination: {
19
+ page: number;
20
+ limit: number;
21
+ total: number;
22
+ totalPages: number;
23
+ };
24
+ }>;
25
+ getContent(slug: string): Promise<string>;
26
+ }
27
+ //# sourceMappingURL=registry-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry-client.d.ts","sourceRoot":"","sources":["../src/registry-client.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,CAAC,EAAE,MAAM;IAItB,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,YAAY,EAAE,CAAC;QAAC,UAAU,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,UAAU,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IAqBvL,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAgBhD"}
@@ -0,0 +1,41 @@
1
+ import { loadConfig } from "./config.js";
2
+ export class RegistryClient {
3
+ baseUrl;
4
+ constructor(baseUrl) {
5
+ this.baseUrl = baseUrl ?? loadConfig().registry_url;
6
+ }
7
+ async search(query, sort, page, limit) {
8
+ const params = new URLSearchParams();
9
+ if (query)
10
+ params.set("search", query);
11
+ if (sort)
12
+ params.set("sort", sort);
13
+ if (page)
14
+ params.set("page", String(page));
15
+ if (limit)
16
+ params.set("limit", String(limit));
17
+ const qs = params.toString();
18
+ const url = `${this.baseUrl}/api/v1/souls${qs ? `?${qs}` : ""}`;
19
+ const res = await fetch(url).catch(() => {
20
+ throw new Error(`Failed to connect to registry at ${this.baseUrl}. Is it reachable?`);
21
+ });
22
+ if (!res.ok) {
23
+ throw new Error(`Registry returned HTTP ${res.status}`);
24
+ }
25
+ return res.json();
26
+ }
27
+ async getContent(slug) {
28
+ const url = `${this.baseUrl}/api/v1/souls/${slug}/content`;
29
+ const res = await fetch(url).catch(() => {
30
+ throw new Error(`Failed to connect to registry at ${this.baseUrl}. Is it reachable?`);
31
+ });
32
+ if (!res.ok) {
33
+ if (res.status === 404) {
34
+ throw new Error(`Soul '${slug}' not found in registry`);
35
+ }
36
+ throw new Error(`Registry returned HTTP ${res.status}`);
37
+ }
38
+ return res.text();
39
+ }
40
+ }
41
+ //# sourceMappingURL=registry-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry-client.js","sourceRoot":"","sources":["../src/registry-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAezC,MAAM,OAAO,cAAc;IACjB,OAAO,CAAS;IAExB,YAAY,OAAgB;QAC1B,IAAI,CAAC,OAAO,GAAG,OAAO,IAAI,UAAU,EAAE,CAAC,YAAY,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAc,EAAE,IAAa,EAAE,IAAa,EAAE,KAAc;QACvE,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QACrC,IAAI,KAAK;YAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACvC,IAAI,IAAI;YAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACnC,IAAI,IAAI;YAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QAC3C,IAAI,KAAK;YAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAE9C,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,gBAAgB,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAEhE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;YACtC,MAAM,IAAI,KAAK,CAAC,oCAAoC,IAAI,CAAC,OAAO,oBAAoB,CAAC,CAAC;QACxF,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,0BAA0B,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QAC1D,CAAC;QAED,OAAO,GAAG,CAAC,IAAI,EAAuH,CAAC;IACzI,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,IAAY;QAC3B,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,iBAAiB,IAAI,UAAU,CAAC;QAE3D,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;YACtC,MAAM,IAAI,KAAK,CAAC,oCAAoC,IAAI,CAAC,OAAO,oBAAoB,CAAC,CAAC;QACxF,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBACvB,MAAM,IAAI,KAAK,CAAC,SAAS,IAAI,yBAAyB,CAAC,CAAC;YAC1D,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,0BAA0B,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QAC1D,CAAC;QAED,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;IACpB,CAAC;CACF"}
package/dist/swap.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ export declare function getSoulPath(): string;
2
+ export declare function isSwapped(): boolean;
3
+ export declare function readCurrentSoul(): string | null;
4
+ export declare function hasBackup(): boolean;
5
+ export declare function swapSoul(newContent: string): {
6
+ backedUp: boolean;
7
+ };
8
+ export declare function rollbackSoul(): boolean;
9
+ //# sourceMappingURL=swap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swap.d.ts","sourceRoot":"","sources":["../src/swap.ts"],"names":[],"mappings":"AAkBA,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,wBAAgB,SAAS,IAAI,OAAO,CAKnC;AAED,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAI/C;AAED,wBAAgB,SAAS,IAAI,OAAO,CAEnC;AAED,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,OAAO,CAAA;CAAE,CAiBlE;AAED,wBAAgB,YAAY,IAAI,OAAO,CAKtC"}
package/dist/swap.js ADDED
@@ -0,0 +1,54 @@
1
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, copyFileSync } from "node:fs";
2
+ import { join, dirname } from "node:path";
3
+ import { homedir } from "node:os";
4
+ const SWAP_MARKER = "<!-- soulmd:swapped -->";
5
+ function soulPath() {
6
+ return join(homedir(), ".openclaw", "workspace", "SOUL.md");
7
+ }
8
+ function backupDir() {
9
+ return join(homedir(), ".soul", "backup");
10
+ }
11
+ function backupPath() {
12
+ return join(backupDir(), "SOUL.md.original");
13
+ }
14
+ export function getSoulPath() {
15
+ return soulPath();
16
+ }
17
+ export function isSwapped() {
18
+ const p = soulPath();
19
+ if (!existsSync(p))
20
+ return false;
21
+ const content = readFileSync(p, "utf-8");
22
+ return content.startsWith(SWAP_MARKER);
23
+ }
24
+ export function readCurrentSoul() {
25
+ const p = soulPath();
26
+ if (!existsSync(p))
27
+ return null;
28
+ return readFileSync(p, "utf-8");
29
+ }
30
+ export function hasBackup() {
31
+ return existsSync(backupPath());
32
+ }
33
+ export function swapSoul(newContent) {
34
+ let backedUp = false;
35
+ const p = soulPath();
36
+ // If current SOUL.md is NOT already a swapped one, back it up
37
+ if (!isSwapped() && existsSync(p)) {
38
+ mkdirSync(backupDir(), { recursive: true });
39
+ copyFileSync(p, backupPath());
40
+ backedUp = true;
41
+ }
42
+ // Write the new soul with the swap marker
43
+ mkdirSync(dirname(p), { recursive: true });
44
+ const marked = `${SWAP_MARKER}\n${newContent}`;
45
+ writeFileSync(p, marked, "utf-8");
46
+ return { backedUp };
47
+ }
48
+ export function rollbackSoul() {
49
+ if (!existsSync(backupPath()))
50
+ return false;
51
+ copyFileSync(backupPath(), soulPath());
52
+ return true;
53
+ }
54
+ //# sourceMappingURL=swap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swap.js","sourceRoot":"","sources":["../src/swap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC3F,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,MAAM,WAAW,GAAG,yBAAyB,CAAC;AAE9C,SAAS,QAAQ;IACf,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;AAC9D,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,UAAU;IACjB,OAAO,IAAI,CAAC,SAAS,EAAE,EAAE,kBAAkB,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,QAAQ,EAAE,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,MAAM,CAAC,GAAG,QAAQ,EAAE,CAAC;IACrB,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACjC,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACzC,OAAO,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,CAAC,GAAG,QAAQ,EAAE,CAAC;IACrB,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAChC,OAAO,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,UAAU,CAAC,UAAU,EAAE,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,UAAkB;IACzC,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,MAAM,CAAC,GAAG,QAAQ,EAAE,CAAC;IAErB,8DAA8D;IAC9D,IAAI,CAAC,SAAS,EAAE,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;QAClC,SAAS,CAAC,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5C,YAAY,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC;QAC9B,QAAQ,GAAG,IAAI,CAAC;IAClB,CAAC;IAED,0CAA0C;IAC1C,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,GAAG,WAAW,KAAK,UAAU,EAAE,CAAC;IAC/C,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAElC,OAAO,EAAE,QAAQ,EAAE,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC;QAAE,OAAO,KAAK,CAAC;IAE5C,YAAY,CAAC,UAAU,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IACvC,OAAO,IAAI,CAAC;AACd,CAAC"}
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "soulmd",
3
+ "version": "0.1.0",
4
+ "description": "Swappable bot personality files — search, pull, and swap SOUL.md files from the Soul.MD registry",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/soulmd/cli"
10
+ },
11
+ "homepage": "https://soulmd.dev",
12
+ "keywords": [
13
+ "soul",
14
+ "soulmd",
15
+ "bot",
16
+ "personality",
17
+ "openclaw",
18
+ "ai",
19
+ "llm",
20
+ "swap"
21
+ ],
22
+ "bin": {
23
+ "soul": "./dist/index.js"
24
+ },
25
+ "files": [
26
+ "dist"
27
+ ],
28
+ "dependencies": {
29
+ "commander": "^13.0.0",
30
+ "picocolors": "^1.1.0",
31
+ "yaml": "^2.7.0",
32
+ "@soulmd/core": "0.1.0"
33
+ },
34
+ "devDependencies": {
35
+ "@types/node": "^22.0.0",
36
+ "vitest": "^3.0.0",
37
+ "typescript": "^5.7.0",
38
+ "tsx": "^4.19.0"
39
+ },
40
+ "scripts": {
41
+ "build": "tsc",
42
+ "test": "vitest run --passWithNoTests",
43
+ "dev": "tsx --watch src/index.ts"
44
+ }
45
+ }