thoth-plugin 1.1.1 → 1.1.2
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/README.md +237 -31
- package/dist/cli.d.ts +3 -2
- package/dist/cli.js +248 -5
- package/dist/config/schema.d.ts +2 -0
- package/dist/defaults/skill/email-draft/skill.md +134 -0
- package/dist/defaults/skill/evening-close/SKILL.md +7 -0
- package/dist/defaults/skill/gardener/SKILL.md +36 -1
- package/dist/defaults/skill/leadership-coach/SKILL.md +7 -0
- package/dist/defaults/skill/mail-triage/SKILL.md +7 -0
- package/dist/defaults/skill/morning-boot/SKILL.md +8 -0
- package/dist/defaults/skill/post-meeting-drill/SKILL.md +6 -0
- package/dist/defaults/skill/skill-generator/SKILL.md +150 -28
- package/dist/defaults/skill/slack-pulse/SKILL.md +6 -0
- package/dist/defaults/skill/thought-router/SKILL.md +7 -0
- package/dist/hooks/frontmatter-enforcer.d.ts +24 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/index.js +294 -61
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,6 +4,96 @@
|
|
|
4
4
|
|
|
5
5
|
Thoth is a knowledge-based life operating system that acts as your chief of staff. Unlike traditional coding assistants, Thoth is designed to **support, guide, and mentor** — not just write code.
|
|
6
6
|
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
### Via npm (Recommended)
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install -g thoth-plugin
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Then add to your OpenCode config (`~/.config/opencode/opencode.json`):
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"plugin": [
|
|
20
|
+
"thoth-plugin"
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Initialize Your Knowledge Base
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# Create a new knowledge base with default structure
|
|
29
|
+
npx thoth-plugin init
|
|
30
|
+
|
|
31
|
+
# Or initialize in a specific directory
|
|
32
|
+
npx thoth-plugin init ./my-thoth-kb
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Configure Knowledge Base Path
|
|
36
|
+
|
|
37
|
+
Create `~/.config/opencode/thoth-plugin.json`:
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"enabled": true,
|
|
42
|
+
"knowledge_base": "/path/to/your/thoth-kb"
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## LLM Installation Instructions
|
|
49
|
+
|
|
50
|
+
<!--
|
|
51
|
+
INSTRUCTIONS FOR AI ASSISTANTS:
|
|
52
|
+
|
|
53
|
+
When a user asks you to "install Thoth plugin" or provides a link to this repository,
|
|
54
|
+
follow these steps:
|
|
55
|
+
|
|
56
|
+
1. Install the plugin globally:
|
|
57
|
+
npm install -g thoth-plugin
|
|
58
|
+
|
|
59
|
+
2. Add to OpenCode config (~/.config/opencode/opencode.json):
|
|
60
|
+
- Read the existing config file
|
|
61
|
+
- Add "thoth-plugin" to the "plugin" array
|
|
62
|
+
- If "plugin" array doesn't exist, create it
|
|
63
|
+
|
|
64
|
+
3. Initialize the knowledge base:
|
|
65
|
+
npx thoth-plugin init ~/thoth-kb
|
|
66
|
+
|
|
67
|
+
4. Configure the knowledge base path (~/.config/opencode/thoth-plugin.json):
|
|
68
|
+
{
|
|
69
|
+
"enabled": true,
|
|
70
|
+
"knowledge_base": "/Users/<username>/thoth-kb"
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
5. Restart OpenCode to load the plugin
|
|
74
|
+
|
|
75
|
+
EXAMPLE COMMANDS:
|
|
76
|
+
```bash
|
|
77
|
+
# Install
|
|
78
|
+
npm install -g thoth-plugin
|
|
79
|
+
|
|
80
|
+
# Add to OpenCode config
|
|
81
|
+
# Edit ~/.config/opencode/opencode.json and add "thoth-plugin" to plugin array
|
|
82
|
+
|
|
83
|
+
# Initialize knowledge base
|
|
84
|
+
npx thoth-plugin init ~/thoth-kb
|
|
85
|
+
|
|
86
|
+
# Create thoth config
|
|
87
|
+
echo '{"enabled": true, "knowledge_base": "'$HOME'/thoth-kb"}' > ~/.config/opencode/thoth-plugin.json
|
|
88
|
+
|
|
89
|
+
# Restart OpenCode
|
|
90
|
+
```
|
|
91
|
+
-->
|
|
92
|
+
|
|
93
|
+
If you're an AI assistant helping a user install Thoth, see the HTML comment above for step-by-step instructions.
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
7
97
|
## Features
|
|
8
98
|
|
|
9
99
|
- **Four Hemispheres**: Organized knowledge across work, life, coding, and system (kernel)
|
|
@@ -11,6 +101,7 @@ Thoth is a knowledge-based life operating system that acts as your chief of staf
|
|
|
11
101
|
- **Smart Delegation**: Routes tasks to specialized sub-agents (Work Master, Life Master, Code Master)
|
|
12
102
|
- **Permission System**: Critical actions require explicit approval
|
|
13
103
|
- **Knowledge Persistence**: Learns and remembers across sessions
|
|
104
|
+
- **Skill System**: Automatic skill triggers for common workflows (morning boot, email triage, etc.)
|
|
14
105
|
|
|
15
106
|
## Depth-Based Specialization
|
|
16
107
|
|
|
@@ -18,56 +109,166 @@ Thoth's personality and expertise change based on your current directory:
|
|
|
18
109
|
|
|
19
110
|
| Depth | Example | Persona |
|
|
20
111
|
|-------|---------|---------|
|
|
21
|
-
| 0 | `/thoth/` | Pure Chief of Staff |
|
|
22
|
-
| 1 | `/thoth/work/` | Executive COS (crisp, P0-focused) |
|
|
23
|
-
| 1 | `/thoth/life/` | Personal Consultant (warm, Socratic) |
|
|
24
|
-
| 2 | `/thoth/work/projects/` | Project Portfolio Manager |
|
|
25
|
-
| 3 | `/thoth/work/projects/x/` | Deep Expert on Project X |
|
|
26
|
-
|
|
27
|
-
See [Persona Building Guide](kernel/knowledge/persona-building.md) for details.
|
|
112
|
+
| 0 | `/thoth-kb/` | Pure Chief of Staff |
|
|
113
|
+
| 1 | `/thoth-kb/work/` | Executive COS (crisp, P0-focused) |
|
|
114
|
+
| 1 | `/thoth-kb/life/` | Personal Consultant (warm, Socratic) |
|
|
115
|
+
| 2 | `/thoth-kb/work/projects/` | Project Portfolio Manager |
|
|
116
|
+
| 3 | `/thoth-kb/work/projects/x/` | Deep Expert on Project X |
|
|
28
117
|
|
|
29
118
|
## Structure
|
|
30
119
|
|
|
31
120
|
```
|
|
32
|
-
thoth/
|
|
33
|
-
├── kernel/
|
|
34
|
-
├── work/
|
|
35
|
-
├── life/
|
|
36
|
-
├── coding/
|
|
37
|
-
└──
|
|
121
|
+
thoth-kb/ # Your knowledge base
|
|
122
|
+
├── kernel/ # System config, memory, standards
|
|
123
|
+
├── work/ # Professional life
|
|
124
|
+
├── life/ # Personal life
|
|
125
|
+
├── coding/ # Technical projects
|
|
126
|
+
└── .opencode/skill/ # Custom skills
|
|
38
127
|
```
|
|
39
128
|
|
|
40
|
-
##
|
|
129
|
+
## Skills
|
|
41
130
|
|
|
42
|
-
Thoth
|
|
131
|
+
Thoth includes built-in skills that trigger automatically based on your intent:
|
|
43
132
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
133
|
+
| Trigger Phrases | Skill |
|
|
134
|
+
|-----------------|-------|
|
|
135
|
+
| "start my day", "morning routine", "prepare me for the day" | morning-boot |
|
|
136
|
+
| "end of day", "wrap up", "evening summary" | evening-close |
|
|
137
|
+
| "check my email", "email triage" | mail-triage |
|
|
138
|
+
| "check slack", "slack mentions" | slack-pulse |
|
|
139
|
+
| "brain dump", "capture this" | thought-router |
|
|
48
140
|
|
|
49
|
-
###
|
|
141
|
+
### Managing Skills
|
|
50
142
|
|
|
51
143
|
```bash
|
|
52
|
-
#
|
|
144
|
+
# List all available skills
|
|
145
|
+
npx thoth-plugin skill list
|
|
146
|
+
|
|
147
|
+
# Update skills to latest version (interactive)
|
|
148
|
+
npx thoth-plugin skill update
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
The `skill update` command:
|
|
152
|
+
- Compares your local skills with the latest package
|
|
153
|
+
- Shows what's new, updated, or locally modified
|
|
154
|
+
- Prompts for confirmation before each update
|
|
155
|
+
- Offers to help you contribute back if your local version is more advanced
|
|
156
|
+
|
|
157
|
+
### Skill Distribution Architecture
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
thoth-core (this repo) thoth-kb (your knowledge base)
|
|
161
|
+
├── defaults/skill/ ──────> ├── .opencode/skill/
|
|
162
|
+
│ ├── skill-generator/ copy │ ├── skill-generator/
|
|
163
|
+
│ ├── email-draft/ on │ ├── email-draft/
|
|
164
|
+
│ ├── morning-boot/ init │ ├── morning-boot/
|
|
165
|
+
│ └── ... or │ └── my-local-skill/
|
|
166
|
+
└── src/cli.ts update └── ...
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**Key principles:**
|
|
170
|
+
- **Source of truth**: `thoth-core/defaults/skill/` is canonical
|
|
171
|
+
- **All skills are public**: Personalization via knowledge base files, not skill forks
|
|
172
|
+
- **Distribution via npm**: Skills ship with the package
|
|
173
|
+
- **Contribute back**: Local improvements can be PR'd to thoth-core
|
|
174
|
+
|
|
175
|
+
### Creating Skills
|
|
176
|
+
|
|
177
|
+
Skills follow a TDD-inspired process (RED-GREEN-REFACTOR):
|
|
178
|
+
|
|
179
|
+
1. **RED**: Test baseline behavior without the skill (using subagent)
|
|
180
|
+
2. **GREEN**: Write minimal skill that fixes the failure
|
|
181
|
+
3. **REFACTOR**: Close loopholes, add to rationalization table
|
|
182
|
+
|
|
183
|
+
Use the `skill-generator` skill:
|
|
184
|
+
```
|
|
185
|
+
/skill-generator
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Skills are defined in `.opencode/skill/` with YAML frontmatter:
|
|
189
|
+
|
|
190
|
+
```yaml
|
|
191
|
+
---
|
|
192
|
+
name: my-skill
|
|
193
|
+
description: Use when [specific triggers]. Third person.
|
|
194
|
+
triggers:
|
|
195
|
+
- phrase that activates this skill
|
|
196
|
+
- another trigger phrase
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
# My Skill
|
|
200
|
+
|
|
201
|
+
**Core principle:** One sentence summary.
|
|
202
|
+
|
|
203
|
+
## When to Use
|
|
204
|
+
- Trigger condition 1
|
|
205
|
+
- Trigger condition 2
|
|
206
|
+
|
|
207
|
+
## Quick Reference
|
|
208
|
+
| Task | Action |
|
|
209
|
+
|------|--------|
|
|
210
|
+
|
|
211
|
+
## Common Mistakes
|
|
212
|
+
| Mistake | Prevention |
|
|
213
|
+
|---------|------------|
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
The `triggers` field enables automatic skill invocation when the user's message matches.
|
|
217
|
+
|
|
218
|
+
## Sub-Agents
|
|
219
|
+
|
|
220
|
+
Thoth delegates to specialized agents:
|
|
221
|
+
|
|
222
|
+
| Agent | Role |
|
|
223
|
+
|-------|------|
|
|
224
|
+
| Work Master | Professional life orchestrator |
|
|
225
|
+
| Life Master | Personal life orchestrator |
|
|
226
|
+
| Code Master | Technical projects (Sisyphus-quality code) |
|
|
227
|
+
| Coach | Reflection and thinking partner |
|
|
228
|
+
| Sentinel | Proactive monitoring |
|
|
229
|
+
| Diplomat | Communication drafting |
|
|
230
|
+
| Chronicler | Meeting and event processing |
|
|
231
|
+
|
|
232
|
+
## Configuration
|
|
233
|
+
|
|
234
|
+
### Global Config
|
|
235
|
+
|
|
236
|
+
`~/.config/opencode/thoth-plugin.json`:
|
|
237
|
+
|
|
238
|
+
```json
|
|
53
239
|
{
|
|
54
|
-
"
|
|
240
|
+
"enabled": true,
|
|
241
|
+
"knowledge_base": "/path/to/your/thoth-kb"
|
|
55
242
|
}
|
|
56
243
|
```
|
|
57
244
|
|
|
58
|
-
###
|
|
245
|
+
### Local Override
|
|
246
|
+
|
|
247
|
+
`.opencode/thoth-plugin.json` in any workspace:
|
|
248
|
+
|
|
249
|
+
```json
|
|
250
|
+
{
|
|
251
|
+
"knowledge_base": "./relative/path/to/kb"
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Development
|
|
256
|
+
|
|
257
|
+
### Building from Source
|
|
59
258
|
|
|
60
259
|
```bash
|
|
61
|
-
|
|
62
|
-
|
|
260
|
+
git clone https://github.com/Skeptomenos/thoth-core.git
|
|
261
|
+
cd thoth-core
|
|
262
|
+
bun install
|
|
263
|
+
bun run build
|
|
63
264
|
```
|
|
64
265
|
|
|
65
|
-
|
|
266
|
+
### Development Workflow
|
|
66
267
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
268
|
+
1. Edit source in `src/`
|
|
269
|
+
2. Build: `bun run build`
|
|
270
|
+
3. Test locally: Add absolute path to OpenCode config
|
|
271
|
+
4. Publish: `npm version patch && npm publish`
|
|
71
272
|
|
|
72
273
|
## Philosophy
|
|
73
274
|
|
|
@@ -79,6 +280,11 @@ Thoth operates on these principles:
|
|
|
79
280
|
4. **Cross-domain synthesis** — Can connect insights across hemispheres
|
|
80
281
|
5. **Continuous learning** — Persists learnings to the knowledge base
|
|
81
282
|
|
|
283
|
+
## Links
|
|
284
|
+
|
|
285
|
+
- **npm**: https://www.npmjs.com/package/thoth-plugin
|
|
286
|
+
- **GitHub**: https://github.com/Skeptomenos/thoth-core
|
|
287
|
+
|
|
82
288
|
## License
|
|
83
289
|
|
|
84
|
-
|
|
290
|
+
MIT
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* Thoth CLI - Knowledge Base
|
|
3
|
+
* Thoth CLI - Knowledge Base Management
|
|
4
4
|
*
|
|
5
5
|
* Usage:
|
|
6
6
|
* npx thoth-plugin init [path]
|
|
7
|
-
* thoth
|
|
7
|
+
* npx thoth-plugin skill update [path]
|
|
8
|
+
* npx thoth-plugin skill list
|
|
8
9
|
*/
|
|
9
10
|
export {};
|
package/dist/cli.js
CHANGED
|
@@ -2,13 +2,46 @@
|
|
|
2
2
|
// @bun
|
|
3
3
|
|
|
4
4
|
// src/cli.ts
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
existsSync,
|
|
7
|
+
mkdirSync,
|
|
8
|
+
cpSync,
|
|
9
|
+
writeFileSync,
|
|
10
|
+
readFileSync,
|
|
11
|
+
readdirSync
|
|
12
|
+
} from "fs";
|
|
6
13
|
import { join, dirname } from "path";
|
|
7
14
|
import { homedir } from "os";
|
|
8
15
|
import { fileURLToPath } from "url";
|
|
16
|
+
import { createInterface } from "readline";
|
|
17
|
+
import { createHash } from "crypto";
|
|
9
18
|
var __filename2 = fileURLToPath(import.meta.url);
|
|
10
19
|
var __dirname2 = dirname(__filename2);
|
|
11
20
|
var NPM_DEFAULTS_PATH = join(__dirname2, "defaults");
|
|
21
|
+
function prompt(question) {
|
|
22
|
+
const rl = createInterface({
|
|
23
|
+
input: process.stdin,
|
|
24
|
+
output: process.stdout
|
|
25
|
+
});
|
|
26
|
+
return new Promise((resolve) => {
|
|
27
|
+
rl.question(question, (answer) => {
|
|
28
|
+
rl.close();
|
|
29
|
+
resolve(answer.trim().toLowerCase());
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
function hashFile(filePath) {
|
|
34
|
+
if (!existsSync(filePath))
|
|
35
|
+
return "";
|
|
36
|
+
const content = readFileSync(filePath, "utf-8");
|
|
37
|
+
return createHash("md5").update(content).digest("hex");
|
|
38
|
+
}
|
|
39
|
+
function countLines(filePath) {
|
|
40
|
+
if (!existsSync(filePath))
|
|
41
|
+
return 0;
|
|
42
|
+
return readFileSync(filePath, "utf-8").split(`
|
|
43
|
+
`).length;
|
|
44
|
+
}
|
|
12
45
|
var README_TEMPLATE = `# Thoth Knowledge Base
|
|
13
46
|
|
|
14
47
|
Welcome to your personal Thoth knowledge base - your AI chief of staff for life orchestration.
|
|
@@ -182,6 +215,196 @@ Index of all knowledge in the ${hemi} hemisphere.
|
|
|
182
215
|
console.log(` 3. Ask: "Help me onboard"
|
|
183
216
|
`);
|
|
184
217
|
}
|
|
218
|
+
function findKbPath(startPath) {
|
|
219
|
+
const searchPaths = [
|
|
220
|
+
startPath,
|
|
221
|
+
process.cwd(),
|
|
222
|
+
join(process.cwd(), ".."),
|
|
223
|
+
join(homedir(), "thoth")
|
|
224
|
+
].filter(Boolean);
|
|
225
|
+
for (const basePath of searchPaths) {
|
|
226
|
+
const skillPath = join(basePath, ".opencode", "skill");
|
|
227
|
+
if (existsSync(skillPath)) {
|
|
228
|
+
return basePath;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
function compareSkills(localSkillDir) {
|
|
234
|
+
const packageSkillDir = join(NPM_DEFAULTS_PATH, "skill");
|
|
235
|
+
const results = [];
|
|
236
|
+
if (!existsSync(packageSkillDir)) {
|
|
237
|
+
console.log("Error: No skills found in package");
|
|
238
|
+
return results;
|
|
239
|
+
}
|
|
240
|
+
const packageSkills = existsSync(packageSkillDir) ? readdirSync(packageSkillDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name) : [];
|
|
241
|
+
const localSkills = existsSync(localSkillDir) ? readdirSync(localSkillDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name) : [];
|
|
242
|
+
const allSkills = [...new Set([...packageSkills, ...localSkills])].sort();
|
|
243
|
+
for (const skill of allSkills) {
|
|
244
|
+
const localPath = join(localSkillDir, skill);
|
|
245
|
+
const packagePath = join(packageSkillDir, skill);
|
|
246
|
+
const localExists = existsSync(localPath);
|
|
247
|
+
const packageExists = existsSync(packagePath);
|
|
248
|
+
const localFile = localExists ? existsSync(join(localPath, "SKILL.md")) ? join(localPath, "SKILL.md") : join(localPath, "skill.md") : "";
|
|
249
|
+
const packageFile = packageExists ? existsSync(join(packagePath, "SKILL.md")) ? join(packagePath, "SKILL.md") : join(packagePath, "skill.md") : "";
|
|
250
|
+
const localHash = localFile ? hashFile(localFile) : "";
|
|
251
|
+
const packageHash = packageFile ? hashFile(packageFile) : "";
|
|
252
|
+
const localLines = localFile ? countLines(localFile) : 0;
|
|
253
|
+
const packageLines = packageFile ? countLines(packageFile) : 0;
|
|
254
|
+
let status;
|
|
255
|
+
if (!localExists && packageExists) {
|
|
256
|
+
status = "package-only";
|
|
257
|
+
} else if (localExists && !packageExists) {
|
|
258
|
+
status = "local-only";
|
|
259
|
+
} else if (localHash === packageHash) {
|
|
260
|
+
status = "identical";
|
|
261
|
+
} else if (localLines > packageLines) {
|
|
262
|
+
status = "local-newer";
|
|
263
|
+
} else {
|
|
264
|
+
status = "package-newer";
|
|
265
|
+
}
|
|
266
|
+
results.push({
|
|
267
|
+
name: skill,
|
|
268
|
+
status,
|
|
269
|
+
localLines: localLines || undefined,
|
|
270
|
+
packageLines: packageLines || undefined,
|
|
271
|
+
localHash: localHash || undefined,
|
|
272
|
+
packageHash: packageHash || undefined
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
return results;
|
|
276
|
+
}
|
|
277
|
+
async function skillUpdate(kbPath) {
|
|
278
|
+
const basePath = findKbPath(kbPath);
|
|
279
|
+
if (!basePath) {
|
|
280
|
+
console.log(`
|
|
281
|
+
Error: Could not find Thoth knowledge base.`);
|
|
282
|
+
console.log("Run this command from your knowledge base directory, or specify the path:");
|
|
283
|
+
console.log(` npx thoth-plugin skill update ~/thoth
|
|
284
|
+
`);
|
|
285
|
+
process.exit(1);
|
|
286
|
+
}
|
|
287
|
+
const localSkillDir = join(basePath, ".opencode", "skill");
|
|
288
|
+
const packageSkillDir = join(NPM_DEFAULTS_PATH, "skill");
|
|
289
|
+
console.log(`
|
|
290
|
+
Comparing skills in: ${localSkillDir}
|
|
291
|
+
`);
|
|
292
|
+
const comparisons = compareSkills(localSkillDir);
|
|
293
|
+
const identical = comparisons.filter((c) => c.status === "identical");
|
|
294
|
+
const packageNewer = comparisons.filter((c) => c.status === "package-newer");
|
|
295
|
+
const localNewer = comparisons.filter((c) => c.status === "local-newer");
|
|
296
|
+
const packageOnly = comparisons.filter((c) => c.status === "package-only");
|
|
297
|
+
const localOnly = comparisons.filter((c) => c.status === "local-only");
|
|
298
|
+
console.log("Skill Status Summary:");
|
|
299
|
+
console.log("\u2500".repeat(60));
|
|
300
|
+
if (identical.length > 0) {
|
|
301
|
+
console.log(`
|
|
302
|
+
\u2713 Up to date (${identical.length}):`);
|
|
303
|
+
identical.forEach((s) => console.log(` ${s.name}`));
|
|
304
|
+
}
|
|
305
|
+
if (packageNewer.length > 0) {
|
|
306
|
+
console.log(`
|
|
307
|
+
\u2193 Updates available (${packageNewer.length}):`);
|
|
308
|
+
packageNewer.forEach((s) => console.log(` ${s.name} (local: ${s.localLines} lines \u2192 package: ${s.packageLines} lines)`));
|
|
309
|
+
}
|
|
310
|
+
if (localNewer.length > 0) {
|
|
311
|
+
console.log(`
|
|
312
|
+
\u2191 Local is more advanced (${localNewer.length}):`);
|
|
313
|
+
localNewer.forEach((s) => console.log(` ${s.name} (local: ${s.localLines} lines vs package: ${s.packageLines} lines)`));
|
|
314
|
+
}
|
|
315
|
+
if (packageOnly.length > 0) {
|
|
316
|
+
console.log(`
|
|
317
|
+
+ New skills available (${packageOnly.length}):`);
|
|
318
|
+
packageOnly.forEach((s) => console.log(` ${s.name}`));
|
|
319
|
+
}
|
|
320
|
+
if (localOnly.length > 0) {
|
|
321
|
+
console.log(`
|
|
322
|
+
\u25CB Local only (${localOnly.length}):`);
|
|
323
|
+
localOnly.forEach((s) => console.log(` ${s.name}`));
|
|
324
|
+
}
|
|
325
|
+
console.log(`
|
|
326
|
+
` + "\u2500".repeat(60));
|
|
327
|
+
const toUpdate = [...packageNewer, ...packageOnly];
|
|
328
|
+
if (toUpdate.length === 0) {
|
|
329
|
+
console.log(`
|
|
330
|
+
\u2713 All skills are up to date!
|
|
331
|
+
`);
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
console.log(`
|
|
335
|
+
${toUpdate.length} skill(s) can be updated.
|
|
336
|
+
`);
|
|
337
|
+
for (const skill of toUpdate) {
|
|
338
|
+
const action = skill.status === "package-only" ? "install" : "update";
|
|
339
|
+
const answer = await prompt(`${action === "install" ? "Install" : "Update"} ${skill.name}? [y/N/q] `);
|
|
340
|
+
if (answer === "q") {
|
|
341
|
+
console.log(`
|
|
342
|
+
Aborted.
|
|
343
|
+
`);
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
if (answer === "y" || answer === "yes") {
|
|
347
|
+
const source = join(packageSkillDir, skill.name);
|
|
348
|
+
const target = join(localSkillDir, skill.name);
|
|
349
|
+
cpSync(source, target, { recursive: true });
|
|
350
|
+
console.log(` \u2713 ${skill.name} ${action}d`);
|
|
351
|
+
} else {
|
|
352
|
+
console.log(` \u25CB ${skill.name} skipped`);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
if (localNewer.length > 0) {
|
|
356
|
+
console.log(`
|
|
357
|
+
` + "\u2500".repeat(60));
|
|
358
|
+
console.log(`
|
|
359
|
+
You have skills that are more advanced than the package.`);
|
|
360
|
+
console.log(`Consider contributing them back to Thoth!
|
|
361
|
+
`);
|
|
362
|
+
for (const skill of localNewer) {
|
|
363
|
+
const answer = await prompt(`Would you like to contribute ${skill.name} back to Thoth? [y/N] `);
|
|
364
|
+
if (answer === "y" || answer === "yes") {
|
|
365
|
+
console.log(`
|
|
366
|
+
To contribute ${skill.name}:`);
|
|
367
|
+
console.log(` 1. Fork https://github.com/davidhelmus/thoth-core`);
|
|
368
|
+
console.log(` 2. Copy your skill to defaults/skill/${skill.name}/`);
|
|
369
|
+
console.log(` 3. Open a Pull Request
|
|
370
|
+
`);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
console.log(`
|
|
375
|
+
\u2713 Done!
|
|
376
|
+
`);
|
|
377
|
+
}
|
|
378
|
+
function skillList(kbPath) {
|
|
379
|
+
const basePath = findKbPath(kbPath);
|
|
380
|
+
if (!basePath) {
|
|
381
|
+
console.log(`
|
|
382
|
+
Showing skills from package only (no knowledge base found).
|
|
383
|
+
`);
|
|
384
|
+
}
|
|
385
|
+
const packageSkillDir = join(NPM_DEFAULTS_PATH, "skill");
|
|
386
|
+
const localSkillDir = basePath ? join(basePath, ".opencode", "skill") : null;
|
|
387
|
+
const packageSkills = existsSync(packageSkillDir) ? readdirSync(packageSkillDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name) : [];
|
|
388
|
+
const localSkills = localSkillDir && existsSync(localSkillDir) ? readdirSync(localSkillDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name) : [];
|
|
389
|
+
const allSkills = [...new Set([...packageSkills, ...localSkills])].sort();
|
|
390
|
+
console.log(`
|
|
391
|
+
Available Skills:`);
|
|
392
|
+
console.log("\u2500".repeat(40));
|
|
393
|
+
for (const skill of allSkills) {
|
|
394
|
+
const inPackage = packageSkills.includes(skill);
|
|
395
|
+
const inLocal = localSkills.includes(skill);
|
|
396
|
+
let status = "";
|
|
397
|
+
if (inPackage && inLocal)
|
|
398
|
+
status = "\u2713";
|
|
399
|
+
else if (inLocal)
|
|
400
|
+
status = "\u25CB (local only)";
|
|
401
|
+
else
|
|
402
|
+
status = "+ (available)";
|
|
403
|
+
console.log(` ${status} ${skill}`);
|
|
404
|
+
}
|
|
405
|
+
console.log(`
|
|
406
|
+
`);
|
|
407
|
+
}
|
|
185
408
|
function showHelp() {
|
|
186
409
|
console.log(`
|
|
187
410
|
Thoth - Life Orchestrator for OpenCode
|
|
@@ -190,21 +413,41 @@ Usage:
|
|
|
190
413
|
npx thoth-plugin <command> [options]
|
|
191
414
|
|
|
192
415
|
Commands:
|
|
193
|
-
init [path]
|
|
416
|
+
init [path] Create a new knowledge base (default: ~/thoth)
|
|
417
|
+
skill update [path] Update skills from the latest package
|
|
418
|
+
skill list List available skills
|
|
194
419
|
|
|
195
420
|
Examples:
|
|
196
|
-
npx thoth-plugin init
|
|
197
|
-
npx thoth-plugin init ~/my-thoth
|
|
198
|
-
npx thoth-plugin
|
|
421
|
+
npx thoth-plugin init # Create at ~/thoth
|
|
422
|
+
npx thoth-plugin init ~/my-thoth # Create at custom path
|
|
423
|
+
npx thoth-plugin skill update # Update skills in current KB
|
|
424
|
+
npx thoth-plugin skill list # List all available skills
|
|
199
425
|
|
|
200
426
|
Learn more: https://github.com/davidhelmus/thoth-core
|
|
201
427
|
`);
|
|
202
428
|
}
|
|
203
429
|
var command = process.argv[2];
|
|
430
|
+
var subcommand = process.argv[3];
|
|
204
431
|
switch (command) {
|
|
205
432
|
case "init":
|
|
206
433
|
init(process.argv[3]);
|
|
207
434
|
break;
|
|
435
|
+
case "skill":
|
|
436
|
+
switch (subcommand) {
|
|
437
|
+
case "update":
|
|
438
|
+
skillUpdate(process.argv[4]);
|
|
439
|
+
break;
|
|
440
|
+
case "list":
|
|
441
|
+
skillList(process.argv[4]);
|
|
442
|
+
break;
|
|
443
|
+
default:
|
|
444
|
+
console.log(`
|
|
445
|
+
Unknown skill command: ${subcommand}`);
|
|
446
|
+
console.log(`Available: skill update, skill list
|
|
447
|
+
`);
|
|
448
|
+
process.exit(1);
|
|
449
|
+
}
|
|
450
|
+
break;
|
|
208
451
|
case "help":
|
|
209
452
|
case "--help":
|
|
210
453
|
case "-h":
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ declare const HooksConfigSchema: z.ZodObject<{
|
|
|
12
12
|
"temporal-awareness": z.ZodOptional<z.ZodBoolean>;
|
|
13
13
|
"knowledge-persistence": z.ZodOptional<z.ZodBoolean>;
|
|
14
14
|
"directory-agents-injector": z.ZodOptional<z.ZodBoolean>;
|
|
15
|
+
"frontmatter-enforcer": z.ZodOptional<z.ZodBoolean>;
|
|
15
16
|
"todo-continuation": z.ZodOptional<z.ZodBoolean>;
|
|
16
17
|
"session-recovery": z.ZodOptional<z.ZodBoolean>;
|
|
17
18
|
"context-window-monitor": z.ZodOptional<z.ZodBoolean>;
|
|
@@ -65,6 +66,7 @@ export declare const ThothPluginConfigSchema: z.ZodObject<{
|
|
|
65
66
|
"temporal-awareness": z.ZodOptional<z.ZodBoolean>;
|
|
66
67
|
"knowledge-persistence": z.ZodOptional<z.ZodBoolean>;
|
|
67
68
|
"directory-agents-injector": z.ZodOptional<z.ZodBoolean>;
|
|
69
|
+
"frontmatter-enforcer": z.ZodOptional<z.ZodBoolean>;
|
|
68
70
|
"todo-continuation": z.ZodOptional<z.ZodBoolean>;
|
|
69
71
|
"session-recovery": z.ZodOptional<z.ZodBoolean>;
|
|
70
72
|
"context-window-monitor": z.ZodOptional<z.ZodBoolean>;
|