agentspd 1.0.0 → 1.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/README.md +77 -294
- package/dist/api.d.ts +66 -0
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +147 -0
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +114 -32
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/auth.js +58 -41
- package/dist/commands/index.d.ts +2 -0
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +2 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +111 -19
- package/dist/commands/openclaw.d.ts +3 -0
- package/dist/commands/openclaw.d.ts.map +1 -0
- package/dist/commands/openclaw.js +1033 -0
- package/dist/commands/policies.d.ts.map +1 -1
- package/dist/commands/policies.js +137 -41
- package/dist/commands/threats.d.ts.map +1 -1
- package/dist/commands/threats.js +75 -29
- package/dist/commands/webhooks.d.ts.map +1 -1
- package/dist/commands/webhooks.js +24 -21
- package/dist/commands/workspaces.d.ts +5 -0
- package/dist/commands/workspaces.d.ts.map +1 -0
- package/dist/commands/workspaces.js +514 -0
- package/dist/config.d.ts +6 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +34 -23
- package/dist/index.js +178 -155
- package/dist/openclaw-api.d.ts +81 -0
- package/dist/openclaw-api.d.ts.map +1 -0
- package/dist/openclaw-api.js +262 -0
- package/package.json +6 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"policies.d.ts","sourceRoot":"","sources":["../../src/commands/policies.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkDpC,wBAAgB,qBAAqB,IAAI,OAAO,
|
|
1
|
+
{"version":3,"file":"policies.d.ts","sourceRoot":"","sources":["../../src/commands/policies.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkDpC,wBAAgB,qBAAqB,IAAI,OAAO,CAqa/C"}
|
|
@@ -74,17 +74,65 @@ export function createPoliciesCommand() {
|
|
|
74
74
|
content = DEFAULT_POLICY_TEMPLATE;
|
|
75
75
|
}
|
|
76
76
|
else {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
77
|
+
// Offer AI generation as the primary option
|
|
78
|
+
const { method } = await inquirer.prompt([{
|
|
79
|
+
type: 'list',
|
|
80
|
+
name: 'method',
|
|
81
|
+
message: 'Create policy from:',
|
|
82
|
+
choices: [
|
|
83
|
+
{ name: 'Natural language description (AI generates the policy)', value: 'ai' },
|
|
84
|
+
{ name: 'YAML editor (manual)', value: 'editor' },
|
|
85
|
+
{ name: 'Default template', value: 'template' },
|
|
86
|
+
],
|
|
87
|
+
}]);
|
|
88
|
+
if (method === 'ai') {
|
|
89
|
+
const { prompt } = await inquirer.prompt([{
|
|
90
|
+
type: 'input',
|
|
91
|
+
name: 'prompt',
|
|
92
|
+
message: 'Describe what your agent does and what it should be allowed to do:',
|
|
93
|
+
validate: (input) => input.length > 0 || 'Description is required',
|
|
94
|
+
}]);
|
|
95
|
+
const genSpinner = ora('Generating policy with AI...').start();
|
|
96
|
+
const genResult = await api.generatePolicy({ prompt, mode: 'single' });
|
|
97
|
+
if (genResult.error || !genResult.data?.generatedPolicy) {
|
|
98
|
+
genSpinner.fail('AI generation failed');
|
|
99
|
+
output.error(genResult.error?.message ?? 'Empty response');
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
content = genResult.data.generatedPolicy;
|
|
103
|
+
genSpinner.succeed('Policy generated!');
|
|
104
|
+
console.log();
|
|
105
|
+
console.log(content);
|
|
106
|
+
console.log();
|
|
107
|
+
const { confirmed } = await inquirer.prompt([{
|
|
108
|
+
type: 'confirm',
|
|
109
|
+
name: 'confirmed',
|
|
110
|
+
message: 'Use this generated policy?',
|
|
111
|
+
default: true,
|
|
112
|
+
}]);
|
|
113
|
+
if (!confirmed) {
|
|
114
|
+
// Let them edit it
|
|
115
|
+
const editAnswers = await inquirer.prompt([{
|
|
116
|
+
type: 'editor',
|
|
117
|
+
name: 'content',
|
|
118
|
+
message: 'Edit the generated policy:',
|
|
119
|
+
default: content,
|
|
120
|
+
}]);
|
|
121
|
+
content = editAnswers.content;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
else if (method === 'template') {
|
|
125
|
+
content = DEFAULT_POLICY_TEMPLATE;
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
const answers = await inquirer.prompt([{
|
|
129
|
+
type: 'editor',
|
|
130
|
+
name: 'content',
|
|
131
|
+
message: 'Policy content:',
|
|
132
|
+
default: DEFAULT_POLICY_TEMPLATE,
|
|
133
|
+
}]);
|
|
134
|
+
content = answers.content;
|
|
135
|
+
}
|
|
88
136
|
}
|
|
89
137
|
// Get name and description if not provided
|
|
90
138
|
if (!name) {
|
|
@@ -123,7 +171,12 @@ export function createPoliciesCommand() {
|
|
|
123
171
|
}
|
|
124
172
|
return;
|
|
125
173
|
}
|
|
126
|
-
|
|
174
|
+
if (options.json) {
|
|
175
|
+
validateSpinner.stop();
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
validateSpinner.succeed('Policy validated');
|
|
179
|
+
}
|
|
127
180
|
// Create policy
|
|
128
181
|
const spinner = ora('Creating policy...').start();
|
|
129
182
|
const result = await api.createPolicy({ name, description, content });
|
|
@@ -132,23 +185,26 @@ export function createPoliciesCommand() {
|
|
|
132
185
|
output.error(result.error.message);
|
|
133
186
|
return;
|
|
134
187
|
}
|
|
135
|
-
spinner.succeed('Policy created successfully!');
|
|
136
188
|
if (options.json) {
|
|
189
|
+
spinner.stop();
|
|
137
190
|
output.printJson(result.data);
|
|
138
191
|
}
|
|
139
|
-
else
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
[
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
192
|
+
else {
|
|
193
|
+
spinner.succeed('Policy created successfully!');
|
|
194
|
+
if (result.data) {
|
|
195
|
+
console.log();
|
|
196
|
+
output.printKeyValue([
|
|
197
|
+
['Policy ID', result.data.id],
|
|
198
|
+
['Name', result.data.name],
|
|
199
|
+
['Version', result.data.version],
|
|
200
|
+
['Active', result.data.isActive ? 'Yes' : 'No'],
|
|
201
|
+
['Created', output.formatDate(result.data.createdAt)],
|
|
202
|
+
]);
|
|
203
|
+
console.log();
|
|
204
|
+
output.info('Next steps:');
|
|
205
|
+
console.log(` 1. Activate policy: ${output.highlight(`emotos policies activate ${result.data.id}`)}`);
|
|
206
|
+
console.log(` 2. Assign to agent: ${output.highlight(`emotos agents create --policy ${result.data.id}`)}`);
|
|
207
|
+
}
|
|
152
208
|
}
|
|
153
209
|
});
|
|
154
210
|
policies
|
|
@@ -181,10 +237,18 @@ export function createPoliciesCommand() {
|
|
|
181
237
|
policies
|
|
182
238
|
.command('get <policyId>')
|
|
183
239
|
.alias('show')
|
|
184
|
-
.description('Get policy details')
|
|
240
|
+
.description('Get policy details (accepts name or ID)')
|
|
185
241
|
.option('--json', 'Output as JSON')
|
|
186
242
|
.option('--content', 'Show policy content only')
|
|
187
|
-
.action(async (
|
|
243
|
+
.action(async (policyIdOrName, options) => {
|
|
244
|
+
let policyId;
|
|
245
|
+
try {
|
|
246
|
+
policyId = await api.resolvePolicy(policyIdOrName);
|
|
247
|
+
}
|
|
248
|
+
catch (e) {
|
|
249
|
+
output.error(e.message);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
188
252
|
const spinner = ora('Fetching policy...').start();
|
|
189
253
|
const result = await api.getPolicy(policyId);
|
|
190
254
|
if (result.error) {
|
|
@@ -218,10 +282,18 @@ export function createPoliciesCommand() {
|
|
|
218
282
|
});
|
|
219
283
|
policies
|
|
220
284
|
.command('update <policyId>')
|
|
221
|
-
.description('Update a policy')
|
|
285
|
+
.description('Update a policy (accepts name or ID)')
|
|
222
286
|
.option('-f, --file <path>', 'Read policy content from file')
|
|
223
287
|
.option('--json', 'Output as JSON')
|
|
224
|
-
.action(async (
|
|
288
|
+
.action(async (policyIdOrName, options) => {
|
|
289
|
+
let policyId;
|
|
290
|
+
try {
|
|
291
|
+
policyId = await api.resolvePolicy(policyIdOrName);
|
|
292
|
+
}
|
|
293
|
+
catch (e) {
|
|
294
|
+
output.error(e.message);
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
225
297
|
let content;
|
|
226
298
|
if (options.file) {
|
|
227
299
|
if (!fs.existsSync(options.file)) {
|
|
@@ -259,7 +331,12 @@ export function createPoliciesCommand() {
|
|
|
259
331
|
}
|
|
260
332
|
return;
|
|
261
333
|
}
|
|
262
|
-
|
|
334
|
+
if (options.json) {
|
|
335
|
+
validateSpinner.stop();
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
validateSpinner.succeed('Policy validated');
|
|
339
|
+
}
|
|
263
340
|
// Update policy
|
|
264
341
|
const spinner = ora('Updating policy...').start();
|
|
265
342
|
const result = await api.updatePolicy(policyId, content);
|
|
@@ -268,15 +345,18 @@ export function createPoliciesCommand() {
|
|
|
268
345
|
output.error(result.error.message);
|
|
269
346
|
return;
|
|
270
347
|
}
|
|
271
|
-
spinner.succeed('Policy updated successfully!');
|
|
272
348
|
if (options.json) {
|
|
349
|
+
spinner.stop();
|
|
273
350
|
output.printJson(result.data);
|
|
274
351
|
}
|
|
275
|
-
else
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
352
|
+
else {
|
|
353
|
+
spinner.succeed('Policy updated successfully!');
|
|
354
|
+
if (result.data) {
|
|
355
|
+
output.printKeyValue([
|
|
356
|
+
['Version', result.data.version],
|
|
357
|
+
['Updated', result.data.updatedAt ? output.formatDate(result.data.updatedAt) : 'Now'],
|
|
358
|
+
]);
|
|
359
|
+
}
|
|
280
360
|
}
|
|
281
361
|
});
|
|
282
362
|
policies
|
|
@@ -310,8 +390,16 @@ export function createPoliciesCommand() {
|
|
|
310
390
|
});
|
|
311
391
|
policies
|
|
312
392
|
.command('activate <policyId>')
|
|
313
|
-
.description('Activate a policy')
|
|
314
|
-
.action(async (
|
|
393
|
+
.description('Activate a policy (accepts name or ID)')
|
|
394
|
+
.action(async (policyIdOrName) => {
|
|
395
|
+
let policyId;
|
|
396
|
+
try {
|
|
397
|
+
policyId = await api.resolvePolicy(policyIdOrName);
|
|
398
|
+
}
|
|
399
|
+
catch (e) {
|
|
400
|
+
output.error(e.message);
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
315
403
|
const spinner = ora('Activating policy...').start();
|
|
316
404
|
const result = await api.activatePolicy(policyId);
|
|
317
405
|
if (result.error) {
|
|
@@ -323,8 +411,16 @@ export function createPoliciesCommand() {
|
|
|
323
411
|
});
|
|
324
412
|
policies
|
|
325
413
|
.command('deactivate <policyId>')
|
|
326
|
-
.description('Deactivate a policy')
|
|
327
|
-
.action(async (
|
|
414
|
+
.description('Deactivate a policy (accepts name or ID)')
|
|
415
|
+
.action(async (policyIdOrName) => {
|
|
416
|
+
let policyId;
|
|
417
|
+
try {
|
|
418
|
+
policyId = await api.resolvePolicy(policyIdOrName);
|
|
419
|
+
}
|
|
420
|
+
catch (e) {
|
|
421
|
+
output.error(e.message);
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
328
424
|
const spinner = ora('Deactivating policy...').start();
|
|
329
425
|
const result = await api.deactivatePolicy(policyId);
|
|
330
426
|
if (result.error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"threats.d.ts","sourceRoot":"","sources":["../../src/commands/threats.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,oBAAoB,IAAI,OAAO,
|
|
1
|
+
{"version":3,"file":"threats.d.ts","sourceRoot":"","sources":["../../src/commands/threats.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,oBAAoB,IAAI,OAAO,CAkO9C"}
|
package/dist/commands/threats.js
CHANGED
|
@@ -82,38 +82,84 @@ export function createThreatsCommand() {
|
|
|
82
82
|
output.heading('Threat Monitor');
|
|
83
83
|
output.info('Press Ctrl+C to stop');
|
|
84
84
|
console.log();
|
|
85
|
-
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
85
|
+
// Try SSE stream first, fall back to polling
|
|
86
|
+
const streamPath = options.agent
|
|
87
|
+
? `/threats/stream?agentId=${encodeURIComponent(options.agent)}`
|
|
88
|
+
: '/threats/stream';
|
|
89
|
+
const reader = await api.streamEvents(streamPath);
|
|
90
|
+
if (reader) {
|
|
91
|
+
output.info('Connected via real-time stream');
|
|
92
|
+
console.log();
|
|
93
|
+
const decoder = new TextDecoder();
|
|
94
|
+
let buffer = '';
|
|
95
|
+
const read = async () => {
|
|
96
|
+
try {
|
|
97
|
+
while (true) {
|
|
98
|
+
const { done, value } = await reader.read();
|
|
99
|
+
if (done)
|
|
100
|
+
break;
|
|
101
|
+
buffer += decoder.decode(value, { stream: true });
|
|
102
|
+
const lines = buffer.split('\n');
|
|
103
|
+
buffer = lines.pop() ?? '';
|
|
104
|
+
for (const line of lines) {
|
|
105
|
+
if (line.startsWith('data: ')) {
|
|
106
|
+
try {
|
|
107
|
+
const threat = JSON.parse(line.slice(6));
|
|
108
|
+
const severityStr = output.formatSeverity(threat.severity ?? 'medium');
|
|
109
|
+
const statusStr = output.formatStatus(threat.status ?? 'detected');
|
|
110
|
+
console.log(`[${output.formatDate(threat.createdAt ?? new Date().toISOString())}] ${severityStr} ${threat.threatType ?? 'threat'} - Agent: ${threat.agentId ?? 'unknown'} - Status: ${statusStr}`);
|
|
111
|
+
}
|
|
112
|
+
catch { /* ignore parse errors */ }
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
if (err.name !== 'AbortError') {
|
|
119
|
+
output.warn('Stream disconnected, falling back to polling...');
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
read();
|
|
124
|
+
process.on('SIGINT', () => {
|
|
125
|
+
reader.cancel();
|
|
126
|
+
console.log();
|
|
127
|
+
output.info('Monitoring stopped');
|
|
128
|
+
process.exit(0);
|
|
91
129
|
});
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
// Fallback: polling every 3 seconds
|
|
133
|
+
let lastSeen = null;
|
|
134
|
+
const fetchThreats = async () => {
|
|
135
|
+
const result = await api.listThreats({
|
|
136
|
+
agentId: options.agent,
|
|
137
|
+
severity: options.severity,
|
|
138
|
+
limit: 10,
|
|
139
|
+
});
|
|
140
|
+
if (result.data && result.data.items.length > 0) {
|
|
141
|
+
const newThreats = lastSeen
|
|
142
|
+
? result.data.items.filter(t => t.id !== lastSeen && new Date(t.createdAt) > new Date(lastSeen))
|
|
143
|
+
: result.data.items;
|
|
144
|
+
if (newThreats.length > 0) {
|
|
145
|
+
for (const threat of newThreats) {
|
|
146
|
+
const severityStr = output.formatSeverity(threat.severity);
|
|
147
|
+
const statusStr = output.formatStatus(threat.status);
|
|
148
|
+
console.log(`[${output.formatDate(threat.createdAt)}] ${severityStr} ${threat.threatType} - Agent: ${threat.agentId} - Status: ${statusStr}`);
|
|
149
|
+
}
|
|
150
|
+
lastSeen = result.data.items[0].id;
|
|
101
151
|
}
|
|
102
|
-
lastSeen = result.data.items[0].id;
|
|
103
152
|
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
output.info('Monitoring stopped');
|
|
115
|
-
process.exit(0);
|
|
116
|
-
});
|
|
153
|
+
};
|
|
154
|
+
await fetchThreats();
|
|
155
|
+
const interval = setInterval(fetchThreats, 3000);
|
|
156
|
+
process.on('SIGINT', () => {
|
|
157
|
+
clearInterval(interval);
|
|
158
|
+
console.log();
|
|
159
|
+
output.info('Monitoring stopped');
|
|
160
|
+
process.exit(0);
|
|
161
|
+
});
|
|
162
|
+
}
|
|
117
163
|
});
|
|
118
164
|
threats
|
|
119
165
|
.command('stats')
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../../src/commands/webhooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoBpC,wBAAgB,qBAAqB,IAAI,OAAO,
|
|
1
|
+
{"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../../src/commands/webhooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoBpC,wBAAgB,qBAAqB,IAAI,OAAO,CAoO/C"}
|
|
@@ -85,30 +85,33 @@ export function createWebhooksCommand() {
|
|
|
85
85
|
output.error(result.error.message);
|
|
86
86
|
return;
|
|
87
87
|
}
|
|
88
|
-
spinner.succeed('Webhook created successfully!');
|
|
89
88
|
if (options.json) {
|
|
89
|
+
spinner.stop();
|
|
90
90
|
output.printJson(result.data);
|
|
91
91
|
}
|
|
92
|
-
else
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
[
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
92
|
+
else {
|
|
93
|
+
spinner.succeed('Webhook created successfully!');
|
|
94
|
+
if (result.data) {
|
|
95
|
+
console.log();
|
|
96
|
+
output.printKeyValue([
|
|
97
|
+
['Webhook ID', result.data.id],
|
|
98
|
+
['URL', result.data.url],
|
|
99
|
+
['Events', result.data.events.join(', ')],
|
|
100
|
+
['Created', output.formatDate(result.data.createdAt)],
|
|
101
|
+
]);
|
|
102
|
+
console.log();
|
|
103
|
+
output.info('Webhook payload example:');
|
|
104
|
+
output.printJson({
|
|
105
|
+
id: 'evt_123',
|
|
106
|
+
type: 'threat.blocked',
|
|
107
|
+
timestamp: new Date().toISOString(),
|
|
108
|
+
data: {
|
|
109
|
+
agentId: 'agent_abc',
|
|
110
|
+
threatType: 'prompt_injection',
|
|
111
|
+
severity: 'high',
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
}
|
|
112
115
|
}
|
|
113
116
|
});
|
|
114
117
|
webhooks
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspaces.d.ts","sourceRoot":"","sources":["../../src/commands/workspaces.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,uBAAuB,IAAI,OAAO,CAuYjD;AAID,wBAAgB,2BAA2B,IAAI,OAAO,CAwCrD;AAED,wBAAgB,yBAAyB,IAAI,OAAO,CAkCnD"}
|