@plosson/agentio 0.1.23 → 0.1.25
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/package.json +3 -2
- package/src/commands/claude.ts +215 -131
- package/src/commands/rss.ts +68 -0
- package/src/config/config-manager.ts +1 -1
- package/src/index.ts +2 -0
- package/src/services/claude-plugin/agentio-json.ts +36 -41
- package/src/services/rss/client.ts +230 -0
- package/src/types/claude-plugin.ts +3 -63
- package/src/types/rss.ts +33 -0
- package/src/utils/output.ts +48 -0
- package/src/services/claude-plugin/installer.ts +0 -405
- package/src/services/claude-plugin/source-parser.ts +0 -114
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plosson/agentio",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.25",
|
|
4
4
|
"description": "CLI for LLM agents to interact with communication and tracking services",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"commander": "^14.0.2",
|
|
50
|
-
"googleapis": "^169.0.0"
|
|
50
|
+
"googleapis": "^169.0.0",
|
|
51
|
+
"rss-parser": "^3.13.0"
|
|
51
52
|
}
|
|
52
53
|
}
|
package/src/commands/claude.ts
CHANGED
|
@@ -1,183 +1,267 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import * as path from 'path';
|
|
3
|
-
import
|
|
3
|
+
import { spawn } from 'child_process';
|
|
4
4
|
import { CliError, handleError } from '../utils/errors';
|
|
5
5
|
import {
|
|
6
6
|
loadAgentioJson,
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
addMarketplace,
|
|
8
|
+
addPlugin,
|
|
9
|
+
removeMarketplace,
|
|
9
10
|
removePlugin,
|
|
10
|
-
getPlugin,
|
|
11
11
|
} from '../services/claude-plugin/agentio-json';
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Execute a claude CLI command and return the result.
|
|
15
|
+
*/
|
|
16
|
+
async function execClaude(
|
|
17
|
+
args: string[]
|
|
18
|
+
): Promise<{ success: boolean; stdout: string; stderr: string }> {
|
|
19
|
+
return new Promise((resolve) => {
|
|
20
|
+
const proc = spawn('claude', args, {
|
|
21
|
+
stdio: ['inherit', 'pipe', 'pipe'],
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
let stdout = '';
|
|
25
|
+
let stderr = '';
|
|
26
|
+
|
|
27
|
+
proc.stdout?.on('data', (data) => {
|
|
28
|
+
stdout += data.toString();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
proc.stderr?.on('data', (data) => {
|
|
32
|
+
stderr += data.toString();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
proc.on('close', (code) => {
|
|
36
|
+
resolve({
|
|
37
|
+
success: code === 0,
|
|
38
|
+
stdout,
|
|
39
|
+
stderr,
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
proc.on('error', (err) => {
|
|
44
|
+
resolve({
|
|
45
|
+
success: false,
|
|
46
|
+
stdout: '',
|
|
47
|
+
stderr: err.message,
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Install a marketplace by calling claude plugin marketplace add.
|
|
55
|
+
* Silently skips if already installed.
|
|
56
|
+
*/
|
|
57
|
+
async function installMarketplace(url: string): Promise<boolean> {
|
|
58
|
+
console.error(`Adding marketplace: ${url}`);
|
|
59
|
+
const result = await execClaude(['plugin', 'marketplace', 'add', url]);
|
|
60
|
+
|
|
61
|
+
if (result.success) {
|
|
62
|
+
console.log(` Added: ${url}`);
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Check if already installed (skip silently)
|
|
67
|
+
const errLower = result.stderr.toLowerCase();
|
|
68
|
+
if (errLower.includes('already') || errLower.includes('exists')) {
|
|
69
|
+
console.log(` Skipped (already added): ${url}`);
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
console.error(` Failed: ${result.stderr.trim()}`);
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Install a plugin by calling claude plugin install --scope project.
|
|
79
|
+
*/
|
|
80
|
+
async function installPluginCmd(name: string): Promise<boolean> {
|
|
81
|
+
console.error(`Installing plugin: ${name}`);
|
|
82
|
+
const result = await execClaude(['plugin', 'install', name, '--scope', 'project']);
|
|
83
|
+
|
|
84
|
+
if (result.success) {
|
|
85
|
+
console.log(` Installed: ${name}`);
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
console.error(` Failed: ${result.stderr.trim()}`);
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Uninstall a plugin by calling claude plugin uninstall --scope project.
|
|
95
|
+
*/
|
|
96
|
+
async function uninstallPluginCmd(name: string): Promise<boolean> {
|
|
97
|
+
console.error(`Uninstalling plugin: ${name}`);
|
|
98
|
+
const result = await execClaude(['plugin', 'uninstall', name, '--scope', 'project']);
|
|
99
|
+
|
|
100
|
+
if (result.success) {
|
|
101
|
+
console.log(` Uninstalled: ${name}`);
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Check if not installed (skip silently)
|
|
106
|
+
const errLower = result.stderr.toLowerCase();
|
|
107
|
+
if (errLower.includes('not installed') || errLower.includes('not found')) {
|
|
108
|
+
console.log(` Skipped (not installed): ${name}`);
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
console.error(` Failed: ${result.stderr.trim()}`);
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
17
115
|
|
|
18
116
|
export function registerClaudeCommands(program: Command): void {
|
|
19
117
|
const claude = program
|
|
20
118
|
.command('claude')
|
|
21
119
|
.description('Claude Code plugin operations');
|
|
22
120
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
.
|
|
28
|
-
.
|
|
29
|
-
.
|
|
30
|
-
.option('--
|
|
31
|
-
.
|
|
32
|
-
.option('--agents', 'Install only agents')
|
|
33
|
-
.option('-f, --force', 'Force reinstall if already exists')
|
|
34
|
-
.option('-d, --dir <path>', 'Target directory (default: current directory)')
|
|
35
|
-
.option('-v, --verbose', 'Show detailed installation logs')
|
|
36
|
-
.action(async (source, options) => {
|
|
121
|
+
// install command group
|
|
122
|
+
const install = claude.command('install').description('Install marketplaces and plugins');
|
|
123
|
+
|
|
124
|
+
install
|
|
125
|
+
.command('marketplace')
|
|
126
|
+
.description('Add a plugin marketplace')
|
|
127
|
+
.argument('<url>', 'Marketplace GitHub URL')
|
|
128
|
+
.option('-d, --dir <path>', 'Directory with agentio.json (default: current directory)')
|
|
129
|
+
.action(async (url, options) => {
|
|
37
130
|
try {
|
|
38
131
|
const targetDir = options.dir ? path.resolve(options.dir) : process.cwd();
|
|
39
132
|
|
|
40
|
-
|
|
41
|
-
|
|
133
|
+
const success = await installMarketplace(url);
|
|
134
|
+
if (success) {
|
|
135
|
+
addMarketplace(targetDir, url);
|
|
42
136
|
}
|
|
137
|
+
} catch (error) {
|
|
138
|
+
handleError(error);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
43
141
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
hooks: options.hooks,
|
|
53
|
-
agents: options.agents,
|
|
54
|
-
force: options.force,
|
|
55
|
-
targetDir,
|
|
56
|
-
verbose: options.verbose,
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
console.log(`\nInstalled: ${result.manifest.name} v${result.manifest.version}`);
|
|
60
|
-
if (result.installed.length > 0) {
|
|
61
|
-
console.log(`Components: ${result.installed.length}`);
|
|
62
|
-
for (const comp of result.installed) {
|
|
63
|
-
console.log(` ${comp.type}/${comp.name}`);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
} else {
|
|
67
|
-
// Install all plugins from agentio.json
|
|
68
|
-
if (!agentioJsonExists(targetDir)) {
|
|
69
|
-
throw new CliError(
|
|
70
|
-
'NOT_FOUND',
|
|
71
|
-
'No agentio.json found',
|
|
72
|
-
'Run: agentio claude plugin install <source> to install a plugin'
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const agentioJson = loadAgentioJson(targetDir);
|
|
77
|
-
const plugins = Object.entries(agentioJson.plugins);
|
|
78
|
-
|
|
79
|
-
if (plugins.length === 0) {
|
|
80
|
-
console.log('No plugins defined in agentio.json');
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
console.error(`Installing ${plugins.length} plugin(s) from agentio.json...`);
|
|
85
|
-
console.error(`Target: ${path.join(targetDir, '.claude')}`);
|
|
86
|
-
|
|
87
|
-
let installed = 0;
|
|
88
|
-
for (const [name, entry] of plugins) {
|
|
89
|
-
console.error(`\nInstalling ${name}...`);
|
|
90
|
-
|
|
91
|
-
// Determine component flags based on entry.components
|
|
92
|
-
const installOptions = {
|
|
93
|
-
skills:
|
|
94
|
-
!entry.components || entry.components.includes('skills'),
|
|
95
|
-
commands:
|
|
96
|
-
!entry.components || entry.components.includes('commands'),
|
|
97
|
-
hooks: !entry.components || entry.components.includes('hooks'),
|
|
98
|
-
agents: !entry.components || entry.components.includes('agents'),
|
|
99
|
-
force: options.force,
|
|
100
|
-
targetDir,
|
|
101
|
-
verbose: options.verbose,
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
try {
|
|
105
|
-
const result = await installPlugin(entry.source, installOptions);
|
|
106
|
-
console.log(` Installed: ${result.manifest.name} v${result.manifest.version}`);
|
|
107
|
-
installed++;
|
|
108
|
-
} catch (error) {
|
|
109
|
-
console.error(` Failed to install ${name}: ${error}`);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
142
|
+
install
|
|
143
|
+
.command('plugin')
|
|
144
|
+
.description('Install a plugin')
|
|
145
|
+
.argument('<name>', 'Plugin name (e.g., plugin-name@marketplace)')
|
|
146
|
+
.option('-d, --dir <path>', 'Directory with agentio.json (default: current directory)')
|
|
147
|
+
.action(async (name, options) => {
|
|
148
|
+
try {
|
|
149
|
+
const targetDir = options.dir ? path.resolve(options.dir) : process.cwd();
|
|
112
150
|
|
|
113
|
-
|
|
151
|
+
const success = await installPluginCmd(name);
|
|
152
|
+
if (success) {
|
|
153
|
+
addPlugin(targetDir, name);
|
|
114
154
|
}
|
|
115
155
|
} catch (error) {
|
|
116
156
|
handleError(error);
|
|
117
157
|
}
|
|
118
158
|
});
|
|
119
159
|
|
|
120
|
-
|
|
160
|
+
// install with no subcommand - install all from agentio.json
|
|
161
|
+
install.action(async (options) => {
|
|
162
|
+
try {
|
|
163
|
+
const targetDir = options.dir ? path.resolve(options.dir) : process.cwd();
|
|
164
|
+
const config = loadAgentioJson(targetDir);
|
|
165
|
+
|
|
166
|
+
if (config.marketplaces.length === 0 && config.plugins.length === 0) {
|
|
167
|
+
console.log('No marketplaces or plugins defined in agentio.json');
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
console.error(`Installing from agentio.json...`);
|
|
172
|
+
|
|
173
|
+
// Install marketplaces first
|
|
174
|
+
if (config.marketplaces.length > 0) {
|
|
175
|
+
console.error(`\nMarketplaces (${config.marketplaces.length}):`);
|
|
176
|
+
for (const url of config.marketplaces) {
|
|
177
|
+
await installMarketplace(url);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Then install plugins
|
|
182
|
+
if (config.plugins.length > 0) {
|
|
183
|
+
console.error(`\nPlugins (${config.plugins.length}):`);
|
|
184
|
+
for (const name of config.plugins) {
|
|
185
|
+
await installPluginCmd(name);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
console.log('\nDone.');
|
|
190
|
+
} catch (error) {
|
|
191
|
+
handleError(error);
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
// list command
|
|
196
|
+
claude
|
|
121
197
|
.command('list')
|
|
122
|
-
.description('List plugins from agentio.json')
|
|
198
|
+
.description('List marketplaces and plugins from agentio.json')
|
|
123
199
|
.option('-d, --dir <path>', 'Directory with agentio.json (default: current directory)')
|
|
124
200
|
.action(async (options) => {
|
|
125
201
|
try {
|
|
126
202
|
const targetDir = options.dir ? path.resolve(options.dir) : process.cwd();
|
|
203
|
+
const config = loadAgentioJson(targetDir);
|
|
127
204
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if (plugins.length === 0) {
|
|
131
|
-
console.log('No plugins in agentio.json');
|
|
205
|
+
if (config.marketplaces.length === 0 && config.plugins.length === 0) {
|
|
206
|
+
console.log('No marketplaces or plugins defined in agentio.json');
|
|
132
207
|
return;
|
|
133
208
|
}
|
|
134
209
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
210
|
+
if (config.marketplaces.length > 0) {
|
|
211
|
+
console.log(`Marketplaces (${config.marketplaces.length}):`);
|
|
212
|
+
for (const url of config.marketplaces) {
|
|
213
|
+
console.log(` ${url}`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (config.plugins.length > 0) {
|
|
218
|
+
if (config.marketplaces.length > 0) {
|
|
219
|
+
console.log('');
|
|
220
|
+
}
|
|
221
|
+
console.log(`Plugins (${config.plugins.length}):`);
|
|
222
|
+
for (const name of config.plugins) {
|
|
223
|
+
console.log(` ${name}`);
|
|
141
224
|
}
|
|
142
|
-
console.log('');
|
|
143
225
|
}
|
|
144
226
|
} catch (error) {
|
|
145
227
|
handleError(error);
|
|
146
228
|
}
|
|
147
229
|
});
|
|
148
230
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
231
|
+
// remove command group
|
|
232
|
+
const remove = claude.command('remove').description('Remove marketplaces and plugins');
|
|
233
|
+
|
|
234
|
+
remove
|
|
235
|
+
.command('marketplace')
|
|
236
|
+
.description('Remove a marketplace from agentio.json')
|
|
237
|
+
.argument('<url>', 'Marketplace URL to remove')
|
|
153
238
|
.option('-d, --dir <path>', 'Directory with agentio.json (default: current directory)')
|
|
154
|
-
.action(async (
|
|
239
|
+
.action(async (url, options) => {
|
|
155
240
|
try {
|
|
156
241
|
const targetDir = options.dir ? path.resolve(options.dir) : process.cwd();
|
|
157
242
|
|
|
158
|
-
const
|
|
159
|
-
if (
|
|
160
|
-
|
|
243
|
+
const removed = removeMarketplace(targetDir, url);
|
|
244
|
+
if (removed) {
|
|
245
|
+
console.log(`Removed marketplace: ${url}`);
|
|
246
|
+
} else {
|
|
247
|
+
throw new CliError('NOT_FOUND', `Marketplace not found: ${url}`);
|
|
161
248
|
}
|
|
249
|
+
} catch (error) {
|
|
250
|
+
handleError(error);
|
|
251
|
+
}
|
|
252
|
+
});
|
|
162
253
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
254
|
+
remove
|
|
255
|
+
.command('plugin')
|
|
256
|
+
.description('Uninstall a plugin and remove from agentio.json')
|
|
257
|
+
.argument('<name>', 'Plugin name to remove')
|
|
258
|
+
.option('-d, --dir <path>', 'Directory with agentio.json (default: current directory)')
|
|
259
|
+
.action(async (name, options) => {
|
|
260
|
+
try {
|
|
261
|
+
const targetDir = options.dir ? path.resolve(options.dir) : process.cwd();
|
|
170
262
|
|
|
171
|
-
|
|
263
|
+
await uninstallPluginCmd(name);
|
|
172
264
|
removePlugin(targetDir, name);
|
|
173
|
-
|
|
174
|
-
console.log(`Removed: ${name}`);
|
|
175
|
-
if (components.length > 0) {
|
|
176
|
-
console.log(`Removed components: ${components.length}`);
|
|
177
|
-
for (const comp of components) {
|
|
178
|
-
console.log(` ${comp.type}/${comp.name}`);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
265
|
} catch (error) {
|
|
182
266
|
handleError(error);
|
|
183
267
|
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { RssClient } from '../services/rss/client';
|
|
3
|
+
import { handleError } from '../utils/errors';
|
|
4
|
+
import {
|
|
5
|
+
printRssArticleList,
|
|
6
|
+
printRssArticle,
|
|
7
|
+
printRssFeedInfo,
|
|
8
|
+
} from '../utils/output';
|
|
9
|
+
|
|
10
|
+
export function registerRssCommands(program: Command): void {
|
|
11
|
+
const rss = program
|
|
12
|
+
.command('rss')
|
|
13
|
+
.description('RSS feed operations');
|
|
14
|
+
|
|
15
|
+
// Get articles from a feed
|
|
16
|
+
rss
|
|
17
|
+
.command('articles')
|
|
18
|
+
.description('List articles from a blog')
|
|
19
|
+
.argument('<url>', 'Blog URL (feed will be auto-discovered)')
|
|
20
|
+
.option('--limit <n>', 'Number of articles', '20')
|
|
21
|
+
.option('--since <date>', 'Only articles after this date (YYYY-MM-DD)')
|
|
22
|
+
.action(async (url, options) => {
|
|
23
|
+
try {
|
|
24
|
+
const client = new RssClient();
|
|
25
|
+
const listOptions = {
|
|
26
|
+
limit: parseInt(options.limit, 10),
|
|
27
|
+
since: options.since ? new Date(options.since) : undefined,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const info = await client.getInfo(url);
|
|
31
|
+
const articles = await client.list(url, listOptions);
|
|
32
|
+
printRssArticleList(articles, info.title);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
handleError(error);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Get a specific article
|
|
39
|
+
rss
|
|
40
|
+
.command('get')
|
|
41
|
+
.description('Get a specific article')
|
|
42
|
+
.argument('<url>', 'Blog URL (feed will be auto-discovered)')
|
|
43
|
+
.argument('<article-id>', 'Article ID or URL')
|
|
44
|
+
.action(async (url, articleId) => {
|
|
45
|
+
try {
|
|
46
|
+
const client = new RssClient();
|
|
47
|
+
const article = await client.get(url, articleId);
|
|
48
|
+
printRssArticle(article);
|
|
49
|
+
} catch (error) {
|
|
50
|
+
handleError(error);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Get feed info
|
|
55
|
+
rss
|
|
56
|
+
.command('info')
|
|
57
|
+
.description('Get feed information')
|
|
58
|
+
.argument('<url>', 'Blog URL (feed will be auto-discovered)')
|
|
59
|
+
.action(async (url) => {
|
|
60
|
+
try {
|
|
61
|
+
const client = new RssClient();
|
|
62
|
+
const info = await client.getInfo(url);
|
|
63
|
+
printRssFeedInfo(info);
|
|
64
|
+
} catch (error) {
|
|
65
|
+
handleError(error);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
@@ -115,7 +115,7 @@ export async function listProfiles(service?: ServiceName): Promise<{
|
|
|
115
115
|
default?: string;
|
|
116
116
|
}[]> {
|
|
117
117
|
const config = await loadConfig();
|
|
118
|
-
const services: ServiceName[] = service ? [service] : ['gmail', 'gchat', 'jira', 'telegram'];
|
|
118
|
+
const services: ServiceName[] = service ? [service] : ['gmail', 'gchat', 'jira', 'slack', 'telegram'];
|
|
119
119
|
|
|
120
120
|
return services.map((svc) => ({
|
|
121
121
|
service: svc,
|
package/src/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { registerTelegramCommands } from './commands/telegram';
|
|
|
5
5
|
import { registerGChatCommands } from './commands/gchat';
|
|
6
6
|
import { registerJiraCommands } from './commands/jira';
|
|
7
7
|
import { registerSlackCommands } from './commands/slack';
|
|
8
|
+
import { registerRssCommands } from './commands/rss';
|
|
8
9
|
import { registerUpdateCommand } from './commands/update';
|
|
9
10
|
import { registerConfigCommands } from './commands/config';
|
|
10
11
|
import { registerClaudeCommands } from './commands/claude';
|
|
@@ -31,6 +32,7 @@ registerTelegramCommands(program);
|
|
|
31
32
|
registerGChatCommands(program);
|
|
32
33
|
registerJiraCommands(program);
|
|
33
34
|
registerSlackCommands(program);
|
|
35
|
+
registerRssCommands(program);
|
|
34
36
|
registerUpdateCommand(program);
|
|
35
37
|
registerConfigCommands(program);
|
|
36
38
|
registerClaudeCommands(program);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
2
|
import * as path from 'path';
|
|
3
|
-
import type { AgentioJson
|
|
3
|
+
import type { AgentioJson } from '../../types/claude-plugin';
|
|
4
4
|
|
|
5
5
|
const AGENTIO_JSON_FILE = 'agentio.json';
|
|
6
6
|
|
|
@@ -19,15 +19,18 @@ export function loadAgentioJson(dir: string): AgentioJson {
|
|
|
19
19
|
const filePath = getAgentioJsonPath(dir);
|
|
20
20
|
|
|
21
21
|
if (!fs.existsSync(filePath)) {
|
|
22
|
-
return { plugins:
|
|
22
|
+
return { marketplaces: [], plugins: [] };
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
const content = fs.readFileSync(filePath, 'utf-8');
|
|
26
26
|
const data = JSON.parse(content) as AgentioJson;
|
|
27
27
|
|
|
28
|
-
// Ensure
|
|
28
|
+
// Ensure arrays exist
|
|
29
|
+
if (!data.marketplaces) {
|
|
30
|
+
data.marketplaces = [];
|
|
31
|
+
}
|
|
29
32
|
if (!data.plugins) {
|
|
30
|
-
data.plugins =
|
|
33
|
+
data.plugins = [];
|
|
31
34
|
}
|
|
32
35
|
|
|
33
36
|
return data;
|
|
@@ -43,61 +46,53 @@ export function saveAgentioJson(dir: string, data: AgentioJson): void {
|
|
|
43
46
|
}
|
|
44
47
|
|
|
45
48
|
/**
|
|
46
|
-
*
|
|
49
|
+
* Add a marketplace URL if not already present.
|
|
47
50
|
*/
|
|
48
|
-
export function
|
|
49
|
-
|
|
51
|
+
export function addMarketplace(dir: string, url: string): void {
|
|
52
|
+
const data = loadAgentioJson(dir);
|
|
53
|
+
if (!data.marketplaces.includes(url)) {
|
|
54
|
+
data.marketplaces.push(url);
|
|
55
|
+
saveAgentioJson(dir, data);
|
|
56
|
+
}
|
|
50
57
|
}
|
|
51
58
|
|
|
52
59
|
/**
|
|
53
|
-
* Add
|
|
60
|
+
* Add a plugin name if not already present.
|
|
54
61
|
*/
|
|
55
|
-
export function addPlugin(
|
|
56
|
-
dir: string,
|
|
57
|
-
name: string,
|
|
58
|
-
entry: AgentioPluginEntry
|
|
59
|
-
): void {
|
|
62
|
+
export function addPlugin(dir: string, name: string): void {
|
|
60
63
|
const data = loadAgentioJson(dir);
|
|
61
|
-
data.plugins
|
|
62
|
-
|
|
64
|
+
if (!data.plugins.includes(name)) {
|
|
65
|
+
data.plugins.push(name);
|
|
66
|
+
saveAgentioJson(dir, data);
|
|
67
|
+
}
|
|
63
68
|
}
|
|
64
69
|
|
|
65
70
|
/**
|
|
66
|
-
* Remove a
|
|
67
|
-
* Returns true if
|
|
71
|
+
* Remove a marketplace URL.
|
|
72
|
+
* Returns true if found and removed.
|
|
68
73
|
*/
|
|
69
|
-
export function
|
|
74
|
+
export function removeMarketplace(dir: string, url: string): boolean {
|
|
70
75
|
const data = loadAgentioJson(dir);
|
|
71
|
-
|
|
72
|
-
if (
|
|
76
|
+
const index = data.marketplaces.indexOf(url);
|
|
77
|
+
if (index === -1) {
|
|
73
78
|
return false;
|
|
74
79
|
}
|
|
75
|
-
|
|
76
|
-
delete data.plugins[name];
|
|
80
|
+
data.marketplaces.splice(index, 1);
|
|
77
81
|
saveAgentioJson(dir, data);
|
|
78
82
|
return true;
|
|
79
83
|
}
|
|
80
84
|
|
|
81
85
|
/**
|
|
82
|
-
*
|
|
83
|
-
|
|
84
|
-
export function getPlugin(
|
|
85
|
-
dir: string,
|
|
86
|
-
name: string
|
|
87
|
-
): AgentioPluginEntry | undefined {
|
|
88
|
-
const data = loadAgentioJson(dir);
|
|
89
|
-
return data.plugins[name];
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* List all plugins in agentio.json.
|
|
86
|
+
* Remove a plugin name.
|
|
87
|
+
* Returns true if found and removed.
|
|
94
88
|
*/
|
|
95
|
-
export function
|
|
96
|
-
dir: string
|
|
97
|
-
): Array<{ name: string; entry: AgentioPluginEntry }> {
|
|
89
|
+
export function removePlugin(dir: string, name: string): boolean {
|
|
98
90
|
const data = loadAgentioJson(dir);
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
91
|
+
const index = data.plugins.indexOf(name);
|
|
92
|
+
if (index === -1) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
data.plugins.splice(index, 1);
|
|
96
|
+
saveAgentioJson(dir, data);
|
|
97
|
+
return true;
|
|
103
98
|
}
|