@actiondock/core 2.0.1 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@actiondock/core",
3
- "version": "2.0.1",
3
+ "version": "2.0.2",
4
4
  "description": "ActionDock Core Engine - Project loader, runtime execution, SQLite storage, standalone builder, and skill exporter",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -291,12 +291,262 @@ export async function fetchRemoteActionShow(
291
291
 
292
292
  export async function fetchRemoteInfo(
293
293
  serverUrl: string,
294
- token?: string
294
+ token?: string,
295
+ options?: { intent?: string; package?: string; tree?: boolean }
295
296
  ): Promise<any> {
297
+ const params = new URLSearchParams();
298
+ if (options?.intent) params.set("intent", options.intent);
299
+ if (options?.package) params.set("package", options.package);
300
+ if (options?.tree) params.set("tree", "true");
301
+ const qs = params.toString() ? `?${params.toString()}` : "";
296
302
  return fetchRemoteJson(
297
303
  serverUrl,
298
- "/api/v1/info",
304
+ `/api/v1/info${qs}`,
299
305
  token,
300
306
  { errorPrefix: "Failed to fetch remote info" }
301
307
  );
302
308
  }
309
+
310
+ export async function fetchRemoteDoctor(
311
+ serverUrl: string,
312
+ token?: string,
313
+ targetPackage?: string
314
+ ): Promise<any> {
315
+ const query = targetPackage ? `?package=${encodeURIComponent(targetPackage)}` : "";
316
+ return fetchRemoteJson(
317
+ serverUrl,
318
+ `/api/v1/doctor${query}`,
319
+ token,
320
+ { errorPrefix: "Failed to fetch remote doctor report" }
321
+ );
322
+ }
323
+
324
+ export async function fetchRemotePlaybooks(
325
+ serverUrl: string,
326
+ token?: string,
327
+ options?: { intent?: string; package?: string }
328
+ ): Promise<Array<{ id: string; description: string; actions: string[]; packageId: string; filePath: string }>> {
329
+ const params = new URLSearchParams();
330
+ if (options?.intent) params.set("intent", options.intent);
331
+ if (options?.package) params.set("package", options.package);
332
+ const qs = params.toString() ? `?${params.toString()}` : "";
333
+ return fetchRemoteJson(
334
+ serverUrl,
335
+ `/api/v1/playbooks${qs}`,
336
+ token,
337
+ { errorPrefix: "Failed to fetch remote playbooks" }
338
+ );
339
+ }
340
+
341
+ export async function fetchRemotePlaybookShow(
342
+ serverUrl: string,
343
+ playbookId: string,
344
+ token?: string
345
+ ): Promise<any> {
346
+ return fetchRemoteJson(
347
+ serverUrl,
348
+ `/api/v1/playbooks/${encodeURIComponent(playbookId)}`,
349
+ token,
350
+ { errorPrefix: `Failed to fetch remote playbook '${playbookId}'` }
351
+ );
352
+ }
353
+
354
+ export async function fetchRemoteRuns(
355
+ serverUrl: string,
356
+ token?: string,
357
+ options?: { status?: string; actionId?: string; packageId?: string; intent?: string; limit?: number }
358
+ ): Promise<{ ok: boolean; total: number; items: RunRecord[] }> {
359
+ const params = new URLSearchParams();
360
+ if (options?.status) params.set("status", options.status);
361
+ if (options?.actionId) params.set("actionId", options.actionId);
362
+ if (options?.packageId) params.set("packageId", options.packageId);
363
+ if (options?.intent) params.set("intent", options.intent);
364
+ if (options?.limit) params.set("limit", String(options.limit));
365
+ const qs = params.toString() ? `?${params.toString()}` : "";
366
+ return fetchRemoteJson(
367
+ serverUrl,
368
+ `/api/v1/runs${qs}`,
369
+ token,
370
+ { errorPrefix: "Failed to fetch remote runs" }
371
+ );
372
+ }
373
+
374
+ export async function clearRemoteRuns(
375
+ serverUrl: string,
376
+ token?: string,
377
+ options?: { packageId?: string; actionId?: string; status?: string }
378
+ ): Promise<{ ok: boolean; clearedCount: number }> {
379
+ return fetchRemoteJson(
380
+ serverUrl,
381
+ "/api/v1/runs/clear",
382
+ token,
383
+ {
384
+ method: "POST",
385
+ body: options || {},
386
+ errorPrefix: "Failed to clear remote runs",
387
+ }
388
+ );
389
+ }
390
+
391
+ export async function fetchRemoteStateList(
392
+ serverUrl: string,
393
+ token?: string,
394
+ options?: { package?: string; namespace?: string; prefix?: string }
395
+ ): Promise<{ ok: boolean; packageId: string; keys: string[] }> {
396
+ const params = new URLSearchParams();
397
+ if (options?.package) params.set("package", options.package);
398
+ if (options?.namespace !== undefined) params.set("namespace", options.namespace);
399
+ if (options?.prefix) params.set("prefix", options.prefix);
400
+ const qs = params.toString() ? `?${params.toString()}` : "";
401
+ return fetchRemoteJson(
402
+ serverUrl,
403
+ `/api/v1/state${qs}`,
404
+ token,
405
+ { errorPrefix: "Failed to list remote state keys" }
406
+ );
407
+ }
408
+
409
+ export async function getRemoteStateKey(
410
+ serverUrl: string,
411
+ key: string,
412
+ token?: string,
413
+ options?: { package?: string; namespace?: string }
414
+ ): Promise<any> {
415
+ const params = new URLSearchParams();
416
+ if (options?.package) params.set("package", options.package);
417
+ if (options?.namespace !== undefined) params.set("namespace", options.namespace);
418
+ const qs = params.toString() ? `?${params.toString()}` : "";
419
+ return fetchRemoteJson(
420
+ serverUrl,
421
+ `/api/v1/state/${encodeURIComponent(key)}${qs}`,
422
+ token,
423
+ { errorPrefix: `Failed to fetch remote state key '${key}'` }
424
+ );
425
+ }
426
+
427
+ export async function setRemoteStateKey(
428
+ serverUrl: string,
429
+ key: string,
430
+ value: unknown,
431
+ token?: string,
432
+ options?: { package?: string; namespace?: string; ttl?: number }
433
+ ): Promise<any> {
434
+ return fetchRemoteJson(
435
+ serverUrl,
436
+ `/api/v1/state/${encodeURIComponent(key)}`,
437
+ token,
438
+ {
439
+ method: "PUT",
440
+ body: {
441
+ value,
442
+ package: options?.package,
443
+ namespace: options?.namespace,
444
+ ttl: options?.ttl,
445
+ },
446
+ errorPrefix: `Failed to set remote state key '${key}'`,
447
+ }
448
+ );
449
+ }
450
+
451
+ export async function deleteRemoteStateKey(
452
+ serverUrl: string,
453
+ key: string,
454
+ token?: string,
455
+ options?: { package?: string; namespace?: string }
456
+ ): Promise<any> {
457
+ const params = new URLSearchParams();
458
+ if (options?.package) params.set("package", options.package);
459
+ if (options?.namespace !== undefined) params.set("namespace", options.namespace);
460
+ const qs = params.toString() ? `?${params.toString()}` : "";
461
+ return fetchRemoteJson(
462
+ serverUrl,
463
+ `/api/v1/state/${encodeURIComponent(key)}${qs}`,
464
+ token,
465
+ {
466
+ method: "DELETE",
467
+ errorPrefix: `Failed to delete remote state key '${key}'`,
468
+ }
469
+ );
470
+ }
471
+
472
+ export async function clearRemoteState(
473
+ serverUrl: string,
474
+ token?: string,
475
+ options?: { package?: string; namespace?: string; prefix?: string; all?: boolean }
476
+ ): Promise<{ ok: boolean; packageId: string; clearedCount: number }> {
477
+ return fetchRemoteJson(
478
+ serverUrl,
479
+ "/api/v1/state/clear",
480
+ token,
481
+ {
482
+ method: "POST",
483
+ body: options || {},
484
+ errorPrefix: "Failed to clear remote state",
485
+ }
486
+ );
487
+ }
488
+
489
+ export async function fetchRemoteConfig(
490
+ serverUrl: string,
491
+ token?: string,
492
+ packageId?: string
493
+ ): Promise<any> {
494
+ const query = packageId ? `?package=${encodeURIComponent(packageId)}` : "";
495
+ return fetchRemoteJson(
496
+ serverUrl,
497
+ `/api/v1/config${query}`,
498
+ token,
499
+ { errorPrefix: "Failed to fetch remote config" }
500
+ );
501
+ }
502
+
503
+ export async function setRemoteConfig(
504
+ serverUrl: string,
505
+ key: string,
506
+ value: unknown,
507
+ token?: string,
508
+ packageId?: string
509
+ ): Promise<any> {
510
+ return fetchRemoteJson(
511
+ serverUrl,
512
+ "/api/v1/config",
513
+ token,
514
+ {
515
+ method: "PUT",
516
+ body: { key, value, package: packageId },
517
+ errorPrefix: `Failed to set remote config '${key}'`,
518
+ }
519
+ );
520
+ }
521
+
522
+ export async function deleteRemoteConfig(
523
+ serverUrl: string,
524
+ key: string,
525
+ token?: string,
526
+ packageId?: string
527
+ ): Promise<any> {
528
+ const query = packageId ? `?package=${encodeURIComponent(packageId)}` : "";
529
+ return fetchRemoteJson(
530
+ serverUrl,
531
+ `/api/v1/config/${encodeURIComponent(key)}${query}`,
532
+ token,
533
+ {
534
+ method: "DELETE",
535
+ errorPrefix: `Failed to delete remote config '${key}'`,
536
+ }
537
+ );
538
+ }
539
+
540
+ export async function fetchRemoteConfigEnv(
541
+ serverUrl: string,
542
+ token?: string,
543
+ packageId?: string
544
+ ): Promise<any> {
545
+ const query = packageId ? `?package=${encodeURIComponent(packageId)}` : "";
546
+ return fetchRemoteJson(
547
+ serverUrl,
548
+ `/api/v1/config/env${query}`,
549
+ token,
550
+ { errorPrefix: "Failed to fetch remote config env checks" }
551
+ );
552
+ }
@@ -12,12 +12,47 @@ import type { RuntimeStorage } from "../storage/types";
12
12
  */
13
13
  export class ServerRuntimeRegistry {
14
14
  private storages = new Map<string, RuntimeStorage>();
15
+ private listeners = new Map<string, Set<(event: { type: string; data: any }) => void>>();
15
16
  public executionManager: ExecutionManager;
16
17
 
17
18
  constructor() {
18
19
  this.executionManager = new ExecutionManager();
19
20
  }
20
21
 
22
+ /**
23
+ * 订阅指定 runId 的事件(用于 SSE 流式推送)。
24
+ */
25
+ public subscribe(runId: string, listener: (event: { type: string; data: any }) => void): () => void {
26
+ let set = this.listeners.get(runId);
27
+ if (!set) {
28
+ set = new Set();
29
+ this.listeners.set(runId, set);
30
+ }
31
+ set.add(listener);
32
+ return () => {
33
+ set?.delete(listener);
34
+ if (set && set.size === 0) {
35
+ this.listeners.delete(runId);
36
+ }
37
+ };
38
+ }
39
+
40
+ /**
41
+ * 向指定 runId 的订阅者广播事件。
42
+ */
43
+ public emit(runId: string, event: { type: string; data: any }): void {
44
+ const set = this.listeners.get(runId);
45
+ if (set) {
46
+ for (const listener of set) {
47
+ try {
48
+ listener(event);
49
+ } catch {
50
+ // 忽略单个监听器错误
51
+ }
52
+ }
53
+ }
54
+ }
55
+
21
56
  /**
22
57
  * 获取或懒加载指定 Package 和 projectRoot 的缓存 RuntimeStorage 实例。
23
58
  *