@actiondock/core 2.9.1 → 2.11.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 +1 -2
- package/dist/catalog/action-catalog.js +3 -33
- package/dist/catalog/discovery.d.ts +0 -3
- package/dist/catalog/discovery.js +4 -4
- package/dist/catalog/graph.d.ts +0 -4
- package/dist/catalog/graph.js +12 -15
- package/dist/{profile/client-actions.d.ts → client/actions.d.ts} +1 -1
- package/dist/{profile/client-actions.js → client/actions.js} +2 -8
- package/dist/{profile/client-config.d.ts → client/config.d.ts} +1 -1
- package/dist/{profile/client-config.js → client/config.js} +1 -1
- package/dist/client/dispatcher.d.ts +4 -0
- package/dist/client/dispatcher.js +21 -0
- package/dist/client/health.d.ts +38 -0
- package/dist/{profile/client-health.js → client/health.js} +9 -6
- package/dist/client/index.d.ts +16 -0
- package/dist/client/index.js +20 -0
- package/dist/{profile/client-playbooks.d.ts → client/playbooks.d.ts} +1 -1
- package/dist/{profile/client-playbooks.js → client/playbooks.js} +1 -1
- package/dist/{profile/client-runs.d.ts → client/runs.d.ts} +4 -2
- package/dist/{profile/client-runs.js → client/runs.js} +7 -1
- package/dist/{profile/client-state.d.ts → client/state.d.ts} +1 -1
- package/dist/{profile/client-state.js → client/state.js} +1 -1
- package/dist/{profile/client-transport.d.ts → client/transport.d.ts} +29 -10
- package/dist/{profile/client-transport.js → client/transport.js} +125 -35
- package/dist/doctor/checks/index.d.ts +1 -1
- package/dist/doctor/checks/index.js +1 -1
- package/dist/doctor/checks/project.js +24 -92
- package/dist/doctor/checks/registry.js +1 -1
- package/dist/doctor/checks/runtime.d.ts +0 -4
- package/dist/doctor/checks/runtime.js +0 -28
- package/dist/doctor/doctor.js +1 -2
- package/dist/errors.d.ts +85 -4
- package/dist/errors.js +114 -4
- package/dist/execution/service.d.ts +55 -37
- package/dist/execution/service.js +601 -212
- package/dist/execution/types.d.ts +24 -5
- package/dist/host/host.d.ts +42 -22
- package/dist/host/host.js +565 -150
- package/dist/host/routing.js +6 -6
- package/dist/host/types.d.ts +25 -13
- package/dist/index.d.ts +9 -4
- package/dist/index.js +5 -2
- package/dist/input/advice.d.ts +0 -44
- package/dist/input/advice.js +7 -141
- package/dist/input/describe.d.ts +6 -0
- package/dist/input/describe.js +26 -1
- package/dist/input/flat-materializer.js +1 -1
- package/dist/input/flat-parser.js +1 -1
- package/dist/input/index.d.ts +0 -1
- package/dist/input/index.js +0 -1
- package/dist/input/input-resolver.js +2 -2
- package/dist/input/validation-mapper.d.ts +1 -1
- package/dist/invocation/policy.js +2 -0
- package/dist/ipc/diagnostic.d.ts +8 -21
- package/dist/ipc/diagnostic.js +24 -57
- package/dist/ipc/host.js +21 -7
- package/dist/ipc/service.d.ts +14 -0
- package/dist/ipc/service.js +132 -26
- package/dist/ipc/types.d.ts +0 -4
- package/dist/package/index.d.ts +4 -5
- package/dist/package/index.js +1 -2
- package/dist/package/runtime.d.ts +94 -23
- package/dist/package/runtime.js +628 -274
- package/dist/package/static-index.d.ts +3 -6
- package/dist/package/static-index.js +11 -40
- package/dist/package/types.d.ts +19 -4
- package/dist/platform/index.d.ts +2 -1
- package/dist/platform/index.js +2 -1
- package/dist/platform/loader-hook.d.ts +32 -0
- package/dist/platform/loader-hook.js +90 -0
- package/dist/{node → platform}/module-loader.d.ts +13 -0
- package/dist/{node → platform}/module-loader.js +51 -4
- package/dist/platform/node.d.ts +19 -8
- package/dist/platform/node.js +50 -20
- package/dist/platform/types.d.ts +7 -47
- package/dist/process/context-process.d.ts +3 -18
- package/dist/process/context-process.js +3 -44
- package/dist/process/control.d.ts +21 -0
- package/dist/process/control.js +34 -0
- package/dist/process/converters.d.ts +23 -0
- package/dist/process/converters.js +92 -0
- package/dist/process/cursor.js +2 -22
- package/dist/process/{diagnostics-sink.d.ts → diagnostics.d.ts} +0 -7
- package/dist/process/{diagnostics-sink.js → diagnostics.js} +6 -8
- package/dist/process/index.d.ts +1 -3
- package/dist/process/index.js +1 -3
- package/dist/process/input-dispatcher.d.ts +4 -13
- package/dist/process/input-dispatcher.js +48 -69
- package/dist/process/managed-record.d.ts +3 -31
- package/dist/process/metadata-store.d.ts +0 -41
- package/dist/process/metadata-store.js +2 -341
- package/dist/process/process-driver.js +2 -2
- package/dist/process/process-manager.d.ts +8 -50
- package/dist/process/process-manager.js +28 -417
- package/dist/process/quotas.d.ts +14 -0
- package/dist/process/quotas.js +29 -0
- package/dist/process/run-executor.js +0 -1
- package/dist/process/terminal-output-cache.d.ts +20 -34
- package/dist/process/terminal-output-cache.js +43 -64
- package/dist/profile/index.d.ts +1 -2
- package/dist/profile/index.js +1 -2
- package/dist/profile/manager.d.ts +2 -4
- package/dist/profile/manager.js +10 -40
- package/dist/profile/types.d.ts +1 -17
- package/dist/project/digest.d.ts +5 -1
- package/dist/project/digest.js +81 -219
- package/dist/project/index.d.ts +4 -5
- package/dist/project/index.js +4 -5
- package/dist/project/init.js +2 -2
- package/dist/project/loader.d.ts +3 -3
- package/dist/project/loader.js +72 -50
- package/dist/project/lockfile.js +6 -5
- package/dist/project/manifest.js +5 -4
- package/dist/project/transactions.d.ts +4 -42
- package/dist/project/transactions.js +83 -138
- package/dist/project/types-generator.js +2 -1
- package/dist/project/types.d.ts +2 -0
- package/dist/registry/index.d.ts +0 -1
- package/dist/registry/index.js +0 -1
- package/dist/registry/lock.d.ts +2 -11
- package/dist/registry/lock.js +14 -183
- package/dist/registry/registry.d.ts +1 -6
- package/dist/registry/registry.js +5 -17
- package/dist/runtime/action-registry.d.ts +1 -5
- package/dist/runtime/action-registry.js +0 -12
- package/dist/runtime/context.js +2 -2
- package/dist/runtime/events.d.ts +11 -50
- package/dist/runtime/events.js +88 -368
- package/dist/runtime/index.d.ts +0 -4
- package/dist/runtime/index.js +0 -4
- package/dist/runtime/run-persistence.d.ts +2 -0
- package/dist/runtime/run-persistence.js +2 -1
- package/dist/runtime/standalone-commands.d.ts +18 -0
- package/dist/runtime/standalone-commands.js +466 -0
- package/dist/runtime/standalone-help.d.ts +20 -0
- package/dist/runtime/standalone-help.js +72 -0
- package/dist/runtime/standalone.d.ts +1 -44
- package/dist/runtime/standalone.js +31 -526
- package/dist/schema/validator.d.ts +2 -2
- package/dist/schema/validator.js +2 -9
- package/dist/server/index.d.ts +0 -2
- package/dist/server/index.js +0 -2
- package/dist/server/routes/actions.js +1 -1
- package/dist/server/routes/info.js +1 -1
- package/dist/server/routes/playbooks.js +1 -1
- package/dist/server/routes/runs.js +123 -16
- package/dist/server/routes/state.js +43 -18
- package/dist/server/security.d.ts +1 -1
- package/dist/server/security.js +2 -2
- package/dist/server/server.js +3 -7
- package/dist/service/factory.js +4 -3
- package/dist/service/index.d.ts +1 -1
- package/dist/service/index.js +1 -1
- package/dist/service/remote-errors.d.ts +1 -1
- package/dist/service/remote-errors.js +6 -6
- package/dist/service/remote-polling.d.ts +3 -0
- package/dist/service/remote-polling.js +10 -5
- package/dist/service/remote.d.ts +5 -1
- package/dist/service/remote.js +108 -17
- package/dist/service/sse-stream.js +2 -2
- package/dist/service/types.d.ts +22 -19
- package/dist/service/types.js +1 -24
- package/dist/storage/clock.d.ts +1 -1
- package/dist/storage/clock.js +1 -1
- package/dist/storage/data-dir-lock.d.ts +10 -22
- package/dist/storage/data-dir-lock.js +28 -56
- package/dist/storage/file-lock.d.ts +64 -0
- package/dist/storage/file-lock.js +447 -0
- package/dist/storage/index.d.ts +2 -2
- package/dist/storage/index.js +5 -4
- package/dist/storage/run-liveness.d.ts +48 -0
- package/dist/storage/run-liveness.js +44 -0
- package/dist/storage/sqlite-config.d.ts +16 -0
- package/dist/storage/sqlite-config.js +59 -0
- package/dist/storage/sqlite-driver.d.ts +3 -1
- package/dist/storage/sqlite-driver.js +14 -4
- package/dist/storage/sqlite-events.d.ts +13 -0
- package/dist/storage/sqlite-events.js +48 -0
- package/dist/storage/sqlite-runs.d.ts +107 -0
- package/dist/storage/sqlite-runs.js +622 -0
- package/dist/storage/sqlite-schema.d.ts +5 -0
- package/dist/storage/sqlite-schema.js +143 -0
- package/dist/storage/sqlite-state.d.ts +33 -0
- package/dist/storage/sqlite-state.js +270 -0
- package/dist/storage/sqlite.d.ts +30 -57
- package/dist/storage/sqlite.js +84 -741
- package/dist/storage/types.d.ts +35 -2
- package/dist/utils/index.d.ts +18 -14
- package/dist/utils/index.js +37 -29
- package/dist/utils/semver.d.ts +18 -0
- package/dist/utils/semver.js +19 -0
- package/dist/utils/warning.d.ts +1 -0
- package/dist/utils/warning.js +52 -0
- package/dist/{json/value-validator.d.ts → value-validator.d.ts} +9 -0
- package/dist/value-validator.js +330 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +10 -12
- package/dist/execution/index.d.ts +0 -2
- package/dist/execution/index.js +0 -2
- package/dist/filter/index.d.ts +0 -1
- package/dist/filter/index.js +0 -1
- package/dist/graph/index.d.ts +0 -4
- package/dist/graph/index.js +0 -4
- package/dist/input/metadata.d.ts +0 -99
- package/dist/input/metadata.js +0 -99
- package/dist/invocation/index.d.ts +0 -2
- package/dist/invocation/index.js +0 -2
- package/dist/ipc/index.d.ts +0 -4
- package/dist/ipc/index.js +0 -4
- package/dist/json/index.d.ts +0 -1
- package/dist/json/index.js +0 -1
- package/dist/json/value-validator.js +0 -330
- package/dist/node/index.d.ts +0 -1
- package/dist/node/index.js +0 -1
- package/dist/platform/node-fs.d.ts +0 -37
- package/dist/platform/node-fs.js +0 -81
- package/dist/process/control-arbiter.d.ts +0 -108
- package/dist/process/control-arbiter.js +0 -250
- package/dist/process/process-executor.d.ts +0 -47
- package/dist/process/process-executor.js +0 -296
- package/dist/profile/client-health.d.ts +0 -14
- package/dist/profile/client-query.d.ts +0 -30
- package/dist/profile/client-query.js +0 -69
- package/dist/profile/client.d.ts +0 -26
- package/dist/profile/client.js +0 -31
- package/dist/project/closure.d.ts +0 -25
- package/dist/project/closure.js +0 -74
- package/dist/registry/store.d.ts +0 -42
- package/dist/registry/store.js +0 -43
- package/dist/runtime/clock.d.ts +0 -7
- package/dist/runtime/clock.js +0 -7
- package/dist/runtime/module-loader.d.ts +0 -2
- package/dist/runtime/module-loader.js +0 -1
- package/dist/runtime/process.d.ts +0 -8
- package/dist/runtime/process.js +0 -1
- package/dist/runtime/runner.d.ts +0 -234
- package/dist/runtime/runner.js +0 -609
- package/dist/schema/index.d.ts +0 -1
- package/dist/schema/index.js +0 -1
- package/dist/server/dispatcher.d.ts +0 -25
- package/dist/server/dispatcher.js +0 -54
- package/dist/service/local.d.ts +0 -27
- package/dist/service/local.js +0 -141
- package/dist/storage/driver.d.ts +0 -10
- package/dist/storage/driver.js +0 -10
- package/dist/storage/lazy.d.ts +0 -8
- package/dist/storage/lazy.js +0 -45
- package/dist/storage/lock-core.d.ts +0 -158
- package/dist/storage/lock-core.js +0 -872
- package/dist/utils/net.d.ts +0 -10
- package/dist/utils/net.js +0 -16
- package/dist/utils/process.d.ts +0 -10
- package/dist/utils/process.js +0 -21
- /package/dist/{filter → utils}/intent.d.ts +0 -0
- /package/dist/{filter → utils}/intent.js +0 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { QUOTA_EXCEEDED, ProcessError } from "../errors.js";
|
|
2
|
+
export class ProcessQuotaTracker {
|
|
3
|
+
ctx;
|
|
4
|
+
constructor(ctx) {
|
|
5
|
+
this.ctx = ctx;
|
|
6
|
+
}
|
|
7
|
+
checkSpawnQuotas(_scope, requestedBufferBytes) {
|
|
8
|
+
let hostActive = 0;
|
|
9
|
+
for (const p of this.ctx.processes.values()) {
|
|
10
|
+
if (p.info.state === "starting" ||
|
|
11
|
+
p.info.state === "running" ||
|
|
12
|
+
p.info.state === "stopping") {
|
|
13
|
+
hostActive += 1;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
if (hostActive >= this.ctx.quotas.maxActiveProcessesPerHost) {
|
|
17
|
+
throw new ProcessError(QUOTA_EXCEEDED, "Host active process quota exceeded", {
|
|
18
|
+
limit: this.ctx.quotas.maxActiveProcessesPerHost,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
const perProcBuf = requestedBufferBytes ?? this.ctx.defaultLimits.outputBufferBytes;
|
|
22
|
+
if (perProcBuf > this.ctx.quotas.maxOutputBufferBytesPerProcess) {
|
|
23
|
+
throw new ProcessError(QUOTA_EXCEEDED, "Output buffer per process quota exceeded", {
|
|
24
|
+
requested: perProcBuf,
|
|
25
|
+
limit: this.ctx.quotas.maxOutputBufferBytesPerProcess,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -1,57 +1,39 @@
|
|
|
1
1
|
import type { ProcessOutputLog } from "./output-log.js";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* 终态输出日志保留缓存配置选项。
|
|
4
4
|
*/
|
|
5
|
-
export interface
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
export interface TerminalOutputCacheOptions {
|
|
6
|
+
/** 保留时长(毫秒) */
|
|
7
|
+
retentionMs?: number;
|
|
8
|
+
/** 宿主输出缓冲区字节总配额 */
|
|
9
|
+
maxHostBufferBytes?: number;
|
|
10
|
+
/** 保留日志最大条目数,默认 512 */
|
|
11
|
+
maxEntries?: number;
|
|
9
12
|
}
|
|
10
13
|
/**
|
|
11
14
|
* 终态输出日志保留缓存。
|
|
12
15
|
*
|
|
13
|
-
*
|
|
14
|
-
* 保留缓存支撑后续游标读取;TTL 过期转墓碑与 LRU 淘汰均保持同步原子。
|
|
16
|
+
* 维护已退出进程的输出日志,提供基于最大条目数与宿主缓冲总量的有界内存缓存。
|
|
15
17
|
*/
|
|
16
18
|
export declare class TerminalOutputCache {
|
|
17
19
|
/** 保留日志最大条目数上限(默认) */
|
|
18
20
|
static readonly DEFAULT_MAX_ENTRIES = 512;
|
|
19
|
-
/** 墓碑最大登记条数上限(默认) */
|
|
20
|
-
static readonly DEFAULT_MAX_TOMBSTONES = 2048;
|
|
21
21
|
private readonly entries;
|
|
22
|
-
private readonly tombstones;
|
|
23
22
|
private readonly retentionMs;
|
|
24
23
|
private readonly maxHostBufferBytes;
|
|
25
24
|
private readonly maxEntries;
|
|
26
|
-
private
|
|
27
|
-
constructor(options
|
|
28
|
-
/** 保留时长(毫秒) */
|
|
29
|
-
retentionMs: number;
|
|
30
|
-
/** 宿主输出缓冲区字节总配额 */
|
|
31
|
-
maxHostBufferBytes: number;
|
|
32
|
-
/** 保留日志最大条目数,默认 512 */
|
|
33
|
-
maxEntries?: number;
|
|
34
|
-
/** 墓碑最大登记条数,默认 2048 */
|
|
35
|
-
maxTombstones?: number;
|
|
36
|
-
});
|
|
25
|
+
private totalBytes;
|
|
26
|
+
constructor(options?: TerminalOutputCacheOptions);
|
|
37
27
|
/**
|
|
38
|
-
*
|
|
39
|
-
*/
|
|
40
|
-
private recordTombstone;
|
|
41
|
-
/**
|
|
42
|
-
* 清理已过期的终态输出日志条目并转为墓碑。
|
|
28
|
+
* 清理已过期的终态输出日志条目。
|
|
43
29
|
*/
|
|
44
30
|
private cleanExpired;
|
|
45
31
|
/**
|
|
46
|
-
*
|
|
47
|
-
*/
|
|
48
|
-
getTombstone(processId: string): EvictedOutputTombstone | undefined;
|
|
49
|
-
/**
|
|
50
|
-
* 统计终态保留日志当前在内存中实际占用的输出缓冲字节总数(附带过期清理)。
|
|
32
|
+
* 统计终态保留日志当前在内存中实际占用的输出缓冲字节总数。
|
|
51
33
|
*/
|
|
52
34
|
retainedBytes(): number;
|
|
53
35
|
/**
|
|
54
|
-
*
|
|
36
|
+
* 将终态输出日志存入保留缓存,并根据容量上限淘汰旧条目。
|
|
55
37
|
*/
|
|
56
38
|
retain(processId: string, log: ProcessOutputLog): void;
|
|
57
39
|
/**
|
|
@@ -59,8 +41,12 @@ export declare class TerminalOutputCache {
|
|
|
59
41
|
*/
|
|
60
42
|
get(processId: string): ProcessOutputLog | undefined;
|
|
61
43
|
/**
|
|
62
|
-
* 按 LRU
|
|
63
|
-
*
|
|
44
|
+
* 按 LRU 顺序逐条淘汰最旧保留日志,直至剩余保留字节数不超过给定的可容纳上限。
|
|
45
|
+
* 返回被淘汰条目释放的字节总数。
|
|
64
46
|
*/
|
|
65
47
|
evictLRUUntil(fits: number): number;
|
|
48
|
+
/**
|
|
49
|
+
* 清空所有缓存。
|
|
50
|
+
*/
|
|
51
|
+
clear(): void;
|
|
66
52
|
}
|
|
@@ -1,97 +1,72 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 终态输出日志保留缓存。
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* 保留缓存支撑后续游标读取;TTL 过期转墓碑与 LRU 淘汰均保持同步原子。
|
|
4
|
+
* 维护已退出进程的输出日志,提供基于最大条目数与宿主缓冲总量的有界内存缓存。
|
|
6
5
|
*/
|
|
7
6
|
export class TerminalOutputCache {
|
|
8
7
|
/** 保留日志最大条目数上限(默认) */
|
|
9
8
|
static DEFAULT_MAX_ENTRIES = 512;
|
|
10
|
-
/** 墓碑最大登记条数上限(默认) */
|
|
11
|
-
static DEFAULT_MAX_TOMBSTONES = 2048;
|
|
12
9
|
entries = new Map();
|
|
13
|
-
tombstones = new Map();
|
|
14
10
|
retentionMs;
|
|
15
11
|
maxHostBufferBytes;
|
|
16
12
|
maxEntries;
|
|
17
|
-
|
|
18
|
-
constructor(options) {
|
|
19
|
-
this.retentionMs = options.retentionMs;
|
|
20
|
-
this.maxHostBufferBytes = options.maxHostBufferBytes;
|
|
13
|
+
totalBytes = 0;
|
|
14
|
+
constructor(options = {}) {
|
|
15
|
+
this.retentionMs = options.retentionMs ?? 5 * 60 * 1000;
|
|
16
|
+
this.maxHostBufferBytes = options.maxHostBufferBytes ?? 64 * 1024 * 1024;
|
|
21
17
|
this.maxEntries = options.maxEntries ?? TerminalOutputCache.DEFAULT_MAX_ENTRIES;
|
|
22
|
-
this.maxTombstones = options.maxTombstones ?? TerminalOutputCache.DEFAULT_MAX_TOMBSTONES;
|
|
23
18
|
}
|
|
24
19
|
/**
|
|
25
|
-
*
|
|
26
|
-
*/
|
|
27
|
-
recordTombstone(processId, tombstone) {
|
|
28
|
-
if (this.tombstones.size >= this.maxTombstones) {
|
|
29
|
-
const oldestKey = this.tombstones.keys().next().value;
|
|
30
|
-
if (oldestKey) {
|
|
31
|
-
this.tombstones.delete(oldestKey);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
this.tombstones.set(processId, tombstone);
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* 清理已过期的终态输出日志条目并转为墓碑。
|
|
20
|
+
* 清理已过期的终态输出日志条目。
|
|
38
21
|
*/
|
|
39
22
|
cleanExpired() {
|
|
23
|
+
if (this.retentionMs <= 0)
|
|
24
|
+
return;
|
|
40
25
|
const now = Date.now();
|
|
41
26
|
for (const [id, entry] of this.entries.entries()) {
|
|
42
|
-
if (now - entry.
|
|
43
|
-
this.
|
|
44
|
-
tailCursor: entry.log.tailCursor,
|
|
45
|
-
earliestCursor: entry.log.earliestCursor,
|
|
46
|
-
evictedAt: now,
|
|
47
|
-
});
|
|
27
|
+
if (now - entry.retainedAt > this.retentionMs) {
|
|
28
|
+
this.totalBytes -= entry.log.currentBytes;
|
|
48
29
|
this.entries.delete(id);
|
|
49
30
|
}
|
|
50
31
|
}
|
|
32
|
+
if (this.totalBytes < 0) {
|
|
33
|
+
this.totalBytes = 0;
|
|
34
|
+
}
|
|
51
35
|
}
|
|
52
36
|
/**
|
|
53
|
-
*
|
|
54
|
-
*/
|
|
55
|
-
getTombstone(processId) {
|
|
56
|
-
return this.tombstones.get(processId);
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* 统计终态保留日志当前在内存中实际占用的输出缓冲字节总数(附带过期清理)。
|
|
37
|
+
* 统计终态保留日志当前在内存中实际占用的输出缓冲字节总数。
|
|
60
38
|
*/
|
|
61
39
|
retainedBytes() {
|
|
62
40
|
this.cleanExpired();
|
|
63
|
-
|
|
64
|
-
for (const entry of this.entries.values()) {
|
|
65
|
-
bytes += entry.log.currentBytes;
|
|
66
|
-
}
|
|
67
|
-
return bytes;
|
|
41
|
+
return this.totalBytes;
|
|
68
42
|
}
|
|
69
43
|
/**
|
|
70
|
-
*
|
|
44
|
+
* 将终态输出日志存入保留缓存,并根据容量上限淘汰旧条目。
|
|
71
45
|
*/
|
|
72
46
|
retain(processId, log) {
|
|
73
47
|
this.cleanExpired();
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
this.
|
|
77
|
-
this.entries.
|
|
48
|
+
const existing = this.entries.get(processId);
|
|
49
|
+
if (existing) {
|
|
50
|
+
this.totalBytes -= existing.log.currentBytes;
|
|
51
|
+
this.entries.delete(processId);
|
|
52
|
+
}
|
|
53
|
+
while (this.entries.size > 0 &&
|
|
54
|
+
(this.entries.size >= this.maxEntries ||
|
|
55
|
+
this.totalBytes + log.currentBytes > this.maxHostBufferBytes)) {
|
|
78
56
|
const oldestKey = this.entries.keys().next().value;
|
|
79
57
|
if (!oldestKey)
|
|
80
58
|
break;
|
|
81
|
-
const
|
|
82
|
-
if (
|
|
83
|
-
this.
|
|
84
|
-
tailCursor: oldestEntry.log.tailCursor,
|
|
85
|
-
earliestCursor: oldestEntry.log.earliestCursor,
|
|
86
|
-
evictedAt: Date.now(),
|
|
87
|
-
});
|
|
59
|
+
const oldest = this.entries.get(oldestKey);
|
|
60
|
+
if (oldest) {
|
|
61
|
+
this.totalBytes -= oldest.log.currentBytes;
|
|
88
62
|
}
|
|
89
63
|
this.entries.delete(oldestKey);
|
|
90
64
|
}
|
|
91
65
|
this.entries.set(processId, {
|
|
92
66
|
log,
|
|
93
|
-
|
|
67
|
+
retainedAt: Date.now(),
|
|
94
68
|
});
|
|
69
|
+
this.totalBytes += log.currentBytes;
|
|
95
70
|
}
|
|
96
71
|
/**
|
|
97
72
|
* 获取终态保留日志(附带过期清理与 LRU 触达更新)。
|
|
@@ -101,32 +76,36 @@ export class TerminalOutputCache {
|
|
|
101
76
|
const entry = this.entries.get(processId);
|
|
102
77
|
if (!entry)
|
|
103
78
|
return undefined;
|
|
104
|
-
// 触达刷新 LRU 顺序
|
|
105
79
|
this.entries.delete(processId);
|
|
106
80
|
this.entries.set(processId, entry);
|
|
107
81
|
return entry.log;
|
|
108
82
|
}
|
|
109
83
|
/**
|
|
110
|
-
* 按 LRU
|
|
111
|
-
*
|
|
84
|
+
* 按 LRU 顺序逐条淘汰最旧保留日志,直至剩余保留字节数不超过给定的可容纳上限。
|
|
85
|
+
* 返回被淘汰条目释放的字节总数。
|
|
112
86
|
*/
|
|
113
87
|
evictLRUUntil(fits) {
|
|
88
|
+
this.cleanExpired();
|
|
114
89
|
let evictedBytes = 0;
|
|
115
|
-
while (this.entries.size > 0 && this.
|
|
90
|
+
while (this.entries.size > 0 && this.totalBytes > fits) {
|
|
116
91
|
const oldestKey = this.entries.keys().next().value;
|
|
117
92
|
if (!oldestKey)
|
|
118
93
|
break;
|
|
119
94
|
const oldest = this.entries.get(oldestKey);
|
|
120
95
|
if (oldest) {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
evictedAt: Date.now(),
|
|
125
|
-
});
|
|
126
|
-
evictedBytes += oldest.log.currentBytes;
|
|
96
|
+
const bytes = oldest.log.currentBytes;
|
|
97
|
+
this.totalBytes -= bytes;
|
|
98
|
+
evictedBytes += bytes;
|
|
127
99
|
}
|
|
128
100
|
this.entries.delete(oldestKey);
|
|
129
101
|
}
|
|
130
102
|
return evictedBytes;
|
|
131
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* 清空所有缓存。
|
|
106
|
+
*/
|
|
107
|
+
clear() {
|
|
108
|
+
this.entries.clear();
|
|
109
|
+
this.totalBytes = 0;
|
|
110
|
+
}
|
|
132
111
|
}
|
package/dist/profile/index.d.ts
CHANGED
package/dist/profile/index.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import type { ProfileEntry, ProfilesConfig, ResolvedTarget, TokenResolutionSource } from "./types.js";
|
|
2
|
+
import { normalizeServerUrl } from "../client/index.js";
|
|
3
|
+
export { normalizeServerUrl };
|
|
2
4
|
/**
|
|
3
5
|
* 默认初始 Profiles 配置(预设 local 本地环境)。
|
|
4
6
|
*/
|
|
5
7
|
export declare const DEFAULT_PROFILES_CONFIG: ProfilesConfig;
|
|
6
|
-
/**
|
|
7
|
-
* 格式化并规范化 Server URL 地址(若未指定协议,本地回环地址默认使用 http://,非本地回环地址默认使用 https://,并移除末尾斜杠)。
|
|
8
|
-
*/
|
|
9
|
-
export declare function normalizeServerUrl(url: string): string;
|
|
10
8
|
/**
|
|
11
9
|
* 获取 profiles.json 配置文件的物理绝对路径(~/.actiondock/profiles.json)。
|
|
12
10
|
*/
|
package/dist/profile/manager.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
3
|
import { toSnakeUpperCase } from "../runtime/env.js";
|
|
4
|
-
import { isLoopbackHost } from "../utils/net.js";
|
|
5
4
|
import { getActionDockHome } from "../utils/index.js";
|
|
6
|
-
import { ActionDockError, INVALID_ARGUMENT } from "../errors.js";
|
|
5
|
+
import { ActionDockError, INVALID_ARGUMENT, PROFILE_NOT_FOUND } from "../errors.js";
|
|
6
|
+
import { normalizeServerUrl } from "../client/index.js";
|
|
7
|
+
export { normalizeServerUrl };
|
|
7
8
|
const PROFILE_NAME_REGEX = /^[a-zA-Z0-9_\-\.]+$/;
|
|
8
9
|
/**
|
|
9
10
|
* 默认初始 Profiles 配置(预设 local 本地环境)。
|
|
@@ -17,37 +18,6 @@ export const DEFAULT_PROFILES_CONFIG = {
|
|
|
17
18
|
},
|
|
18
19
|
},
|
|
19
20
|
};
|
|
20
|
-
/**
|
|
21
|
-
* 格式化并规范化 Server URL 地址(若未指定协议,本地回环地址默认使用 http://,非本地回环地址默认使用 https://,并移除末尾斜杠)。
|
|
22
|
-
*/
|
|
23
|
-
export function normalizeServerUrl(url) {
|
|
24
|
-
let cleaned = url.trim().replace(/\/+$/, "");
|
|
25
|
-
if (!cleaned || cleaned === "local") {
|
|
26
|
-
return cleaned;
|
|
27
|
-
}
|
|
28
|
-
if (!/^https?:\/\//i.test(cleaned)) {
|
|
29
|
-
let hostname = cleaned;
|
|
30
|
-
const slashIdx = hostname.indexOf("/");
|
|
31
|
-
if (slashIdx !== -1) {
|
|
32
|
-
hostname = hostname.slice(0, slashIdx);
|
|
33
|
-
}
|
|
34
|
-
if (hostname.startsWith("[")) {
|
|
35
|
-
const endBracket = hostname.indexOf("]");
|
|
36
|
-
if (endBracket !== -1) {
|
|
37
|
-
hostname = hostname.slice(1, endBracket);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
const colonIdx = hostname.indexOf(":");
|
|
42
|
-
if (colonIdx !== -1) {
|
|
43
|
-
hostname = hostname.slice(0, colonIdx);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
const isLoopback = isLoopbackHost(hostname);
|
|
47
|
-
cleaned = `${isLoopback ? "http" : "https"}://${cleaned}`;
|
|
48
|
-
}
|
|
49
|
-
return cleaned;
|
|
50
|
-
}
|
|
51
21
|
/**
|
|
52
22
|
* 获取 profiles.json 配置文件的物理绝对路径(~/.actiondock/profiles.json)。
|
|
53
23
|
*/
|
|
@@ -141,10 +111,10 @@ export function saveProfiles(data, customHome) {
|
|
|
141
111
|
export function addProfile(name, entry, customHome) {
|
|
142
112
|
const trimmedName = name.trim();
|
|
143
113
|
if (!trimmedName) {
|
|
144
|
-
throw new
|
|
114
|
+
throw new ActionDockError(INVALID_ARGUMENT, "Profile name cannot be empty");
|
|
145
115
|
}
|
|
146
116
|
if (!PROFILE_NAME_REGEX.test(trimmedName)) {
|
|
147
|
-
throw new
|
|
117
|
+
throw new ActionDockError(INVALID_ARGUMENT, `Invalid profile name '${trimmedName}'. Profile names may only contain letters, numbers, hyphens, underscores, and dots.`);
|
|
148
118
|
}
|
|
149
119
|
const profilesConfig = loadProfiles(customHome);
|
|
150
120
|
const normalizedServer = normalizeServerUrl(entry.serverUrl);
|
|
@@ -160,12 +130,12 @@ export function addProfile(name, entry, customHome) {
|
|
|
160
130
|
export function updateProfile(name, entry, customHome) {
|
|
161
131
|
const trimmedName = name.trim();
|
|
162
132
|
if (!trimmedName) {
|
|
163
|
-
throw new
|
|
133
|
+
throw new ActionDockError(INVALID_ARGUMENT, "Profile name cannot be empty");
|
|
164
134
|
}
|
|
165
135
|
const profilesConfig = loadProfiles(customHome);
|
|
166
136
|
const existing = profilesConfig.profiles[trimmedName];
|
|
167
137
|
if (!existing) {
|
|
168
|
-
throw new
|
|
138
|
+
throw new ActionDockError(PROFILE_NOT_FOUND, `Profile '${trimmedName}' not found. Configure it with 'ad profile add ${trimmedName} --server <url>'`);
|
|
169
139
|
}
|
|
170
140
|
const serverUrl = entry.serverUrl ? normalizeServerUrl(entry.serverUrl) : existing.serverUrl;
|
|
171
141
|
profilesConfig.profiles[trimmedName] = {
|
|
@@ -194,7 +164,7 @@ export function useProfile(name, customHome) {
|
|
|
194
164
|
const trimmedName = name.trim();
|
|
195
165
|
const profilesConfig = loadProfiles(customHome);
|
|
196
166
|
if (trimmedName !== "local" && !profilesConfig.profiles[trimmedName]) {
|
|
197
|
-
throw new
|
|
167
|
+
throw new ActionDockError(PROFILE_NOT_FOUND, `Profile '${trimmedName}' not found. Use 'ad profile list' to see available profiles or 'ad profile add' to register one.`);
|
|
198
168
|
}
|
|
199
169
|
profilesConfig.currentProfile = trimmedName;
|
|
200
170
|
saveProfiles(profilesConfig, customHome);
|
|
@@ -298,7 +268,7 @@ export function resolveTarget(options, customHome) {
|
|
|
298
268
|
}
|
|
299
269
|
const found = profilesConfig.profiles[pName];
|
|
300
270
|
if (!found) {
|
|
301
|
-
throw new
|
|
271
|
+
throw new ActionDockError(PROFILE_NOT_FOUND, `Profile '${pName}' not found. Configure it with 'ad profile add ${pName} --server <url>'`);
|
|
302
272
|
}
|
|
303
273
|
const resolvedToken = resolveProfileToken(pName, found, options.token);
|
|
304
274
|
const effectiveInsecure = options.insecure !== undefined
|
|
@@ -335,7 +305,7 @@ export function resolveTarget(options, customHome) {
|
|
|
335
305
|
}
|
|
336
306
|
const found = profilesConfig.profiles[pName];
|
|
337
307
|
if (!found) {
|
|
338
|
-
throw new
|
|
308
|
+
throw new ActionDockError(PROFILE_NOT_FOUND, `Profile '${pName}' (from ACTIONDOCK_PROFILE) not found. Configure it with 'ad profile add ${pName} --server <url>'`);
|
|
339
309
|
}
|
|
340
310
|
const resolvedToken = resolveProfileToken(pName, found, options?.token);
|
|
341
311
|
const effectiveInsecure = options?.insecure !== undefined
|
package/dist/profile/types.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export type { RemoteHealthResult } from "../client/index.js";
|
|
1
2
|
/**
|
|
2
3
|
* 单个远端配置环境(Profile)实体定义。
|
|
3
4
|
*/
|
|
@@ -48,20 +49,3 @@ export interface ResolvedTarget {
|
|
|
48
49
|
/** 是否允许向非回环地址发送明文 HTTP 请求 */
|
|
49
50
|
allowInsecureHttp?: boolean;
|
|
50
51
|
}
|
|
51
|
-
/**
|
|
52
|
-
* 远端服务器健康探测与时延检测结果。
|
|
53
|
-
*/
|
|
54
|
-
export interface RemoteHealthResult {
|
|
55
|
-
/** 服务端是否连通且鉴权成功 */
|
|
56
|
-
ok: boolean;
|
|
57
|
-
/** 服务端状态标识(如 "ok") */
|
|
58
|
-
status?: string;
|
|
59
|
-
/** 远端 ActionDock 版本号 */
|
|
60
|
-
version?: string;
|
|
61
|
-
/** 远端服务运行时间(秒) */
|
|
62
|
-
uptime?: number;
|
|
63
|
-
/** 网络往返延迟(毫秒) */
|
|
64
|
-
latencyMs: number;
|
|
65
|
-
/** 探测失败时的错误信息 */
|
|
66
|
-
error?: string;
|
|
67
|
-
}
|
package/dist/project/digest.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 解析 JSON 文本并在检测到重复键时抛出错误。
|
|
3
|
-
* 遵循 RFC 8785
|
|
3
|
+
* 遵循 RFC 8785 清单校验规范:解析阶段必须率先拦截并拒绝重复键。
|
|
4
|
+
*
|
|
5
|
+
* 实现策略:JSON.parse 主解析 + 轻量键名扫描器做重复键检测。
|
|
6
|
+
* 扫描器以状态机遍历原始文本,仅在对象键位置(冒号前的字符串字面量)记录键名,
|
|
7
|
+
* 同一对象层级内出现重复键名即抛错;字符串内部与转义字符不参与键名提取。
|
|
4
8
|
*/
|
|
5
9
|
export declare function parseJsonWithoutDuplicates<T = unknown>(jsonText: string): T;
|
|
6
10
|
/**
|