@actiondock/core 2.0.11 → 2.2.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.
Files changed (258) hide show
  1. package/README.md +61 -30
  2. package/dist/app/app.d.ts +73 -0
  3. package/dist/app/app.js +700 -0
  4. package/dist/app/index.d.ts +2 -0
  5. package/dist/app/index.js +2 -0
  6. package/dist/app/types.d.ts +283 -0
  7. package/dist/app/types.js +1 -0
  8. package/dist/catalog/action-index.d.ts +9 -0
  9. package/dist/catalog/action-index.js +93 -0
  10. package/dist/catalog/action-resolver.d.ts +20 -0
  11. package/dist/catalog/action-resolver.js +95 -0
  12. package/dist/catalog/index.d.ts +5 -0
  13. package/dist/catalog/index.js +5 -0
  14. package/dist/catalog/location-registry.d.ts +15 -0
  15. package/dist/catalog/location-registry.js +138 -0
  16. package/dist/catalog/package-catalog.d.ts +7 -0
  17. package/dist/catalog/package-catalog.js +76 -0
  18. package/dist/catalog/types.d.ts +68 -0
  19. package/dist/catalog/types.js +1 -0
  20. package/dist/doctor/doctor.d.ts +7 -0
  21. package/dist/doctor/doctor.js +613 -0
  22. package/dist/doctor/index.d.ts +2 -0
  23. package/dist/doctor/index.js +2 -0
  24. package/dist/doctor/types.d.ts +23 -0
  25. package/dist/doctor/types.js +1 -0
  26. package/dist/errors.d.ts +122 -0
  27. package/dist/errors.js +123 -0
  28. package/dist/execution/index.d.ts +2 -0
  29. package/dist/execution/index.js +2 -0
  30. package/dist/execution/service.d.ts +79 -0
  31. package/dist/execution/service.js +633 -0
  32. package/dist/execution/types.d.ts +131 -0
  33. package/dist/execution/types.js +1 -0
  34. package/dist/export/index.d.ts +1 -0
  35. package/dist/export/index.js +1 -0
  36. package/dist/export/templates.d.ts +71 -0
  37. package/dist/export/templates.js +621 -0
  38. package/dist/filter/index.d.ts +1 -0
  39. package/dist/filter/index.js +1 -0
  40. package/dist/filter/intent.d.ts +33 -0
  41. package/dist/filter/intent.js +123 -0
  42. package/dist/host/host.d.ts +55 -0
  43. package/dist/host/host.js +740 -0
  44. package/dist/host/index.d.ts +2 -0
  45. package/dist/host/index.js +2 -0
  46. package/dist/host/types.d.ts +81 -0
  47. package/dist/host/types.js +1 -0
  48. package/dist/index.d.ts +21 -0
  49. package/dist/index.js +20 -0
  50. package/dist/ipc/diagnostic.d.ts +65 -0
  51. package/dist/ipc/diagnostic.js +129 -0
  52. package/dist/ipc/host.d.ts +7 -0
  53. package/dist/ipc/host.js +93 -0
  54. package/dist/ipc/index.d.ts +4 -0
  55. package/dist/ipc/index.js +4 -0
  56. package/dist/ipc/target.d.ts +56 -0
  57. package/dist/ipc/target.js +297 -0
  58. package/dist/ipc/types.d.ts +42 -0
  59. package/dist/ipc/types.js +1 -0
  60. package/dist/platform/default.d.ts +32 -0
  61. package/dist/platform/default.js +40 -0
  62. package/dist/platform/index.d.ts +3 -0
  63. package/dist/platform/index.js +3 -0
  64. package/dist/platform/node-fs.d.ts +37 -0
  65. package/dist/platform/node-fs.js +81 -0
  66. package/dist/platform/types.d.ts +104 -0
  67. package/dist/platform/types.js +1 -0
  68. package/dist/profile/client.d.ts +162 -0
  69. package/dist/profile/client.js +467 -0
  70. package/dist/profile/index.d.ts +3 -0
  71. package/dist/profile/index.js +3 -0
  72. package/dist/profile/manager.d.ts +47 -0
  73. package/dist/profile/manager.js +294 -0
  74. package/dist/profile/types.d.ts +61 -0
  75. package/dist/profile/types.js +1 -0
  76. package/dist/project/closure.d.ts +25 -0
  77. package/dist/project/closure.js +68 -0
  78. package/dist/project/digest.d.ts +29 -0
  79. package/dist/project/digest.js +324 -0
  80. package/dist/project/index.d.ts +10 -0
  81. package/dist/project/index.js +10 -0
  82. package/dist/project/init.d.ts +26 -0
  83. package/dist/project/init.js +175 -0
  84. package/dist/project/loader.d.ts +99 -0
  85. package/dist/project/loader.js +484 -0
  86. package/dist/project/lockfile.d.ts +55 -0
  87. package/dist/project/lockfile.js +175 -0
  88. package/dist/project/manifest.d.ts +22 -0
  89. package/dist/project/manifest.js +220 -0
  90. package/dist/project/resolver.d.ts +116 -0
  91. package/dist/project/resolver.js +376 -0
  92. package/dist/project/transactions.d.ts +103 -0
  93. package/dist/project/transactions.js +1203 -0
  94. package/dist/project/types-generator.d.ts +33 -0
  95. package/dist/project/types-generator.js +168 -0
  96. package/dist/project/types.d.ts +107 -0
  97. package/dist/project/types.js +1 -0
  98. package/dist/registry/index.d.ts +5 -0
  99. package/dist/registry/index.js +5 -0
  100. package/dist/registry/lock.d.ts +27 -0
  101. package/dist/registry/lock.js +93 -0
  102. package/dist/registry/registry.d.ts +45 -0
  103. package/dist/registry/registry.js +611 -0
  104. package/dist/registry/resolve.d.ts +62 -0
  105. package/dist/registry/resolve.js +195 -0
  106. package/dist/registry/scan.d.ts +38 -0
  107. package/dist/registry/scan.js +135 -0
  108. package/dist/registry/types.d.ts +117 -0
  109. package/dist/registry/types.js +1 -0
  110. package/dist/runtime/action-collection.d.ts +27 -0
  111. package/dist/runtime/action-collection.js +57 -0
  112. package/dist/runtime/clock.d.ts +19 -0
  113. package/dist/runtime/clock.js +17 -0
  114. package/dist/runtime/context.d.ts +86 -0
  115. package/dist/runtime/context.js +242 -0
  116. package/dist/runtime/env.d.ts +56 -0
  117. package/dist/runtime/env.js +159 -0
  118. package/dist/runtime/events.d.ts +93 -0
  119. package/dist/runtime/events.js +604 -0
  120. package/dist/runtime/execution-manager.d.ts +48 -0
  121. package/dist/runtime/execution-manager.js +66 -0
  122. package/dist/runtime/index.d.ts +10 -0
  123. package/dist/runtime/index.js +10 -0
  124. package/dist/runtime/module-loader.d.ts +34 -0
  125. package/dist/runtime/module-loader.js +16 -0
  126. package/dist/runtime/process.d.ts +9 -0
  127. package/dist/runtime/process.js +146 -0
  128. package/dist/runtime/runner.d.ts +293 -0
  129. package/dist/runtime/runner.js +984 -0
  130. package/dist/runtime/standalone.d.ts +89 -0
  131. package/dist/runtime/standalone.js +536 -0
  132. package/dist/schema/validator.d.ts +28 -0
  133. package/dist/schema/validator.js +116 -0
  134. package/dist/server/body.d.ts +40 -0
  135. package/dist/server/body.js +93 -0
  136. package/dist/server/index.d.ts +5 -0
  137. package/dist/server/index.js +5 -0
  138. package/dist/server/routes/actions.d.ts +5 -0
  139. package/dist/server/routes/actions.js +298 -0
  140. package/dist/server/routes/common.d.ts +47 -0
  141. package/dist/server/routes/common.js +104 -0
  142. package/dist/server/routes/config.d.ts +6 -0
  143. package/dist/server/routes/config.js +173 -0
  144. package/dist/server/routes/doctor.d.ts +5 -0
  145. package/dist/server/routes/doctor.js +63 -0
  146. package/dist/server/routes/health.d.ts +5 -0
  147. package/dist/server/routes/health.js +35 -0
  148. package/dist/server/routes/index.d.ts +9 -0
  149. package/dist/server/routes/index.js +9 -0
  150. package/dist/server/routes/info.d.ts +7 -0
  151. package/dist/server/routes/info.js +158 -0
  152. package/dist/server/routes/playbooks.d.ts +5 -0
  153. package/dist/server/routes/playbooks.js +134 -0
  154. package/dist/server/routes/runs.d.ts +5 -0
  155. package/dist/server/routes/runs.js +343 -0
  156. package/dist/server/routes/state.d.ts +6 -0
  157. package/dist/server/routes/state.js +169 -0
  158. package/dist/server/security.d.ts +44 -0
  159. package/dist/server/security.js +101 -0
  160. package/dist/server/server.d.ts +15 -0
  161. package/dist/server/server.js +355 -0
  162. package/dist/server/types.d.ts +78 -0
  163. package/dist/server/types.js +1 -0
  164. package/dist/storage/data-dir-lock.d.ts +119 -0
  165. package/dist/storage/data-dir-lock.js +1016 -0
  166. package/dist/storage/driver.d.ts +9 -0
  167. package/dist/storage/driver.js +59 -0
  168. package/dist/storage/index.d.ts +64 -0
  169. package/dist/storage/index.js +98 -0
  170. package/dist/storage/lazy.d.ts +8 -0
  171. package/dist/storage/lazy.js +44 -0
  172. package/dist/storage/mask.d.ts +26 -0
  173. package/dist/storage/mask.js +48 -0
  174. package/dist/storage/params.d.ts +13 -0
  175. package/dist/storage/params.js +32 -0
  176. package/dist/storage/sqlite.d.ts +79 -0
  177. package/dist/storage/sqlite.js +689 -0
  178. package/dist/storage/types.d.ts +172 -0
  179. package/dist/storage/types.js +14 -0
  180. package/dist/target/index.d.ts +4 -0
  181. package/dist/target/index.js +4 -0
  182. package/dist/target/local.d.ts +52 -0
  183. package/dist/target/local.js +343 -0
  184. package/dist/target/remote.d.ts +76 -0
  185. package/dist/target/remote.js +839 -0
  186. package/dist/target/target.d.ts +6 -0
  187. package/dist/target/target.js +35 -0
  188. package/dist/target/types.d.ts +246 -0
  189. package/dist/target/types.js +34 -0
  190. package/dist/utils/index.d.ts +49 -0
  191. package/dist/utils/index.js +180 -0
  192. package/dist/version.d.ts +4 -0
  193. package/dist/version.js +4 -0
  194. package/package.json +13 -13
  195. package/src/build/index.ts +0 -1
  196. package/src/build/templates.ts +0 -59
  197. package/src/catalog/action-index.ts +0 -92
  198. package/src/catalog/action-resolver.ts +0 -120
  199. package/src/catalog/index.ts +0 -5
  200. package/src/catalog/location-registry.ts +0 -134
  201. package/src/catalog/package-catalog.ts +0 -87
  202. package/src/catalog/types.ts +0 -75
  203. package/src/doctor/doctor.ts +0 -419
  204. package/src/doctor/index.ts +0 -2
  205. package/src/doctor/types.ts +0 -25
  206. package/src/execution/index.ts +0 -2
  207. package/src/execution/service.ts +0 -322
  208. package/src/execution/types.ts +0 -73
  209. package/src/export/index.ts +0 -1
  210. package/src/export/templates.ts +0 -590
  211. package/src/filter/index.ts +0 -1
  212. package/src/filter/intent.ts +0 -154
  213. package/src/index.ts +0 -16
  214. package/src/profile/client.ts +0 -552
  215. package/src/profile/index.ts +0 -3
  216. package/src/profile/manager.ts +0 -341
  217. package/src/profile/types.ts +0 -71
  218. package/src/project/index.ts +0 -4
  219. package/src/project/init.ts +0 -242
  220. package/src/project/loader.ts +0 -479
  221. package/src/project/manifest.ts +0 -299
  222. package/src/project/types.ts +0 -141
  223. package/src/registry/index.ts +0 -2
  224. package/src/registry/registry.ts +0 -940
  225. package/src/registry/types.ts +0 -127
  226. package/src/runtime/clock.ts +0 -41
  227. package/src/runtime/context.ts +0 -259
  228. package/src/runtime/env.ts +0 -172
  229. package/src/runtime/events.ts +0 -142
  230. package/src/runtime/execution-manager.ts +0 -74
  231. package/src/runtime/index.ts +0 -10
  232. package/src/runtime/module-loader.ts +0 -67
  233. package/src/runtime/process.ts +0 -245
  234. package/src/runtime/runner.ts +0 -527
  235. package/src/runtime/standalone.ts +0 -429
  236. package/src/schema/validator.ts +0 -61
  237. package/src/server/body.ts +0 -112
  238. package/src/server/index.ts +0 -7
  239. package/src/server/routes/actions.ts +0 -262
  240. package/src/server/routes/common.ts +0 -126
  241. package/src/server/routes/config.ts +0 -147
  242. package/src/server/routes/doctor.ts +0 -29
  243. package/src/server/routes/health.ts +0 -40
  244. package/src/server/routes/index.ts +0 -9
  245. package/src/server/routes/info.ts +0 -221
  246. package/src/server/routes/playbooks.ts +0 -109
  247. package/src/server/routes/runs.ts +0 -301
  248. package/src/server/routes/state.ts +0 -133
  249. package/src/server/runtime-registry.ts +0 -115
  250. package/src/server/security.ts +0 -115
  251. package/src/server/server.ts +0 -251
  252. package/src/server/types.ts +0 -57
  253. package/src/storage/driver.ts +0 -126
  254. package/src/storage/index.ts +0 -81
  255. package/src/storage/mask.ts +0 -34
  256. package/src/storage/sqlite.ts +0 -714
  257. package/src/storage/types.ts +0 -139
  258. package/src/utils/index.ts +0 -62
@@ -0,0 +1,162 @@
1
+ import type { ExecutionResult, RunRecord } from "@actiondock/sdk";
2
+ import type { RemoteHealthResult } from "./types.js";
3
+ /**
4
+ * 校验在携带认证 Token 时传输层协议是否安全。
5
+ * 若请求携带认证 Token 且目标为非本地回环的明文 http://,默认报错拒绝。
6
+ * 可通过 allowInsecureHttp 选项、ACTIONDOCK_ALLOW_INSECURE_HTTP 环境变量或 --allow-insecure-http 命令行参数豁免。
7
+ */
8
+ export declare function assertSecureTransport(serverUrl: string, token?: string, allowInsecureHttp?: boolean): void;
9
+ /**
10
+ * 调用远端 ActionDock 服务端执行 Action 时的选项参数。
11
+ */
12
+ export interface RemoteExecuteOptions {
13
+ /** 动态配置覆盖 */
14
+ configOverrides?: Record<string, unknown>;
15
+ /** 鉴权 Bearer Token */
16
+ token?: string;
17
+ /** 超时毫秒数 */
18
+ timeoutMs?: number;
19
+ /** 中断信号 */
20
+ signal?: AbortSignal;
21
+ /** 幂等请求去重标识 */
22
+ requestId?: string;
23
+ /** 是否异步触发(202 Accepted 立即返回 runId) */
24
+ async?: boolean;
25
+ /** 是否允许通过非回环明文 HTTP 发送认证 Token */
26
+ allowInsecureHttp?: boolean;
27
+ }
28
+ /**
29
+ * 远端 Action 执行结果信封对象。
30
+ */
31
+ export type RemoteExecutionResult<T = unknown> = ExecutionResult<T> & {
32
+ status?: string;
33
+ };
34
+ /**
35
+ * 探测指定远端 ActionDock 服务的健康状态与网络延迟。
36
+ *
37
+ * @param serverUrl 目标服务端地址
38
+ * @param token 鉴权 Token(可选)
39
+ * @param timeoutMs 探测超时时间(默认 5000ms)
40
+ */
41
+ export declare function checkRemoteHealth(serverUrl: string, token?: string, timeoutMs?: number, options?: {
42
+ allowInsecureHttp?: boolean;
43
+ }): Promise<RemoteHealthResult>;
44
+ export declare function executeRemoteAction<T = unknown>(serverUrl: string, actionId: string, input?: unknown, configOverridesOrOptions?: Record<string, unknown> | RemoteExecuteOptions, tokenArg?: string): Promise<RemoteExecutionResult<T>>;
45
+ export declare function fetchRemoteRun(serverUrl: string, runId: string, token?: string, options?: {
46
+ allowInsecureHttp?: boolean;
47
+ }): Promise<RunRecord>;
48
+ export declare function cancelRemoteRun(serverUrl: string, runId: string, token?: string, reason?: string, options?: {
49
+ allowInsecureHttp?: boolean;
50
+ }): Promise<{
51
+ ok: boolean;
52
+ runId: string;
53
+ status: string;
54
+ }>;
55
+ export declare function fetchRemoteActions(serverUrl: string, token?: string, intent?: string, options?: {
56
+ allowInsecureHttp?: boolean;
57
+ }): Promise<Array<{
58
+ id: string;
59
+ description: string;
60
+ packageId?: string;
61
+ }>>;
62
+ export declare function fetchRemoteActionShow(serverUrl: string, actionId: string, token?: string, options?: {
63
+ allowInsecureHttp?: boolean;
64
+ }): Promise<any>;
65
+ export declare function fetchRemoteInfo(serverUrl: string, token?: string, options?: {
66
+ intent?: string;
67
+ package?: string;
68
+ tree?: boolean;
69
+ allowInsecureHttp?: boolean;
70
+ }): Promise<any>;
71
+ export declare function fetchRemoteDoctor(serverUrl: string, token?: string, targetPackage?: string, options?: {
72
+ allowInsecureHttp?: boolean;
73
+ }): Promise<any>;
74
+ export declare function fetchRemotePlaybooks(serverUrl: string, token?: string, options?: {
75
+ intent?: string;
76
+ package?: string;
77
+ allowInsecureHttp?: boolean;
78
+ }): Promise<Array<{
79
+ id: string;
80
+ description: string;
81
+ actions: string[];
82
+ packageId: string;
83
+ filePath: string;
84
+ }>>;
85
+ export declare function fetchRemotePlaybookShow(serverUrl: string, playbookId: string, token?: string, options?: {
86
+ allowInsecureHttp?: boolean;
87
+ }): Promise<any>;
88
+ export declare function fetchRemoteRuns(serverUrl: string, token?: string, options?: {
89
+ status?: string;
90
+ actionId?: string;
91
+ packageId?: string;
92
+ intent?: string;
93
+ limit?: number;
94
+ allowInsecureHttp?: boolean;
95
+ }): Promise<{
96
+ ok: boolean;
97
+ total: number;
98
+ items: RunRecord[];
99
+ }>;
100
+ export declare function clearRemoteRuns(serverUrl: string, token?: string, options?: {
101
+ packageId?: string;
102
+ actionId?: string;
103
+ status?: string;
104
+ allowInsecureHttp?: boolean;
105
+ }): Promise<{
106
+ ok: boolean;
107
+ clearedCount: number;
108
+ }>;
109
+ export declare function fetchRemoteStateList(serverUrl: string, token?: string, options?: {
110
+ package?: string;
111
+ action?: string;
112
+ namespace?: string;
113
+ prefix?: string;
114
+ allowInsecureHttp?: boolean;
115
+ }): Promise<{
116
+ ok: boolean;
117
+ packageId: string;
118
+ keys: string[];
119
+ }>;
120
+ export declare function getRemoteStateKey(serverUrl: string, key: string, token?: string, options?: {
121
+ package?: string;
122
+ action?: string;
123
+ namespace?: string;
124
+ allowInsecureHttp?: boolean;
125
+ }): Promise<any>;
126
+ export declare function setRemoteStateKey(serverUrl: string, key: string, value: unknown, token?: string, options?: {
127
+ package?: string;
128
+ action?: string;
129
+ namespace?: string;
130
+ ttl?: number;
131
+ allowInsecureHttp?: boolean;
132
+ }): Promise<any>;
133
+ export declare function deleteRemoteStateKey(serverUrl: string, key: string, token?: string, options?: {
134
+ package?: string;
135
+ action?: string;
136
+ namespace?: string;
137
+ allowInsecureHttp?: boolean;
138
+ }): Promise<any>;
139
+ export declare function clearRemoteState(serverUrl: string, token?: string, options?: {
140
+ package?: string;
141
+ action?: string;
142
+ namespace?: string;
143
+ prefix?: string;
144
+ all?: boolean;
145
+ allowInsecureHttp?: boolean;
146
+ }): Promise<{
147
+ ok: boolean;
148
+ packageId: string;
149
+ clearedCount: number;
150
+ }>;
151
+ export declare function fetchRemoteConfig(serverUrl: string, token?: string, packageId?: string, options?: {
152
+ allowInsecureHttp?: boolean;
153
+ }): Promise<any>;
154
+ export declare function setRemoteConfig(serverUrl: string, key: string, value: unknown, token?: string, packageId?: string, options?: {
155
+ allowInsecureHttp?: boolean;
156
+ }): Promise<any>;
157
+ export declare function deleteRemoteConfig(serverUrl: string, key: string, token?: string, packageId?: string, options?: {
158
+ allowInsecureHttp?: boolean;
159
+ }): Promise<any>;
160
+ export declare function fetchRemoteConfigEnv(serverUrl: string, token?: string, packageId?: string, options?: {
161
+ allowInsecureHttp?: boolean;
162
+ }): Promise<any>;
@@ -0,0 +1,467 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { normalizeServerUrl } from "./manager.js";
3
+ import { ACTION_CANCELLED, NETWORK_ERROR } from "../errors.js";
4
+ import { isLoopbackHost } from "../server/security.js";
5
+ /**
6
+ * 校验在携带认证 Token 时传输层协议是否安全。
7
+ * 若请求携带认证 Token 且目标为非本地回环的明文 http://,默认报错拒绝。
8
+ * 可通过 allowInsecureHttp 选项、ACTIONDOCK_ALLOW_INSECURE_HTTP 环境变量或 --allow-insecure-http 命令行参数豁免。
9
+ */
10
+ export function assertSecureTransport(serverUrl, token, allowInsecureHttp) {
11
+ if (!token || !token.trim()) {
12
+ return;
13
+ }
14
+ const allow = allowInsecureHttp === true ||
15
+ (typeof process !== "undefined" &&
16
+ (process.env?.ACTIONDOCK_ALLOW_INSECURE_HTTP === "true" ||
17
+ process.env?.ACTIONDOCK_ALLOW_INSECURE_HTTP === "1" ||
18
+ process.argv?.includes("--allow-insecure-http")));
19
+ if (allow) {
20
+ return;
21
+ }
22
+ const base = normalizeServerUrl(serverUrl);
23
+ if (base.startsWith("http://")) {
24
+ try {
25
+ const parsed = new URL(base);
26
+ if (!isLoopbackHost(parsed.hostname)) {
27
+ const err = new Error(`Insecure HTTP connection with authentication token to non-loopback host '${parsed.hostname}' is prohibited. Use HTTPS or pass --allow-insecure-http to override.`);
28
+ err.code = "INSECURE_TRANSPORT";
29
+ throw err;
30
+ }
31
+ }
32
+ catch (e) {
33
+ if (e.code === "INSECURE_TRANSPORT") {
34
+ throw e;
35
+ }
36
+ }
37
+ }
38
+ }
39
+ function buildHeaders(token) {
40
+ const headers = {
41
+ Accept: "application/json",
42
+ };
43
+ if (token && token.trim()) {
44
+ headers.Authorization = `Bearer ${token.trim()}`;
45
+ }
46
+ return headers;
47
+ }
48
+ /**
49
+ * 探测指定远端 ActionDock 服务的健康状态与网络延迟。
50
+ *
51
+ * @param serverUrl 目标服务端地址
52
+ * @param token 鉴权 Token(可选)
53
+ * @param timeoutMs 探测超时时间(默认 5000ms)
54
+ */
55
+ export async function checkRemoteHealth(serverUrl, token, timeoutMs = 5000, options) {
56
+ const startTime = Date.now();
57
+ let timer;
58
+ try {
59
+ assertSecureTransport(serverUrl, token, options?.allowInsecureHttp);
60
+ const base = normalizeServerUrl(serverUrl);
61
+ const v2Url = `${base}/api/v2/health`;
62
+ const controller = new AbortController();
63
+ timer = setTimeout(() => controller.abort(), timeoutMs);
64
+ let res = await fetch(v2Url, {
65
+ method: "GET",
66
+ headers: buildHeaders(token),
67
+ signal: controller.signal,
68
+ });
69
+ if (res.status === 404) {
70
+ try {
71
+ const v1Res = await fetch(`${base}/api/v1/health`, {
72
+ method: "GET",
73
+ headers: buildHeaders(token),
74
+ signal: controller.signal,
75
+ });
76
+ if (v1Res.ok || v1Res.status !== 404) {
77
+ res = v1Res;
78
+ }
79
+ }
80
+ catch { }
81
+ }
82
+ const latencyMs = Date.now() - startTime;
83
+ if (!res.ok) {
84
+ const text = await res.text().catch(() => "");
85
+ return {
86
+ ok: false,
87
+ latencyMs,
88
+ error: `Server responded with status ${res.status}: ${text || res.statusText}`,
89
+ };
90
+ }
91
+ const data = (await res.json().catch(() => ({})));
92
+ return {
93
+ ok: true,
94
+ status: data.status || "healthy",
95
+ version: data.version,
96
+ uptime: data.uptime,
97
+ latencyMs,
98
+ };
99
+ }
100
+ catch (err) {
101
+ const latencyMs = Date.now() - startTime;
102
+ return {
103
+ ok: false,
104
+ latencyMs,
105
+ error: err.name === "AbortError" ? "Connection timed out" : err.message,
106
+ };
107
+ }
108
+ finally {
109
+ if (timer !== undefined) {
110
+ clearTimeout(timer);
111
+ }
112
+ }
113
+ }
114
+ export async function executeRemoteAction(serverUrl, actionId, input = {}, configOverridesOrOptions, tokenArg) {
115
+ // Parse options / backwards compatibility
116
+ let configOverrides;
117
+ let token = tokenArg;
118
+ let timeoutMs;
119
+ let signal;
120
+ let isAsync = false;
121
+ let requestId;
122
+ let allowInsecureHttp;
123
+ if (configOverridesOrOptions && typeof configOverridesOrOptions === "object") {
124
+ if ("token" in configOverridesOrOptions ||
125
+ "timeoutMs" in configOverridesOrOptions ||
126
+ "signal" in configOverridesOrOptions ||
127
+ "async" in configOverridesOrOptions ||
128
+ "requestId" in configOverridesOrOptions ||
129
+ "configOverrides" in configOverridesOrOptions ||
130
+ "allowInsecureHttp" in configOverridesOrOptions) {
131
+ const opts = configOverridesOrOptions;
132
+ configOverrides = opts.configOverrides;
133
+ token = opts.token ?? tokenArg;
134
+ timeoutMs = opts.timeoutMs;
135
+ signal = opts.signal;
136
+ isAsync = Boolean(opts.async);
137
+ requestId = opts.requestId;
138
+ allowInsecureHttp = opts.allowInsecureHttp;
139
+ }
140
+ else {
141
+ configOverrides = configOverridesOrOptions;
142
+ }
143
+ }
144
+ assertSecureTransport(serverUrl, token, allowInsecureHttp);
145
+ const base = normalizeServerUrl(serverUrl);
146
+ const v2Url = `${base}/api/v2/actions/${encodeURIComponent(actionId)}/run`;
147
+ const executionPayload = {};
148
+ if (isAsync) {
149
+ executionPayload.mode = "async";
150
+ }
151
+ if (typeof timeoutMs === "number" && timeoutMs > 0) {
152
+ executionPayload.timeoutMs = timeoutMs;
153
+ }
154
+ if (requestId) {
155
+ executionPayload.requestId = requestId;
156
+ }
157
+ try {
158
+ const headers = {
159
+ ...buildHeaders(token),
160
+ "Content-Type": "application/json",
161
+ };
162
+ if (requestId) {
163
+ headers["Idempotency-Key"] = requestId;
164
+ headers["x-request-id"] = requestId;
165
+ }
166
+ const reqBody = JSON.stringify({
167
+ input,
168
+ config: configOverrides,
169
+ execution: Object.keys(executionPayload).length > 0 ? executionPayload : undefined,
170
+ });
171
+ let res = await fetch(v2Url, {
172
+ method: "POST",
173
+ headers,
174
+ body: reqBody,
175
+ signal,
176
+ });
177
+ if (res.status === 404) {
178
+ try {
179
+ const v1Res = await fetch(`${base}/api/v1/actions/${encodeURIComponent(actionId)}/run`, {
180
+ method: "POST",
181
+ headers,
182
+ body: reqBody,
183
+ signal,
184
+ });
185
+ if (v1Res.ok || v1Res.status !== 404) {
186
+ res = v1Res;
187
+ }
188
+ }
189
+ catch { }
190
+ }
191
+ const data = (await res.json().catch(() => null));
192
+ if (data && typeof data === "object" && typeof data.ok === "boolean") {
193
+ return data;
194
+ }
195
+ if (!res.ok) {
196
+ return {
197
+ ok: false,
198
+ runId: randomUUID(),
199
+ error: {
200
+ code: res.status === 401 ? "UNAUTHORIZED" : "REMOTE_EXECUTION_FAILED",
201
+ message: `Remote server HTTP ${res.status}: ${res.statusText}`,
202
+ details: data,
203
+ },
204
+ };
205
+ }
206
+ return {
207
+ ok: true,
208
+ runId: randomUUID(),
209
+ data,
210
+ };
211
+ }
212
+ catch (err) {
213
+ if (err.name === "AbortError" || signal?.aborted) {
214
+ return {
215
+ ok: false,
216
+ runId: randomUUID(),
217
+ error: {
218
+ code: ACTION_CANCELLED,
219
+ message: "Action execution was cancelled",
220
+ },
221
+ };
222
+ }
223
+ return {
224
+ ok: false,
225
+ runId: randomUUID(),
226
+ error: {
227
+ code: NETWORK_ERROR,
228
+ message: `Failed to connect to remote ActionDock server at ${serverUrl}: ${err.message}`,
229
+ },
230
+ };
231
+ }
232
+ }
233
+ async function fetchRemoteJson(serverUrl, path, token, options = {}) {
234
+ assertSecureTransport(serverUrl, token, options.allowInsecureHttp);
235
+ const base = normalizeServerUrl(serverUrl);
236
+ const normalizedPath = path.startsWith("/") ? path : `/${path}`;
237
+ const url = `${base}${normalizedPath}`;
238
+ const method = options.method || "GET";
239
+ const headers = {
240
+ ...buildHeaders(token),
241
+ };
242
+ if (options.body !== undefined) {
243
+ headers["Content-Type"] = "application/json";
244
+ }
245
+ let res = await fetch(url, {
246
+ method,
247
+ headers,
248
+ body: options.body !== undefined ? JSON.stringify(options.body) : undefined,
249
+ });
250
+ if (res.status === 404 && normalizedPath.startsWith("/api/v2/")) {
251
+ const v1Path = normalizedPath.replace("/api/v2/", "/api/v1/");
252
+ try {
253
+ const v1Res = await fetch(`${base}${v1Path}`, {
254
+ method,
255
+ headers,
256
+ body: options.body !== undefined ? JSON.stringify(options.body) : undefined,
257
+ });
258
+ if (v1Res.ok || v1Res.status !== 404) {
259
+ res = v1Res;
260
+ }
261
+ }
262
+ catch { }
263
+ }
264
+ const data = (await res.json().catch(() => ({})));
265
+ if (!res.ok || (options.method === "POST" && data && data.ok === false)) {
266
+ const errorPrefix = options.errorPrefix || "Remote request failed";
267
+ const msg = data?.error?.message || `${errorPrefix} (${res.status}): ${res.statusText}`;
268
+ const err = new Error(msg);
269
+ if (data?.error?.code) {
270
+ err.code = data.error.code;
271
+ }
272
+ err.status = res.status;
273
+ err.errorData = data?.error;
274
+ err.details = data?.error?.details ?? data?.error;
275
+ throw err;
276
+ }
277
+ return data;
278
+ }
279
+ export async function fetchRemoteRun(serverUrl, runId, token, options) {
280
+ return fetchRemoteJson(serverUrl, `/api/v2/runs/${encodeURIComponent(runId)}`, token, {
281
+ errorPrefix: `Failed to fetch remote run '${runId}'`,
282
+ allowInsecureHttp: options?.allowInsecureHttp,
283
+ });
284
+ }
285
+ export async function cancelRemoteRun(serverUrl, runId, token, reason, options) {
286
+ return fetchRemoteJson(serverUrl, `/api/v2/runs/${encodeURIComponent(runId)}/cancel`, token, {
287
+ method: "POST",
288
+ body: { reason },
289
+ errorPrefix: `Failed to cancel remote run '${runId}'`,
290
+ allowInsecureHttp: options?.allowInsecureHttp,
291
+ });
292
+ }
293
+ export async function fetchRemoteActions(serverUrl, token, intent, options) {
294
+ const query = intent ? `?intent=${encodeURIComponent(intent)}` : "";
295
+ return fetchRemoteJson(serverUrl, `/api/v2/actions${query}`, token, {
296
+ errorPrefix: "Failed to fetch remote actions",
297
+ allowInsecureHttp: options?.allowInsecureHttp,
298
+ });
299
+ }
300
+ export async function fetchRemoteActionShow(serverUrl, actionId, token, options) {
301
+ return fetchRemoteJson(serverUrl, `/api/v2/actions/${encodeURIComponent(actionId)}`, token, {
302
+ errorPrefix: `Failed to fetch remote action '${actionId}'`,
303
+ allowInsecureHttp: options?.allowInsecureHttp,
304
+ });
305
+ }
306
+ export async function fetchRemoteInfo(serverUrl, token, options) {
307
+ const params = new URLSearchParams();
308
+ if (options?.intent)
309
+ params.set("intent", options.intent);
310
+ if (options?.package)
311
+ params.set("package", options.package);
312
+ if (options?.tree)
313
+ params.set("tree", "true");
314
+ const qs = params.toString() ? `?${params.toString()}` : "";
315
+ return fetchRemoteJson(serverUrl, `/api/v2/info${qs}`, token, {
316
+ errorPrefix: "Failed to fetch remote info",
317
+ allowInsecureHttp: options?.allowInsecureHttp,
318
+ });
319
+ }
320
+ export async function fetchRemoteDoctor(serverUrl, token, targetPackage, options) {
321
+ const query = targetPackage ? `?package=${encodeURIComponent(targetPackage)}` : "";
322
+ return fetchRemoteJson(serverUrl, `/api/v2/doctor${query}`, token, {
323
+ errorPrefix: "Failed to fetch remote doctor report",
324
+ allowInsecureHttp: options?.allowInsecureHttp,
325
+ });
326
+ }
327
+ export async function fetchRemotePlaybooks(serverUrl, token, options) {
328
+ const params = new URLSearchParams();
329
+ if (options?.intent)
330
+ params.set("intent", options.intent);
331
+ if (options?.package)
332
+ params.set("package", options.package);
333
+ const qs = params.toString() ? `?${params.toString()}` : "";
334
+ return fetchRemoteJson(serverUrl, `/api/v2/playbooks${qs}`, token, {
335
+ errorPrefix: "Failed to fetch remote playbooks",
336
+ allowInsecureHttp: options?.allowInsecureHttp,
337
+ });
338
+ }
339
+ export async function fetchRemotePlaybookShow(serverUrl, playbookId, token, options) {
340
+ return fetchRemoteJson(serverUrl, `/api/v2/playbooks/${encodeURIComponent(playbookId)}`, token, {
341
+ errorPrefix: `Failed to fetch remote playbook '${playbookId}'`,
342
+ allowInsecureHttp: options?.allowInsecureHttp,
343
+ });
344
+ }
345
+ export async function fetchRemoteRuns(serverUrl, token, options) {
346
+ const params = new URLSearchParams();
347
+ if (options?.status)
348
+ params.set("status", options.status);
349
+ if (options?.actionId)
350
+ params.set("actionId", options.actionId);
351
+ if (options?.packageId)
352
+ params.set("packageId", options.packageId);
353
+ if (options?.intent)
354
+ params.set("intent", options.intent);
355
+ if (options?.limit)
356
+ params.set("limit", String(options.limit));
357
+ const qs = params.toString() ? `?${params.toString()}` : "";
358
+ return fetchRemoteJson(serverUrl, `/api/v2/runs${qs}`, token, {
359
+ errorPrefix: "Failed to fetch remote runs",
360
+ allowInsecureHttp: options?.allowInsecureHttp,
361
+ });
362
+ }
363
+ export async function clearRemoteRuns(serverUrl, token, options) {
364
+ return fetchRemoteJson(serverUrl, "/api/v2/runs/clear", token, {
365
+ method: "POST",
366
+ body: options || {},
367
+ errorPrefix: "Failed to clear remote runs",
368
+ allowInsecureHttp: options?.allowInsecureHttp,
369
+ });
370
+ }
371
+ export async function fetchRemoteStateList(serverUrl, token, options) {
372
+ const params = new URLSearchParams();
373
+ if (options?.package)
374
+ params.set("package", options.package);
375
+ if (options?.action)
376
+ params.set("action", options.action);
377
+ if (options?.namespace !== undefined)
378
+ params.set("namespace", options.namespace);
379
+ if (options?.prefix)
380
+ params.set("prefix", options.prefix);
381
+ const qs = params.toString() ? `?${params.toString()}` : "";
382
+ return fetchRemoteJson(serverUrl, `/api/v2/state${qs}`, token, {
383
+ errorPrefix: "Failed to list remote state keys",
384
+ allowInsecureHttp: options?.allowInsecureHttp,
385
+ });
386
+ }
387
+ export async function getRemoteStateKey(serverUrl, key, token, options) {
388
+ const params = new URLSearchParams();
389
+ if (options?.package)
390
+ params.set("package", options.package);
391
+ if (options?.action)
392
+ params.set("action", options.action);
393
+ if (options?.namespace !== undefined)
394
+ params.set("namespace", options.namespace);
395
+ const qs = params.toString() ? `?${params.toString()}` : "";
396
+ return fetchRemoteJson(serverUrl, `/api/v2/state/${encodeURIComponent(key)}${qs}`, token, {
397
+ errorPrefix: `Failed to fetch remote state key '${key}'`,
398
+ allowInsecureHttp: options?.allowInsecureHttp,
399
+ });
400
+ }
401
+ export async function setRemoteStateKey(serverUrl, key, value, token, options) {
402
+ return fetchRemoteJson(serverUrl, `/api/v2/state/${encodeURIComponent(key)}`, token, {
403
+ method: "PUT",
404
+ body: {
405
+ value,
406
+ package: options?.package,
407
+ action: options?.action,
408
+ namespace: options?.namespace,
409
+ ttl: options?.ttl,
410
+ },
411
+ errorPrefix: `Failed to set remote state key '${key}'`,
412
+ allowInsecureHttp: options?.allowInsecureHttp,
413
+ });
414
+ }
415
+ export async function deleteRemoteStateKey(serverUrl, key, token, options) {
416
+ const params = new URLSearchParams();
417
+ if (options?.package)
418
+ params.set("package", options.package);
419
+ if (options?.action)
420
+ params.set("action", options.action);
421
+ if (options?.namespace !== undefined)
422
+ params.set("namespace", options.namespace);
423
+ const qs = params.toString() ? `?${params.toString()}` : "";
424
+ return fetchRemoteJson(serverUrl, `/api/v2/state/${encodeURIComponent(key)}${qs}`, token, {
425
+ method: "DELETE",
426
+ errorPrefix: `Failed to delete remote state key '${key}'`,
427
+ allowInsecureHttp: options?.allowInsecureHttp,
428
+ });
429
+ }
430
+ export async function clearRemoteState(serverUrl, token, options) {
431
+ return fetchRemoteJson(serverUrl, "/api/v2/state/clear", token, {
432
+ method: "POST",
433
+ body: options || {},
434
+ errorPrefix: "Failed to clear remote state",
435
+ allowInsecureHttp: options?.allowInsecureHttp,
436
+ });
437
+ }
438
+ export async function fetchRemoteConfig(serverUrl, token, packageId, options) {
439
+ const query = packageId ? `?package=${encodeURIComponent(packageId)}` : "";
440
+ return fetchRemoteJson(serverUrl, `/api/v2/config${query}`, token, {
441
+ errorPrefix: "Failed to fetch remote config",
442
+ allowInsecureHttp: options?.allowInsecureHttp,
443
+ });
444
+ }
445
+ export async function setRemoteConfig(serverUrl, key, value, token, packageId, options) {
446
+ return fetchRemoteJson(serverUrl, "/api/v2/config", token, {
447
+ method: "PUT",
448
+ body: { key, value, package: packageId },
449
+ errorPrefix: `Failed to set remote config '${key}'`,
450
+ allowInsecureHttp: options?.allowInsecureHttp,
451
+ });
452
+ }
453
+ export async function deleteRemoteConfig(serverUrl, key, token, packageId, options) {
454
+ const query = packageId ? `?package=${encodeURIComponent(packageId)}` : "";
455
+ return fetchRemoteJson(serverUrl, `/api/v2/config/${encodeURIComponent(key)}${query}`, token, {
456
+ method: "DELETE",
457
+ errorPrefix: `Failed to delete remote config '${key}'`,
458
+ allowInsecureHttp: options?.allowInsecureHttp,
459
+ });
460
+ }
461
+ export async function fetchRemoteConfigEnv(serverUrl, token, packageId, options) {
462
+ const query = packageId ? `?package=${encodeURIComponent(packageId)}` : "";
463
+ return fetchRemoteJson(serverUrl, `/api/v2/config/env${query}`, token, {
464
+ errorPrefix: "Failed to fetch remote config env checks",
465
+ allowInsecureHttp: options?.allowInsecureHttp,
466
+ });
467
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./types.js";
2
+ export * from "./manager.js";
3
+ export * from "./client.js";
@@ -0,0 +1,3 @@
1
+ export * from "./types.js";
2
+ export * from "./manager.js";
3
+ export * from "./client.js";
@@ -0,0 +1,47 @@
1
+ import type { ProfileEntry, ProfilesConfig, ResolvedTarget, TokenResolutionSource } from "./types.js";
2
+ /**
3
+ * 默认初始 Profiles 配置(预设 local 本地环境)。
4
+ */
5
+ export declare const DEFAULT_PROFILES_CONFIG: ProfilesConfig;
6
+ /**
7
+ * 格式化并规范化 Server URL 地址(若未指定协议,本地回环地址默认使用 http://,非本地回环地址默认使用 https://,并移除末尾斜杠)。
8
+ */
9
+ export declare function normalizeServerUrl(url: string): string;
10
+ /**
11
+ * 获取 profiles.json 配置文件的物理绝对路径(~/.actiondock/profiles.json)。
12
+ */
13
+ export declare function getProfilesFilePath(customHome?: string): string;
14
+ /**
15
+ * 加载并读取 profiles.json 配置文件。
16
+ */
17
+ export declare function loadProfiles(customHome?: string): ProfilesConfig;
18
+ /**
19
+ * 保存并写入 profiles.json 配置文件,并严格限制文件权限为 0600。
20
+ */
21
+ export declare function saveProfiles(data: ProfilesConfig, customHome?: string): void;
22
+ export declare function addProfile(name: string, entry: ProfileEntry, customHome?: string): void;
23
+ export declare function removeProfile(name: string, customHome?: string): boolean;
24
+ export declare function useProfile(name: string, customHome?: string): void;
25
+ export declare function getProfile(name: string, customHome?: string): ProfileEntry | undefined;
26
+ export declare function listProfiles(customHome?: string): Array<{
27
+ name: string;
28
+ isCurrent: boolean;
29
+ entry: ProfileEntry;
30
+ }>;
31
+ /**
32
+ * Resolves token following multi-tier precedence:
33
+ * 1. CLI explicit --token
34
+ * 2. profile.tokenEnv specified environment variable
35
+ * 3. Derived profile environment variable: ACTIONDOCK_<PROFILE>_TOKEN or <PROFILE>_TOKEN
36
+ * 4. Stored token in profiles.json (deprecated)
37
+ * 5. Global ACTIONDOCK_TOKEN
38
+ */
39
+ export declare function resolveProfileToken(profileName?: string, entry?: ProfileEntry, explicitToken?: string): {
40
+ token?: string;
41
+ source: TokenResolutionSource;
42
+ };
43
+ export declare function resolveTarget(options?: {
44
+ profile?: string;
45
+ server?: string;
46
+ token?: string;
47
+ }, customHome?: string): ResolvedTarget;