0xkobold 0.0.1 â 0.0.3
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 +83 -19
- package/dist/package.json +4 -4
- package/dist/src/extensions/core/extension-scaffold-extension.js +449 -0
- package/dist/src/extensions/core/extension-scaffold-extension.js.map +1 -0
- package/dist/src/extensions/core/git-commit-extension.js +527 -0
- package/dist/src/extensions/core/git-commit-extension.js.map +1 -0
- package/dist/src/extensions/core/mode-manager-extension.js +2 -0
- package/dist/src/extensions/core/mode-manager-extension.js.map +1 -1
- package/dist/src/extensions/core/ollama-cloud-extension.js +132 -0
- package/dist/src/extensions/core/ollama-cloud-extension.js.map +1 -0
- package/dist/src/extensions/core/ollama-router-extension.js +100 -0
- package/dist/src/extensions/core/ollama-router-extension.js.map +1 -0
- package/dist/src/extensions/core/websearch-extension.js +43 -17
- package/dist/src/extensions/core/websearch-extension.js.map +1 -1
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/llm/ollama.js +80 -9
- package/dist/src/llm/ollama.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -64,15 +64,15 @@ npx 0xkobold start
|
|
|
64
64
|
|
|
65
65
|
```bash
|
|
66
66
|
# Clone and install
|
|
67
|
-
git clone https://github.com/
|
|
67
|
+
git clone https://github.com/moikapy/0xkobold.git
|
|
68
68
|
cd 0xkobold
|
|
69
69
|
bun install
|
|
70
70
|
|
|
71
71
|
# Start Ollama (in another terminal)
|
|
72
72
|
ollama run kimi-k2.5:cloud
|
|
73
73
|
|
|
74
|
-
# Start the
|
|
75
|
-
bun run
|
|
74
|
+
# Start the TUI
|
|
75
|
+
bun run tui
|
|
76
76
|
```
|
|
77
77
|
|
|
78
78
|
## Project Structure
|
|
@@ -150,37 +150,101 @@ const result = await agent.spawn('Research this topic');
|
|
|
150
150
|
|
|
151
151
|
The `spawn_subagent` skill is built-in and lets agents create child agents automatically.
|
|
152
152
|
|
|
153
|
+
## Ollama Cloud đŠī¸
|
|
154
|
+
|
|
155
|
+
0xKobold now supports Ollama Cloud for access to larger models without running Ollama locally.
|
|
156
|
+
|
|
157
|
+
### Setup Cloud Access
|
|
158
|
+
|
|
159
|
+
1. Get your API key from [ollama.com/settings/keys](https://ollama.com/settings/keys)
|
|
160
|
+
|
|
161
|
+
2. Login via the TUI:
|
|
162
|
+
```
|
|
163
|
+
/login
|
|
164
|
+
# Select "Ollama Cloud"
|
|
165
|
+
# Paste your API key
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
3. Switch between modes:
|
|
169
|
+
```
|
|
170
|
+
/ollama-mode cloud # Use cloud exclusively
|
|
171
|
+
/ollama-mode local # Use local Ollama
|
|
172
|
+
/ollama-mode auto # Auto-detect (default)
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Cloud Models Available
|
|
176
|
+
|
|
177
|
+
- **GPT-OSS 120B** - State-of-the-art open source
|
|
178
|
+
- **Qwen 2.5 72B/32B** - Alibaba's instruction-tuned model
|
|
179
|
+
- **DeepSeek R1 671B** - Reasoning-capable model
|
|
180
|
+
- **Llama 3.2** - Meta's latest open weights
|
|
181
|
+
|
|
182
|
+
### Quick Commands
|
|
183
|
+
|
|
184
|
+
- `/ollama-mode` - Show current mode and status
|
|
185
|
+
- `/ollama-status` - Check cloud connection
|
|
186
|
+
- `/ollama-local` - Switch to local mode
|
|
187
|
+
- `/ollama-cloud` - Switch to cloud mode
|
|
188
|
+
|
|
189
|
+
Your API key is securely stored in `~/.0xkobold/auth.json` with 0600 permissions.
|
|
190
|
+
|
|
153
191
|
## Commands
|
|
154
192
|
|
|
155
193
|
```bash
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
194
|
+
# Global install (recommended)
|
|
195
|
+
npm install -g 0xkobold
|
|
196
|
+
|
|
197
|
+
# Interactive TUI (default)
|
|
198
|
+
0xkobold
|
|
199
|
+
# or explicitly
|
|
200
|
+
0xkobold tui
|
|
201
|
+
|
|
202
|
+
# Project mode (per-directory config)
|
|
203
|
+
0xkobold local
|
|
204
|
+
|
|
205
|
+
# Gateway service
|
|
206
|
+
0xkobold start # Start daemon
|
|
207
|
+
0xkobold start -f # Start foreground
|
|
208
|
+
0xkobold stop # Stop daemon
|
|
209
|
+
0xkobold status # Check status
|
|
210
|
+
0xkobold logs # View logs
|
|
211
|
+
|
|
212
|
+
# Using npx (no install)
|
|
213
|
+
npx 0xkobold
|
|
214
|
+
npx 0xkobold tui --local
|
|
159
215
|
```
|
|
160
216
|
|
|
161
217
|
## Configuration
|
|
162
218
|
|
|
163
|
-
Config is stored in `~/.
|
|
219
|
+
Config is stored in `~/.config/kobold/kobold.json`:
|
|
164
220
|
|
|
165
|
-
```
|
|
221
|
+
```json
|
|
166
222
|
{
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
model: 'ollama/kimi-k2.5:cloud',
|
|
170
|
-
capabilities: ['chat', 'code'],
|
|
171
|
-
},
|
|
223
|
+
"meta": {
|
|
224
|
+
"version": "1.0.0"
|
|
172
225
|
},
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
226
|
+
"providers": {
|
|
227
|
+
"ollama": {
|
|
228
|
+
"enabled": true,
|
|
229
|
+
"model": "kimi-k2.5:cloud"
|
|
230
|
+
}
|
|
176
231
|
},
|
|
177
|
-
|
|
178
|
-
enabled:
|
|
179
|
-
|
|
232
|
+
"gateway": {
|
|
233
|
+
"enabled": true,
|
|
234
|
+
"port": 18789
|
|
180
235
|
},
|
|
236
|
+
"discord": {
|
|
237
|
+
"enabled": false,
|
|
238
|
+
"token": "${DISCORD_BOT_TOKEN}"
|
|
239
|
+
}
|
|
181
240
|
}
|
|
182
241
|
```
|
|
183
242
|
|
|
243
|
+
Or use **Local Mode** for per-project configs:
|
|
244
|
+
```bash
|
|
245
|
+
0xkobold local # Creates/uses ./kobold.json in current directory
|
|
246
|
+
```
|
|
247
|
+
|
|
184
248
|
## Architecture Differences from OpenClaw
|
|
185
249
|
|
|
186
250
|
| Aspect | OpenClaw | 0xKobold |
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "0xkobold",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "Your digital familiar - a personal AI assistant that learns and evolves",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"types": "dist/src/index.d.ts",
|
|
@@ -34,9 +34,9 @@
|
|
|
34
34
|
"author": "0xKobold Team",
|
|
35
35
|
"license": "MIT",
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@mariozechner/pi-agent-core": "0.
|
|
38
|
-
"@mariozechner/pi-coding-agent": "0.
|
|
39
|
-
"@mariozechner/pi-tui": "0.
|
|
37
|
+
"@mariozechner/pi-agent-core": "0.57.1",
|
|
38
|
+
"@mariozechner/pi-coding-agent": "0.57.1",
|
|
39
|
+
"@mariozechner/pi-tui": "0.57.1",
|
|
40
40
|
"ajv": "^8.18.0",
|
|
41
41
|
"blessed": "^0.1.81",
|
|
42
42
|
"commander": "^11.1.0",
|
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extension Scaffold Extension
|
|
3
|
+
*
|
|
4
|
+
* Makes it easier to create new 0xKobold extensions by providing:
|
|
5
|
+
* - Command to scaffold new extensions
|
|
6
|
+
* - Template generators for common patterns
|
|
7
|
+
* - Type helpers and utilities
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* /ext-scaffold my-extension "A cool extension that does things"
|
|
11
|
+
* Creates: src/extensions/core/my-extension.ts
|
|
12
|
+
*/
|
|
13
|
+
import { existsSync, writeFileSync } from "fs";
|
|
14
|
+
import { resolve, dirname, basename } from "path";
|
|
15
|
+
// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
|
16
|
+
// TEMPLATES
|
|
17
|
+
// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
|
18
|
+
const EXTENSION_TEMPLATE = (name, description, author) => `/**
|
|
19
|
+
* ${description}
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
23
|
+
|
|
24
|
+
export default function ${toCamelCase(name)}Extension(pi: ExtensionAPI) {
|
|
25
|
+
// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
|
26
|
+
// CONFIGURATION
|
|
27
|
+
// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
|
28
|
+
|
|
29
|
+
const CONFIG = {
|
|
30
|
+
// Add your configuration here
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
|
34
|
+
// LIFECYCLE HOOKS
|
|
35
|
+
// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
|
36
|
+
|
|
37
|
+
pi.on("session_start", async (event, ctx) => {
|
|
38
|
+
console.log("[${name}] Session started:", event.name);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
pi.on("session_end", async (event) => {
|
|
42
|
+
console.log("[${name}] Session ended:", event.name);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
pi.on("turn_start", async () => {
|
|
46
|
+
// Called at the start of each turn
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
pi.on("turn_end", async () => {
|
|
50
|
+
// Called at the end of each turn
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
|
54
|
+
// USER COMMANDS
|
|
55
|
+
// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
|
56
|
+
|
|
57
|
+
pi.registerCommand("${name}", {
|
|
58
|
+
description: "${description}",
|
|
59
|
+
handler: async (args, ctx) => {
|
|
60
|
+
// Command implementation
|
|
61
|
+
ctx.ui?.notify?.("Command executed!", "info");
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
|
66
|
+
// AGENT TOOLS
|
|
67
|
+
// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
|
68
|
+
|
|
69
|
+
pi.registerTool({
|
|
70
|
+
name: "${name.replace(/-/g, "_")}_tool",
|
|
71
|
+
label: "${name}_tool",
|
|
72
|
+
description: "A tool provided by the ${name} extension",
|
|
73
|
+
// @ts-ignore TSchema mismatch
|
|
74
|
+
parameters: {
|
|
75
|
+
type: "object",
|
|
76
|
+
properties: {
|
|
77
|
+
param1: {
|
|
78
|
+
type: "string",
|
|
79
|
+
description: "First parameter description",
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
required: ["param1"],
|
|
83
|
+
},
|
|
84
|
+
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
85
|
+
const { param1 } = params as { param1: string };
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
// Tool implementation
|
|
89
|
+
const result = \`Processed: \${param1}\`;
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
content: [{ type: "text", text: result }],
|
|
93
|
+
details: { success: true, param1 },
|
|
94
|
+
};
|
|
95
|
+
} catch (error) {
|
|
96
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
97
|
+
return {
|
|
98
|
+
content: [{ type: "text", text: \`Error: \${errorMsg}\` }],
|
|
99
|
+
details: { success: false, error: errorMsg },
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
console.log("[${name}] Extension loaded - ${author}");
|
|
106
|
+
}
|
|
107
|
+
`;
|
|
108
|
+
const TOOL_ONLY_TEMPLATE = (name, description) => `/**
|
|
109
|
+
* ${description}
|
|
110
|
+
*/
|
|
111
|
+
|
|
112
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
113
|
+
|
|
114
|
+
export default function ${toCamelCase(name)}Extension(pi: ExtensionAPI) {
|
|
115
|
+
// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
|
116
|
+
// AGENT TOOLS
|
|
117
|
+
// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
|
118
|
+
|
|
119
|
+
pi.registerTool({
|
|
120
|
+
name: "${name.replace(/-/g, "_")}",
|
|
121
|
+
label: "${name}",
|
|
122
|
+
description: "${description}",
|
|
123
|
+
// @ts-ignore TSchema mismatch
|
|
124
|
+
parameters: {
|
|
125
|
+
type: "object",
|
|
126
|
+
properties: {},
|
|
127
|
+
required: [],
|
|
128
|
+
},
|
|
129
|
+
async execute(_toolCallId, _params, _signal, _onUpdate, _ctx) {
|
|
130
|
+
return {
|
|
131
|
+
content: [{ type: "text", text: "Tool executed!" }],
|
|
132
|
+
details: { success: true },
|
|
133
|
+
};
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
console.log("[${name}] Tool extension loaded");
|
|
138
|
+
}
|
|
139
|
+
`;
|
|
140
|
+
const COMMAND_ONLY_TEMPLATE = (name, description) => `/**
|
|
141
|
+
* ${description}
|
|
142
|
+
*/
|
|
143
|
+
|
|
144
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
145
|
+
|
|
146
|
+
export default function ${toCamelCase(name)}Extension(pi: ExtensionAPI) {
|
|
147
|
+
// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
|
148
|
+
// USER COMMANDS
|
|
149
|
+
// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
|
150
|
+
|
|
151
|
+
pi.registerCommand("${name}", {
|
|
152
|
+
description: "${description}",
|
|
153
|
+
handler: async (args, ctx) => {
|
|
154
|
+
ctx.ui?.notify?.("Command executed!", "info");
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
console.log("[${name}] Command extension loaded");
|
|
159
|
+
}
|
|
160
|
+
`;
|
|
161
|
+
// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
|
162
|
+
// UTILITY FUNCTIONS
|
|
163
|
+
// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
|
164
|
+
function toCamelCase(str) {
|
|
165
|
+
return str
|
|
166
|
+
.replace(/[-_]+(.)?/g, (_, char) => char ? char.toUpperCase() : "")
|
|
167
|
+
.replace(/^./, char => char.toLowerCase());
|
|
168
|
+
}
|
|
169
|
+
function toPascalCase(str) {
|
|
170
|
+
const camel = toCamelCase(str);
|
|
171
|
+
return camel.charAt(0).toUpperCase() + camel.slice(1);
|
|
172
|
+
}
|
|
173
|
+
function sanitizeFilename(name) {
|
|
174
|
+
return name
|
|
175
|
+
.toLowerCase()
|
|
176
|
+
.replace(/[^a-z0-9-]/g, "-")
|
|
177
|
+
.replace(/-+/g, "-")
|
|
178
|
+
.replace(/^-|-$/g, "");
|
|
179
|
+
}
|
|
180
|
+
// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
|
181
|
+
// EXTENSION LOADER
|
|
182
|
+
// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
|
183
|
+
export default function extensionScaffoldExtension(pi) {
|
|
184
|
+
// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
|
185
|
+
// COMMANDS
|
|
186
|
+
// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
|
187
|
+
pi.registerCommand("ext-scaffold", {
|
|
188
|
+
description: "Scaffold a new extension (usage: /ext-scaffold [name] [description] --type=full|tool|command)",
|
|
189
|
+
handler: async (args, ctx) => {
|
|
190
|
+
const parsed = parseArgs(args);
|
|
191
|
+
const { name, description, type } = parsed;
|
|
192
|
+
if (!name) {
|
|
193
|
+
ctx.ui?.notify?.("Usage: /ext-scaffold [name] [description] [--type=full|tool|command]\n" +
|
|
194
|
+
"Examples:\n" +
|
|
195
|
+
" /ext-scaffold my-tool \"Does something cool\"\n" +
|
|
196
|
+
" /ext-scaffold my-cmd \"A command\" --type=command", "warning");
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
const safeName = sanitizeFilename(name);
|
|
200
|
+
const safeDesc = description || `Extension: ${safeName}`;
|
|
201
|
+
try {
|
|
202
|
+
// Determine target directory
|
|
203
|
+
// Try relative to current working directory first, then fall back
|
|
204
|
+
const possiblePaths = [
|
|
205
|
+
resolve(process.cwd(), "src", "extensions", "core"),
|
|
206
|
+
resolve(__dirname), // Current directory
|
|
207
|
+
resolve(dirname(__dirname), "core"), // Parent extensions/core
|
|
208
|
+
];
|
|
209
|
+
let targetDir = possiblePaths.find(p => existsSync(dirname(p)));
|
|
210
|
+
if (!targetDir) {
|
|
211
|
+
targetDir = possiblePaths[1]; // Fallback to current
|
|
212
|
+
}
|
|
213
|
+
const filePath = resolve(targetDir, `${safeName}-extension.ts`);
|
|
214
|
+
if (existsSync(filePath)) {
|
|
215
|
+
ctx.ui?.notify?.(`Extension already exists: ${basename(filePath)}`, "warning");
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
// Generate content based on type
|
|
219
|
+
let content;
|
|
220
|
+
const author = "0xKobold";
|
|
221
|
+
switch (type) {
|
|
222
|
+
case "tool":
|
|
223
|
+
content = TOOL_ONLY_TEMPLATE(safeName, safeDesc);
|
|
224
|
+
break;
|
|
225
|
+
case "command":
|
|
226
|
+
content = COMMAND_ONLY_TEMPLATE(safeName, safeDesc);
|
|
227
|
+
break;
|
|
228
|
+
case "full":
|
|
229
|
+
default:
|
|
230
|
+
content = EXTENSION_TEMPLATE(safeName, safeDesc, author);
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
// Write file
|
|
234
|
+
writeFileSync(filePath, content, "utf-8");
|
|
235
|
+
ctx.ui?.notify?.(`â
Created extension: ${basename(filePath)}\n` +
|
|
236
|
+
` Location: ${filePath}\n` +
|
|
237
|
+
` Type: ${type || "full"}\n\n` +
|
|
238
|
+
` Next steps:\n` +
|
|
239
|
+
` 1. Edit the file to implement your extension\n` +
|
|
240
|
+
` 2. Restart 0xKobold to load it`, "info");
|
|
241
|
+
}
|
|
242
|
+
catch (error) {
|
|
243
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
244
|
+
ctx.ui?.notify?.(`Error creating extension: ${errorMsg}`, "error");
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
});
|
|
248
|
+
pi.registerCommand("ext-list", {
|
|
249
|
+
description: "List all built-in extensions",
|
|
250
|
+
handler: async (_args, ctx) => {
|
|
251
|
+
try {
|
|
252
|
+
const { readdir } = await import("fs/promises");
|
|
253
|
+
const coreDir = resolve(__dirname);
|
|
254
|
+
const files = await readdir(coreDir);
|
|
255
|
+
const extensions = files
|
|
256
|
+
.filter(f => f.endsWith("-extension.ts"))
|
|
257
|
+
.map(f => f.replace("-extension.ts", ""))
|
|
258
|
+
.sort();
|
|
259
|
+
const list = extensions.map((ext, i) => ` ${i + 1}. ${ext}`).join("\n");
|
|
260
|
+
ctx.ui?.notify?.(`đĻ Built-in Extensions (${extensions.length}):\n\n${list}`, "info");
|
|
261
|
+
}
|
|
262
|
+
catch (error) {
|
|
263
|
+
ctx.ui?.notify?.("Failed to list extensions", "error");
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
});
|
|
267
|
+
pi.registerCommand("ext-help", {
|
|
268
|
+
description: "Show extension development help",
|
|
269
|
+
handler: async (_args, ctx) => {
|
|
270
|
+
ctx.ui?.notify?.("đ Extension Development Quick Reference:\n\n" +
|
|
271
|
+
"Commands:\n" +
|
|
272
|
+
" /ext-scaffold [name] [desc] [--type] Create new extension\n" +
|
|
273
|
+
" /ext-list List built-in extensions\n" +
|
|
274
|
+
" /ext-help Show this help\n\n" +
|
|
275
|
+
"Extension Types:\n" +
|
|
276
|
+
" --type=full Full extension (commands + tools + hooks) [default]\n" +
|
|
277
|
+
" --type=tool Tool-only extension\n" +
|
|
278
|
+
" --type=command Command-only extension\n\n" +
|
|
279
|
+
"Lifecycle Hooks:\n" +
|
|
280
|
+
" pi.on('session_start', ... ) When session begins\n" +
|
|
281
|
+
" pi.on('session_end', ... ) When session ends\n" +
|
|
282
|
+
" pi.on('turn_start', ... ) When agent turn starts\n" +
|
|
283
|
+
" pi.on('turn_end', ... ) When agent turn ends\n\n" +
|
|
284
|
+
"API:\n" +
|
|
285
|
+
" pi.registerCommand(name, { description, handler })\n" +
|
|
286
|
+
" pi.registerTool({ name, description, parameters, execute })\n" +
|
|
287
|
+
" pi.setSessionName(name), pi.getSessionName()\n" +
|
|
288
|
+
" ctx.ui.notify(message, type)", "info");
|
|
289
|
+
},
|
|
290
|
+
});
|
|
291
|
+
// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
|
292
|
+
// AGENT TOOLS
|
|
293
|
+
// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
|
294
|
+
pi.registerTool({
|
|
295
|
+
name: "create_extension",
|
|
296
|
+
label: "create_extension",
|
|
297
|
+
description: "Create a new extension scaffold. Use this when the user wants to create a new extension or when they say they want to extend functionality in a modular way.",
|
|
298
|
+
// @ts-ignore TSchema mismatch
|
|
299
|
+
parameters: {
|
|
300
|
+
type: "object",
|
|
301
|
+
properties: {
|
|
302
|
+
name: {
|
|
303
|
+
type: "string",
|
|
304
|
+
description: "Extension name (kebab-case, e.g., 'my-tool', 'image-processor')",
|
|
305
|
+
},
|
|
306
|
+
description: {
|
|
307
|
+
type: "string",
|
|
308
|
+
description: "Brief description of what the extension does",
|
|
309
|
+
},
|
|
310
|
+
type: {
|
|
311
|
+
type: "string",
|
|
312
|
+
enum: ["full", "tool", "command"],
|
|
313
|
+
description: "Extension template type",
|
|
314
|
+
default: "full",
|
|
315
|
+
},
|
|
316
|
+
},
|
|
317
|
+
required: ["name", "description"],
|
|
318
|
+
},
|
|
319
|
+
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
320
|
+
const { name, description, type = "full" } = params;
|
|
321
|
+
try {
|
|
322
|
+
const safeName = sanitizeFilename(name);
|
|
323
|
+
const coreDir = resolve(__dirname);
|
|
324
|
+
const filePath = resolve(coreDir, `${safeName}-extension.ts`);
|
|
325
|
+
if (existsSync(filePath)) {
|
|
326
|
+
return {
|
|
327
|
+
content: [{
|
|
328
|
+
type: "text",
|
|
329
|
+
text: `â ī¸ Extension already exists: ${safeName}-extension.ts`
|
|
330
|
+
}],
|
|
331
|
+
details: { success: false, exists: true, path: filePath },
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
// Select template
|
|
335
|
+
let content;
|
|
336
|
+
const author = "0xKobold";
|
|
337
|
+
switch (type) {
|
|
338
|
+
case "tool":
|
|
339
|
+
content = TOOL_ONLY_TEMPLATE(safeName, description);
|
|
340
|
+
break;
|
|
341
|
+
case "command":
|
|
342
|
+
content = COMMAND_ONLY_TEMPLATE(safeName, description);
|
|
343
|
+
break;
|
|
344
|
+
default:
|
|
345
|
+
content = EXTENSION_TEMPLATE(safeName, description, author);
|
|
346
|
+
}
|
|
347
|
+
writeFileSync(filePath, content, "utf-8");
|
|
348
|
+
return {
|
|
349
|
+
content: [{
|
|
350
|
+
type: "text",
|
|
351
|
+
text: `â
Created ${type} extension: ${safeName}-extension.ts\n\n` +
|
|
352
|
+
`The extension has been scaffolded with:\n` +
|
|
353
|
+
(type === "full" ?
|
|
354
|
+
` - Lifecycle hooks (session_start, session_end, etc.)\n` +
|
|
355
|
+
` - A command: /${safeName}\n` +
|
|
356
|
+
` - A tool: ${safeName.replace(/-/g, "_")}_tool\n` :
|
|
357
|
+
type === "tool" ?
|
|
358
|
+
` - A tool: ${safeName.replace(/-/g, "_")}\n` :
|
|
359
|
+
` - A command: /${safeName}\n`) +
|
|
360
|
+
`\nFile location: ${filePath}\n\n` +
|
|
361
|
+
`Next steps:\n` +
|
|
362
|
+
`1. Edit the file to implement your logic\n` +
|
|
363
|
+
`2. Restart 0xKobold to load the extension`
|
|
364
|
+
}],
|
|
365
|
+
details: {
|
|
366
|
+
success: true,
|
|
367
|
+
name: safeName,
|
|
368
|
+
type,
|
|
369
|
+
path: filePath
|
|
370
|
+
},
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
catch (error) {
|
|
374
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
375
|
+
return {
|
|
376
|
+
content: [{ type: "text", text: `â Error: ${errorMsg}` }],
|
|
377
|
+
details: { success: false, error: errorMsg },
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
},
|
|
381
|
+
});
|
|
382
|
+
pi.registerTool({
|
|
383
|
+
name: "list_extensions",
|
|
384
|
+
label: "list_extensions",
|
|
385
|
+
description: "List all available built-in extensions. Use this when the user wants to see what extensions are available.",
|
|
386
|
+
// @ts-ignore TSchema mismatch
|
|
387
|
+
parameters: {
|
|
388
|
+
type: "object",
|
|
389
|
+
properties: {},
|
|
390
|
+
},
|
|
391
|
+
async execute(_toolCallId, _params, _signal, _onUpdate, _ctx) {
|
|
392
|
+
try {
|
|
393
|
+
const { readdir, readFile } = await import("fs/promises");
|
|
394
|
+
const coreDir = resolve(__dirname);
|
|
395
|
+
const files = await readdir(coreDir);
|
|
396
|
+
const extensions = await Promise.all(files
|
|
397
|
+
.filter(f => f.endsWith("-extension.ts"))
|
|
398
|
+
.map(async (f) => {
|
|
399
|
+
const content = await readFile(resolve(coreDir, f), "utf-8");
|
|
400
|
+
const descMatch = content.match(/\\*\\s*([^\\n]+(?:does|provides|handles)[^\\n]*)/i);
|
|
401
|
+
return {
|
|
402
|
+
name: f.replace("-extension.ts", ""),
|
|
403
|
+
filename: f,
|
|
404
|
+
description: descMatch ? descMatch[1].trim() : "No description",
|
|
405
|
+
};
|
|
406
|
+
}));
|
|
407
|
+
const sorted = extensions.sort((a, b) => a.name.localeCompare(b.name));
|
|
408
|
+
const list = sorted.map(e => ` âĸ ${e.name}: ${e.description}`).join("\n");
|
|
409
|
+
return {
|
|
410
|
+
content: [{
|
|
411
|
+
type: "text",
|
|
412
|
+
text: `đĻ Available Extensions (${sorted.length}):\n\n${list}`
|
|
413
|
+
}],
|
|
414
|
+
details: { success: true, count: sorted.length, extensions: sorted },
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
catch (error) {
|
|
418
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
419
|
+
return {
|
|
420
|
+
content: [{ type: "text", text: `â Error: ${errorMsg}` }],
|
|
421
|
+
details: { success: false, error: errorMsg },
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
},
|
|
425
|
+
});
|
|
426
|
+
console.log("[ExtensionScaffold] Extension loaded - /ext-scaffold, /ext-list, /ext-help");
|
|
427
|
+
}
|
|
428
|
+
// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
|
429
|
+
// ARGUMENT PARSER
|
|
430
|
+
// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
|
431
|
+
function parseArgs(input) {
|
|
432
|
+
const parts = input.trim().split(/\\s+/);
|
|
433
|
+
// Find type flag
|
|
434
|
+
const typeIndex = parts.findIndex(p => p.startsWith("--type="));
|
|
435
|
+
let type = "full";
|
|
436
|
+
if (typeIndex !== -1) {
|
|
437
|
+
const typeValue = parts[typeIndex].replace("--type=", "").toLowerCase();
|
|
438
|
+
if (["full", "tool", "command"].includes(typeValue)) {
|
|
439
|
+
type = typeValue;
|
|
440
|
+
}
|
|
441
|
+
parts.splice(typeIndex, 1);
|
|
442
|
+
}
|
|
443
|
+
// First non-flag is name
|
|
444
|
+
const name = parts[0] || "";
|
|
445
|
+
// Everything else before type flag is description
|
|
446
|
+
const description = parts.slice(1).join(" ") || "";
|
|
447
|
+
return { name, description, type };
|
|
448
|
+
}
|
|
449
|
+
//# sourceMappingURL=extension-scaffold-extension.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extension-scaffold-extension.js","sourceRoot":"","sources":["../../../../src/extensions/core/extension-scaffold-extension.ts"],"names":[],"mappings":"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"}
|