@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 +1 -1
- package/src/profile/client.ts +252 -2
- package/src/server/runtime-registry.ts +35 -0
- package/src/server/server.ts +892 -66
- package/src/server/types.ts +4 -0
- package/src/storage/sqlite.ts +43 -16
- package/src/storage/types.ts +2 -0
package/package.json
CHANGED
package/src/profile/client.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
*
|