@sema-agent/settings-schema 6.4.0 → 7.0.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/CHANGELOG.md +159 -0
- package/README.md +34 -2
- package/bin/settings-schema.mjs +22 -0
- package/conformance/VERSION +1 -1
- package/conformance/cases/c50-s784-lane-host-legal/expected.json +102 -0
- package/conformance/cases/c50-s784-lane-host-legal/input.json +29 -0
- package/conformance/cases/c50-s784-lane-host-legal/meta.json +5 -0
- package/conformance/cases/c51-s784-lane-e2b-legal/expected.json +104 -0
- package/conformance/cases/c51-s784-lane-e2b-legal/input.json +32 -0
- package/conformance/cases/c51-s784-lane-e2b-legal/meta.json +5 -0
- package/conformance/cases/c52-s784-lane-k8s-legal/expected.json +106 -0
- package/conformance/cases/c52-s784-lane-k8s-legal/input.json +34 -0
- package/conformance/cases/c52-s784-lane-k8s-legal/meta.json +5 -0
- package/conformance/cases/c53-s784-lane-ssh-legal/expected.json +106 -0
- package/conformance/cases/c53-s784-lane-ssh-legal/input.json +34 -0
- package/conformance/cases/c53-s784-lane-ssh-legal/meta.json +5 -0
- package/conformance/cases/c54-s784-lane-adb-legal/expected.json +102 -0
- package/conformance/cases/c54-s784-lane-adb-legal/input.json +29 -0
- package/conformance/cases/c54-s784-lane-adb-legal/meta.json +5 -0
- package/conformance/cases/c55-s784-lane-local-docker-legal/expected.json +103 -0
- package/conformance/cases/c55-s784-lane-local-docker-legal/input.json +30 -0
- package/conformance/cases/c55-s784-lane-local-docker-legal/meta.json +5 -0
- package/conformance/cases/c56-s784-lane-device-legal/expected.json +109 -0
- package/conformance/cases/c56-s784-lane-device-legal/input.json +36 -0
- package/conformance/cases/c56-s784-lane-device-legal/meta.json +5 -0
- package/conformance/cases/c57-s784-g1-enabled-no-lane/expected.json +83 -0
- package/conformance/cases/c57-s784-g1-enabled-no-lane/input.json +23 -0
- package/conformance/cases/c57-s784-g1-enabled-no-lane/meta.json +5 -0
- package/conformance/cases/c58-s784-g2-multitenant-host/expected.json +83 -0
- package/conformance/cases/c58-s784-g2-multitenant-host/input.json +34 -0
- package/conformance/cases/c58-s784-g2-multitenant-host/meta.json +5 -0
- package/conformance/cases/c59-s784-g3-k8s-missing-image/expected.json +83 -0
- package/conformance/cases/c59-s784-g3-k8s-missing-image/input.json +26 -0
- package/conformance/cases/c59-s784-g3-k8s-missing-image/meta.json +5 -0
- package/conformance/cases/c60-s784-g3-e2b-missing-key/expected.json +83 -0
- package/conformance/cases/c60-s784-g3-e2b-missing-key/input.json +26 -0
- package/conformance/cases/c60-s784-g3-e2b-missing-key/meta.json +5 -0
- package/conformance/cases/c61-s784-g3-other-lane-key/expected.json +83 -0
- package/conformance/cases/c61-s784-g3-other-lane-key/input.json +30 -0
- package/conformance/cases/c61-s784-g3-other-lane-key/meta.json +5 -0
- package/conformance/cases/c62-s784-g7a-session-tidb/expected.json +83 -0
- package/conformance/cases/c62-s784-g7a-session-tidb/input.json +27 -0
- package/conformance/cases/c62-s784-g7a-session-tidb/meta.json +5 -0
- package/conformance/cases/c63-s784-host-two-replicas/expected.json +83 -0
- package/conformance/cases/c63-s784-host-two-replicas/input.json +27 -0
- package/conformance/cases/c63-s784-host-two-replicas/meta.json +5 -0
- package/conformance/cases/c64-s784-multitenant-local-store/expected.json +83 -0
- package/conformance/cases/c64-s784-multitenant-local-store/input.json +30 -0
- package/conformance/cases/c64-s784-multitenant-local-store/meta.json +5 -0
- package/conformance/cases/c65-s784-pg-without-db/expected.json +83 -0
- package/conformance/cases/c65-s784-pg-without-db/input.json +27 -0
- package/conformance/cases/c65-s784-pg-without-db/meta.json +5 -0
- package/conformance/cases/c66-s784-memory-backend-mismatch/expected.json +83 -0
- package/conformance/cases/c66-s784-memory-backend-mismatch/input.json +36 -0
- package/conformance/cases/c66-s784-memory-backend-mismatch/meta.json +5 -0
- package/conformance/cases/c67-s784-retired-field-loud/expected.json +83 -0
- package/conformance/cases/c67-s784-retired-field-loud/input.json +22 -0
- package/conformance/cases/c67-s784-retired-field-loud/meta.json +5 -0
- package/conformance/cases/c68-s784-device-local-store/expected.json +83 -0
- package/conformance/cases/c68-s784-device-local-store/input.json +26 -0
- package/conformance/cases/c68-s784-device-local-store/meta.json +5 -0
- package/conformance/cases/cli04-env-value-with-newline/expected.json +13 -2
- package/conformance/cases/cli04-env-value-with-newline/input.json +8 -1
- package/conformance/cases/cli04-env-value-with-newline/meta.json +1 -1
- package/conformance/migrate-workers/m01-g5-k8s-env-lifted/expected.json +49 -0
- package/conformance/migrate-workers/m01-g5-k8s-env-lifted/input.json +26 -0
- package/conformance/migrate-workers/m01-g5-k8s-env-lifted/meta.json +4 -0
- package/conformance/migrate-workers/m02-g5-idempotent/expected.json +38 -0
- package/conformance/migrate-workers/m02-g5-idempotent/input.json +33 -0
- package/conformance/migrate-workers/m02-g5-idempotent/meta.json +5 -0
- package/conformance/migrate-workers/m03-g5-refused-no-lane/expected.json +71 -0
- package/conformance/migrate-workers/m03-g5-refused-no-lane/input.json +42 -0
- package/conformance/migrate-workers/m03-g5-refused-no-lane/meta.json +4 -0
- package/conformance/migrate-workers/m04-g7b-session-tidb-lifted/expected.json +52 -0
- package/conformance/migrate-workers/m04-g7b-session-tidb-lifted/input.json +30 -0
- package/conformance/migrate-workers/m04-g7b-session-tidb-lifted/meta.json +4 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.js +70 -0
- package/dist/execution-lane-index.d.ts +19 -0
- package/dist/execution-lane-index.js +23 -0
- package/dist/execution-lanes.d.ts +64 -0
- package/dist/execution-lanes.js +152 -0
- package/dist/file-edit.js +26 -21
- package/dist/hooks.d.ts +4 -4
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/migrate-workers.d.ts +63 -0
- package/dist/migrate-workers.js +331 -0
- package/dist/remote-exec.d.ts +23 -64
- package/dist/remote-exec.js +20 -71
- package/dist/secret-refs.d.ts +7 -1
- package/dist/secret-refs.js +9 -3
- package/dist/types.d.ts +1356 -455
- package/dist/types.js +258 -63
- package/package.json +9 -1
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
{
|
|
2
|
+
"domains": {
|
|
3
|
+
"outcome": "rejected",
|
|
4
|
+
"stage": "validate",
|
|
5
|
+
"why": "7.0.0 写闸(WorkerSpec)拒 —— workers 是 gate 域,一只坏 worker 整域拒,不逐条容错"
|
|
6
|
+
},
|
|
7
|
+
"wire": {
|
|
8
|
+
"outcome": "rejected",
|
|
9
|
+
"stage": "validate",
|
|
10
|
+
"why": "wire 腿把同一份文档交给同一个 buildEffective,拒绝层相同"
|
|
11
|
+
},
|
|
12
|
+
"localRoot": {
|
|
13
|
+
"outcome": "effective",
|
|
14
|
+
"effective": {
|
|
15
|
+
"collab": {
|
|
16
|
+
"templates": []
|
|
17
|
+
},
|
|
18
|
+
"entitlement": {
|
|
19
|
+
"budgetGroups": [],
|
|
20
|
+
"groupBindings": [],
|
|
21
|
+
"subjects": [],
|
|
22
|
+
"tiers": []
|
|
23
|
+
},
|
|
24
|
+
"execution": {
|
|
25
|
+
"allowedLanes": [
|
|
26
|
+
"host"
|
|
27
|
+
],
|
|
28
|
+
"required": false
|
|
29
|
+
},
|
|
30
|
+
"governance": {},
|
|
31
|
+
"hosts": {
|
|
32
|
+
"hosts": []
|
|
33
|
+
},
|
|
34
|
+
"limits": {},
|
|
35
|
+
"mcp": {
|
|
36
|
+
"servers": []
|
|
37
|
+
},
|
|
38
|
+
"models": {
|
|
39
|
+
"models": [],
|
|
40
|
+
"roles": {},
|
|
41
|
+
"tierGroups": []
|
|
42
|
+
},
|
|
43
|
+
"plugins": {
|
|
44
|
+
"plugins": []
|
|
45
|
+
},
|
|
46
|
+
"projects": {
|
|
47
|
+
"projects": {}
|
|
48
|
+
},
|
|
49
|
+
"prompts": {
|
|
50
|
+
"bindings": []
|
|
51
|
+
},
|
|
52
|
+
"rosters": {
|
|
53
|
+
"rosters": []
|
|
54
|
+
},
|
|
55
|
+
"runtime": {},
|
|
56
|
+
"scenarios": {
|
|
57
|
+
"scenarios": []
|
|
58
|
+
},
|
|
59
|
+
"skills": {
|
|
60
|
+
"skills": []
|
|
61
|
+
},
|
|
62
|
+
"systems": {
|
|
63
|
+
"systems": []
|
|
64
|
+
},
|
|
65
|
+
"workers": {
|
|
66
|
+
"workers": []
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"warnings": [
|
|
70
|
+
{
|
|
71
|
+
"domain": "workers",
|
|
72
|
+
"file": "workers.json",
|
|
73
|
+
"kind": "unread-config-file",
|
|
74
|
+
"why": "non-portable-domain"
|
|
75
|
+
}
|
|
76
|
+
],
|
|
77
|
+
"metadata": {
|
|
78
|
+
"version": 2617555914511015,
|
|
79
|
+
"updatedAt": "1970-01-01T00:00:00.000Z"
|
|
80
|
+
},
|
|
81
|
+
"why": "workers 是非便携域:本机腿不读 config.d/workers.json(只报 unread-config-file),写闸判据只在 domains / wire 两腿上可观察"
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"meta": {
|
|
3
|
+
"version": 7,
|
|
4
|
+
"updatedAt": "2026-10-03T00:00:00.000Z"
|
|
5
|
+
},
|
|
6
|
+
"domains": {
|
|
7
|
+
"workers": {
|
|
8
|
+
"workers": [
|
|
9
|
+
{
|
|
10
|
+
"name": "w",
|
|
11
|
+
"secretRefs": {
|
|
12
|
+
"apiKeyEnv": "MODEL_KEY"
|
|
13
|
+
},
|
|
14
|
+
"runtime": {
|
|
15
|
+
"execution": {
|
|
16
|
+
"lane": "device"
|
|
17
|
+
},
|
|
18
|
+
"store": {
|
|
19
|
+
"backend": "local"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -65,10 +65,21 @@
|
|
|
65
65
|
"image": "sema-server:latest",
|
|
66
66
|
"name": "w1",
|
|
67
67
|
"runtime": {
|
|
68
|
-
"
|
|
68
|
+
"execution": {
|
|
69
|
+
"coords": {},
|
|
70
|
+
"lane": "host",
|
|
71
|
+
"secretRefs": {}
|
|
72
|
+
},
|
|
69
73
|
"rateLimitRpm": 0,
|
|
70
74
|
"requirePrincipal": false,
|
|
71
|
-
"
|
|
75
|
+
"store": {
|
|
76
|
+
"backend": "local",
|
|
77
|
+
"memory": {
|
|
78
|
+
"backend": "file",
|
|
79
|
+
"engine": "on"
|
|
80
|
+
},
|
|
81
|
+
"session": "auto"
|
|
82
|
+
}
|
|
72
83
|
},
|
|
73
84
|
"secretRefs": {
|
|
74
85
|
"apiKeyEnv": "OPENAI_API_KEY"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
2
|
"contributor": "cli",
|
|
3
|
-
"claim": "壳视角④:worker 的 env 值里有换行 / 回车 ⇒ 读侧**原样承运**(不折叠、不截断、不静默改写)。壳的 `/config show` 单行渲染会断行,那是显示面的事;读侧一改,配置就与运维写下的不是同一份。注意这一域是非便携域:local-root 腿看不到它,只报 unread-config-file —— 三腿三样,壳要知道自己问的是哪一腿。",
|
|
3
|
+
"claim": "壳视角④:worker 的 env 值里有换行 / 回车 ⇒ 读侧**原样承运**(不折叠、不截断、不静默改写)。壳的 `/config show` 单行渲染会断行,那是显示面的事;读侧一改,配置就与运维写下的不是同一份。注意这一域是非便携域:local-root 腿看不到它,只报 unread-config-file —— 三腿三样,壳要知道自己问的是哪一腿。 (7.0.0:输入的 worker 改成 7.0.0 形 —— 显式声明 `runtime.execution {lane: host}` + `runtime.store {backend: local}`。6.x 原输入是 enabled 且无车道的 `runtime: {}`,正是 WA-49 病例,一次性迁移对它是 refused,迁不出可读形;本条要打的是 env 值的承运,与车道无关,所以按新形写明车道,不是放宽读侧。)",
|
|
4
4
|
"firstRedOn": []
|
|
5
5
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"doc": {
|
|
3
|
+
"workers": [
|
|
4
|
+
{
|
|
5
|
+
"name": "direct",
|
|
6
|
+
"enabled": true,
|
|
7
|
+
"host": "default",
|
|
8
|
+
"image": "sema-server:latest",
|
|
9
|
+
"secretRefs": {
|
|
10
|
+
"apiKeyEnv": "MODEL_KEY"
|
|
11
|
+
},
|
|
12
|
+
"runtime": {
|
|
13
|
+
"requirePrincipal": false,
|
|
14
|
+
"rateLimitRpm": 0,
|
|
15
|
+
"execution": {
|
|
16
|
+
"lane": "k8s",
|
|
17
|
+
"coords": {
|
|
18
|
+
"K8S_SANDBOX_IMAGE": "registry.internal/sandbox@sha256:abc",
|
|
19
|
+
"K8S_NAMESPACE": "sandboxes"
|
|
20
|
+
},
|
|
21
|
+
"secretRefs": {}
|
|
22
|
+
},
|
|
23
|
+
"store": {
|
|
24
|
+
"backend": "local",
|
|
25
|
+
"session": "auto"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"coords": {},
|
|
29
|
+
"env": {
|
|
30
|
+
"LOG_LEVEL": "debug"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
"changed": [
|
|
36
|
+
"direct"
|
|
37
|
+
],
|
|
38
|
+
"dropped": [
|
|
39
|
+
{
|
|
40
|
+
"name": "direct",
|
|
41
|
+
"index": 0,
|
|
42
|
+
"field": [
|
|
43
|
+
"runtime",
|
|
44
|
+
"memoryBackend"
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
"refused": []
|
|
49
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"workers": [
|
|
3
|
+
{
|
|
4
|
+
"name": "direct",
|
|
5
|
+
"enabled": true,
|
|
6
|
+
"host": "default",
|
|
7
|
+
"image": "sema-server:latest",
|
|
8
|
+
"secretRefs": {
|
|
9
|
+
"apiKeyEnv": "MODEL_KEY"
|
|
10
|
+
},
|
|
11
|
+
"runtime": {
|
|
12
|
+
"sessionBackend": "auto",
|
|
13
|
+
"memoryBackend": "off",
|
|
14
|
+
"requirePrincipal": false,
|
|
15
|
+
"rateLimitRpm": 0
|
|
16
|
+
},
|
|
17
|
+
"coords": {},
|
|
18
|
+
"env": {
|
|
19
|
+
"REMOTE_EXEC": "k8s",
|
|
20
|
+
"K8S_SANDBOX_IMAGE": "registry.internal/sandbox@sha256:abc",
|
|
21
|
+
"K8S_NAMESPACE": "sandboxes",
|
|
22
|
+
"LOG_LEVEL": "debug"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"doc": {
|
|
3
|
+
"workers": [
|
|
4
|
+
{
|
|
5
|
+
"name": "direct",
|
|
6
|
+
"enabled": true,
|
|
7
|
+
"host": "default",
|
|
8
|
+
"image": "sema-server:latest",
|
|
9
|
+
"secretRefs": {
|
|
10
|
+
"apiKeyEnv": "MODEL_KEY"
|
|
11
|
+
},
|
|
12
|
+
"runtime": {
|
|
13
|
+
"requirePrincipal": false,
|
|
14
|
+
"rateLimitRpm": 0,
|
|
15
|
+
"execution": {
|
|
16
|
+
"lane": "k8s",
|
|
17
|
+
"coords": {
|
|
18
|
+
"K8S_SANDBOX_IMAGE": "registry.internal/sandbox@sha256:abc",
|
|
19
|
+
"K8S_NAMESPACE": "sandboxes"
|
|
20
|
+
},
|
|
21
|
+
"secretRefs": {}
|
|
22
|
+
},
|
|
23
|
+
"store": {
|
|
24
|
+
"backend": "local",
|
|
25
|
+
"session": "auto"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"coords": {},
|
|
29
|
+
"env": {
|
|
30
|
+
"LOG_LEVEL": "debug"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
"changed": [],
|
|
36
|
+
"dropped": [],
|
|
37
|
+
"refused": []
|
|
38
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"workers": [
|
|
3
|
+
{
|
|
4
|
+
"name": "direct",
|
|
5
|
+
"enabled": true,
|
|
6
|
+
"host": "default",
|
|
7
|
+
"image": "sema-server:latest",
|
|
8
|
+
"secretRefs": {
|
|
9
|
+
"apiKeyEnv": "MODEL_KEY"
|
|
10
|
+
},
|
|
11
|
+
"runtime": {
|
|
12
|
+
"requirePrincipal": false,
|
|
13
|
+
"rateLimitRpm": 0,
|
|
14
|
+
"execution": {
|
|
15
|
+
"lane": "k8s",
|
|
16
|
+
"coords": {
|
|
17
|
+
"K8S_SANDBOX_IMAGE": "registry.internal/sandbox@sha256:abc",
|
|
18
|
+
"K8S_NAMESPACE": "sandboxes"
|
|
19
|
+
},
|
|
20
|
+
"secretRefs": {}
|
|
21
|
+
},
|
|
22
|
+
"store": {
|
|
23
|
+
"backend": "local",
|
|
24
|
+
"session": "auto"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"coords": {},
|
|
28
|
+
"env": {
|
|
29
|
+
"LOG_LEVEL": "debug"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"doc": {
|
|
3
|
+
"workers": [
|
|
4
|
+
{
|
|
5
|
+
"name": "canary",
|
|
6
|
+
"enabled": true,
|
|
7
|
+
"host": "default",
|
|
8
|
+
"image": "sema-server:latest",
|
|
9
|
+
"secretRefs": {
|
|
10
|
+
"apiKeyEnv": "MODEL_KEY"
|
|
11
|
+
},
|
|
12
|
+
"runtime": {
|
|
13
|
+
"requirePrincipal": false,
|
|
14
|
+
"rateLimitRpm": 0,
|
|
15
|
+
"execution": {
|
|
16
|
+
"lane": "e2b",
|
|
17
|
+
"coords": {},
|
|
18
|
+
"secretRefs": {
|
|
19
|
+
"E2B_API_KEY": "HOST_E2B_KEY"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"store": {
|
|
23
|
+
"backend": "local",
|
|
24
|
+
"session": "auto"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"coords": {}
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
},
|
|
31
|
+
"changed": [
|
|
32
|
+
"canary"
|
|
33
|
+
],
|
|
34
|
+
"dropped": [
|
|
35
|
+
{
|
|
36
|
+
"name": "canary",
|
|
37
|
+
"index": 1,
|
|
38
|
+
"field": [
|
|
39
|
+
"runtime",
|
|
40
|
+
"memoryBackend"
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
],
|
|
44
|
+
"refused": [
|
|
45
|
+
{
|
|
46
|
+
"name": "handless",
|
|
47
|
+
"index": 0,
|
|
48
|
+
"field": [
|
|
49
|
+
"env",
|
|
50
|
+
"REMOTE_EXEC"
|
|
51
|
+
],
|
|
52
|
+
"reason": "an enabled worker names no execution lane (env.REMOTE_EXEC is unset) — it boots with no hands and still reports tasks completed. The migration does not guess a lane: set runtime.execution.lane (host | e2b | k8s | ssh | adb | local-docker | device) by hand, or disable the worker",
|
|
53
|
+
"original": {
|
|
54
|
+
"name": "handless",
|
|
55
|
+
"enabled": true,
|
|
56
|
+
"host": "default",
|
|
57
|
+
"image": "sema-server:latest",
|
|
58
|
+
"secretRefs": {
|
|
59
|
+
"apiKeyEnv": "MODEL_KEY"
|
|
60
|
+
},
|
|
61
|
+
"runtime": {
|
|
62
|
+
"sessionBackend": "auto",
|
|
63
|
+
"memoryBackend": "off",
|
|
64
|
+
"requirePrincipal": false,
|
|
65
|
+
"rateLimitRpm": 0
|
|
66
|
+
},
|
|
67
|
+
"coords": {}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"workers": [
|
|
3
|
+
{
|
|
4
|
+
"name": "handless",
|
|
5
|
+
"enabled": true,
|
|
6
|
+
"host": "default",
|
|
7
|
+
"image": "sema-server:latest",
|
|
8
|
+
"secretRefs": {
|
|
9
|
+
"apiKeyEnv": "MODEL_KEY"
|
|
10
|
+
},
|
|
11
|
+
"runtime": {
|
|
12
|
+
"sessionBackend": "auto",
|
|
13
|
+
"memoryBackend": "off",
|
|
14
|
+
"requirePrincipal": false,
|
|
15
|
+
"rateLimitRpm": 0
|
|
16
|
+
},
|
|
17
|
+
"coords": {}
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"name": "canary",
|
|
21
|
+
"enabled": true,
|
|
22
|
+
"host": "default",
|
|
23
|
+
"image": "sema-server:latest",
|
|
24
|
+
"secretRefs": {
|
|
25
|
+
"apiKeyEnv": "MODEL_KEY"
|
|
26
|
+
},
|
|
27
|
+
"runtime": {
|
|
28
|
+
"sessionBackend": "auto",
|
|
29
|
+
"memoryBackend": "off",
|
|
30
|
+
"requirePrincipal": false,
|
|
31
|
+
"rateLimitRpm": 0
|
|
32
|
+
},
|
|
33
|
+
"coords": {},
|
|
34
|
+
"env": {
|
|
35
|
+
"REMOTE_EXEC": "e2b"
|
|
36
|
+
},
|
|
37
|
+
"secretEnv": {
|
|
38
|
+
"E2B_API_KEY": "HOST_E2B_KEY"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"doc": {
|
|
3
|
+
"workers": [
|
|
4
|
+
{
|
|
5
|
+
"name": "persist",
|
|
6
|
+
"enabled": true,
|
|
7
|
+
"host": "default",
|
|
8
|
+
"image": "sema-server:latest",
|
|
9
|
+
"secretRefs": {
|
|
10
|
+
"apiKeyEnv": "MODEL_KEY",
|
|
11
|
+
"dbPasswordEnv": "HOST_TIDB_PW"
|
|
12
|
+
},
|
|
13
|
+
"runtime": {
|
|
14
|
+
"requirePrincipal": false,
|
|
15
|
+
"rateLimitRpm": 0,
|
|
16
|
+
"execution": {
|
|
17
|
+
"lane": "host",
|
|
18
|
+
"coords": {},
|
|
19
|
+
"secretRefs": {}
|
|
20
|
+
},
|
|
21
|
+
"store": {
|
|
22
|
+
"backend": "mysql",
|
|
23
|
+
"session": "mysql",
|
|
24
|
+
"db": {
|
|
25
|
+
"host": "tidb.internal",
|
|
26
|
+
"port": 4000,
|
|
27
|
+
"user": "svc",
|
|
28
|
+
"database": "sema"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"coords": {
|
|
33
|
+
"gitApiBaseUrl": "https://git.internal"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
"changed": [
|
|
39
|
+
"persist"
|
|
40
|
+
],
|
|
41
|
+
"dropped": [
|
|
42
|
+
{
|
|
43
|
+
"name": "persist",
|
|
44
|
+
"index": 0,
|
|
45
|
+
"field": [
|
|
46
|
+
"runtime",
|
|
47
|
+
"memoryBackend"
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
],
|
|
51
|
+
"refused": []
|
|
52
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"workers": [
|
|
3
|
+
{
|
|
4
|
+
"name": "persist",
|
|
5
|
+
"enabled": true,
|
|
6
|
+
"host": "default",
|
|
7
|
+
"image": "sema-server:latest",
|
|
8
|
+
"secretRefs": {
|
|
9
|
+
"apiKeyEnv": "MODEL_KEY",
|
|
10
|
+
"tidbPasswordEnv": "HOST_TIDB_PW"
|
|
11
|
+
},
|
|
12
|
+
"runtime": {
|
|
13
|
+
"sessionBackend": "tidb",
|
|
14
|
+
"memoryBackend": "off",
|
|
15
|
+
"requirePrincipal": false,
|
|
16
|
+
"rateLimitRpm": 0,
|
|
17
|
+
"db": "sema"
|
|
18
|
+
},
|
|
19
|
+
"coords": {
|
|
20
|
+
"gitApiBaseUrl": "https://git.internal",
|
|
21
|
+
"tidbHost": "tidb.internal",
|
|
22
|
+
"tidbPort": 4000,
|
|
23
|
+
"tidbUser": "svc"
|
|
24
|
+
},
|
|
25
|
+
"env": {
|
|
26
|
+
"REMOTE_EXEC": "host"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** 入口注入的 I/O(核心不碰 node:fs)。`writeFileAtomic` 必须原子(写临时文件再改名):半写的 workers 文档比旧文档更糟。 */
|
|
2
|
+
export interface SettingsSchemaCliIo {
|
|
3
|
+
readFile(path: string): Promise<string>;
|
|
4
|
+
writeFileAtomic(path: string, text: string): Promise<void>;
|
|
5
|
+
stdout(text: string): void;
|
|
6
|
+
stderr(text: string): void;
|
|
7
|
+
}
|
|
8
|
+
export declare function runSettingsSchemaCli(argv: readonly string[], io: SettingsSchemaCliIo): Promise<number>;
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `settings-schema` 命令行的核心(7.0.0)—— 子命令只有一个:`migrate-workers <workers.json> [--check]`,即
|
|
3
|
+
* {@link migrateWorkersDomain} 的文件形(文件后端 / 离线用;中心在它的 workers 读口直接调同一只函数)。
|
|
4
|
+
*
|
|
5
|
+
* 本模块不碰 `node:fs`:读写文件由入口 `bin/settings-schema.mjs` 注入(那是本包唯一用 fs 写文件的地方),所以测试可以直接驱动它。
|
|
6
|
+
* 不进主桶 —— 它是 bin 的实现,不是契约面。
|
|
7
|
+
*
|
|
8
|
+
* 退出码:0 = 已写回 / 无事可做;1 = 有 worker 迁不了(refused)或迁出的文档整域读不进 7.0.0,**一字不写**;2 = 用法 / 读文件 /
|
|
9
|
+
* JSON 错;3 = `--check` 且会有改动(不写)。stdout 恒打一行 JSON 报告(`event: "workers_domain_migrated"`,只点名字段、不带值)。
|
|
10
|
+
*/
|
|
11
|
+
import { formatConfigPath, sanitizeZodError } from "./config-fns.js";
|
|
12
|
+
import { migrateWorkersDomain } from "./migrate-workers.js";
|
|
13
|
+
import { DOMAIN_SCHEMAS } from "./types.js";
|
|
14
|
+
const USAGE = [
|
|
15
|
+
"usage: settings-schema migrate-workers <workers.json> [--check]",
|
|
16
|
+
" One-time 7.0.0 migration of a workers domain document ({ \"workers\": [...] }): env.REMOTE_EXEC + lane keys →",
|
|
17
|
+
" runtime.execution, sessionBackend / coords.tidb* / runtime.db / tidbPasswordEnv → runtime.store. Writes the file in",
|
|
18
|
+
" place only when every worker migrates; --check only reports (exit 3 if the file would change).",
|
|
19
|
+
].join("\n");
|
|
20
|
+
export async function runSettingsSchemaCli(argv, io) {
|
|
21
|
+
const [command, ...rest] = argv;
|
|
22
|
+
const check = rest.includes("--check");
|
|
23
|
+
const files = rest.filter((a) => a !== "--check");
|
|
24
|
+
const file = files[0];
|
|
25
|
+
if (command !== "migrate-workers" || files.length !== 1 || file === undefined || file.startsWith("-")) {
|
|
26
|
+
io.stderr(`${USAGE}\n`);
|
|
27
|
+
return 2;
|
|
28
|
+
}
|
|
29
|
+
let text;
|
|
30
|
+
try {
|
|
31
|
+
text = await io.readFile(file);
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
io.stderr(`settings-schema: cannot read ${file}: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
35
|
+
return 2;
|
|
36
|
+
}
|
|
37
|
+
let doc;
|
|
38
|
+
try {
|
|
39
|
+
doc = JSON.parse(text);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
io.stderr(`settings-schema: ${file} is not valid JSON\n`);
|
|
43
|
+
return 2;
|
|
44
|
+
}
|
|
45
|
+
const m = migrateWorkersDomain(doc);
|
|
46
|
+
io.stdout(`${JSON.stringify({
|
|
47
|
+
event: "workers_domain_migrated",
|
|
48
|
+
file,
|
|
49
|
+
changed: m.changed,
|
|
50
|
+
dropped: m.dropped.map((d) => ({ name: d.name, field: formatConfigPath(d.field) })),
|
|
51
|
+
refused: m.refused.map((r) => ({ name: r.name, field: formatConfigPath(r.field), reason: r.reason })),
|
|
52
|
+
})}\n`);
|
|
53
|
+
if (m.refused.length > 0) {
|
|
54
|
+
io.stderr(`settings-schema: ${m.refused.length} worker(s) cannot be migrated (see "refused") — fix them by hand and re-run; nothing was written\n`);
|
|
55
|
+
return 1;
|
|
56
|
+
}
|
|
57
|
+
if (m.changed.length === 0)
|
|
58
|
+
return 0;
|
|
59
|
+
if (check)
|
|
60
|
+
return 3;
|
|
61
|
+
// 整域再判一次(域层规则:名字 / 路由唯一 …)—— 读不进 7.0.0 的文档不落盘。
|
|
62
|
+
const whole = DOMAIN_SCHEMAS.workers.safeParse(m.doc);
|
|
63
|
+
if (!whole.success) {
|
|
64
|
+
const issues = sanitizeZodError(whole.error).issues.map((i) => `${formatConfigPath(i.path)}: ${i.message}`);
|
|
65
|
+
io.stderr(`settings-schema: the migrated document does not read as a 7.0.0 workers domain — ${issues.join("; ")}; nothing was written\n`);
|
|
66
|
+
return 1;
|
|
67
|
+
}
|
|
68
|
+
await io.writeFileAtomic(file, `${JSON.stringify(m.doc, null, 2)}\n`);
|
|
69
|
+
return 0;
|
|
70
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 包内私有:车道表({@link EXECUTION_LANES})的两只**派生索引**,供 `types.ts`(写闸)与 `migrate-workers.ts`(一次性迁移)同读。
|
|
3
|
+
* 不进主桶、不进 `package.json` 的 `exports`(与 `secret-scan.ts` 同一姿势)—— 消费方只拿表本身,索引是本包的实现细节。
|
|
4
|
+
* 索引只从表派生,不另存任何词:表改了,这里跟着变。
|
|
5
|
+
*/
|
|
6
|
+
import { type ExecutionLane, type ExecutionLaneRow } from "./execution-lanes.js";
|
|
7
|
+
/** 一条车道的表行。词表与表行由 `execution-lanes.ts` 的 `satisfies Record<ExecutionLane, …>` 一一对应 ——
|
|
8
|
+
* 找不到 = 本包自身的不变量坏了(不是输入错),所以抛。 */
|
|
9
|
+
export declare function laneRowOf(lane: ExecutionLane): ExecutionLaneRow;
|
|
10
|
+
/** 一个车道 env 名归谁:哪条车道、密钥栏还是坐标栏、必需还是可选。 */
|
|
11
|
+
export interface LaneEnvOwner {
|
|
12
|
+
readonly lane: ExecutionLane;
|
|
13
|
+
readonly secret: boolean;
|
|
14
|
+
readonly required: boolean;
|
|
15
|
+
}
|
|
16
|
+
/** 车道 env 名 → 归属。四栏两两不交、跨车道不交(`test/execution-lanes-7.0.0.test.ts` 钉),所以每个名恰好一个归属。 */
|
|
17
|
+
export declare const LANE_ENV_OWNER: ReadonlyMap<string, LaneEnvOwner>;
|
|
18
|
+
/** 一个车道 env 名在 WorkerSpec 里的**唯一写位**(保留键的拒因指路用它)。 */
|
|
19
|
+
export declare function laneEnvSeat(name: string, owner: LaneEnvOwner): string;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 包内私有:车道表({@link EXECUTION_LANES})的两只**派生索引**,供 `types.ts`(写闸)与 `migrate-workers.ts`(一次性迁移)同读。
|
|
3
|
+
* 不进主桶、不进 `package.json` 的 `exports`(与 `secret-scan.ts` 同一姿势)—— 消费方只拿表本身,索引是本包的实现细节。
|
|
4
|
+
* 索引只从表派生,不另存任何词:表改了,这里跟着变。
|
|
5
|
+
*/
|
|
6
|
+
import { EXECUTION_LANES } from "./execution-lanes.js";
|
|
7
|
+
/** 一条车道的表行。词表与表行由 `execution-lanes.ts` 的 `satisfies Record<ExecutionLane, …>` 一一对应 ——
|
|
8
|
+
* 找不到 = 本包自身的不变量坏了(不是输入错),所以抛。 */
|
|
9
|
+
export function laneRowOf(lane) {
|
|
10
|
+
const row = EXECUTION_LANES.find((r) => r.lane === lane);
|
|
11
|
+
if (row === undefined)
|
|
12
|
+
throw new Error(`execution lane table has no row for "${lane}" (package invariant broken)`);
|
|
13
|
+
return row;
|
|
14
|
+
}
|
|
15
|
+
/** 车道 env 名 → 归属。四栏两两不交、跨车道不交(`test/execution-lanes-7.0.0.test.ts` 钉),所以每个名恰好一个归属。 */
|
|
16
|
+
export const LANE_ENV_OWNER = new Map(EXECUTION_LANES.flatMap((r) => {
|
|
17
|
+
const own = (names, secret, required) => names.map((k) => [k, { lane: r.lane, secret, required }]);
|
|
18
|
+
return [...own(r.requiredEnv, false, true), ...own(r.optionalEnv, false, false), ...own(r.requiredSecretEnv, true, true), ...own(r.optionalSecretEnv, true, false)];
|
|
19
|
+
}));
|
|
20
|
+
/** 一个车道 env 名在 WorkerSpec 里的**唯一写位**(保留键的拒因指路用它)。 */
|
|
21
|
+
export function laneEnvSeat(name, owner) {
|
|
22
|
+
return `runtime.execution.${owner.secret ? "secretRefs" : "coords"}.${name}`;
|
|
23
|
+
}
|