opensoul 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/SKILL.md +100 -0
- package/dist/cache.d.ts +18 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +86 -0
- package/dist/cache.js.map +1 -0
- package/dist/config.d.ts +10 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +41 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +471 -0
- package/dist/index.js.map +1 -0
- package/dist/registry-client.d.ts +28 -0
- package/dist/registry-client.d.ts.map +1 -0
- package/dist/registry-client.js +54 -0
- package/dist/registry-client.js.map +1 -0
- package/dist/skill.d.ts +8 -0
- package/dist/skill.d.ts.map +1 -0
- package/dist/skill.js +41 -0
- package/dist/skill.js.map +1 -0
- package/dist/swap.d.ts +9 -0
- package/dist/swap.d.ts.map +1 -0
- package/dist/swap.js +59 -0
- package/dist/swap.js.map +1 -0
- package/package.json +48 -0
package/SKILL.md
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: opensoul
|
|
3
|
+
description: Search, browse, and swap bot personality (SOUL.md) files from the OpenSOUL.md registry
|
|
4
|
+
metadata:
|
|
5
|
+
{
|
|
6
|
+
"openclaw": { "requires": { "bins": ["soul"] }, "primaryEnv": null },
|
|
7
|
+
"install":
|
|
8
|
+
[
|
|
9
|
+
{
|
|
10
|
+
"id": "npm",
|
|
11
|
+
"kind": "node",
|
|
12
|
+
"package": "opensoul",
|
|
13
|
+
"bins": ["soul"],
|
|
14
|
+
"label": "Install via npm",
|
|
15
|
+
},
|
|
16
|
+
],
|
|
17
|
+
}
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
You can manage the bot's personality by swapping SOUL.md files from the OpenSoul registry.
|
|
21
|
+
|
|
22
|
+
## Available actions
|
|
23
|
+
|
|
24
|
+
### Possess — swap soul
|
|
25
|
+
|
|
26
|
+
When the user asks to change personality/soul:
|
|
27
|
+
|
|
28
|
+
1. Run `soul possess <name> --yes` — this auto-summons from the registry if the soul isn't cached locally.
|
|
29
|
+
|
|
30
|
+
You can also possess from a local file path: `soul possess /path/to/SOUL.md --yes`
|
|
31
|
+
|
|
32
|
+
Use `--dry-run` to preview what would happen without writing anything.
|
|
33
|
+
|
|
34
|
+
### Exorcise — restore original
|
|
35
|
+
|
|
36
|
+
If the user wants to go back to their original personality: `soul exorcise`
|
|
37
|
+
|
|
38
|
+
This restores the backed-up SOUL.md from before the first possession.
|
|
39
|
+
|
|
40
|
+
### Search souls
|
|
41
|
+
|
|
42
|
+
To search the registry: `soul search <query> --no-interactive`
|
|
43
|
+
|
|
44
|
+
Sorting options:
|
|
45
|
+
|
|
46
|
+
- `--top` — sort by highest-rated
|
|
47
|
+
- `--popular` — sort by most downloaded
|
|
48
|
+
|
|
49
|
+
To show all available souls: `soul search --top --no-interactive`
|
|
50
|
+
|
|
51
|
+
### Summon — download without swapping
|
|
52
|
+
|
|
53
|
+
To download a soul to local cache without activating it: `soul summon <label>`
|
|
54
|
+
|
|
55
|
+
The user can activate it later with `soul possess <name>`.
|
|
56
|
+
|
|
57
|
+
### List cached souls
|
|
58
|
+
|
|
59
|
+
To show locally cached souls: `soul list`
|
|
60
|
+
|
|
61
|
+
Supports pagination with `--page <n>` and `--per-page <n>`.
|
|
62
|
+
|
|
63
|
+
### Banish — remove from cache
|
|
64
|
+
|
|
65
|
+
To remove a soul from the local cache: `soul banish <name>`
|
|
66
|
+
|
|
67
|
+
### Status
|
|
68
|
+
|
|
69
|
+
To check what soul is currently loaded: `soul status`
|
|
70
|
+
|
|
71
|
+
Shows the SOUL.md path, swap state (original or swapped), and backup status.
|
|
72
|
+
|
|
73
|
+
### Path — show or set SOUL.md location
|
|
74
|
+
|
|
75
|
+
To show the current SOUL.md path: `soul path`
|
|
76
|
+
|
|
77
|
+
To set a new path: `soul path /path/to/SOUL.md`
|
|
78
|
+
|
|
79
|
+
To show or set the OpenClaw skills directory: `soul path --skills` or `soul path /path/to/skills --skills`
|
|
80
|
+
|
|
81
|
+
### Config
|
|
82
|
+
|
|
83
|
+
To get or set CLI configuration values:
|
|
84
|
+
|
|
85
|
+
- `soul config get <key>`
|
|
86
|
+
- `soul config set <key> <value>`
|
|
87
|
+
|
|
88
|
+
### Install / Uninstall skill
|
|
89
|
+
|
|
90
|
+
To install the OpenSoul skill into OpenClaw: `soul install`
|
|
91
|
+
|
|
92
|
+
To remove it: `soul uninstall`
|
|
93
|
+
|
|
94
|
+
## Important notes
|
|
95
|
+
|
|
96
|
+
- Always use `--no-interactive` with `soul search` since you cannot use interactive TUI controls.
|
|
97
|
+
- Always use `--yes` with `soul possess` to skip the confirmation prompt.
|
|
98
|
+
- `soul possess` auto-summons from the registry if the soul isn't in the local cache — you don't need to summon first.
|
|
99
|
+
- After possessing a soul, let the user know they can use `soul exorcise` to restore their original personality.
|
|
100
|
+
- The soul takes effect on the next conversation — the current conversation is not affected.
|
package/dist/cache.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface CacheEntry {
|
|
2
|
+
name: string;
|
|
3
|
+
label?: string;
|
|
4
|
+
file: string;
|
|
5
|
+
hash: string;
|
|
6
|
+
cachedAt: string;
|
|
7
|
+
lastUsedAt?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function cacheSoul(name: string, content: string, hash: string, label?: string): string;
|
|
10
|
+
export declare function listCached(): CacheEntry[];
|
|
11
|
+
export declare function getCached(query: string): {
|
|
12
|
+
content: string;
|
|
13
|
+
entry: CacheEntry;
|
|
14
|
+
} | null;
|
|
15
|
+
export declare function touchCached(query: string): void;
|
|
16
|
+
export declare function removeCached(query: string): boolean;
|
|
17
|
+
export {};
|
|
18
|
+
//# 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,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAoCD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CA4B7F;AAED,wBAAgB,UAAU,IAAI,UAAU,EAAE,CAEzC;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE,GAAG,IAAI,CAStF;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAO/C;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAcnD"}
|
package/dist/cache.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, rmSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
function getCacheDir() {
|
|
5
|
+
return join(homedir(), ".soul", "cache");
|
|
6
|
+
}
|
|
7
|
+
function indexPath() {
|
|
8
|
+
return join(getCacheDir(), "index.json");
|
|
9
|
+
}
|
|
10
|
+
function loadIndex() {
|
|
11
|
+
const path = indexPath();
|
|
12
|
+
if (!existsSync(path)) {
|
|
13
|
+
return { entries: [] };
|
|
14
|
+
}
|
|
15
|
+
return JSON.parse(readFileSync(path, "utf-8"));
|
|
16
|
+
}
|
|
17
|
+
function saveIndex(index) {
|
|
18
|
+
const dir = getCacheDir();
|
|
19
|
+
mkdirSync(dir, { recursive: true });
|
|
20
|
+
writeFileSync(indexPath(), JSON.stringify(index, null, 2), "utf-8");
|
|
21
|
+
}
|
|
22
|
+
function matchesEntry(entry, query) {
|
|
23
|
+
const q = query.toLowerCase();
|
|
24
|
+
return (entry.name.toLowerCase() === q ||
|
|
25
|
+
(entry.label != null && entry.label.toLowerCase() === q));
|
|
26
|
+
}
|
|
27
|
+
export function cacheSoul(name, content, hash, label) {
|
|
28
|
+
const dir = getCacheDir();
|
|
29
|
+
mkdirSync(dir, { recursive: true });
|
|
30
|
+
const filename = `${(label ?? name).toLowerCase().replace(/\s+/g, "-")}.soul.md`;
|
|
31
|
+
const filePath = join(dir, filename);
|
|
32
|
+
writeFileSync(filePath, content, "utf-8");
|
|
33
|
+
const index = loadIndex();
|
|
34
|
+
const existing = index.entries.findIndex((e) => e.name === name || (label != null && e.label === label));
|
|
35
|
+
const entry = {
|
|
36
|
+
name,
|
|
37
|
+
label,
|
|
38
|
+
file: filename,
|
|
39
|
+
hash,
|
|
40
|
+
cachedAt: new Date().toISOString(),
|
|
41
|
+
};
|
|
42
|
+
if (existing >= 0) {
|
|
43
|
+
index.entries[existing] = entry;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
index.entries.push(entry);
|
|
47
|
+
}
|
|
48
|
+
saveIndex(index);
|
|
49
|
+
return filePath;
|
|
50
|
+
}
|
|
51
|
+
export function listCached() {
|
|
52
|
+
return loadIndex().entries;
|
|
53
|
+
}
|
|
54
|
+
export function getCached(query) {
|
|
55
|
+
const index = loadIndex();
|
|
56
|
+
const entry = index.entries.find((e) => matchesEntry(e, query));
|
|
57
|
+
if (!entry)
|
|
58
|
+
return null;
|
|
59
|
+
const filePath = join(getCacheDir(), entry.file);
|
|
60
|
+
if (!existsSync(filePath))
|
|
61
|
+
return null;
|
|
62
|
+
return { content: readFileSync(filePath, "utf-8"), entry };
|
|
63
|
+
}
|
|
64
|
+
export function touchCached(query) {
|
|
65
|
+
const index = loadIndex();
|
|
66
|
+
const entry = index.entries.find((e) => matchesEntry(e, query));
|
|
67
|
+
if (entry) {
|
|
68
|
+
entry.lastUsedAt = new Date().toISOString();
|
|
69
|
+
saveIndex(index);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
export function removeCached(query) {
|
|
73
|
+
const index = loadIndex();
|
|
74
|
+
const idx = index.entries.findIndex((e) => matchesEntry(e, query));
|
|
75
|
+
if (idx === -1)
|
|
76
|
+
return false;
|
|
77
|
+
const entry = index.entries[idx];
|
|
78
|
+
const filePath = join(getCacheDir(), entry.file);
|
|
79
|
+
if (existsSync(filePath)) {
|
|
80
|
+
rmSync(filePath);
|
|
81
|
+
}
|
|
82
|
+
index.entries.splice(idx, 1);
|
|
83
|
+
saveIndex(index);
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface SoulConfig {
|
|
2
|
+
registry_url: string;
|
|
3
|
+
soul_path: string;
|
|
4
|
+
skills_path: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function loadConfig(): SoulConfig;
|
|
7
|
+
export declare function saveConfig(config: SoulConfig): void;
|
|
8
|
+
export declare function getConfigValue(key: string): string | undefined;
|
|
9
|
+
export declare function setConfigValue(key: string, value: string): void;
|
|
10
|
+
//# 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,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAcD,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,41 @@
|
|
|
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
|
+
registry_url: "https://opensoul-api.zyliu-daniel.workers.dev",
|
|
8
|
+
soul_path: join(homedir(), ".openclaw", "workspace", "SOUL.md"),
|
|
9
|
+
skills_path: join(homedir(), ".openclaw", "skills"),
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
function configPath() {
|
|
13
|
+
return join(homedir(), ".soulrc.yaml");
|
|
14
|
+
}
|
|
15
|
+
export function loadConfig() {
|
|
16
|
+
const path = configPath();
|
|
17
|
+
const defaults = defaultConfig();
|
|
18
|
+
if (!existsSync(path)) {
|
|
19
|
+
saveConfig(defaults);
|
|
20
|
+
return { ...defaults };
|
|
21
|
+
}
|
|
22
|
+
const raw = readFileSync(path, "utf-8");
|
|
23
|
+
const parsed = parse(raw);
|
|
24
|
+
return { ...defaults, ...parsed };
|
|
25
|
+
}
|
|
26
|
+
export function saveConfig(config) {
|
|
27
|
+
const path = configPath();
|
|
28
|
+
writeFileSync(path, stringify(config), "utf-8");
|
|
29
|
+
}
|
|
30
|
+
export function getConfigValue(key) {
|
|
31
|
+
const config = loadConfig();
|
|
32
|
+
const record = config;
|
|
33
|
+
return record[key];
|
|
34
|
+
}
|
|
35
|
+
export function setConfigValue(key, value) {
|
|
36
|
+
const config = loadConfig();
|
|
37
|
+
const record = config;
|
|
38
|
+
record[key] = value;
|
|
39
|
+
saveConfig(config);
|
|
40
|
+
}
|
|
41
|
+
//# 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;AAQxC,SAAS,aAAa;IACpB,OAAO;QACL,YAAY,EAAE,+CAA+C;QAC7D,SAAS,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,CAAC;QAC/D,WAAW,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,QAAQ,CAAC;KACpD,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"}
|
package/dist/index.d.ts
ADDED
|
@@ -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,471 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
4
|
+
import { resolve, dirname, basename } from "node:path";
|
|
5
|
+
import { createInterface } from "node:readline";
|
|
6
|
+
import pc from "picocolors";
|
|
7
|
+
import { createHash } from "node:crypto";
|
|
8
|
+
import { loadConfig, getConfigValue, setConfigValue } from "./config.js";
|
|
9
|
+
import { listCached, getCached, cacheSoul, removeCached, touchCached, } from "./cache.js";
|
|
10
|
+
import { swapSoul, rollbackSoul, hasBackup, isSwapped, readCurrentSoul, getSoulPath, } from "./swap.js";
|
|
11
|
+
import { RegistryClient } from "./registry-client.js";
|
|
12
|
+
import { installSkill, uninstallSkill, isSkillInstalled, } from "./skill.js";
|
|
13
|
+
import { fileURLToPath } from "node:url";
|
|
14
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
const pkg = JSON.parse(readFileSync(resolve(__dirname, "../package.json"), "utf-8"));
|
|
16
|
+
let verbose = false;
|
|
17
|
+
function log(...args) {
|
|
18
|
+
if (verbose)
|
|
19
|
+
console.error(pc.dim("[verbose]"), ...args);
|
|
20
|
+
}
|
|
21
|
+
function fail(message) {
|
|
22
|
+
console.error(pc.red(message));
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
const SPINNER_FRAMES = ["◐", "◓", "◑", "◒"];
|
|
26
|
+
function spinner(message) {
|
|
27
|
+
let i = 0;
|
|
28
|
+
const stream = process.stderr;
|
|
29
|
+
stream.write(` ${SPINNER_FRAMES[0]} ${message}`);
|
|
30
|
+
const timer = setInterval(() => {
|
|
31
|
+
i = (i + 1) % SPINNER_FRAMES.length;
|
|
32
|
+
stream.write(`\r ${SPINNER_FRAMES[i]} ${message}`);
|
|
33
|
+
}, 100);
|
|
34
|
+
return {
|
|
35
|
+
stop(finalMessage) {
|
|
36
|
+
clearInterval(timer);
|
|
37
|
+
stream.write(`\r${" ".repeat(message.length + 10)}\r`);
|
|
38
|
+
if (finalMessage)
|
|
39
|
+
console.log(finalMessage);
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function confirm(prompt, defaultYes = false) {
|
|
44
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
45
|
+
const hint = defaultYes ? "[Y/n]" : "[y/N]";
|
|
46
|
+
return new Promise((resolve) => {
|
|
47
|
+
rl.question(`${prompt} ${hint} `, (answer) => {
|
|
48
|
+
rl.close();
|
|
49
|
+
const trimmed = answer.trim().toLowerCase();
|
|
50
|
+
if (trimmed === "")
|
|
51
|
+
resolve(defaultYes);
|
|
52
|
+
else
|
|
53
|
+
resolve(trimmed === "y");
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
const program = new Command();
|
|
58
|
+
program
|
|
59
|
+
.name("soul")
|
|
60
|
+
.description("OpenSoul CLI — manage swappable bot personality files")
|
|
61
|
+
.version(pkg.version, "-v, --version")
|
|
62
|
+
.option("--verbose", "Enable verbose output for debugging")
|
|
63
|
+
.hook("preAction", () => {
|
|
64
|
+
verbose = program.opts().verbose ?? false;
|
|
65
|
+
});
|
|
66
|
+
// --- possess ---
|
|
67
|
+
program
|
|
68
|
+
.command("possess <pathOrName>")
|
|
69
|
+
.description("Swap your bot's SOUL.md with a soul file or cached soul")
|
|
70
|
+
.option("--dry-run", "Preview the swap without writing anything")
|
|
71
|
+
.option("-y, --yes", "Skip confirmation prompt")
|
|
72
|
+
.action(async (pathOrName, opts) => {
|
|
73
|
+
let content;
|
|
74
|
+
let source;
|
|
75
|
+
let soulName;
|
|
76
|
+
const filePath = resolve(pathOrName);
|
|
77
|
+
if (existsSync(filePath)) {
|
|
78
|
+
content = readFileSync(filePath, "utf-8");
|
|
79
|
+
source = filePath;
|
|
80
|
+
log(`Reading from file: ${filePath}`);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
const cached = getCached(pathOrName);
|
|
84
|
+
if (cached) {
|
|
85
|
+
content = cached.content;
|
|
86
|
+
source = `cache:${cached.entry.name}`;
|
|
87
|
+
soulName = cached.entry.name;
|
|
88
|
+
log(`Reading from cache: ${cached.entry.name}`);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
// Check cache for fuzzy matches before hitting the network
|
|
92
|
+
const normalize = (s) => s
|
|
93
|
+
.toLowerCase()
|
|
94
|
+
.replace(/[-_\s]+/g, " ")
|
|
95
|
+
.trim();
|
|
96
|
+
const input = normalize(pathOrName);
|
|
97
|
+
const allCached = listCached();
|
|
98
|
+
const fuzzyMatches = allCached.filter((e) => {
|
|
99
|
+
const n = normalize(e.name);
|
|
100
|
+
return n.includes(input) || input.includes(n);
|
|
101
|
+
});
|
|
102
|
+
if (fuzzyMatches.length > 0) {
|
|
103
|
+
const labels = fuzzyMatches.map((e) => pc.cyan(e.name));
|
|
104
|
+
fail(`Soul '${pathOrName}' not found in cache.\n\n Did you mean one of these?\n${labels.map((l) => ` ${l}`).join("\n")}\n\n Use the exact name, or 'soul summon <label>' to download from the registry.`);
|
|
105
|
+
}
|
|
106
|
+
// Auto-summon from registry — normalize to label format (spaces → hyphens, lowercase)
|
|
107
|
+
const label = pathOrName.trim().toLowerCase().replace(/\s+/g, "-");
|
|
108
|
+
const s = spinner(pc.cyan("🔮 Summoning soul from registry..."));
|
|
109
|
+
try {
|
|
110
|
+
const client = new RegistryClient();
|
|
111
|
+
log(`Registry URL: ${loadConfig().registry_url}`);
|
|
112
|
+
log(`Trying label: ${label}`);
|
|
113
|
+
const [meta, fetchedContent] = await Promise.all([
|
|
114
|
+
client.getMeta(label),
|
|
115
|
+
client.getContent(label),
|
|
116
|
+
]);
|
|
117
|
+
content = fetchedContent;
|
|
118
|
+
const hash = createHash("sha256").update(content).digest("hex");
|
|
119
|
+
const name = meta.name;
|
|
120
|
+
cacheSoul(name, content, hash, meta.label);
|
|
121
|
+
soulName = name;
|
|
122
|
+
source = `registry:${meta.label}`;
|
|
123
|
+
s.stop(pc.green(`🔮 Summoned ${pc.yellow(pc.bold(name))} (${meta.label})`));
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
s.stop();
|
|
127
|
+
// Try to suggest similar souls from the registry — search by first word for broader matches
|
|
128
|
+
let suggestion = "";
|
|
129
|
+
try {
|
|
130
|
+
const words = pathOrName
|
|
131
|
+
.replace(/[-_]/g, " ")
|
|
132
|
+
.trim()
|
|
133
|
+
.split(/\s+/);
|
|
134
|
+
const searchTerm = words[0];
|
|
135
|
+
const client = new RegistryClient();
|
|
136
|
+
const { data: results } = await client.search(searchTerm, undefined, undefined, 5);
|
|
137
|
+
if (results.length > 0) {
|
|
138
|
+
const labels = results.map((r) => pc.cyan(r.label));
|
|
139
|
+
suggestion = `\n\n Did you mean one of these?\n${labels.map((l) => ` ${l}`).join("\n")}`;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
// Search failed too — just show the original error
|
|
144
|
+
}
|
|
145
|
+
fail(`Soul '${pathOrName}' not found as a local file, in cache, or in the registry.${suggestion}`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
const filename = pathOrName.split("/").pop() ?? pathOrName;
|
|
150
|
+
// Validate the target soul path before attempting the swap
|
|
151
|
+
const targetPath = getSoulPath();
|
|
152
|
+
const targetDir = dirname(targetPath);
|
|
153
|
+
if (!existsSync(targetDir)) {
|
|
154
|
+
fail(`Target directory not found: ${pc.yellow(targetDir)}\n\n Your configured SOUL.md path is: ${pc.cyan(targetPath)}\n Use ${pc.bold("soul path <newPath>")} to set the correct path to your SOUL.md file.`);
|
|
155
|
+
}
|
|
156
|
+
if (basename(targetPath) !== "SOUL.md") {
|
|
157
|
+
fail(`Configured path points to ${pc.yellow(basename(targetPath))}, expected ${pc.cyan("SOUL.md")}\n\n Your configured path is: ${pc.cyan(targetPath)}\n Use ${pc.bold("soul path <newPath>")} to set it to a valid SOUL.md file or its parent directory.`);
|
|
158
|
+
}
|
|
159
|
+
if (opts.dryRun) {
|
|
160
|
+
console.log(pc.bold("\n[dry-run] Would possess with:"));
|
|
161
|
+
console.log(` Source: ${source}`);
|
|
162
|
+
console.log(` Target: ${getSoulPath()}`);
|
|
163
|
+
console.log(` Backup: ${!isSwapped() && existsSync(getSoulPath()) ? "would create" : "already exists"}`);
|
|
164
|
+
const preview = content.trim().split("\n")[0] ?? "";
|
|
165
|
+
console.log(` Preview: ${pc.cyan(preview)}`);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
// Confirmation prompt on first swap (unless --yes or non-interactive)
|
|
169
|
+
if (!opts.yes &&
|
|
170
|
+
!isSwapped() &&
|
|
171
|
+
existsSync(getSoulPath()) &&
|
|
172
|
+
process.stdin.isTTY) {
|
|
173
|
+
console.log(pc.dim(` SOUL.md location: ${getSoulPath()}`));
|
|
174
|
+
const ok = await confirm("This will modify your SOUL.md (original will be backed up locally). Continue?", true);
|
|
175
|
+
if (!ok) {
|
|
176
|
+
console.log(pc.dim("Aborted."));
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
const s = spinner(pc.cyan("👻 Possessing..."));
|
|
181
|
+
const { backedUp } = swapSoul(content);
|
|
182
|
+
if (soulName)
|
|
183
|
+
touchCached(soulName);
|
|
184
|
+
s.stop(pc.green(`\n👻 Possessed with ${pc.yellow(pc.bold(filename))}`));
|
|
185
|
+
console.log(pc.dim(` Written to ${getSoulPath()}`));
|
|
186
|
+
if (backedUp) {
|
|
187
|
+
console.log(pc.dim(` Original SOUL.md backed up (use 'soul exorcise' to restore)`));
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
// --- exorcise ---
|
|
191
|
+
program
|
|
192
|
+
.command("exorcise")
|
|
193
|
+
.description("Restore the original SOUL.md from backup")
|
|
194
|
+
.action(() => {
|
|
195
|
+
if (!hasBackup()) {
|
|
196
|
+
fail("No backup found. Nothing to exorcise.");
|
|
197
|
+
}
|
|
198
|
+
const restored = rollbackSoul();
|
|
199
|
+
if (restored) {
|
|
200
|
+
console.log(pc.green(`\n🕯️ Soul exorcised — ${pc.yellow("SOUL.md")} restored`));
|
|
201
|
+
console.log(pc.dim(` ${getSoulPath()}`));
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
fail("Failed to exorcise soul.");
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
// --- search ---
|
|
208
|
+
program
|
|
209
|
+
.command("search [query]")
|
|
210
|
+
.description("Search the soul registry")
|
|
211
|
+
.option("--top", "Sort by highest-rated")
|
|
212
|
+
.option("--popular", "Sort by most popular")
|
|
213
|
+
.option("--no-interactive", "Print results without interactive selection")
|
|
214
|
+
.action(async (query, opts) => {
|
|
215
|
+
try {
|
|
216
|
+
const client = new RegistryClient();
|
|
217
|
+
const sort = opts.top ? "top" : opts.popular ? "popular" : undefined;
|
|
218
|
+
log(`Searching registry: query=${query ?? "(all)"} sort=${sort ?? "recent"}`);
|
|
219
|
+
const { data: results, pagination } = await client.search(query, sort);
|
|
220
|
+
if (results.length === 0) {
|
|
221
|
+
console.log(pc.yellow("No souls found."));
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
// Non-interactive mode: just print results
|
|
225
|
+
if (!process.stdin.isTTY || opts.interactive === false) {
|
|
226
|
+
console.log(pc.bold(`\n${pagination.total} soul(s) found (page ${pagination.page}/${pagination.totalPages}):\n`));
|
|
227
|
+
for (const soul of results) {
|
|
228
|
+
const rating = soul.rating_avg
|
|
229
|
+
? pc.yellow(` ★ ${soul.rating_avg.toFixed(1)}`) +
|
|
230
|
+
pc.dim(` (${soul.rating_count} ratings)`)
|
|
231
|
+
: "";
|
|
232
|
+
const desc = soul.description
|
|
233
|
+
? pc.dim(` — ${soul.description}`)
|
|
234
|
+
: "";
|
|
235
|
+
const nameTag = soul.name !== soul.label ? ` ${pc.yellow(`(${soul.name})`)}` : "";
|
|
236
|
+
console.log(` ${pc.cyan(pc.bold(soul.label))}${nameTag} ${pc.magenta(`by ${soul.author}`)}${rating}${desc}`);
|
|
237
|
+
}
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
// Interactive mode: let user pick a soul
|
|
241
|
+
const { select, confirm: inquirerConfirm } = await import("@inquirer/prompts");
|
|
242
|
+
const choices = results.map((soul) => {
|
|
243
|
+
const rating = soul.rating_avg
|
|
244
|
+
? pc.yellow(` ★ ${soul.rating_avg.toFixed(1)}`) +
|
|
245
|
+
pc.dim(` (${soul.rating_count})`)
|
|
246
|
+
: "";
|
|
247
|
+
const author = pc.magenta(`by ${soul.author}`);
|
|
248
|
+
const desc = soul.description ? pc.dim(` — ${soul.description}`) : "";
|
|
249
|
+
const nameTag = soul.name !== soul.label ? ` ${pc.yellow(`(${soul.name})`)}` : "";
|
|
250
|
+
return {
|
|
251
|
+
name: `${pc.cyan(pc.bold(soul.label))}${nameTag} ${author}${rating}${desc}`,
|
|
252
|
+
value: soul.label,
|
|
253
|
+
};
|
|
254
|
+
});
|
|
255
|
+
console.log(pc.bold(`\n${pagination.total} soul(s) found:\n`));
|
|
256
|
+
const label = await select({
|
|
257
|
+
message: "Select a soul to pull",
|
|
258
|
+
choices: [
|
|
259
|
+
...choices,
|
|
260
|
+
{ name: pc.dim("Cancel"), value: "__cancel__" },
|
|
261
|
+
],
|
|
262
|
+
});
|
|
263
|
+
if (label === "__cancel__") {
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
// Summon the selected soul
|
|
267
|
+
log(`Summoning soul '${label}' from registry`);
|
|
268
|
+
const [meta, content] = await Promise.all([
|
|
269
|
+
client.getMeta(label),
|
|
270
|
+
client.getContent(label),
|
|
271
|
+
]);
|
|
272
|
+
const hash = createHash("sha256").update(content).digest("hex");
|
|
273
|
+
const name = meta.name;
|
|
274
|
+
cacheSoul(name, content, hash, meta.label);
|
|
275
|
+
console.log(pc.green(`🔮 Summoned ${pc.yellow(pc.bold(name))} (${label})`));
|
|
276
|
+
// Ask if they want to possess immediately
|
|
277
|
+
const shouldSwap = await inquirerConfirm({
|
|
278
|
+
message: "Possess your bot with this soul now?",
|
|
279
|
+
default: true,
|
|
280
|
+
});
|
|
281
|
+
if (shouldSwap) {
|
|
282
|
+
const { backedUp } = swapSoul(content);
|
|
283
|
+
console.log(pc.green(`\n👻 Possessed with ${pc.yellow(pc.bold(name))}`));
|
|
284
|
+
console.log(pc.dim(` Written to ${getSoulPath()}`));
|
|
285
|
+
if (backedUp) {
|
|
286
|
+
console.log(pc.dim(` Original SOUL.md backed up (use 'soul exorcise' to restore)`));
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
console.log(pc.dim(` Use 'soul possess ${name}' to activate later.`));
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
catch (err) {
|
|
294
|
+
if (err.name === "ExitPromptError") {
|
|
295
|
+
// User pressed Ctrl+C during prompt
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
fail(err.message);
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
// --- summon ---
|
|
302
|
+
program
|
|
303
|
+
.command("summon <label>")
|
|
304
|
+
.description("Download a soul from the registry to local cache")
|
|
305
|
+
.action(async (label) => {
|
|
306
|
+
log(`Summoning soul '${label}' from registry`);
|
|
307
|
+
try {
|
|
308
|
+
const client = new RegistryClient();
|
|
309
|
+
log(`Registry URL: ${loadConfig().registry_url}`);
|
|
310
|
+
const [meta, content] = await Promise.all([
|
|
311
|
+
client.getMeta(label),
|
|
312
|
+
client.getContent(label),
|
|
313
|
+
]);
|
|
314
|
+
const hash = createHash("sha256").update(content).digest("hex");
|
|
315
|
+
const name = meta.name;
|
|
316
|
+
cacheSoul(name, content, hash, meta.label);
|
|
317
|
+
console.log(pc.green(`\n🔮 Summoned ${pc.yellow(pc.bold(name))} (${label})`));
|
|
318
|
+
console.log(pc.dim(` Cached locally. Use 'soul possess ${name}' to activate.`));
|
|
319
|
+
}
|
|
320
|
+
catch (err) {
|
|
321
|
+
fail(err.message);
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
// --- list ---
|
|
325
|
+
program
|
|
326
|
+
.command("list")
|
|
327
|
+
.description("List locally cached souls (most recently used first)")
|
|
328
|
+
.option("-p, --page <number>", "Page number", "1")
|
|
329
|
+
.option("-n, --per-page <number>", "Souls per page", "20")
|
|
330
|
+
.action((opts) => {
|
|
331
|
+
const cached = listCached();
|
|
332
|
+
if (cached.length === 0) {
|
|
333
|
+
console.log(pc.yellow("No cached souls. Use 'soul summon <label>' to download one."));
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
const sorted = [...cached].sort((a, b) => {
|
|
337
|
+
const aUsed = a.lastUsedAt ?? "";
|
|
338
|
+
const bUsed = b.lastUsedAt ?? "";
|
|
339
|
+
if (aUsed !== bUsed)
|
|
340
|
+
return bUsed.localeCompare(aUsed);
|
|
341
|
+
return (b.cachedAt ?? "").localeCompare(a.cachedAt ?? "");
|
|
342
|
+
});
|
|
343
|
+
const perPage = Math.max(1, parseInt(opts.perPage, 10) || 20);
|
|
344
|
+
const totalPages = Math.ceil(sorted.length / perPage);
|
|
345
|
+
const page = Math.min(Math.max(1, parseInt(opts.page, 10) || 1), totalPages);
|
|
346
|
+
const start = (page - 1) * perPage;
|
|
347
|
+
const pageItems = sorted.slice(start, start + perPage);
|
|
348
|
+
for (const entry of pageItems) {
|
|
349
|
+
const label = entry.label ?? entry.name.toLowerCase().replace(/\s+/g, "-");
|
|
350
|
+
const nameDisplay = entry.label && entry.name !== entry.label
|
|
351
|
+
? ` ${pc.dim(`(${entry.name})`)}`
|
|
352
|
+
: "";
|
|
353
|
+
console.log(` ${pc.yellow(label)}${nameDisplay}`);
|
|
354
|
+
}
|
|
355
|
+
if (totalPages > 1) {
|
|
356
|
+
console.log(pc.dim(`\n Page ${page}/${totalPages} (${sorted.length} souls)`));
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
// --- banish ---
|
|
360
|
+
program
|
|
361
|
+
.command("banish <name>")
|
|
362
|
+
.description("Remove a soul from the local cache")
|
|
363
|
+
.action((name) => {
|
|
364
|
+
const removed = removeCached(name);
|
|
365
|
+
if (removed) {
|
|
366
|
+
console.log(pc.green(`\n🚪 Banished ${pc.yellow(pc.bold(name))} from cache`));
|
|
367
|
+
}
|
|
368
|
+
else {
|
|
369
|
+
fail(`Soul '${name}' not found in cache.`);
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
// --- status ---
|
|
373
|
+
program
|
|
374
|
+
.command("status")
|
|
375
|
+
.description("Show current SOUL.md status and swap state")
|
|
376
|
+
.action(() => {
|
|
377
|
+
const soulPath = getSoulPath();
|
|
378
|
+
const wsDir = dirname(soulPath);
|
|
379
|
+
if (!existsSync(wsDir)) {
|
|
380
|
+
console.log(pc.yellow(`OpenClaw workspace not found at ${wsDir}`));
|
|
381
|
+
console.log(pc.dim("Is OpenClaw installed? Expected ~/.openclaw/workspace/"));
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
const content = readCurrentSoul();
|
|
385
|
+
if (!content) {
|
|
386
|
+
console.log(pc.yellow(`No SOUL.md found at ${soulPath}`));
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
const swapped = isSwapped();
|
|
390
|
+
console.log(pc.bold("\nSOUL.md Status"));
|
|
391
|
+
console.log(`Path: ${soulPath}`);
|
|
392
|
+
console.log(`State: ${swapped ? pc.cyan("swapped") : pc.green("original")}`);
|
|
393
|
+
console.log(`Backup: ${hasBackup() ? pc.green("saved") : pc.dim("none")}`);
|
|
394
|
+
if (swapped) {
|
|
395
|
+
const rawContent = content.split("\n").slice(1).join("\n");
|
|
396
|
+
const firstLine = rawContent.trim().split("\n")[0] ?? "";
|
|
397
|
+
console.log(`Preview: ${pc.cyan(firstLine)}`);
|
|
398
|
+
}
|
|
399
|
+
});
|
|
400
|
+
// --- path ---
|
|
401
|
+
program
|
|
402
|
+
.command("path [newPath]")
|
|
403
|
+
.description("Show or set the SOUL.md file path (or --skills for skills dir)")
|
|
404
|
+
.option("--skills", "Show or set the OpenClaw skills directory path")
|
|
405
|
+
.action((newPath, opts) => {
|
|
406
|
+
const key = opts.skills ? "skills_path" : "soul_path";
|
|
407
|
+
const label = opts.skills ? "Skills path" : "SOUL.md path";
|
|
408
|
+
if (newPath) {
|
|
409
|
+
const resolved = resolve(newPath);
|
|
410
|
+
setConfigValue(key, resolved);
|
|
411
|
+
console.log(pc.green(` ${label} set to ${pc.yellow(resolved)}`));
|
|
412
|
+
}
|
|
413
|
+
else {
|
|
414
|
+
console.log(opts.skills ? loadConfig().skills_path : getSoulPath());
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
// --- install ---
|
|
418
|
+
program
|
|
419
|
+
.command("install")
|
|
420
|
+
.description("Install the OpenSoul skill into OpenClaw")
|
|
421
|
+
.action(() => {
|
|
422
|
+
const { path, updated } = installSkill();
|
|
423
|
+
if (updated) {
|
|
424
|
+
console.log(pc.green(`\n✓ Updated OpenSOUL skill`));
|
|
425
|
+
}
|
|
426
|
+
else {
|
|
427
|
+
console.log(pc.green(`\n✓ Installed OpenSOUL skill`));
|
|
428
|
+
}
|
|
429
|
+
console.log(pc.dim(` ${path}`));
|
|
430
|
+
console.log(pc.dim(` Your OpenClaw bot can now swap souls via natural language.`));
|
|
431
|
+
});
|
|
432
|
+
// --- uninstall ---
|
|
433
|
+
program
|
|
434
|
+
.command("uninstall")
|
|
435
|
+
.description("Remove the OpenSoul skill from OpenClaw")
|
|
436
|
+
.action(() => {
|
|
437
|
+
if (!isSkillInstalled()) {
|
|
438
|
+
console.log(pc.yellow("OpenSoul skill is not installed."));
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
const removed = uninstallSkill();
|
|
442
|
+
if (removed) {
|
|
443
|
+
console.log(pc.green("\n✓ Uninstalled OpenSOUL skill"));
|
|
444
|
+
}
|
|
445
|
+
else {
|
|
446
|
+
fail("Failed to uninstall skill.");
|
|
447
|
+
}
|
|
448
|
+
});
|
|
449
|
+
// --- config ---
|
|
450
|
+
const configCmd = program
|
|
451
|
+
.command("config")
|
|
452
|
+
.description("Get or set CLI configuration values");
|
|
453
|
+
configCmd
|
|
454
|
+
.command("get <key>")
|
|
455
|
+
.description("Get a config value")
|
|
456
|
+
.action((key) => {
|
|
457
|
+
const value = getConfigValue(key);
|
|
458
|
+
if (value === undefined) {
|
|
459
|
+
fail(`Unknown config key: ${key}`);
|
|
460
|
+
}
|
|
461
|
+
console.log(value);
|
|
462
|
+
});
|
|
463
|
+
configCmd
|
|
464
|
+
.command("set <key> <value>")
|
|
465
|
+
.description("Set a config value")
|
|
466
|
+
.action((key, value) => {
|
|
467
|
+
setConfigValue(key, value);
|
|
468
|
+
console.log(pc.green(`Set ${key} = ${value}`));
|
|
469
|
+
});
|
|
470
|
+
program.parse();
|
|
471
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EACL,UAAU,EACV,SAAS,EACT,SAAS,EACT,YAAY,EACZ,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,QAAQ,EACR,YAAY,EACZ,SAAS,EACT,SAAS,EACT,eAAe,EACf,WAAW,GACZ,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EACL,YAAY,EACZ,cAAc,EACd,gBAAgB,GAEjB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CACpB,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC,CAC7D,CAAC;AAEF,IAAI,OAAO,GAAG,KAAK,CAAC;AAEpB,SAAS,GAAG,CAAC,GAAG,IAAe;IAC7B,IAAI,OAAO;QAAE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,IAAI,CAAC,OAAe;IAC3B,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAE5C,SAAS,OAAO,CAAC,OAAe;IAC9B,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAC9B,MAAM,CAAC,KAAK,CAAC,KAAK,cAAc,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;QAC7B,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC;IACtD,CAAC,EAAE,GAAG,CAAC,CAAC;IACR,OAAO;QACL,IAAI,CAAC,YAAqB;YACxB,aAAa,CAAC,KAAK,CAAC,CAAC;YACrB,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;YACvD,IAAI,YAAY;gBAAE,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAC9C,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,MAAc,EAAE,UAAU,GAAG,KAAK;IACjD,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7E,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;IAC5C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,EAAE,CAAC,QAAQ,CAAC,GAAG,MAAM,IAAI,IAAI,GAAG,EAAE,CAAC,MAAM,EAAE,EAAE;YAC3C,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;YAC5C,IAAI,OAAO,KAAK,EAAE;gBAAE,OAAO,CAAC,UAAU,CAAC,CAAC;;gBACnC,OAAO,CAAC,OAAO,KAAK,GAAG,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,MAAM,CAAC;KACZ,WAAW,CAAC,uDAAuD,CAAC;KACpE,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,eAAe,CAAC;KACrC,MAAM,CAAC,WAAW,EAAE,qCAAqC,CAAC;KAC1D,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE;IACtB,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,OAAO,IAAI,KAAK,CAAC;AAC5C,CAAC,CAAC,CAAC;AAEL,kBAAkB;AAClB,OAAO;KACJ,OAAO,CAAC,sBAAsB,CAAC;KAC/B,WAAW,CAAC,yDAAyD,CAAC;KACtE,MAAM,CAAC,WAAW,EAAE,2CAA2C,CAAC;KAChE,MAAM,CAAC,WAAW,EAAE,0BAA0B,CAAC;KAC/C,MAAM,CACL,KAAK,EAAE,UAAkB,EAAE,IAAyC,EAAE,EAAE;IACtE,IAAI,OAAe,CAAC;IACpB,IAAI,MAAc,CAAC;IACnB,IAAI,QAA4B,CAAC;IACjC,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAErC,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC1C,MAAM,GAAG,QAAQ,CAAC;QAClB,GAAG,CAAC,sBAAsB,QAAQ,EAAE,CAAC,CAAC;IACxC,CAAC;SAAM,CAAC;QACN,MAAM,MAAM,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;QACrC,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;YACzB,MAAM,GAAG,SAAS,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YACtC,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;YAC7B,GAAG,CAAC,uBAAuB,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAClD,CAAC;aAAM,CAAC;YACN,2DAA2D;YAC3D,MAAM,SAAS,GAAG,CAAC,CAAS,EAAE,EAAE,CAC9B,CAAC;iBACE,WAAW,EAAE;iBACb,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC;iBACxB,IAAI,EAAE,CAAC;YACZ,MAAM,KAAK,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;YACpC,MAAM,SAAS,GAAG,UAAU,EAAE,CAAC;YAC/B,MAAM,YAAY,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;gBAC1C,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;gBAC5B,OAAO,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YAChD,CAAC,CAAC,CAAC;YAEH,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC5B,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;gBACxD,IAAI,CACF,SAAS,UAAU,0DAA0D,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,mFAAmF,CACzM,CAAC;YACJ,CAAC;YAED,sFAAsF;YACtF,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YACnE,MAAM,CAAC,GAAG,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC,CAAC;YACjE,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;gBACpC,GAAG,CAAC,iBAAiB,UAAU,EAAE,CAAC,YAAY,EAAE,CAAC,CAAC;gBAClD,GAAG,CAAC,iBAAiB,KAAK,EAAE,CAAC,CAAC;gBAC9B,MAAM,CAAC,IAAI,EAAE,cAAc,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;oBAC/C,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;oBACrB,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC;iBACzB,CAAC,CAAC;gBACH,OAAO,GAAG,cAAc,CAAC;gBACzB,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAChE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;gBACvB,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC3C,QAAQ,GAAG,IAAI,CAAC;gBAChB,MAAM,GAAG,YAAY,IAAI,CAAC,KAAK,EAAE,CAAC;gBAClC,CAAC,CAAC,IAAI,CACJ,EAAE,CAAC,KAAK,CACN,eAAe,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,KAAK,GAAG,CAC1D,CACF,CAAC;YACJ,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,CAAC,CAAC,IAAI,EAAE,CAAC;gBAET,4FAA4F;gBAC5F,IAAI,UAAU,GAAG,EAAE,CAAC;gBACpB,IAAI,CAAC;oBACH,MAAM,KAAK,GAAG,UAAU;yBACrB,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;yBACrB,IAAI,EAAE;yBACN,KAAK,CAAC,KAAK,CAAC,CAAC;oBAChB,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;oBAC5B,MAAM,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;oBACpC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,CAC3C,UAAU,EACV,SAAS,EACT,SAAS,EACT,CAAC,CACF,CAAC;oBACF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBACvB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;wBACpD,UAAU,GAAG,qCAAqC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC/F,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,mDAAmD;gBACrD,CAAC;gBAED,IAAI,CACF,SAAS,UAAU,6DAA6D,UAAU,EAAE,CAC7F,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,UAAU,CAAC;IAE3D,2DAA2D;IAC3D,MAAM,UAAU,GAAG,WAAW,EAAE,CAAC;IACjC,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACtC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,IAAI,CACF,+BAA+B,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,0CAA0C,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,qBAAqB,CAAC,gDAAgD,CAC1M,CAAC;IACJ,CAAC;IACD,IAAI,QAAQ,CAAC,UAAU,CAAC,KAAK,SAAS,EAAE,CAAC;QACvC,IAAI,CACF,6BAA6B,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,kCAAkC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,qBAAqB,CAAC,6DAA6D,CACxP,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC,CAAC;QACxD,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,EAAE,CAAC,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,aAAa,WAAW,EAAE,EAAE,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CACT,aAAa,CAAC,SAAS,EAAE,IAAI,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,gBAAgB,EAAE,CAC7F,CAAC;QACF,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC9C,OAAO;IACT,CAAC;IAED,sEAAsE;IACtE,IACE,CAAC,IAAI,CAAC,GAAG;QACT,CAAC,SAAS,EAAE;QACZ,UAAU,CAAC,WAAW,EAAE,CAAC;QACzB,OAAO,CAAC,KAAK,CAAC,KAAK,EACnB,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,uBAAuB,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC;QAC5D,MAAM,EAAE,GAAG,MAAM,OAAO,CACtB,+EAA+E,EAC/E,IAAI,CACL,CAAC;QACF,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;YAChC,OAAO;QACT,CAAC;IACH,CAAC;IAED,MAAM,CAAC,GAAG,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC;IAC/C,MAAM,EAAE,QAAQ,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IACvC,IAAI,QAAQ;QAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,uBAAuB,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAExE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,gBAAgB,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC;IACrD,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,GAAG,CACJ,+DAA+D,CAChE,CACF,CAAC;IACJ,CAAC;AACH,CAAC,CACF,CAAC;AAEJ,mBAAmB;AACnB,OAAO;KACJ,OAAO,CAAC,UAAU,CAAC;KACnB,WAAW,CAAC,0CAA0C,CAAC;KACvD,MAAM,CAAC,GAAG,EAAE;IACX,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;QACjB,IAAI,CAAC,uCAAuC,CAAC,CAAC;IAChD,CAAC;IAED,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC;IAChC,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,KAAK,CAAC,2BAA2B,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,CACrE,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC;IAC5C,CAAC;SAAM,CAAC;QACN,IAAI,CAAC,0BAA0B,CAAC,CAAC;IACnC,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,iBAAiB;AACjB,OAAO;KACJ,OAAO,CAAC,gBAAgB,CAAC;KACzB,WAAW,CAAC,0BAA0B,CAAC;KACvC,MAAM,CAAC,OAAO,EAAE,uBAAuB,CAAC;KACxC,MAAM,CAAC,WAAW,EAAE,sBAAsB,CAAC;KAC3C,MAAM,CAAC,kBAAkB,EAAE,6CAA6C,CAAC;KACzE,MAAM,CACL,KAAK,EACH,KAAyB,EACzB,IAAiE,EACjE,EAAE;IACF,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;QACpC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;QACrE,GAAG,CACD,6BAA6B,KAAK,IAAI,OAAO,SAAS,IAAI,IAAI,QAAQ,EAAE,CACzE,CAAC;QACF,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAEvE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC;YAC1C,OAAO;QACT,CAAC;QAED,2CAA2C;QAC3C,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,WAAW,KAAK,KAAK,EAAE,CAAC;YACvD,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,IAAI,CACL,KAAK,UAAU,CAAC,KAAK,wBAAwB,UAAU,CAAC,IAAI,IAAI,UAAU,CAAC,UAAU,MAAM,CAC5F,CACF,CAAC;YACF,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;gBAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU;oBAC5B,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;wBAC7C,EAAE,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,YAAY,WAAW,CAAC;oBAC3C,CAAC,CAAC,EAAE,CAAC;gBACP,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW;oBAC3B,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;oBAClC,CAAC,CAAC,EAAE,CAAC;gBACP,MAAM,OAAO,GACX,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpE,OAAO,CAAC,GAAG,CACT,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,OAAO,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,GAAG,IAAI,EAAE,CACjG,CAAC;YACJ,CAAC;YACD,OAAO;QACT,CAAC;QAED,yCAAyC;QACzC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,GACxC,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;QAEpC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACnC,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU;gBAC5B,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC7C,EAAE,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,YAAY,GAAG,CAAC;gBACnC,CAAC,CAAC,EAAE,CAAC;YACP,MAAM,MAAM,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;YAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACtE,MAAM,OAAO,GACX,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpE,OAAO;gBACL,IAAI,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,OAAO,IAAI,MAAM,GAAG,MAAM,GAAG,IAAI,EAAE;gBAC3E,KAAK,EAAE,IAAI,CAAC,KAAK;aAClB,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC,KAAK,mBAAmB,CAAC,CAAC,CAAC;QAE/D,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC;YACzB,OAAO,EAAE,uBAAuB;YAChC,OAAO,EAAE;gBACP,GAAG,OAAO;gBACV,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE;aAChD;SACF,CAAC,CAAC;QAEH,IAAI,KAAK,KAAK,YAAY,EAAE,CAAC;YAC3B,OAAO;QACT,CAAC;QAED,2BAA2B;QAC3B,GAAG,CAAC,mBAAmB,KAAK,iBAAiB,CAAC,CAAC;QAC/C,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACxC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;YACrB,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC;SACzB,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAChE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACvB,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,KAAK,CAAC,eAAe,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,GAAG,CAAC,CAC/D,CAAC;QAEF,0CAA0C;QAC1C,MAAM,UAAU,GAAG,MAAM,eAAe,CAAC;YACvC,OAAO,EAAE,sCAAsC;YAC/C,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QAEH,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,EAAE,QAAQ,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;YACvC,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,KAAK,CAAC,uBAAuB,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAC5D,CAAC;YACF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,gBAAgB,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC;YACrD,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,GAAG,CACJ,+DAA+D,CAChE,CACF,CAAC;YACJ,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,GAAG,CAAC,uBAAuB,IAAI,sBAAsB,CAAC,CAC1D,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAAa,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;YAC9C,oCAAoC;YACpC,OAAO;QACT,CAAC;QACD,IAAI,CAAE,GAAa,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;AACH,CAAC,CACF,CAAC;AAEJ,iBAAiB;AACjB,OAAO;KACJ,OAAO,CAAC,gBAAgB,CAAC;KACzB,WAAW,CAAC,kDAAkD,CAAC;KAC/D,MAAM,CAAC,KAAK,EAAE,KAAa,EAAE,EAAE;IAC9B,GAAG,CAAC,mBAAmB,KAAK,iBAAiB,CAAC,CAAC;IAC/C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;QACpC,GAAG,CAAC,iBAAiB,UAAU,EAAE,CAAC,YAAY,EAAE,CAAC,CAAC;QAClD,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACxC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;YACrB,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC;SACzB,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAChE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QAEvB,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAE3C,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,GAAG,CAAC,CACjE,CAAC;QACF,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,GAAG,CAAC,uCAAuC,IAAI,gBAAgB,CAAC,CACpE,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAE,GAAa,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,eAAe;AACf,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,sDAAsD,CAAC;KACnE,MAAM,CAAC,qBAAqB,EAAE,aAAa,EAAE,GAAG,CAAC;KACjD,MAAM,CAAC,yBAAyB,EAAE,gBAAgB,EAAE,IAAI,CAAC;KACzD,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;IACf,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,MAAM,CACP,6DAA6D,CAC9D,CACF,CAAC;QACF,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACvC,MAAM,KAAK,GAAG,CAAC,CAAC,UAAU,IAAI,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG,CAAC,CAAC,UAAU,IAAI,EAAE,CAAC;QACjC,IAAI,KAAK,KAAK,KAAK;YAAE,OAAO,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACvD,OAAO,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC;IACtD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CACnB,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,EACzC,UAAU,CACX,CAAC;IACF,MAAM,KAAK,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC;IACnC,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,CAAC;IAEvD,KAAK,MAAM,KAAK,IAAI,SAAS,EAAE,CAAC;QAC9B,MAAM,KAAK,GACT,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC/D,MAAM,WAAW,GACf,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,KAAK;YACvC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,IAAI,GAAG,CAAC,EAAE;YACjC,CAAC,CAAC,EAAE,CAAC;QACT,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,WAAW,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;QACnB,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,GAAG,CAAC,YAAY,IAAI,IAAI,UAAU,KAAK,MAAM,CAAC,MAAM,SAAS,CAAC,CAClE,CAAC;IACJ,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,iBAAiB;AACjB,OAAO;KACJ,OAAO,CAAC,eAAe,CAAC;KACxB,WAAW,CAAC,oCAAoC,CAAC;KACjD,MAAM,CAAC,CAAC,IAAY,EAAE,EAAE;IACvB,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACnC,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,aAAa,CAAC,CACjE,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,IAAI,CAAC,SAAS,IAAI,uBAAuB,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,iBAAiB;AACjB,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,4CAA4C,CAAC;KACzD,MAAM,CAAC,GAAG,EAAE;IACX,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAEhC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,mCAAmC,KAAK,EAAE,CAAC,CAAC,CAAC;QACnE,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,GAAG,CAAC,wDAAwD,CAAC,CACjE,CAAC;QACF,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,eAAe,EAAE,CAAC;IAClC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,uBAAuB,QAAQ,EAAE,CAAC,CAAC,CAAC;QAC1D,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;IAC5B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CAAC,SAAS,QAAQ,EAAE,CAAC,CAAC;IACjC,OAAO,CAAC,GAAG,CACT,UAAU,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAChE,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,WAAW,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAE3E,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3D,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACzD,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IAChD,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,eAAe;AACf,OAAO;KACJ,OAAO,CAAC,gBAAgB,CAAC;KACzB,WAAW,CAAC,gEAAgE,CAAC;KAC7E,MAAM,CAAC,UAAU,EAAE,gDAAgD,CAAC;KACpE,MAAM,CAAC,CAAC,OAA2B,EAAE,IAA0B,EAAE,EAAE;IAClE,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,WAAW,CAAC;IACtD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,cAAc,CAAC;IAC3D,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAClC,cAAc,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,WAAW,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;IACpE,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IACtE,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,kBAAkB;AAClB,OAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,0CAA0C,CAAC;KACvD,MAAM,CAAC,GAAG,EAAE;IACX,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,YAAY,EAAE,CAAC;IACzC,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC,CAAC;IACtD,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC;IACjC,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,GAAG,CAAC,8DAA8D,CAAC,CACvE,CAAC;AACJ,CAAC,CAAC,CAAC;AAEL,oBAAoB;AACpB,OAAO;KACJ,OAAO,CAAC,WAAW,CAAC;KACpB,WAAW,CAAC,yCAAyC,CAAC;KACtD,MAAM,CAAC,GAAG,EAAE;IACX,IAAI,CAAC,gBAAgB,EAAE,EAAE,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,kCAAkC,CAAC,CAAC,CAAC;QAC3D,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,cAAc,EAAE,CAAC;IACjC,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC,CAAC;IAC1D,CAAC;SAAM,CAAC;QACN,IAAI,CAAC,4BAA4B,CAAC,CAAC;IACrC,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,iBAAiB;AACjB,MAAM,SAAS,GAAG,OAAO;KACtB,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,qCAAqC,CAAC,CAAC;AAEtD,SAAS;KACN,OAAO,CAAC,WAAW,CAAC;KACpB,WAAW,CAAC,oBAAoB,CAAC;KACjC,MAAM,CAAC,CAAC,GAAW,EAAE,EAAE;IACtB,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,IAAI,CAAC,uBAAuB,GAAG,EAAE,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACrB,CAAC,CAAC,CAAC;AAEL,SAAS;KACN,OAAO,CAAC,mBAAmB,CAAC;KAC5B,WAAW,CAAC,oBAAoB,CAAC;KACjC,MAAM,CAAC,CAAC,GAAW,EAAE,KAAa,EAAE,EAAE;IACrC,cAAc,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC3B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC;AACjD,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface RegistrySoul {
|
|
2
|
+
slug: string;
|
|
3
|
+
label: string;
|
|
4
|
+
name: string;
|
|
5
|
+
author: string;
|
|
6
|
+
description: string | null;
|
|
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
|
+
getMeta(id: string): Promise<RegistrySoul>;
|
|
26
|
+
getContent(id: string): Promise<string>;
|
|
27
|
+
}
|
|
28
|
+
//# 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,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,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,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAiB1C,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAgB9C"}
|
|
@@ -0,0 +1,54 @@
|
|
|
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 getMeta(id) {
|
|
28
|
+
const url = `${this.baseUrl}/api/v1/souls/${id}`;
|
|
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 '${id}' not found in registry`);
|
|
35
|
+
}
|
|
36
|
+
throw new Error(`Registry returned HTTP ${res.status}`);
|
|
37
|
+
}
|
|
38
|
+
return res.json();
|
|
39
|
+
}
|
|
40
|
+
async getContent(id) {
|
|
41
|
+
const url = `${this.baseUrl}/api/v1/souls/${id}/content`;
|
|
42
|
+
const res = await fetch(url).catch(() => {
|
|
43
|
+
throw new Error(`Failed to connect to registry at ${this.baseUrl}. Is it reachable?`);
|
|
44
|
+
});
|
|
45
|
+
if (!res.ok) {
|
|
46
|
+
if (res.status === 404) {
|
|
47
|
+
throw new Error(`Soul '${id}' not found in registry`);
|
|
48
|
+
}
|
|
49
|
+
throw new Error(`Registry returned HTTP ${res.status}`);
|
|
50
|
+
}
|
|
51
|
+
return res.text();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=registry-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry-client.js","sourceRoot":"","sources":["../src/registry-client.ts"],"names":[],"mappings":"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"}
|
package/dist/skill.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function isSkillInstalled(): boolean;
|
|
2
|
+
export declare function getSkillPath(): string;
|
|
3
|
+
export declare function installSkill(): {
|
|
4
|
+
path: string;
|
|
5
|
+
updated: boolean;
|
|
6
|
+
};
|
|
7
|
+
export declare function uninstallSkill(): boolean;
|
|
8
|
+
//# sourceMappingURL=skill.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"AAiCA,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C;AAED,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,wBAAgB,YAAY,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CASjE;AAED,wBAAgB,cAAc,IAAI,OAAO,CAKxC"}
|
package/dist/skill.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { writeFileSync, readFileSync, mkdirSync, existsSync, rmSync, } from "node:fs";
|
|
2
|
+
import { join, dirname } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { loadConfig } from "./config.js";
|
|
5
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
const SKILL_DIR_NAME = "opensoul";
|
|
7
|
+
function skillsDir() {
|
|
8
|
+
return loadConfig().skills_path;
|
|
9
|
+
}
|
|
10
|
+
function skillDir() {
|
|
11
|
+
return join(skillsDir(), SKILL_DIR_NAME);
|
|
12
|
+
}
|
|
13
|
+
function skillPath() {
|
|
14
|
+
return join(skillDir(), "SKILL.md");
|
|
15
|
+
}
|
|
16
|
+
function loadSkillContent() {
|
|
17
|
+
// SKILL.md is bundled at the package root (sibling to dist/)
|
|
18
|
+
const path = join(__dirname, "..", "SKILL.md");
|
|
19
|
+
return readFileSync(path, "utf-8");
|
|
20
|
+
}
|
|
21
|
+
export function isSkillInstalled() {
|
|
22
|
+
return existsSync(skillPath());
|
|
23
|
+
}
|
|
24
|
+
export function getSkillPath() {
|
|
25
|
+
return skillPath();
|
|
26
|
+
}
|
|
27
|
+
export function installSkill() {
|
|
28
|
+
const dir = skillDir();
|
|
29
|
+
const path = skillPath();
|
|
30
|
+
const updated = existsSync(path);
|
|
31
|
+
mkdirSync(dir, { recursive: true });
|
|
32
|
+
writeFileSync(path, loadSkillContent(), "utf-8");
|
|
33
|
+
return { path, updated };
|
|
34
|
+
}
|
|
35
|
+
export function uninstallSkill() {
|
|
36
|
+
if (!existsSync(skillPath()))
|
|
37
|
+
return false;
|
|
38
|
+
rmSync(skillDir(), { recursive: true });
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=skill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill.js","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,YAAY,EACZ,SAAS,EACT,UAAU,EACV,MAAM,GACP,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE1D,MAAM,cAAc,GAAG,UAAU,CAAC;AAElC,SAAS,SAAS;IAChB,OAAO,UAAU,EAAE,CAAC,WAAW,CAAC;AAClC,CAAC;AAED,SAAS,QAAQ;IACf,OAAO,IAAI,CAAC,SAAS,EAAE,EAAE,cAAc,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,IAAI,CAAC,QAAQ,EAAE,EAAE,UAAU,CAAC,CAAC;AACtC,CAAC;AAED,SAAS,gBAAgB;IACvB,6DAA6D;IAC7D,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;IAC/C,OAAO,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,SAAS,EAAE,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,MAAM,GAAG,GAAG,QAAQ,EAAE,CAAC;IACvB,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;IACzB,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAEjC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpC,aAAa,CAAC,IAAI,EAAE,gBAAgB,EAAE,EAAE,OAAO,CAAC,CAAC;IAEjD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC;QAAE,OAAO,KAAK,CAAC;IAE3C,MAAM,CAAC,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACxC,OAAO,IAAI,CAAC;AACd,CAAC"}
|
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":"AAuBA,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,59 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, copyFileSync, statSync } from "node:fs";
|
|
2
|
+
import { join, dirname } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { loadConfig } from "./config.js";
|
|
5
|
+
const SWAP_MARKER = "<!-- opensoul:swapped -->";
|
|
6
|
+
function soulPath() {
|
|
7
|
+
const p = loadConfig().soul_path;
|
|
8
|
+
if (existsSync(p) && statSync(p).isDirectory()) {
|
|
9
|
+
return join(p, "SOUL.md");
|
|
10
|
+
}
|
|
11
|
+
return p;
|
|
12
|
+
}
|
|
13
|
+
function backupDir() {
|
|
14
|
+
return join(homedir(), ".soul", "backup");
|
|
15
|
+
}
|
|
16
|
+
function backupPath() {
|
|
17
|
+
return join(backupDir(), "SOUL.md.original");
|
|
18
|
+
}
|
|
19
|
+
export function getSoulPath() {
|
|
20
|
+
return soulPath();
|
|
21
|
+
}
|
|
22
|
+
export function isSwapped() {
|
|
23
|
+
const p = soulPath();
|
|
24
|
+
if (!existsSync(p))
|
|
25
|
+
return false;
|
|
26
|
+
const content = readFileSync(p, "utf-8");
|
|
27
|
+
return content.startsWith(SWAP_MARKER);
|
|
28
|
+
}
|
|
29
|
+
export function readCurrentSoul() {
|
|
30
|
+
const p = soulPath();
|
|
31
|
+
if (!existsSync(p))
|
|
32
|
+
return null;
|
|
33
|
+
return readFileSync(p, "utf-8");
|
|
34
|
+
}
|
|
35
|
+
export function hasBackup() {
|
|
36
|
+
return existsSync(backupPath());
|
|
37
|
+
}
|
|
38
|
+
export function swapSoul(newContent) {
|
|
39
|
+
let backedUp = false;
|
|
40
|
+
const p = soulPath();
|
|
41
|
+
// If current SOUL.md is NOT already a swapped one, back it up
|
|
42
|
+
if (!isSwapped() && existsSync(p)) {
|
|
43
|
+
mkdirSync(backupDir(), { recursive: true });
|
|
44
|
+
copyFileSync(p, backupPath());
|
|
45
|
+
backedUp = true;
|
|
46
|
+
}
|
|
47
|
+
// Write the new soul with the swap marker
|
|
48
|
+
mkdirSync(dirname(p), { recursive: true });
|
|
49
|
+
const marked = `${SWAP_MARKER}\n${newContent}`;
|
|
50
|
+
writeFileSync(p, marked, "utf-8");
|
|
51
|
+
return { backedUp };
|
|
52
|
+
}
|
|
53
|
+
export function rollbackSoul() {
|
|
54
|
+
if (!existsSync(backupPath()))
|
|
55
|
+
return false;
|
|
56
|
+
copyFileSync(backupPath(), soulPath());
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=swap.js.map
|
package/dist/swap.js.map
ADDED
|
@@ -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,QAAQ,EAAE,MAAM,SAAS,CAAC;AACrG,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,WAAW,GAAG,2BAA2B,CAAC;AAEhD,SAAS,QAAQ;IACf,MAAM,CAAC,GAAG,UAAU,EAAE,CAAC,SAAS,CAAC;IACjC,IAAI,UAAU,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;QAC/C,OAAO,IAAI,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,CAAC,CAAC;AACX,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,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "opensoul",
|
|
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/opensoul/cli"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://opensoul.md",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"soul",
|
|
14
|
+
"opensoul",
|
|
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
|
+
"SKILL.md"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsc",
|
|
31
|
+
"test": "vitest run --passWithNoTests",
|
|
32
|
+
"dev": "tsx --watch src/index.ts",
|
|
33
|
+
"prepublishOnly": "pnpm run build"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@inquirer/prompts": "^8.2.0",
|
|
37
|
+
"@opensoul/core": "workspace:*",
|
|
38
|
+
"commander": "^13.0.0",
|
|
39
|
+
"picocolors": "^1.1.0",
|
|
40
|
+
"yaml": "^2.7.0"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/node": "^22.0.0",
|
|
44
|
+
"tsx": "^4.19.0",
|
|
45
|
+
"typescript": "^5.7.0",
|
|
46
|
+
"vitest": "^3.0.0"
|
|
47
|
+
}
|
|
48
|
+
}
|