@southwind-ai/shared 0.3.1 → 0.3.3
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/index.ts +17 -0
- package/package.json +1 -1
- package/src/agent-admin-catalog.ts +73 -0
- package/src/agent-skills.ts +68 -0
- package/src/agent-workbench.ts +100 -0
- package/src/agent-workflow-presets.ts +26 -0
- package/src/diagnostics.ts +13 -0
- package/src/environment-assessment.ts +68 -0
- package/src/environment-policy.ts +205 -0
- package/src/license-console-capabilities.ts +7 -0
- package/src/license.ts +1 -0
- package/src/module-configuration.ts +2 -1
- package/src/rbac.ts +1 -0
package/index.ts
CHANGED
|
@@ -2,6 +2,8 @@ export * from "./src/audit.js";
|
|
|
2
2
|
export * from "./src/ai-operation-readiness.js";
|
|
3
3
|
// @windy-module system.agent begin
|
|
4
4
|
export * from "./src/ai-runtime-report.js";
|
|
5
|
+
export * from "./src/agent-admin-catalog.js";
|
|
6
|
+
export * from "./src/agent-workbench.js";
|
|
5
7
|
export * from "./src/agent-workflow.js";
|
|
6
8
|
export * from "./src/agent-workflow-events.js";
|
|
7
9
|
export * from "./src/agent-workflow-evaluation.js";
|
|
@@ -33,3 +35,18 @@ export * from "./src/stable-key.js";
|
|
|
33
35
|
export * from "./src/workflow.js";
|
|
34
36
|
|
|
35
37
|
export * from "./src/license-console-capabilities.js";
|
|
38
|
+
|
|
39
|
+
// @windy-module system.agent begin
|
|
40
|
+
export * from "./src/agent-skills.js";
|
|
41
|
+
// @windy-module system.agent end
|
|
42
|
+
|
|
43
|
+
// @windy-module system.audit begin
|
|
44
|
+
export * from "./src/diagnostics.js";
|
|
45
|
+
// @windy-module system.audit end
|
|
46
|
+
|
|
47
|
+
// @windy-module system.agent begin
|
|
48
|
+
export * from "./src/agent-workflow-presets.js";
|
|
49
|
+
// @windy-module system.agent end
|
|
50
|
+
|
|
51
|
+
export * from "./src/environment-assessment.js";
|
|
52
|
+
export * from "./src/environment-policy.js";
|
package/package.json
CHANGED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { JsonObject } from "./json.js";
|
|
2
|
+
import type { CandidateRole } from "./workflow.js";
|
|
3
|
+
|
|
4
|
+
/** Public, bounded categories; never include raw Guard events or Provider bodies. */
|
|
5
|
+
export type AgentAdminAvailabilityReason =
|
|
6
|
+
| "allowed"
|
|
7
|
+
| "permission-denied"
|
|
8
|
+
| "feature-unavailable"
|
|
9
|
+
| "license-unavailable"
|
|
10
|
+
| "scope-unavailable"
|
|
11
|
+
| "runtime-unavailable"
|
|
12
|
+
| "workflow-only"
|
|
13
|
+
| "internal-operation"
|
|
14
|
+
| "unsupported-operation"
|
|
15
|
+
| "handler-unavailable"
|
|
16
|
+
| "governance-unavailable";
|
|
17
|
+
|
|
18
|
+
export interface AgentAdminToolCatalogItem {
|
|
19
|
+
readonly key: string;
|
|
20
|
+
readonly label: string;
|
|
21
|
+
readonly description: string;
|
|
22
|
+
readonly module: string;
|
|
23
|
+
readonly operation: "query" | "command" | "background";
|
|
24
|
+
readonly featureKey: string;
|
|
25
|
+
readonly permissionKey: string;
|
|
26
|
+
readonly auditAction: string;
|
|
27
|
+
readonly scopeMode: "platform" | "request";
|
|
28
|
+
readonly executionMode: "host" | "sandbox";
|
|
29
|
+
readonly dataClassification: "public" | "internal" | "sensitive";
|
|
30
|
+
readonly approval: "none" | "required";
|
|
31
|
+
readonly approvalRoles?: readonly CandidateRole[];
|
|
32
|
+
readonly approvalTimeoutSeconds?: number;
|
|
33
|
+
readonly idempotency: "none" | "supported" | "required";
|
|
34
|
+
readonly limits: AgentAdminCatalogLimits;
|
|
35
|
+
readonly inputSchemaKey: string;
|
|
36
|
+
readonly outputSchemaKey: string;
|
|
37
|
+
readonly inputSchema: JsonObject;
|
|
38
|
+
readonly outputSchema: JsonObject;
|
|
39
|
+
readonly allowedOperationKeys: readonly string[];
|
|
40
|
+
/** Current Guard + Scope eligibility, not an execution or approval grant. */
|
|
41
|
+
readonly allowed: boolean;
|
|
42
|
+
readonly availabilityReason: AgentAdminAvailabilityReason;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface AgentAdminCatalogLimits {
|
|
46
|
+
readonly maxDurationSeconds: number;
|
|
47
|
+
readonly maxInputBytes: number;
|
|
48
|
+
readonly maxOutputBytes: number;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface AgentAdminOperationCatalogItem {
|
|
52
|
+
readonly key: string;
|
|
53
|
+
readonly module: string;
|
|
54
|
+
readonly moduleLabel: string;
|
|
55
|
+
readonly kind: string;
|
|
56
|
+
readonly visibility: "public" | "internal";
|
|
57
|
+
readonly execution: string;
|
|
58
|
+
readonly featureKey: string;
|
|
59
|
+
readonly permissionKey: string;
|
|
60
|
+
readonly auditAction: string;
|
|
61
|
+
readonly dataClassification: "public" | "internal" | "sensitive";
|
|
62
|
+
readonly requiredCapabilities: readonly string[];
|
|
63
|
+
readonly inputModalities: readonly string[];
|
|
64
|
+
readonly inputSchemaKey: string;
|
|
65
|
+
readonly outputSchemaKey: string;
|
|
66
|
+
readonly inputSchema?: JsonObject;
|
|
67
|
+
readonly outputSchema?: JsonObject;
|
|
68
|
+
readonly allowedToolKeys: readonly string[];
|
|
69
|
+
readonly limits: AgentAdminCatalogLimits;
|
|
70
|
+
readonly launchAuthority: "direct" | "workflow-artifact";
|
|
71
|
+
readonly selectable: boolean;
|
|
72
|
+
readonly availabilityReason: AgentAdminAvailabilityReason;
|
|
73
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/** DSH 技能是工作方法与文件包,不能授予业务权限或承载可执行授权。 */
|
|
2
|
+
export type AgentSkillScope = "personal" | "department" | "tenant";
|
|
3
|
+
export type AgentSkillOrigin = "builtin" | "shared";
|
|
4
|
+
export type AgentSkillStatus = "published" | "disabled";
|
|
5
|
+
export interface AgentSkillRequirement {
|
|
6
|
+
readonly toolKey: string;
|
|
7
|
+
readonly featureKey: string;
|
|
8
|
+
readonly permissionKey: string;
|
|
9
|
+
}
|
|
10
|
+
export interface AgentSkillFile {
|
|
11
|
+
readonly path: string;
|
|
12
|
+
readonly contentBase64: string;
|
|
13
|
+
}
|
|
14
|
+
export interface AgentSkillBundle {
|
|
15
|
+
readonly name: string;
|
|
16
|
+
readonly displayName: string;
|
|
17
|
+
readonly description: string;
|
|
18
|
+
readonly digest: string;
|
|
19
|
+
readonly files: readonly AgentSkillFile[];
|
|
20
|
+
}
|
|
21
|
+
export interface AgentSkillVersion {
|
|
22
|
+
readonly key: string;
|
|
23
|
+
readonly version: number;
|
|
24
|
+
readonly tenantId: string;
|
|
25
|
+
readonly ownerActorId: string;
|
|
26
|
+
readonly departmentId?: string;
|
|
27
|
+
readonly scope: AgentSkillScope;
|
|
28
|
+
readonly origin: AgentSkillOrigin;
|
|
29
|
+
readonly status: AgentSkillStatus;
|
|
30
|
+
readonly name: string;
|
|
31
|
+
readonly description: string;
|
|
32
|
+
readonly digest: string;
|
|
33
|
+
readonly requirements: readonly AgentSkillRequirement[];
|
|
34
|
+
readonly safetyConstraints: readonly string[];
|
|
35
|
+
readonly createdAt: string;
|
|
36
|
+
readonly createdBy: string;
|
|
37
|
+
readonly restoredFromVersion?: number;
|
|
38
|
+
readonly source: string;
|
|
39
|
+
}
|
|
40
|
+
export interface AgentSkillGovernanceItem {
|
|
41
|
+
readonly skill: AgentSkillVersion;
|
|
42
|
+
readonly available: boolean;
|
|
43
|
+
readonly governable: boolean;
|
|
44
|
+
}
|
|
45
|
+
export interface ImportAgentSkillRequest {
|
|
46
|
+
readonly format: "markdown" | "zip";
|
|
47
|
+
/** SKILL.md 正文,或 ZIP 的标准 base64。 */
|
|
48
|
+
readonly content: string;
|
|
49
|
+
readonly scope: AgentSkillScope;
|
|
50
|
+
readonly expectedVersion: number;
|
|
51
|
+
readonly requirements?: readonly AgentSkillRequirement[];
|
|
52
|
+
readonly safetyConstraints?: readonly string[];
|
|
53
|
+
}
|
|
54
|
+
export interface AgentSkillCommandRequest {
|
|
55
|
+
readonly expectedVersion: number;
|
|
56
|
+
readonly version?: number;
|
|
57
|
+
}
|
|
58
|
+
export interface PublishedAgentSkillBundle {
|
|
59
|
+
readonly skill: AgentSkillVersion;
|
|
60
|
+
readonly bundle: AgentSkillBundle;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface AgentSkillRuntimeBundle {
|
|
64
|
+
readonly key: string;
|
|
65
|
+
readonly version: number;
|
|
66
|
+
readonly digest: string;
|
|
67
|
+
readonly files: readonly AgentSkillFile[];
|
|
68
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { JsonValue } from "./json.js";
|
|
2
|
+
|
|
3
|
+
export type AgentWorkbenchRecordingSourceV1 = "harness" | "business";
|
|
4
|
+
export type AgentWorkbenchCorrelationStatusV1 =
|
|
5
|
+
| "complete"
|
|
6
|
+
| "partial"
|
|
7
|
+
| "missing";
|
|
8
|
+
|
|
9
|
+
export interface AgentWorkbenchEventV1 {
|
|
10
|
+
readonly sequence: number;
|
|
11
|
+
readonly type: string;
|
|
12
|
+
readonly summary: string;
|
|
13
|
+
readonly occurredAt?: string;
|
|
14
|
+
readonly runId?: string;
|
|
15
|
+
readonly turnId?: string;
|
|
16
|
+
readonly stepId?: string;
|
|
17
|
+
readonly modelAttemptId?: string;
|
|
18
|
+
readonly attemptSequence?: number;
|
|
19
|
+
readonly toolCallId?: string;
|
|
20
|
+
readonly toolKey?: string;
|
|
21
|
+
readonly workItemId?: string;
|
|
22
|
+
readonly artifactId?: string;
|
|
23
|
+
readonly workflowRunId?: string;
|
|
24
|
+
readonly nodeRunId?: string;
|
|
25
|
+
readonly outcome?: string;
|
|
26
|
+
readonly usage?: {
|
|
27
|
+
readonly inputTokens?: number;
|
|
28
|
+
readonly outputTokens?: number;
|
|
29
|
+
readonly totalTokens?: number;
|
|
30
|
+
readonly costMicros?: number;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface AgentWorkbenchRunV1 {
|
|
35
|
+
readonly runId: string;
|
|
36
|
+
readonly operationKey: string;
|
|
37
|
+
readonly sessionId?: string;
|
|
38
|
+
readonly turnId?: string;
|
|
39
|
+
readonly messageSequence?: number;
|
|
40
|
+
readonly status: string;
|
|
41
|
+
readonly events: readonly AgentWorkbenchEventV1[];
|
|
42
|
+
readonly result?: { readonly output?: JsonValue; readonly status?: string };
|
|
43
|
+
readonly correlationStatus: AgentWorkbenchCorrelationStatusV1;
|
|
44
|
+
readonly missing: readonly string[];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface AgentWorkbenchWorkflowV1 {
|
|
48
|
+
readonly workflowRunId: string;
|
|
49
|
+
readonly sessionId?: string;
|
|
50
|
+
readonly messageSequence?: number;
|
|
51
|
+
readonly workflowKey: string;
|
|
52
|
+
readonly title: string;
|
|
53
|
+
readonly status: string;
|
|
54
|
+
readonly parentRunId?: string;
|
|
55
|
+
readonly parentNodeRunId?: string;
|
|
56
|
+
readonly nodes: readonly {
|
|
57
|
+
readonly nodeRunId: string;
|
|
58
|
+
readonly nodeId: string;
|
|
59
|
+
readonly type: string;
|
|
60
|
+
readonly status: string;
|
|
61
|
+
readonly attempt: number;
|
|
62
|
+
readonly previousNodeRunId?: string;
|
|
63
|
+
readonly agentRunId?: string;
|
|
64
|
+
readonly workItemId?: string;
|
|
65
|
+
readonly selectedBranch?: string;
|
|
66
|
+
readonly artifactIds: readonly string[];
|
|
67
|
+
}[];
|
|
68
|
+
readonly events: readonly AgentWorkbenchEventV1[];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface AgentWorkbenchRecordingSummaryV1 {
|
|
72
|
+
readonly source: AgentWorkbenchRecordingSourceV1;
|
|
73
|
+
readonly sessionId: string;
|
|
74
|
+
readonly title: string;
|
|
75
|
+
readonly updatedAt: string;
|
|
76
|
+
readonly operationKey?: string;
|
|
77
|
+
readonly sessionStatus?: "active" | "archived";
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface AgentWorkbenchRecordingV1 extends AgentWorkbenchRecordingSummaryV1 {
|
|
81
|
+
readonly mode: "read-only";
|
|
82
|
+
readonly sideEffectPolicy: "no-reexecution";
|
|
83
|
+
readonly correlationStatus: AgentWorkbenchCorrelationStatusV1;
|
|
84
|
+
readonly messages: readonly {
|
|
85
|
+
readonly sequence: number;
|
|
86
|
+
readonly role: "user" | "assistant";
|
|
87
|
+
readonly content: string;
|
|
88
|
+
readonly createdAt: string;
|
|
89
|
+
}[];
|
|
90
|
+
readonly timeline: readonly AgentWorkbenchEventV1[];
|
|
91
|
+
/** Parent forks retain separate original ledger sequences, never renumbered. */
|
|
92
|
+
readonly segments?: readonly {
|
|
93
|
+
readonly sessionId: string;
|
|
94
|
+
readonly throughSequence: number;
|
|
95
|
+
readonly timeline: readonly AgentWorkbenchEventV1[];
|
|
96
|
+
}[];
|
|
97
|
+
readonly runs: readonly AgentWorkbenchRunV1[];
|
|
98
|
+
readonly workflows: readonly AgentWorkbenchWorkflowV1[];
|
|
99
|
+
readonly missing: readonly string[];
|
|
100
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { AgentWorkflowBudget } from "./agent-workflow-run.js";
|
|
2
|
+
import type { AgentWorkflowNodeType } from "./agent-workflow-definition.js";
|
|
3
|
+
|
|
4
|
+
export interface AgentWorkflowPresetSummary {
|
|
5
|
+
readonly key: string;
|
|
6
|
+
readonly moduleKey: string;
|
|
7
|
+
readonly label: string;
|
|
8
|
+
readonly description: string;
|
|
9
|
+
readonly workflowKey: string;
|
|
10
|
+
readonly version: string;
|
|
11
|
+
readonly budget: AgentWorkflowBudget;
|
|
12
|
+
readonly nodes: readonly {
|
|
13
|
+
readonly id: string;
|
|
14
|
+
readonly label: string;
|
|
15
|
+
readonly type: AgentWorkflowNodeType;
|
|
16
|
+
}[];
|
|
17
|
+
readonly availability: "available" | "unavailable";
|
|
18
|
+
readonly safeCode?: string;
|
|
19
|
+
readonly blockedReason?: string;
|
|
20
|
+
/** 由所属模块注册的业务入口;目录本身不发布或启动 Workflow。 */
|
|
21
|
+
readonly entry?: { readonly path: string; readonly label: string };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface AgentWorkflowPresetListResponse {
|
|
25
|
+
readonly items: readonly AgentWorkflowPresetSummary[];
|
|
26
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** 可向授权运维人员公开的失败索引,不包含业务正文、异常堆栈或身份凭据。 */
|
|
2
|
+
export interface DiagnosticRecord {
|
|
3
|
+
readonly diagnosticId: string;
|
|
4
|
+
readonly requestId: string;
|
|
5
|
+
readonly occurredAt: string;
|
|
6
|
+
readonly expiresAt: string;
|
|
7
|
+
readonly service: "server";
|
|
8
|
+
readonly stage: "http";
|
|
9
|
+
readonly method: string;
|
|
10
|
+
readonly route: string;
|
|
11
|
+
readonly statusCode: number;
|
|
12
|
+
readonly errorCode: string;
|
|
13
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/** Host evidence is supplied by an explicitly mounted collector report, never inferred from a container. */
|
|
2
|
+
export const HOST_PROBE_KEYS = [
|
|
3
|
+
"cpu",
|
|
4
|
+
"memory",
|
|
5
|
+
"blockDevices",
|
|
6
|
+
"disks",
|
|
7
|
+
"mounts",
|
|
8
|
+
"network",
|
|
9
|
+
"systemd",
|
|
10
|
+
"docker",
|
|
11
|
+
"compose",
|
|
12
|
+
"containers",
|
|
13
|
+
"gpu",
|
|
14
|
+
] as const;
|
|
15
|
+
export type HostProbeKey = (typeof HOST_PROBE_KEYS)[number];
|
|
16
|
+
export interface HostDiagnosticProbe {
|
|
17
|
+
status:
|
|
18
|
+
| "ok"
|
|
19
|
+
| "missing"
|
|
20
|
+
| "permission-denied"
|
|
21
|
+
| "timeout"
|
|
22
|
+
| "failed"
|
|
23
|
+
| "unsupported";
|
|
24
|
+
exitCode: number | null;
|
|
25
|
+
output: string;
|
|
26
|
+
truncated: boolean;
|
|
27
|
+
}
|
|
28
|
+
export interface HostDiagnosticsReport {
|
|
29
|
+
schemaVersion: 1;
|
|
30
|
+
scope: "host";
|
|
31
|
+
collector: "windy-host-diagnostics-v1";
|
|
32
|
+
collectedAt: string;
|
|
33
|
+
facts: {
|
|
34
|
+
os: string;
|
|
35
|
+
distribution?: string;
|
|
36
|
+
kernel: string;
|
|
37
|
+
architecture: string;
|
|
38
|
+
cpuLogicalCount: number;
|
|
39
|
+
memoryTotalBytes: number | null;
|
|
40
|
+
/** Present only when a successful GPU query establishes the count. */
|
|
41
|
+
gpuCount?: number;
|
|
42
|
+
};
|
|
43
|
+
probes: Record<HostProbeKey, HostDiagnosticProbe>;
|
|
44
|
+
deployment?: {
|
|
45
|
+
status: "available" | "invalid" | "unreadable";
|
|
46
|
+
releaseId?: string;
|
|
47
|
+
gitSha?: string;
|
|
48
|
+
platform?: string;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
export interface EnvironmentSnapshot {
|
|
52
|
+
generatedAt: string;
|
|
53
|
+
process: {
|
|
54
|
+
scope: "process";
|
|
55
|
+
platform: string;
|
|
56
|
+
architecture: string;
|
|
57
|
+
nodeVersion: string;
|
|
58
|
+
bunVersion?: string;
|
|
59
|
+
containerized: boolean;
|
|
60
|
+
logicalCpuCount: number;
|
|
61
|
+
memoryTotalBytes: number;
|
|
62
|
+
};
|
|
63
|
+
host: {
|
|
64
|
+
status: "available" | "not-configured" | "invalid" | "stale" | "unreadable";
|
|
65
|
+
message: string;
|
|
66
|
+
report?: HostDiagnosticsReport;
|
|
67
|
+
};
|
|
68
|
+
}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/** Deployment requirements are recommendations, not authorization or probe results. */
|
|
2
|
+
export interface FeatureEnvironmentPolicy {
|
|
3
|
+
key: string;
|
|
4
|
+
title: string;
|
|
5
|
+
execution: "none" | "cpu" | "local-gpu" | "remote";
|
|
6
|
+
recommendedEnabled?: boolean;
|
|
7
|
+
supportedPlatforms?: string[];
|
|
8
|
+
supportedArchitectures?: string[];
|
|
9
|
+
minMemoryGiB?: number;
|
|
10
|
+
requiredEnvironmentKeys?: string[];
|
|
11
|
+
}
|
|
12
|
+
export const AI_RUNTIME_KINDS = [
|
|
13
|
+
"agent",
|
|
14
|
+
"document",
|
|
15
|
+
"speech",
|
|
16
|
+
"embedding",
|
|
17
|
+
] as const;
|
|
18
|
+
export type AiRuntimeKind = (typeof AI_RUNTIME_KINDS)[number];
|
|
19
|
+
export type AiRuntimeSwitches = Partial<Record<AiRuntimeKind, boolean>>;
|
|
20
|
+
|
|
21
|
+
export interface AntivirusEnvironmentPolicy {
|
|
22
|
+
packaged: boolean;
|
|
23
|
+
enabled: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface EnvironmentPolicy {
|
|
27
|
+
schemaVersion: 1;
|
|
28
|
+
build: { modules: string[]; runtimes?: AiRuntimeSwitches };
|
|
29
|
+
runtime?: AiRuntimeSwitches;
|
|
30
|
+
antivirus?: AntivirusEnvironmentPolicy;
|
|
31
|
+
features: FeatureEnvironmentPolicy[];
|
|
32
|
+
}
|
|
33
|
+
export interface FeatureEnvironmentAssessment {
|
|
34
|
+
key: string;
|
|
35
|
+
title: string;
|
|
36
|
+
status:
|
|
37
|
+
| "hardware"
|
|
38
|
+
| "software"
|
|
39
|
+
| "not-packaged"
|
|
40
|
+
| "configuration"
|
|
41
|
+
| "unknown"
|
|
42
|
+
| "available"
|
|
43
|
+
| "disabled";
|
|
44
|
+
message: string;
|
|
45
|
+
evidence: string[];
|
|
46
|
+
recommendedEnabled?: boolean;
|
|
47
|
+
}
|
|
48
|
+
export interface EnvironmentAssessmentSnapshot {
|
|
49
|
+
status: "available" | "not-configured" | "invalid";
|
|
50
|
+
message: string;
|
|
51
|
+
features: FeatureEnvironmentAssessment[];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function object(
|
|
55
|
+
value: unknown,
|
|
56
|
+
required: string[],
|
|
57
|
+
optional: string[] = [],
|
|
58
|
+
): Record<string, unknown> {
|
|
59
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
60
|
+
throw new Error("环境预设必须为对象");
|
|
61
|
+
const record = value as Record<string, unknown>;
|
|
62
|
+
if (
|
|
63
|
+
required.some((key) => !Object.hasOwn(record, key)) ||
|
|
64
|
+
Object.keys(record).some((key) => ![...required, ...optional].includes(key))
|
|
65
|
+
)
|
|
66
|
+
throw new Error("环境预设缺少必需字段或包含未知字段");
|
|
67
|
+
return record;
|
|
68
|
+
}
|
|
69
|
+
function strings(value: unknown, pattern: RegExp, max = 128): string[] {
|
|
70
|
+
if (
|
|
71
|
+
!Array.isArray(value) ||
|
|
72
|
+
value.length > max ||
|
|
73
|
+
value.some(
|
|
74
|
+
(item) =>
|
|
75
|
+
typeof item !== "string" || item.length > 128 || !pattern.test(item),
|
|
76
|
+
) ||
|
|
77
|
+
new Set(value).size !== value.length
|
|
78
|
+
)
|
|
79
|
+
throw new Error("环境预设列表无效或重复");
|
|
80
|
+
return value as string[];
|
|
81
|
+
}
|
|
82
|
+
export function parseEnvironmentPolicy(value: unknown): EnvironmentPolicy {
|
|
83
|
+
const root = object(
|
|
84
|
+
value,
|
|
85
|
+
["schemaVersion", "build", "features"],
|
|
86
|
+
["runtime", "antivirus"],
|
|
87
|
+
);
|
|
88
|
+
if (root.schemaVersion !== 1) throw new Error("不支持的环境预设版本");
|
|
89
|
+
const build = object(root.build, ["modules"], ["runtimes"]);
|
|
90
|
+
const modules = strings(build.modules, /^[a-z][a-z0-9.-]*$/);
|
|
91
|
+
if (!Array.isArray(root.features) || root.features.length > 128)
|
|
92
|
+
throw new Error("功能评估配置超出上限");
|
|
93
|
+
const features = root.features.map((value): FeatureEnvironmentPolicy => {
|
|
94
|
+
const row = object(
|
|
95
|
+
value,
|
|
96
|
+
["key", "title", "execution"],
|
|
97
|
+
[
|
|
98
|
+
"recommendedEnabled",
|
|
99
|
+
"supportedPlatforms",
|
|
100
|
+
"supportedArchitectures",
|
|
101
|
+
"minMemoryGiB",
|
|
102
|
+
"requiredEnvironmentKeys",
|
|
103
|
+
],
|
|
104
|
+
);
|
|
105
|
+
const [key] = strings([row.key], /^[a-z][a-z0-9.-]*$/);
|
|
106
|
+
if (
|
|
107
|
+
typeof row.title !== "string" ||
|
|
108
|
+
!row.title.trim() ||
|
|
109
|
+
row.title.length > 120
|
|
110
|
+
)
|
|
111
|
+
throw new Error("功能评估标题无效");
|
|
112
|
+
if (!["none", "cpu", "local-gpu", "remote"].includes(String(row.execution)))
|
|
113
|
+
throw new Error("功能执行方式无效");
|
|
114
|
+
if (
|
|
115
|
+
row.recommendedEnabled !== undefined &&
|
|
116
|
+
typeof row.recommendedEnabled !== "boolean"
|
|
117
|
+
)
|
|
118
|
+
throw new Error("推荐开关必须为布尔值");
|
|
119
|
+
if (
|
|
120
|
+
row.minMemoryGiB !== undefined &&
|
|
121
|
+
(typeof row.minMemoryGiB !== "number" ||
|
|
122
|
+
!Number.isFinite(row.minMemoryGiB) ||
|
|
123
|
+
row.minMemoryGiB <= 0 ||
|
|
124
|
+
row.minMemoryGiB > 65536)
|
|
125
|
+
)
|
|
126
|
+
throw new Error("最低内存要求无效");
|
|
127
|
+
return {
|
|
128
|
+
key: key!,
|
|
129
|
+
title: row.title,
|
|
130
|
+
execution: row.execution as FeatureEnvironmentPolicy["execution"],
|
|
131
|
+
...(row.recommendedEnabled === undefined
|
|
132
|
+
? {}
|
|
133
|
+
: { recommendedEnabled: row.recommendedEnabled as boolean }),
|
|
134
|
+
...(row.minMemoryGiB === undefined
|
|
135
|
+
? {}
|
|
136
|
+
: { minMemoryGiB: row.minMemoryGiB as number }),
|
|
137
|
+
...(row.supportedPlatforms === undefined
|
|
138
|
+
? {}
|
|
139
|
+
: {
|
|
140
|
+
supportedPlatforms: strings(
|
|
141
|
+
row.supportedPlatforms,
|
|
142
|
+
/^(linux|darwin|win32)$/,
|
|
143
|
+
),
|
|
144
|
+
}),
|
|
145
|
+
...(row.supportedArchitectures === undefined
|
|
146
|
+
? {}
|
|
147
|
+
: {
|
|
148
|
+
supportedArchitectures: strings(
|
|
149
|
+
row.supportedArchitectures,
|
|
150
|
+
/^(x64|arm64|arm|ia32|ppc64|s390x|riscv64|loong64)$/,
|
|
151
|
+
),
|
|
152
|
+
}),
|
|
153
|
+
...(row.requiredEnvironmentKeys === undefined
|
|
154
|
+
? {}
|
|
155
|
+
: {
|
|
156
|
+
requiredEnvironmentKeys: strings(
|
|
157
|
+
row.requiredEnvironmentKeys,
|
|
158
|
+
/^[A-Z][A-Z0-9_]*$/,
|
|
159
|
+
),
|
|
160
|
+
}),
|
|
161
|
+
};
|
|
162
|
+
});
|
|
163
|
+
if (new Set(features.map(({ key }) => key)).size !== features.length)
|
|
164
|
+
throw new Error("功能评估 Key 重复");
|
|
165
|
+
const runtime = Object.hasOwn(root, "runtime")
|
|
166
|
+
? parseRuntimeSwitches(root.runtime)
|
|
167
|
+
: undefined;
|
|
168
|
+
const runtimes = Object.hasOwn(build, "runtimes")
|
|
169
|
+
? parseRuntimeSwitches(build.runtimes)
|
|
170
|
+
: undefined;
|
|
171
|
+
for (const kind of AI_RUNTIME_KINDS) {
|
|
172
|
+
if (runtimes?.[kind] === false && runtime?.[kind] === true)
|
|
173
|
+
throw new Error(`运行时未随包交付:${kind}`);
|
|
174
|
+
}
|
|
175
|
+
const antivirus = Object.hasOwn(root, "antivirus")
|
|
176
|
+
? parseAntivirusPolicy(root.antivirus)
|
|
177
|
+
: undefined;
|
|
178
|
+
return {
|
|
179
|
+
schemaVersion: 1,
|
|
180
|
+
build: { modules, ...(runtimes ? { runtimes } : {}) },
|
|
181
|
+
features,
|
|
182
|
+
...(runtime ? { runtime } : {}),
|
|
183
|
+
...(antivirus ? { antivirus } : {}),
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function parseRuntimeSwitches(value: unknown): AiRuntimeSwitches {
|
|
188
|
+
const switches = object(value, [], [...AI_RUNTIME_KINDS]);
|
|
189
|
+
const runtime: AiRuntimeSwitches = {};
|
|
190
|
+
for (const kind of AI_RUNTIME_KINDS) {
|
|
191
|
+
if (!Object.hasOwn(switches, kind)) continue;
|
|
192
|
+
const enabled = switches[kind];
|
|
193
|
+
if (typeof enabled !== "boolean") throw new Error("运行时开关必须为布尔值");
|
|
194
|
+
runtime[kind] = enabled;
|
|
195
|
+
}
|
|
196
|
+
return runtime;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function parseAntivirusPolicy(value: unknown): AntivirusEnvironmentPolicy {
|
|
200
|
+
const { packaged, enabled } = object(value, ["packaged", "enabled"]);
|
|
201
|
+
if (typeof packaged !== "boolean" || typeof enabled !== "boolean")
|
|
202
|
+
throw new Error("病毒扫描交付和启用设置必须为布尔值");
|
|
203
|
+
if (enabled && !packaged) throw new Error("病毒扫描未随项目交付,不能启用");
|
|
204
|
+
return { packaged, enabled };
|
|
205
|
+
}
|
|
@@ -101,6 +101,13 @@ export const LICENSE_CONSOLE_CAPABILITIES = {
|
|
|
101
101
|
apis: ["POST /api/auth/sessions/:id/revoke"],
|
|
102
102
|
auditActions: ["auth.session.revoke"],
|
|
103
103
|
},
|
|
104
|
+
profile: {
|
|
105
|
+
feature: "license.profile",
|
|
106
|
+
permission: "license.profile.update",
|
|
107
|
+
entry: "profile",
|
|
108
|
+
apis: ["PATCH /api/auth/me"],
|
|
109
|
+
auditActions: ["license.operator.updated"],
|
|
110
|
+
},
|
|
104
111
|
audit: {
|
|
105
112
|
feature: "license.audit",
|
|
106
113
|
permission: "license.audit.read",
|
package/src/license.ts
CHANGED
|
@@ -20,7 +20,8 @@ export interface ModuleConfigFieldDescriptor {
|
|
|
20
20
|
path: string;
|
|
21
21
|
label: string;
|
|
22
22
|
description: string;
|
|
23
|
-
input: "boolean" | "integer" | "text";
|
|
23
|
+
input: "boolean" | "integer" | "text" | "time-zone";
|
|
24
|
+
unit?: "bytes";
|
|
24
25
|
applyMode?: ModuleConfigApplyMode;
|
|
25
26
|
minimum?: number;
|
|
26
27
|
maximum?: number;
|