@loom-framework/core 0.1.0-alpha.180 → 0.1.0-alpha.182

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.
Files changed (108) hide show
  1. package/builtin-skills/app-skill/SKILL.md +5 -6
  2. package/builtin-skills/app-skill/references/auth.md +79 -79
  3. package/builtin-skills/app-skill/references/events.md +237 -19
  4. package/builtin-skills/app-skill/references/evolution.md +59 -59
  5. package/builtin-skills/app-skill/references/model.md +48 -48
  6. package/builtin-skills/app-skill/references/notification.md +47 -47
  7. package/builtin-skills/app-skill/references/process-builder.md +173 -197
  8. package/builtin-skills/app-skill/references/process.md +274 -163
  9. package/builtin-skills/loom/SKILL.md +17 -10
  10. package/builtin-skills/loom/references/data-model.md +19 -3
  11. package/dist/backend/auth/rbac.js +1 -1
  12. package/dist/backend/auth/rbac.js.map +1 -1
  13. package/dist/backend/events/subscription-service.d.ts +46 -0
  14. package/dist/backend/events/subscription-service.d.ts.map +1 -0
  15. package/dist/backend/events/subscription-service.js +209 -0
  16. package/dist/backend/events/subscription-service.js.map +1 -0
  17. package/dist/backend/index.d.ts +1 -0
  18. package/dist/backend/index.d.ts.map +1 -1
  19. package/dist/backend/index.js +27 -13
  20. package/dist/backend/index.js.map +1 -1
  21. package/dist/backend/lifecycle/manager.d.ts +4 -2
  22. package/dist/backend/lifecycle/manager.d.ts.map +1 -1
  23. package/dist/backend/lifecycle/manager.js +9 -3
  24. package/dist/backend/lifecycle/manager.js.map +1 -1
  25. package/dist/backend/loom-paths.d.ts +3 -1
  26. package/dist/backend/loom-paths.d.ts.map +1 -1
  27. package/dist/backend/loom-paths.js +5 -1
  28. package/dist/backend/loom-paths.js.map +1 -1
  29. package/dist/backend/process/engine.d.ts +15 -1
  30. package/dist/backend/process/engine.d.ts.map +1 -1
  31. package/dist/backend/process/engine.js +79 -23
  32. package/dist/backend/process/engine.js.map +1 -1
  33. package/dist/backend/process/registry.d.ts +44 -9
  34. package/dist/backend/process/registry.d.ts.map +1 -1
  35. package/dist/backend/process/registry.js +208 -40
  36. package/dist/backend/process/registry.js.map +1 -1
  37. package/dist/backend/process/trigger.d.ts +18 -8
  38. package/dist/backend/process/trigger.d.ts.map +1 -1
  39. package/dist/backend/process/trigger.js +86 -32
  40. package/dist/backend/process/trigger.js.map +1 -1
  41. package/dist/backend/routes/ai-config.d.ts.map +1 -1
  42. package/dist/backend/routes/ai-config.js +1 -69
  43. package/dist/backend/routes/ai-config.js.map +1 -1
  44. package/dist/backend/routes/config-writer.d.ts +94 -0
  45. package/dist/backend/routes/config-writer.d.ts.map +1 -0
  46. package/dist/backend/routes/config-writer.js +522 -0
  47. package/dist/backend/routes/config-writer.js.map +1 -0
  48. package/dist/backend/routes/event-routes.d.ts +9 -2
  49. package/dist/backend/routes/event-routes.d.ts.map +1 -1
  50. package/dist/backend/routes/event-routes.js +101 -7
  51. package/dist/backend/routes/event-routes.js.map +1 -1
  52. package/dist/backend/routes/process-routes.d.ts +3 -0
  53. package/dist/backend/routes/process-routes.d.ts.map +1 -1
  54. package/dist/backend/routes/process-routes.js +120 -49
  55. package/dist/backend/routes/process-routes.js.map +1 -1
  56. package/dist/cli/commands/event.d.ts +12 -0
  57. package/dist/cli/commands/event.d.ts.map +1 -0
  58. package/dist/cli/commands/event.js +332 -0
  59. package/dist/cli/commands/event.js.map +1 -0
  60. package/dist/cli/commands/process.d.ts.map +1 -1
  61. package/dist/cli/commands/process.js +82 -44
  62. package/dist/cli/commands/process.js.map +1 -1
  63. package/dist/cli/generators/capability-generator.d.ts.map +1 -1
  64. package/dist/cli/generators/capability-generator.js +33 -34
  65. package/dist/cli/generators/capability-generator.js.map +1 -1
  66. package/dist/cli/helpers/system-page-config.d.ts +1 -1
  67. package/dist/cli/helpers/system-page-config.d.ts.map +1 -1
  68. package/dist/cli/helpers/system-page-config.js +9 -0
  69. package/dist/cli/helpers/system-page-config.js.map +1 -1
  70. package/dist/cli/index.d.ts.map +1 -1
  71. package/dist/cli/index.js +2 -0
  72. package/dist/cli/index.js.map +1 -1
  73. package/dist/cli/templates/dashboard-page.d.ts.map +1 -1
  74. package/dist/cli/templates/dashboard-page.js +10 -3
  75. package/dist/cli/templates/dashboard-page.js.map +1 -1
  76. package/dist/cli/templates/event-management-page.d.ts +8 -0
  77. package/dist/cli/templates/event-management-page.d.ts.map +1 -0
  78. package/dist/cli/templates/event-management-page.js +598 -0
  79. package/dist/cli/templates/event-management-page.js.map +1 -0
  80. package/dist/cli/templates/login-page.d.ts +1 -1
  81. package/dist/cli/templates/login-page.js +1 -1
  82. package/dist/cli/templates/model-management-page.d.ts +1 -1
  83. package/dist/cli/templates/model-management-page.js +1 -1
  84. package/dist/cli/templates/notification-center-page.d.ts +1 -1
  85. package/dist/cli/templates/notification-center-page.js +1 -1
  86. package/dist/cli/templates/notification-detail-page.d.ts +1 -1
  87. package/dist/cli/templates/notification-detail-page.js +1 -1
  88. package/dist/cli/templates/process-management-page.d.ts +1 -1
  89. package/dist/cli/templates/process-management-page.js +1 -1
  90. package/dist/cli/templates/skill-management-page.d.ts +1 -1
  91. package/dist/cli/templates/skill-management-page.js +1 -1
  92. package/dist/cli/templates/user-management-page.d.ts +1 -1
  93. package/dist/cli/templates/user-management-page.js +1 -1
  94. package/dist/config.d.ts +327 -11
  95. package/dist/config.d.ts.map +1 -1
  96. package/dist/config.js +26 -7
  97. package/dist/config.js.map +1 -1
  98. package/dist/index.d.ts +1 -0
  99. package/dist/index.d.ts.map +1 -1
  100. package/dist/index.js.map +1 -1
  101. package/dist/types/event.d.ts +6 -0
  102. package/dist/types/event.d.ts.map +1 -1
  103. package/dist/types/index.d.ts +1 -1
  104. package/dist/types/index.d.ts.map +1 -1
  105. package/dist/types/process.d.ts +45 -7
  106. package/dist/types/process.d.ts.map +1 -1
  107. package/package.json +1 -1
  108. package/builtin-skills/app-skill/references/process-metrics.md +0 -93
@@ -0,0 +1,332 @@
1
+ /**
2
+ * Event CLI Commands
3
+ *
4
+ * loom event list — List all event subscriptions
5
+ * loom event subscribe — Add an event subscription
6
+ * loom event unsubscribe <id> — Remove an event subscription by ID
7
+ * loom event update <id> — Update an event subscription
8
+ * loom event test — Emit a test event
9
+ */
10
+ import chalk from 'chalk';
11
+ import { resolveToken, resolveServer, requireToken, CliAuthError } from '../helpers/auth-client.js';
12
+ /** Handle CliAuthError in catch blocks */
13
+ function handleAuthError(err) {
14
+ if (err instanceof CliAuthError) {
15
+ console.error(chalk.red(err.message));
16
+ process.exit(1);
17
+ }
18
+ }
19
+ async function fetchApi(path, options = {}) {
20
+ const baseUrl = resolveServer(options.server).replace(/\/$/, '');
21
+ const headers = {};
22
+ if (options.body) {
23
+ headers['Content-Type'] = 'application/json';
24
+ }
25
+ if (options.token) {
26
+ headers['Authorization'] = `Bearer ${options.token}`;
27
+ }
28
+ const response = await fetch(`${baseUrl}${path}`, {
29
+ method: options.method ?? 'GET',
30
+ headers,
31
+ body: options.body ? JSON.stringify(options.body) : undefined,
32
+ });
33
+ if (response.status === 401)
34
+ throw new Error('Authentication failed. Token may be expired.');
35
+ if (response.status === 403) {
36
+ const data = await response.json();
37
+ throw new Error(`Permission denied: ${data.error || 'Insufficient permissions'}${data.required ? ` (required: ${data.required}, actual: ${data.actual})` : ''}`);
38
+ }
39
+ const data = await response.json();
40
+ if (!response.ok) {
41
+ throw new Error(data.error ?? `HTTP ${response.status}`);
42
+ }
43
+ return data;
44
+ }
45
+ export function registerEventCommand(program) {
46
+ const eventCmd = program.command('event').description('Event subscription management');
47
+ // loom event list
48
+ eventCmd.command('list')
49
+ .option('--token <token>', 'Auth token')
50
+ .option('--server <url>', 'Server URL')
51
+ .action(async (opts) => {
52
+ try {
53
+ const token = resolveToken(opts.token);
54
+ const result = await fetchApi('/api/v1/events/subscriptions', {
55
+ token: token ?? undefined,
56
+ server: opts.server,
57
+ });
58
+ if (result.subscriptions.length === 0) {
59
+ console.log('No event subscriptions found.');
60
+ return;
61
+ }
62
+ console.log(chalk.bold('Event Subscriptions:'));
63
+ for (const sub of result.subscriptions) {
64
+ const handler = sub.handler;
65
+ const pattern = sub.pattern;
66
+ const config = sub.config;
67
+ const id = sub.id;
68
+ const active = sub.active;
69
+ const handlerColor = handler === 'process' ? chalk.cyan : handler === 'webhook' ? chalk.magenta : handler === 'notify' ? chalk.green : chalk.gray;
70
+ const statusTag = active !== undefined ? (active ? chalk.green('●') : chalk.red('○')) : '';
71
+ let line = ` ${chalk.dim(id ? id.substring(0, 16) : '???')} ${pattern} → ${handlerColor(handler)}`;
72
+ if (statusTag)
73
+ line += ` ${statusTag}`;
74
+ if (handler === 'process' && config.process) {
75
+ line += ` (${config.process})`;
76
+ if (config.filter)
77
+ line += chalk.dim(` filter: ${JSON.stringify(config.filter)}`);
78
+ if (config.debounceMs)
79
+ line += chalk.dim(` debounce: ${config.debounceMs}ms`);
80
+ }
81
+ else if (handler === 'webhook' && config.url) {
82
+ line += ` → ${config.url}`;
83
+ }
84
+ else if (handler === 'notify') {
85
+ const title = config.title;
86
+ if (title)
87
+ line += ` "${title}"`;
88
+ }
89
+ else if (handler === 'log' && config.level) {
90
+ line += ` (${config.level})`;
91
+ }
92
+ console.log(line);
93
+ }
94
+ }
95
+ catch (err) {
96
+ handleAuthError(err);
97
+ console.error(chalk.red(`Error: ${err instanceof Error ? err.message : String(err)}`));
98
+ process.exit(1);
99
+ }
100
+ });
101
+ // loom event subscribe <pattern>
102
+ eventCmd.command('subscribe <pattern>')
103
+ .requiredOption('--handler <type>', 'Handler type: process | webhook | log | notify')
104
+ .option('--process <name>', 'Process name (required when handler=process)')
105
+ .option('--url <url>', 'Webhook URL (required when handler=webhook)')
106
+ .option('--method <method>', 'HTTP method for webhook (default: POST)')
107
+ .option('--headers <json>', 'Webhook headers as JSON')
108
+ .option('--level <level>', 'Log level for handler=log (info|debug|warn)')
109
+ .option('--title <title>', 'Notification title template (handler=notify)')
110
+ .option('--description <text>', 'Notification description template (handler=notify)')
111
+ .option('--filter <json>', 'Event payload filter as JSON (handler=process)')
112
+ .option('--debounce <ms>', 'Debounce window in ms (default: 0, no debounce)', '0')
113
+ .option('--token <token>', 'Auth token')
114
+ .option('--server <url>', 'Server URL')
115
+ .action(async (pattern, opts) => {
116
+ const validHandlers = ['process', 'webhook', 'log', 'notify'];
117
+ if (!validHandlers.includes(opts.handler)) {
118
+ console.error(chalk.red(`Error: --handler must be one of: ${validHandlers.join(', ')}`));
119
+ process.exit(1);
120
+ }
121
+ const config = {};
122
+ if (opts.handler === 'process') {
123
+ if (!opts.process) {
124
+ console.error(chalk.red('Error: --process is required when handler=process'));
125
+ process.exit(1);
126
+ }
127
+ config.process = opts.process;
128
+ if (opts.filter) {
129
+ try {
130
+ config.filter = JSON.parse(opts.filter);
131
+ }
132
+ catch {
133
+ console.error(chalk.red('Error: --filter must be valid JSON'));
134
+ process.exit(1);
135
+ }
136
+ }
137
+ if (opts.debounce)
138
+ config.debounceMs = parseInt(opts.debounce, 10);
139
+ }
140
+ else if (opts.handler === 'webhook') {
141
+ if (!opts.url) {
142
+ console.error(chalk.red('Error: --url is required when handler=webhook'));
143
+ process.exit(1);
144
+ }
145
+ config.url = opts.url;
146
+ if (opts.method)
147
+ config.method = opts.method;
148
+ if (opts.headers) {
149
+ try {
150
+ config.headers = JSON.parse(opts.headers);
151
+ }
152
+ catch {
153
+ console.error(chalk.red('Error: --headers must be valid JSON'));
154
+ process.exit(1);
155
+ }
156
+ }
157
+ }
158
+ else if (opts.handler === 'log') {
159
+ if (opts.level)
160
+ config.level = opts.level;
161
+ }
162
+ else if (opts.handler === 'notify') {
163
+ if (opts.title)
164
+ config.title = opts.title;
165
+ if (opts.description)
166
+ config.description = opts.description;
167
+ }
168
+ try {
169
+ const token = requireToken(opts.token);
170
+ const result = await fetchApi('/api/v1/events/subscriptions', {
171
+ method: 'POST',
172
+ body: { pattern, handler: opts.handler, config },
173
+ token,
174
+ server: opts.server,
175
+ });
176
+ console.log(chalk.green(`Subscription created: ${result.id} ${pattern} → ${opts.handler}`));
177
+ }
178
+ catch (err) {
179
+ handleAuthError(err);
180
+ console.error(chalk.red(`Error: ${err instanceof Error ? err.message : String(err)}`));
181
+ process.exit(1);
182
+ }
183
+ });
184
+ // loom event update <id>
185
+ eventCmd.command('update <id>')
186
+ .option('--pattern <pattern>', 'New event pattern')
187
+ .option('--handler <type>', 'New handler type: process | webhook | log | notify')
188
+ // Process handler options
189
+ .option('--process <name>', 'Process name (handler=process)')
190
+ .option('--filter <json>', 'Event payload filter as JSON (handler=process)')
191
+ .option('--debounce <ms>', 'Debounce window in ms (handler=process)')
192
+ // Webhook handler options
193
+ .option('--url <url>', 'Webhook URL (handler=webhook)')
194
+ .option('--method <method>', 'HTTP method for webhook')
195
+ .option('--headers <json>', 'Webhook headers as JSON')
196
+ // Log handler options
197
+ .option('--level <level>', 'Log level (handler=log)')
198
+ // Notify handler options
199
+ .option('--title <title>', 'Notification title (handler=notify)')
200
+ .option('--description <text>', 'Notification description (handler=notify)')
201
+ .option('--token <token>', 'Auth token')
202
+ .option('--server <url>', 'Server URL')
203
+ .action(async (id, opts) => {
204
+ const body = {};
205
+ if (opts.pattern)
206
+ body.pattern = opts.pattern;
207
+ if (opts.handler) {
208
+ const validHandlers = ['process', 'webhook', 'log', 'notify'];
209
+ if (!validHandlers.includes(opts.handler)) {
210
+ console.error(chalk.red(`Error: --handler must be one of: ${validHandlers.join(', ')}`));
211
+ process.exit(1);
212
+ }
213
+ body.handler = opts.handler;
214
+ }
215
+ // Build config if any handler-specific option is provided
216
+ const config = {};
217
+ if (opts.process)
218
+ config.process = opts.process;
219
+ if (opts.filter) {
220
+ try {
221
+ config.filter = JSON.parse(opts.filter);
222
+ }
223
+ catch {
224
+ console.error(chalk.red('Error: --filter must be valid JSON'));
225
+ process.exit(1);
226
+ }
227
+ }
228
+ if (opts.debounce)
229
+ config.debounceMs = parseInt(opts.debounce, 10);
230
+ if (opts.url)
231
+ config.url = opts.url;
232
+ if (opts.method)
233
+ config.method = opts.method;
234
+ if (opts.headers) {
235
+ try {
236
+ config.headers = JSON.parse(opts.headers);
237
+ }
238
+ catch {
239
+ console.error(chalk.red('Error: --headers must be valid JSON'));
240
+ process.exit(1);
241
+ }
242
+ }
243
+ if (opts.level)
244
+ config.level = opts.level;
245
+ if (opts.title)
246
+ config.title = opts.title;
247
+ if (opts.description)
248
+ config.description = opts.description;
249
+ if (Object.keys(config).length > 0)
250
+ body.config = config;
251
+ if (Object.keys(body).length === 0) {
252
+ console.error(chalk.red('Error: At least one update field is required'));
253
+ process.exit(1);
254
+ }
255
+ try {
256
+ const token = requireToken(opts.token);
257
+ const result = await fetchApi(`/api/v1/events/subscriptions/${id}`, {
258
+ method: 'PUT',
259
+ body,
260
+ token,
261
+ server: opts.server,
262
+ });
263
+ console.log(chalk.green(`Subscription updated: ${result.id}`));
264
+ }
265
+ catch (err) {
266
+ handleAuthError(err);
267
+ console.error(chalk.red(`Error: ${err instanceof Error ? err.message : String(err)}`));
268
+ process.exit(1);
269
+ }
270
+ });
271
+ // loom event unsubscribe <id>
272
+ eventCmd.command('unsubscribe <id>')
273
+ .option('--token <token>', 'Auth token')
274
+ .option('--server <url>', 'Server URL')
275
+ .action(async (id, opts) => {
276
+ try {
277
+ const token = requireToken(opts.token);
278
+ const result = await fetchApi(`/api/v1/events/subscriptions/${id}`, {
279
+ method: 'DELETE',
280
+ token,
281
+ server: opts.server,
282
+ });
283
+ const removed = result.removed;
284
+ console.log(chalk.green(`Subscription removed: ${id} ${removed.pattern} → ${removed.handler}`));
285
+ }
286
+ catch (err) {
287
+ handleAuthError(err);
288
+ console.error(chalk.red(`Error: ${err instanceof Error ? err.message : String(err)}`));
289
+ process.exit(1);
290
+ }
291
+ });
292
+ // loom event test <pattern>
293
+ eventCmd.command('test <pattern>')
294
+ .option('--payload <json>', 'Event payload as JSON', '{}')
295
+ .option('--token <token>', 'Auth token')
296
+ .option('--server <url>', 'Server URL')
297
+ .action(async (pattern, opts) => {
298
+ let payload = {};
299
+ if (opts.payload) {
300
+ try {
301
+ payload = JSON.parse(opts.payload);
302
+ }
303
+ catch {
304
+ console.error(chalk.red('Error: --payload must be valid JSON'));
305
+ process.exit(1);
306
+ }
307
+ }
308
+ try {
309
+ const token = resolveToken(opts.token) ?? process.env.LOOM_TOKEN;
310
+ if (!token) {
311
+ console.error(chalk.red('Error: Auth token required (--token or LOOM_TOKEN env)'));
312
+ process.exit(1);
313
+ }
314
+ await fetchApi('/api/v1/events/test', {
315
+ method: 'POST',
316
+ body: { pattern, payload },
317
+ token,
318
+ server: opts.server,
319
+ });
320
+ console.log(chalk.green(`Test event emitted: ${pattern}`));
321
+ if (Object.keys(payload).length > 0) {
322
+ console.log(` Payload: ${JSON.stringify(payload)}`);
323
+ }
324
+ }
325
+ catch (err) {
326
+ handleAuthError(err);
327
+ console.error(chalk.red(`Error: ${err instanceof Error ? err.message : String(err)}`));
328
+ process.exit(1);
329
+ }
330
+ });
331
+ }
332
+ //# sourceMappingURL=event.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event.js","sourceRoot":"","sources":["../../../src/cli/commands/event.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/process.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4CpC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAke3D"}
1
+ {"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/process.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4CpC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAygB3D"}
@@ -45,12 +45,12 @@ export function registerProcessCommand(program) {
45
45
  .requiredOption('--name <name>', 'Process name (^[a-zA-Z][a-zA-Z0-9_-]*$)')
46
46
  .option('--cron <expression>', 'Cron schedule expression')
47
47
  .option('--cron-timezone <tz>', 'Cron timezone (default: system)')
48
- .option('--on-event <pattern>', 'EventBus pattern to trigger on (e.g. "data:create:tasks")')
49
- .option('--event-filter <json>', 'Event payload filter as JSON')
50
- .option('--event-debounce <ms>', 'Debounce window for event triggers (default: 1000)', '1000')
48
+ .option('--subscribe <pattern>', 'EventBus pattern to subscribe (e.g. "data:create:tasks") — creates an event subscription')
49
+ .option('--event-filter <json>', 'Event payload filter as JSON (used with --subscribe)')
50
+ .option('--event-debounce <ms>', 'Debounce window for event triggers in ms (default: 0, no debounce)', '0')
51
51
  .option('--prompt <text>', 'Inline prompt for lightweight process')
52
52
  .option('--process <name>', 'Full process name (expects .loom/processes/{name}/PROCESS.md)')
53
- .option('--source <command>', 'Feeder command (e.g. "bash examples/feeders/dingtalk-mention.sh") — requires --on-event')
53
+ .option('--source <command>', 'Feeder command (e.g. "bash examples/feeders/dingtalk-mention.sh") — requires --subscribe')
54
54
  .option('--description <text>', 'Process description')
55
55
  .option('--owner <username>', 'Owner username (default: from processes config)')
56
56
  .option('--owner-token <jwt>', 'Owner service token (used directly)')
@@ -68,9 +68,9 @@ export function registerProcessCommand(program) {
68
68
  console.error(chalk.red('Error: Cannot specify both --prompt and --process'));
69
69
  process.exit(1);
70
70
  }
71
- // Validate: --source requires --on-event
72
- if (opts.source && !opts.onEvent) {
73
- console.error(chalk.red('Error: --source requires --on-event (feeder must have an event pattern)'));
71
+ // Validate: --source requires --subscribe
72
+ if (opts.source && !opts.subscribe) {
73
+ console.error(chalk.red('Error: --source requires --subscribe (feeder must have an event pattern)'));
74
74
  process.exit(1);
75
75
  }
76
76
  try {
@@ -85,19 +85,6 @@ export function registerProcessCommand(program) {
85
85
  body.cron = opts.cron;
86
86
  if (opts.cronTimezone)
87
87
  body.cronTimezone = opts.cronTimezone;
88
- if (opts.onEvent)
89
- body.onEvent = opts.onEvent;
90
- if (opts.eventFilter) {
91
- try {
92
- body.eventFilter = JSON.parse(opts.eventFilter);
93
- }
94
- catch {
95
- console.error(chalk.red('Error: --event-filter must be valid JSON'));
96
- process.exit(1);
97
- }
98
- }
99
- if (opts.eventDebounce)
100
- body.eventDebounceMs = parseInt(opts.eventDebounce, 10);
101
88
  if (opts.prompt)
102
89
  body.prompt = opts.prompt;
103
90
  if (opts.process)
@@ -119,6 +106,24 @@ export function registerProcessCommand(program) {
119
106
  process.exit(1);
120
107
  }
121
108
  }
109
+ // If --subscribe is provided, create a subscription alongside the process
110
+ if (opts.subscribe) {
111
+ const subscription = {
112
+ pattern: opts.subscribe,
113
+ };
114
+ if (opts.eventFilter) {
115
+ try {
116
+ subscription.filter = JSON.parse(opts.eventFilter);
117
+ }
118
+ catch {
119
+ console.error(chalk.red('Error: --event-filter must be valid JSON'));
120
+ process.exit(1);
121
+ }
122
+ }
123
+ if (opts.eventDebounce)
124
+ subscription.debounceMs = parseInt(opts.eventDebounce, 10);
125
+ body.subscription = subscription;
126
+ }
122
127
  const result = await fetchApi('/api/v1/processes', {
123
128
  method: 'POST',
124
129
  body,
@@ -128,8 +133,8 @@ export function registerProcessCommand(program) {
128
133
  console.log(chalk.green(`Process "${result.data.name}" created successfully`));
129
134
  if (result.data.cron)
130
135
  console.log(` Cron: ${result.data.cron}`);
131
- if (result.data.onEvent)
132
- console.log(` Event: ${result.data.onEvent}`);
136
+ if (opts.subscribe)
137
+ console.log(` Event subscription: ${opts.subscribe}`);
133
138
  if (result.data.source)
134
139
  console.log(` Source: ${result.data.source.command}`);
135
140
  }
@@ -160,8 +165,11 @@ export function registerProcessCommand(program) {
160
165
  const triggers = [];
161
166
  if (proc.cron)
162
167
  triggers.push(`cron: ${proc.cron}`);
163
- if (proc.onEvent)
164
- triggers.push(`event: ${proc.onEvent}`);
168
+ const eventSubs = proc.eventSubscriptions;
169
+ if (eventSubs && eventSubs.length > 0) {
170
+ for (const sub of eventSubs)
171
+ triggers.push(`event: ${sub.pattern}`);
172
+ }
165
173
  const mode = proc.hasProcessFile ? 'full' : 'lightweight';
166
174
  const status = proc.paused ? chalk.yellow('paused') : chalk.green('active');
167
175
  console.log(` ${chalk.bold(proc.name)} (${mode}) ${status}`);
@@ -197,8 +205,19 @@ export function registerProcessCommand(program) {
197
205
  console.log(` Owner: ${proc.owner}`);
198
206
  if (proc.cron)
199
207
  console.log(` Cron: ${proc.cron}${proc.cronTimezone ? ` (${proc.cronTimezone})` : ''}`);
200
- if (proc.onEvent)
201
- console.log(` Event: ${proc.onEvent}${proc.eventDebounceMs ? ` (debounce: ${proc.eventDebounceMs}ms)` : ''}`);
208
+ const eventSubs = proc.eventSubscriptions;
209
+ if (eventSubs && eventSubs.length > 0) {
210
+ for (const sub of eventSubs) {
211
+ const cfg = sub.config;
212
+ const debounce = typeof cfg?.debounceMs === 'number' ? cfg.debounceMs : undefined;
213
+ let line = ` Event: ${sub.pattern}`;
214
+ if (debounce)
215
+ line += ` (debounce: ${debounce}ms)`;
216
+ if (sub.active === false)
217
+ line += ' [inactive]';
218
+ console.log(line);
219
+ }
220
+ }
202
221
  if (proc.source)
203
222
  console.log(` Source: ${proc.source.command}`);
204
223
  if (proc.description)
@@ -298,13 +317,14 @@ export function registerProcessCommand(program) {
298
317
  processCmd.command('update <name>')
299
318
  .option('--cron <expression>', 'Update cron schedule expression')
300
319
  .option('--cron-timezone <tz>', 'Update cron timezone')
301
- .option('--on-event <pattern>', 'Update event trigger pattern')
302
- .option('--event-filter <json>', 'Update event payload filter as JSON')
303
- .option('--event-debounce <ms>', 'Update debounce window for event triggers')
304
320
  .option('--prompt <text>', 'Update inline prompt')
305
321
  .option('--description <text>', 'Update description')
306
- .option('--source <command>', 'Update feeder command — requires --on-event')
322
+ .option('--source <command>', 'Update feeder command')
307
323
  .option('--model <name>', 'Update AI model name (empty string to remove binding)')
324
+ .option('--subscribe-add <pattern>', 'Add an event subscription for this process')
325
+ .option('--subscribe-filter <json>', 'Event payload filter as JSON (used with --subscribe-add)')
326
+ .option('--subscribe-debounce <ms>', 'Debounce window for event triggers in ms (used with --subscribe-add)', '0')
327
+ .option('--subscribe-remove <id>', 'Remove an event subscription by ID')
308
328
  .option('--token <token>', 'Auth token')
309
329
  .option('--server <url>', 'Server URL')
310
330
  .action(async (name, opts) => {
@@ -313,19 +333,6 @@ export function registerProcessCommand(program) {
313
333
  body.cron = opts.cron;
314
334
  if (opts.cronTimezone !== undefined)
315
335
  body.cronTimezone = opts.cronTimezone;
316
- if (opts.onEvent !== undefined)
317
- body.onEvent = opts.onEvent;
318
- if (opts.eventFilter !== undefined) {
319
- try {
320
- body.eventFilter = JSON.parse(opts.eventFilter);
321
- }
322
- catch {
323
- console.error(chalk.red('Error: --event-filter must be valid JSON'));
324
- process.exit(1);
325
- }
326
- }
327
- if (opts.eventDebounce !== undefined)
328
- body.eventDebounceMs = parseInt(opts.eventDebounce, 10);
329
336
  if (opts.prompt !== undefined)
330
337
  body.prompt = opts.prompt;
331
338
  if (opts.description !== undefined)
@@ -334,8 +341,35 @@ export function registerProcessCommand(program) {
334
341
  body.source = { command: opts.source };
335
342
  if (opts.model !== undefined)
336
343
  body.model = opts.model;
344
+ // Handle --subscribe-add
345
+ if (opts.subscribeAdd) {
346
+ const subscription = {
347
+ pattern: opts.subscribeAdd,
348
+ filter: undefined,
349
+ debounceMs: opts.subscribeDebounce ? parseInt(opts.subscribeDebounce, 10) : undefined,
350
+ };
351
+ if (opts.subscribeFilter) {
352
+ try {
353
+ subscription.filter = JSON.parse(opts.subscribeFilter);
354
+ }
355
+ catch {
356
+ console.error(chalk.red('Error: --subscribe-filter must be valid JSON'));
357
+ process.exit(1);
358
+ }
359
+ }
360
+ // Remove undefined entries
361
+ if (!subscription.filter)
362
+ delete subscription.filter;
363
+ if (!subscription.debounceMs)
364
+ delete subscription.debounceMs;
365
+ body.subscriptionAdd = subscription;
366
+ }
367
+ // Handle --subscribe-remove
368
+ if (opts.subscribeRemove) {
369
+ body.subscriptionRemoveId = opts.subscribeRemove;
370
+ }
337
371
  if (Object.keys(body).length === 0) {
338
- console.error(chalk.red('Error: At least one update field is required (--cron, --on-event, --prompt, --description, etc.)'));
372
+ console.error(chalk.red('Error: At least one update field is required (--cron, --prompt, --subscribe-add, etc.)'));
339
373
  process.exit(1);
340
374
  }
341
375
  try {
@@ -347,6 +381,10 @@ export function registerProcessCommand(program) {
347
381
  server: opts.server,
348
382
  });
349
383
  console.log(chalk.green(`Process "${result.data.name}" updated`));
384
+ if (opts.subscribeAdd)
385
+ console.log(` Event subscription added: ${opts.subscribeAdd}`);
386
+ if (opts.subscribeRemove)
387
+ console.log(` Event subscription removed: ${opts.subscribeRemove}`);
350
388
  }
351
389
  catch (err) {
352
390
  handleAuthError(err);