@siming-org/core 0.8.7 → 0.8.9
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/dist/index.d.ts +55 -32
- package/dist/index.js +497 -456
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -141,10 +141,16 @@ var BIZ_CODE_MESSAGES = {
|
|
|
141
141
|
TEMPLATE_DISABLED: "\u6A21\u677F\u5DF2\u505C\u7528\uFF0C\u7981\u6B62\u7528\u4E8E\u521B\u5EFA\u4EFB\u52A1\uFF08Web \u7BA1\u7406\u53F0\u53EF\u91CD\u65B0\u542F\u7528\uFF09",
|
|
142
142
|
// T202608310001:鉴权域(错误响应以 error: bizCode 为机器可判键)
|
|
143
143
|
AUTH_REQUIRED: "\u9700\u8981\u767B\u5F55\u6216\u914D\u7F6E Token\uFF08Web \u767B\u5F55\uFF1BCLI \u8FD0\u884C siming auth token set \u914D\u7F6E\uFF09",
|
|
144
|
-
|
|
144
|
+
// T202610140004:单枚重置模型退役——失效主因变为吊销,文案与治理动作对齐
|
|
145
|
+
AUTH_TOKEN_INVALID: "Token \u65E0\u6548\u6216\u5DF2\u88AB\u540A\u9500\uFF08Web \u7BA1\u7406\u53F0\u67E5\u770B/\u590D\u5236\u6709\u6548 Token\uFF0C\u6216\u91CD\u65B0\u7B7E\u53D1\u540E\u8FD0\u884C siming auth token set \u66F4\u65B0\uFF09",
|
|
145
146
|
AUTH_INVALID_CREDENTIALS: "\u8D26\u53F7\u6216\u5BC6\u7801\u9519\u8BEF",
|
|
146
147
|
AUTH_FORBIDDEN: "\u5F53\u524D\u51ED\u8BC1\u65E0\u6743\u6267\u884C\u6B64\u64CD\u4F5C\uFF08\u9879\u76EE Token \u4EC5\u9650\u672C\u9879\u76EE\u8BFB\u5199\u4E0E\u5168\u5C40\u8D44\u4EA7\u53EA\u8BFB\uFF09",
|
|
147
148
|
AUTH_ACCOUNT_EXISTS: "\u7BA1\u7406\u5458\u8D26\u53F7\u5DF2\u521D\u59CB\u5316\uFF08\u65E0\u9700\u91CD\u590D\u521B\u5EFA\uFF09",
|
|
149
|
+
// T202610140004:Token 多枚治理域。LIMIT 文案不含 scope 词(BIZ_CODE_MESSAGES 静态单源,
|
|
150
|
+
// 管理员/项目语境由端点与页面上下文给出);数值 10 = core AUTH_TOKEN_LIMIT 常量
|
|
151
|
+
AUTH_TOKEN_LIMIT: "Token \u6570\u91CF\u5DF2\u8FBE\u4E0A\u9650\uFF0810 \u679A\uFF09\uFF0C\u8BF7\u5148\u540A\u9500\u4E0D\u518D\u4F7F\u7528\u7684 Token",
|
|
152
|
+
AUTH_TOKEN_NOT_FOUND: "Token \u4E0D\u5B58\u5728\uFF08\u53EF\u80FD\u5DF2\u88AB\u540A\u9500\uFF09",
|
|
153
|
+
AUTH_TOKEN_MISSING_PROJECT_ID: "\u9879\u76EE Token \u7B7E\u53D1\u7F3A\u5C11 projectId\uFF08\u5185\u90E8\u8C03\u7528\u9519\u8BEF\uFF09",
|
|
148
154
|
// T202609010002:批量写入域(信封级——空批/超限整批拒绝并提示拆分)
|
|
149
155
|
BATCH_EMPTY: "\u6279\u91CF\u6761\u76EE\u4E3A\u7A7A\uFF08items \u81F3\u5C11 1 \u6761\uFF09",
|
|
150
156
|
BATCH_LIMIT_EXCEEDED: "\u5355\u6B21\u6279\u91CF\u4E0A\u9650 50 \u6761\uFF0C\u8BF7\u62C6\u5206\u4E3A\u591A\u6B21\u8C03\u7528",
|
|
@@ -2976,7 +2982,133 @@ function createNodeLibraryRepo(db) {
|
|
|
2976
2982
|
|
|
2977
2983
|
// src/store/repos/auth.repo.ts
|
|
2978
2984
|
import { ObjectId as ObjectId3 } from "mongodb";
|
|
2985
|
+
import { z as z7 } from "zod";
|
|
2986
|
+
|
|
2987
|
+
// src/schemas/auth.ts
|
|
2979
2988
|
import { z as z6 } from "zod";
|
|
2989
|
+
var AuthTokenNameSchema = z6.string().trim().min(1, "\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A").max(64, "\u540D\u79F0\u6700\u591A 64 \u4E2A\u5B57\u7B26");
|
|
2990
|
+
var AUTH_TOKEN_LIMIT = 10;
|
|
2991
|
+
var AuthTokenTypeSchema = z6.enum(["admin", "project"]);
|
|
2992
|
+
var AuthAccountSchema = z6.object({
|
|
2993
|
+
id: z6.string().optional(),
|
|
2994
|
+
username: z6.string().min(3, "\u8D26\u53F7\u81F3\u5C11 3 \u4E2A\u5B57\u7B26").max(50).regex(/^[a-zA-Z0-9_-]+$/, "\u8D26\u53F7\u4EC5\u5141\u8BB8\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u4E0B\u5212\u7EBF\u4E0E\u8FDE\u5B57\u7B26"),
|
|
2995
|
+
/** 存储形态:scrypt$N$r$p$salt$hash(base64 段),明文仅存在于请求体 */
|
|
2996
|
+
passwordHash: z6.string().min(1),
|
|
2997
|
+
createdAt: z6.date().optional(),
|
|
2998
|
+
updatedAt: z6.date().optional()
|
|
2999
|
+
});
|
|
3000
|
+
var AuthAccountCreateSchema = z6.object({
|
|
3001
|
+
username: AuthAccountSchema.shape.username,
|
|
3002
|
+
password: z6.string().min(8, "\u5BC6\u7801\u81F3\u5C11 8 \u4E2A\u5B57\u7B26").max(128)
|
|
3003
|
+
});
|
|
3004
|
+
var PasswordChangeSchema = z6.object({
|
|
3005
|
+
currentPassword: z6.string().min(1),
|
|
3006
|
+
newPassword: z6.string().min(8, "\u5BC6\u7801\u81F3\u5C11 8 \u4E2A\u5B57\u7B26").max(128)
|
|
3007
|
+
});
|
|
3008
|
+
var LoginSchema = z6.object({
|
|
3009
|
+
username: z6.string().min(1),
|
|
3010
|
+
password: z6.string().min(1)
|
|
3011
|
+
});
|
|
3012
|
+
var AuthTokenSchema = z6.object({
|
|
3013
|
+
id: z6.string().optional(),
|
|
3014
|
+
name: AuthTokenNameSchema,
|
|
3015
|
+
/** 明文全串含前缀(admin- / project-);唯一性由 token_1 unique 索引兜底 */
|
|
3016
|
+
token: z6.string().min(1),
|
|
3017
|
+
type: AuthTokenTypeSchema,
|
|
3018
|
+
/** type=project 时必填且不可缺失(superRefine 保证);type=admin 时禁止携带。
|
|
3019
|
+
* 指向 projects.id(24-hex) */
|
|
3020
|
+
projectId: z6.string().regex(/^[a-f0-9]{24}$/, "projectId \u5FC5\u987B\u4E3A 24-hex ObjectId").optional(),
|
|
3021
|
+
createdAt: z6.date().optional(),
|
|
3022
|
+
updatedAt: z6.date().optional()
|
|
3023
|
+
}).superRefine((data, ctx) => {
|
|
3024
|
+
if (data.type === "project" && data.projectId === void 0) {
|
|
3025
|
+
ctx.addIssue({ code: "custom", path: ["projectId"], message: "\u9879\u76EE Token \u5FC5\u987B\u7ED1\u5B9A projectId" });
|
|
3026
|
+
}
|
|
3027
|
+
if (data.type === "admin" && data.projectId !== void 0) {
|
|
3028
|
+
ctx.addIssue({ code: "custom", path: ["projectId"], message: "\u7BA1\u7406\u5458 Token \u4E0D\u7ED1\u5B9A\u9879\u76EE" });
|
|
3029
|
+
}
|
|
3030
|
+
});
|
|
3031
|
+
var AuthTokenIssueInputSchema = z6.object({
|
|
3032
|
+
name: AuthTokenNameSchema
|
|
3033
|
+
});
|
|
3034
|
+
var AuthTokenGenResponseSchema = z6.object({
|
|
3035
|
+
id: z6.string(),
|
|
3036
|
+
name: z6.string(),
|
|
3037
|
+
token: z6.string().min(1),
|
|
3038
|
+
type: AuthTokenTypeSchema,
|
|
3039
|
+
projectId: z6.string().optional()
|
|
3040
|
+
});
|
|
3041
|
+
var AuthTokenViewSchema = z6.object({
|
|
3042
|
+
id: z6.string(),
|
|
3043
|
+
name: z6.string(),
|
|
3044
|
+
type: AuthTokenTypeSchema,
|
|
3045
|
+
projectId: z6.string().optional(),
|
|
3046
|
+
token: z6.string().min(1),
|
|
3047
|
+
createdAt: z6.date().nullable().optional()
|
|
3048
|
+
});
|
|
3049
|
+
var AuthWhoamiSchema = z6.object({
|
|
3050
|
+
identity: z6.enum(["admin", "project", "none"]),
|
|
3051
|
+
project: z6.object({
|
|
3052
|
+
id: z6.string(),
|
|
3053
|
+
key: z6.string(),
|
|
3054
|
+
name: z6.string()
|
|
3055
|
+
}).nullable().optional(),
|
|
3056
|
+
authEnabled: z6.boolean(),
|
|
3057
|
+
server: z6.object({
|
|
3058
|
+
url: z6.string()
|
|
3059
|
+
})
|
|
3060
|
+
});
|
|
3061
|
+
var AuthStatusSchema = z6.object({
|
|
3062
|
+
authEnabled: z6.boolean(),
|
|
3063
|
+
/** 鉴权开启且无管理员账号 = 初始化引导窗口(PRD §3.2) */
|
|
3064
|
+
needsSetup: z6.boolean()
|
|
3065
|
+
});
|
|
3066
|
+
|
|
3067
|
+
// src/store/auth-crypto.ts
|
|
3068
|
+
import { randomBytes, scrypt as scryptCb, timingSafeEqual } from "crypto";
|
|
3069
|
+
import { promisify } from "util";
|
|
3070
|
+
var scrypt = promisify(scryptCb);
|
|
3071
|
+
var SCRYPT_N = 16384;
|
|
3072
|
+
var SCRYPT_R = 8;
|
|
3073
|
+
var SCRYPT_P = 1;
|
|
3074
|
+
var SCRYPT_KEYLEN = 64;
|
|
3075
|
+
var SALT_LEN = 16;
|
|
3076
|
+
async function hashPassword(password) {
|
|
3077
|
+
const salt = randomBytes(SALT_LEN);
|
|
3078
|
+
const derived = await scrypt(password, salt, SCRYPT_KEYLEN, { N: SCRYPT_N, r: SCRYPT_R, p: SCRYPT_P });
|
|
3079
|
+
return `scrypt$${SCRYPT_N}$${SCRYPT_R}$${SCRYPT_P}$${salt.toString("base64")}$${derived.toString("base64")}`;
|
|
3080
|
+
}
|
|
3081
|
+
async function verifyPassword(password, stored) {
|
|
3082
|
+
const parts = stored.split("$");
|
|
3083
|
+
if (parts.length !== 6 || parts[0] !== "scrypt") return false;
|
|
3084
|
+
const [, nStr, rStr, pStr, saltB64, hashB64] = parts;
|
|
3085
|
+
const N = Number(nStr);
|
|
3086
|
+
const r = Number(rStr);
|
|
3087
|
+
const p = Number(pStr);
|
|
3088
|
+
if (!Number.isInteger(N) || !Number.isInteger(r) || !Number.isInteger(p)) return false;
|
|
3089
|
+
try {
|
|
3090
|
+
const salt = Buffer.from(saltB64, "base64");
|
|
3091
|
+
const expected = Buffer.from(hashB64, "base64");
|
|
3092
|
+
const derived = await scrypt(password, salt, expected.length, { N, r, p });
|
|
3093
|
+
return derived.length === expected.length && timingSafeEqual(derived, expected);
|
|
3094
|
+
} catch {
|
|
3095
|
+
return false;
|
|
3096
|
+
}
|
|
3097
|
+
}
|
|
3098
|
+
function generateToken(type) {
|
|
3099
|
+
const prefix = type === "admin" ? "admin-" : "project-";
|
|
3100
|
+
return `${prefix}${randomBytes(32).toString("base64url")}`;
|
|
3101
|
+
}
|
|
3102
|
+
function tokenTypeFromValue(token) {
|
|
3103
|
+
if (token.startsWith("admin-")) return "admin";
|
|
3104
|
+
if (token.startsWith("project-")) return "project";
|
|
3105
|
+
return null;
|
|
3106
|
+
}
|
|
3107
|
+
function generateSessionId() {
|
|
3108
|
+
return randomBytes(32).toString("hex");
|
|
3109
|
+
}
|
|
3110
|
+
|
|
3111
|
+
// src/store/repos/auth.repo.ts
|
|
2980
3112
|
var AUTH_COLLECTIONS = {
|
|
2981
3113
|
accounts: "auth_accounts",
|
|
2982
3114
|
tokens: "auth_tokens",
|
|
@@ -3017,67 +3149,84 @@ function createAuthTokenRepo(db) {
|
|
|
3017
3149
|
const base = createRepo(db.collection(AUTH_COLLECTIONS.tokens));
|
|
3018
3150
|
return {
|
|
3019
3151
|
...base,
|
|
3020
|
-
/**
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
async
|
|
3026
|
-
const
|
|
3027
|
-
if (type === "project"
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
* 事务包删+插(rs0 支持——失败窗口不留零 Token 状态,失败不变性);admin 单例 /
|
|
3033
|
-
* project 每项目一枚由 partial unique 索引兜底并发交错 */
|
|
3034
|
-
async upsertToken(type, tokenHash, projectId) {
|
|
3035
|
-
const query = { type };
|
|
3036
|
-
if (type === "project") {
|
|
3037
|
-
if (!projectId) throw new ConflictError("auth-token", "missing-projectId", { message: "project token requires projectId" });
|
|
3038
|
-
query.projectId = projectId;
|
|
3152
|
+
/**
|
|
3153
|
+
* 签发(追加语义,不重置他枚):事务内 ①同类计数(admin=全 type;project=type+projectId)
|
|
3154
|
+
* ②生成明文 ③insert。计数 ≥ AUTH_TOKEN_LIMIT → 409(D2:事务快照隔离防不了幻读,
|
|
3155
|
+
* 单管理员下并发签发概率≈0,理论竞态越界可吊销自愈,计数器文档复杂度不值)。
|
|
3156
|
+
*/
|
|
3157
|
+
async issueToken(input) {
|
|
3158
|
+
const { type, projectId, name } = input;
|
|
3159
|
+
if (type === "project" && projectId === void 0) {
|
|
3160
|
+
throw new ConflictError("auth-token", "missing-project-id", {
|
|
3161
|
+
bizCode: "AUTH_TOKEN_MISSING_PROJECT_ID",
|
|
3162
|
+
message: BIZ_CODE_MESSAGES.AUTH_TOKEN_MISSING_PROJECT_ID
|
|
3163
|
+
});
|
|
3039
3164
|
}
|
|
3040
|
-
const
|
|
3041
|
-
|
|
3165
|
+
const countQuery = { type };
|
|
3166
|
+
if (type === "project") countQuery.projectId = projectId;
|
|
3167
|
+
const now = /* @__PURE__ */ new Date();
|
|
3168
|
+
const holder = { token: null };
|
|
3169
|
+
const session = db.client.startSession();
|
|
3042
3170
|
try {
|
|
3043
|
-
const holder = { token: null };
|
|
3044
3171
|
await session.withTransaction(async () => {
|
|
3045
|
-
await base._collection.
|
|
3046
|
-
|
|
3047
|
-
|
|
3172
|
+
const count = await base._collection.countDocuments(countQuery, { session });
|
|
3173
|
+
if (count >= AUTH_TOKEN_LIMIT) {
|
|
3174
|
+
throw new ConflictError("auth-token", "limit-reached", {
|
|
3175
|
+
bizCode: "AUTH_TOKEN_LIMIT",
|
|
3176
|
+
message: BIZ_CODE_MESSAGES.AUTH_TOKEN_LIMIT
|
|
3177
|
+
});
|
|
3178
|
+
}
|
|
3179
|
+
const token = generateToken(type);
|
|
3180
|
+
const doc = { name, token, type, createdAt: now, updatedAt: now };
|
|
3048
3181
|
if (type === "project" && projectId !== void 0) doc.projectId = projectId;
|
|
3049
3182
|
const result = await base._collection.insertOne(doc, { session });
|
|
3050
3183
|
holder.token = { ...doc, id: result.insertedId.toString() };
|
|
3051
3184
|
});
|
|
3052
|
-
if (holder.token === null) {
|
|
3053
|
-
throw new ConflictError("auth-token", "transaction-empty", { message: "Token upsert \u672A\u4EA7\u751F\u7ED3\u679C" });
|
|
3054
|
-
}
|
|
3055
|
-
return holder.token;
|
|
3056
3185
|
} finally {
|
|
3057
3186
|
await session.endSession();
|
|
3058
3187
|
}
|
|
3188
|
+
if (holder.token === null) {
|
|
3189
|
+
throw new ConflictError("auth-token", "transaction-empty", { message: "Token issue \u672A\u4EA7\u751F\u7ED3\u679C" });
|
|
3190
|
+
}
|
|
3191
|
+
return holder.token;
|
|
3059
3192
|
},
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
const
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3193
|
+
/** 全量清单(project 型跨全项目,行含 projectId);按签发时间升序(追加语义稳定展示) */
|
|
3194
|
+
async listTokens(type) {
|
|
3195
|
+
const docs = await base._collection.find({ type }).sort({ createdAt: 1, _id: 1 }).toArray();
|
|
3196
|
+
return docs.map((doc) => toEntity(doc));
|
|
3197
|
+
},
|
|
3198
|
+
/** 吊销单枚(即时失效,他枚不受影响);非法 hex id 不抛 BSONError,与不存在同归 404(架构评审 F3) */
|
|
3199
|
+
async revokeToken(id) {
|
|
3200
|
+
if (!isValidObjectId(id)) {
|
|
3201
|
+
throw new NotFoundError("auth-token", id, {
|
|
3202
|
+
bizCode: "AUTH_TOKEN_NOT_FOUND",
|
|
3203
|
+
message: BIZ_CODE_MESSAGES.AUTH_TOKEN_NOT_FOUND
|
|
3204
|
+
});
|
|
3068
3205
|
}
|
|
3069
|
-
|
|
3206
|
+
const existing = await base._collection.findOne({ _id: new ObjectId3(id) }, { projection: { _id: 1 } });
|
|
3207
|
+
if (!existing) {
|
|
3208
|
+
throw new NotFoundError("auth-token", id, {
|
|
3209
|
+
bizCode: "AUTH_TOKEN_NOT_FOUND",
|
|
3210
|
+
message: BIZ_CODE_MESSAGES.AUTH_TOKEN_NOT_FOUND
|
|
3211
|
+
});
|
|
3212
|
+
}
|
|
3213
|
+
await base._collection.deleteOne({ _id: existing._id });
|
|
3214
|
+
},
|
|
3215
|
+
/** 明文等值查(token_1 唯一索引命中)——鉴权中间件每请求主通道 */
|
|
3216
|
+
async findValidToken(tokenValue) {
|
|
3217
|
+
const doc = await base._collection.findOne({ token: tokenValue });
|
|
3218
|
+
return doc ? toEntity(doc) : null;
|
|
3070
3219
|
}
|
|
3071
3220
|
};
|
|
3072
3221
|
}
|
|
3073
|
-
var AuthSessionSchema =
|
|
3074
|
-
id:
|
|
3075
|
-
sessionId:
|
|
3222
|
+
var AuthSessionSchema = z7.object({
|
|
3223
|
+
id: z7.string().optional(),
|
|
3224
|
+
sessionId: z7.string().min(1),
|
|
3076
3225
|
/** 管理员账号 id(会话 = 管理员身份) */
|
|
3077
|
-
accountId:
|
|
3078
|
-
expiresAt:
|
|
3079
|
-
createdAt:
|
|
3080
|
-
updatedAt:
|
|
3226
|
+
accountId: z7.string().min(1),
|
|
3227
|
+
expiresAt: z7.date(),
|
|
3228
|
+
createdAt: z7.date().optional(),
|
|
3229
|
+
updatedAt: z7.date().optional()
|
|
3081
3230
|
});
|
|
3082
3231
|
function createAuthSessionRepo(db) {
|
|
3083
3232
|
const base = createRepo(db.collection(AUTH_COLLECTIONS.sessions));
|
|
@@ -3107,70 +3256,26 @@ function createAuthSessionRepo(db) {
|
|
|
3107
3256
|
}
|
|
3108
3257
|
};
|
|
3109
3258
|
}
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
import { createHash, randomBytes, scrypt as scryptCb, timingSafeEqual } from "crypto";
|
|
3113
|
-
import { promisify } from "util";
|
|
3114
|
-
var scrypt = promisify(scryptCb);
|
|
3115
|
-
var SCRYPT_N = 16384;
|
|
3116
|
-
var SCRYPT_R = 8;
|
|
3117
|
-
var SCRYPT_P = 1;
|
|
3118
|
-
var SCRYPT_KEYLEN = 64;
|
|
3119
|
-
var SALT_LEN = 16;
|
|
3120
|
-
async function hashPassword(password) {
|
|
3121
|
-
const salt = randomBytes(SALT_LEN);
|
|
3122
|
-
const derived = await scrypt(password, salt, SCRYPT_KEYLEN, { N: SCRYPT_N, r: SCRYPT_R, p: SCRYPT_P });
|
|
3123
|
-
return `scrypt$${SCRYPT_N}$${SCRYPT_R}$${SCRYPT_P}$${salt.toString("base64")}$${derived.toString("base64")}`;
|
|
3124
|
-
}
|
|
3125
|
-
async function verifyPassword(password, stored) {
|
|
3126
|
-
const parts = stored.split("$");
|
|
3127
|
-
if (parts.length !== 6 || parts[0] !== "scrypt") return false;
|
|
3128
|
-
const [, nStr, rStr, pStr, saltB64, hashB64] = parts;
|
|
3129
|
-
const N = Number(nStr);
|
|
3130
|
-
const r = Number(rStr);
|
|
3131
|
-
const p = Number(pStr);
|
|
3132
|
-
if (!Number.isInteger(N) || !Number.isInteger(r) || !Number.isInteger(p)) return false;
|
|
3133
|
-
try {
|
|
3134
|
-
const salt = Buffer.from(saltB64, "base64");
|
|
3135
|
-
const expected = Buffer.from(hashB64, "base64");
|
|
3136
|
-
const derived = await scrypt(password, salt, expected.length, { N, r, p });
|
|
3137
|
-
return derived.length === expected.length && timingSafeEqual(derived, expected);
|
|
3138
|
-
} catch {
|
|
3139
|
-
return false;
|
|
3140
|
-
}
|
|
3141
|
-
}
|
|
3142
|
-
function generateToken(type) {
|
|
3143
|
-
const prefix = type === "admin" ? "admin-" : "project-";
|
|
3144
|
-
return `${prefix}${randomBytes(32).toString("base64url")}`;
|
|
3145
|
-
}
|
|
3146
|
-
function tokenTypeFromValue(token) {
|
|
3147
|
-
if (token.startsWith("admin-")) return "admin";
|
|
3148
|
-
if (token.startsWith("project-")) return "project";
|
|
3149
|
-
return null;
|
|
3150
|
-
}
|
|
3151
|
-
function hashToken(token) {
|
|
3152
|
-
return createHash("sha256").update(token).digest("hex");
|
|
3153
|
-
}
|
|
3154
|
-
function generateSessionId() {
|
|
3155
|
-
return randomBytes(32).toString("hex");
|
|
3259
|
+
function isValidObjectId(id) {
|
|
3260
|
+
return ObjectId3.isValid(id);
|
|
3156
3261
|
}
|
|
3157
3262
|
|
|
3158
3263
|
// src/schemas/agent.ts
|
|
3159
|
-
import { z as
|
|
3264
|
+
import { z as z9 } from "zod";
|
|
3160
3265
|
|
|
3161
3266
|
// src/schemas/model-alias.ts
|
|
3162
|
-
import { z as
|
|
3267
|
+
import { z as z8 } from "zod";
|
|
3163
3268
|
var SIMING_CODE_REGEX = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
3164
|
-
var ModelAliasShapeSchema =
|
|
3165
|
-
id:
|
|
3269
|
+
var ModelAliasShapeSchema = z8.object({
|
|
3270
|
+
id: z8.string().optional(),
|
|
3166
3271
|
/** siming code:创建后不可变(PUT 显式拒绝 MODEL_CODE_IMMUTABLE,非静默剥离) */
|
|
3167
|
-
code:
|
|
3272
|
+
code: z8.string().regex(SIMING_CODE_REGEX, "code \u5FC5\u987B\u4E3A kebab-case\uFF08\u5982 primary\u3001fast-model\uFF09"),
|
|
3168
3273
|
/** 展示名(如「主力模型」) */
|
|
3169
|
-
name:
|
|
3274
|
+
name: z8.string().min(1, "\u5C55\u793A\u540D\u4E0D\u80FD\u4E3A\u7A7A"),
|
|
3170
3275
|
/** 真实模型标识(如 zhipuai/glm-5.3;改此处 = 引用方全局替换生效) */
|
|
3171
|
-
realModel:
|
|
3172
|
-
createdAt:
|
|
3173
|
-
updatedAt:
|
|
3276
|
+
realModel: z8.string().min(1, "\u771F\u5B9E\u6A21\u578B\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A"),
|
|
3277
|
+
createdAt: z8.date().optional(),
|
|
3278
|
+
updatedAt: z8.date().optional()
|
|
3174
3279
|
});
|
|
3175
3280
|
var ModelAliasSchema = ModelAliasShapeSchema;
|
|
3176
3281
|
var ModelAliasCreateSchema = ModelAliasShapeSchema.omit({
|
|
@@ -3178,18 +3283,18 @@ var ModelAliasCreateSchema = ModelAliasShapeSchema.omit({
|
|
|
3178
3283
|
createdAt: true,
|
|
3179
3284
|
updatedAt: true
|
|
3180
3285
|
});
|
|
3181
|
-
var ModelAliasUpdateSchema =
|
|
3182
|
-
code:
|
|
3183
|
-
name:
|
|
3184
|
-
realModel:
|
|
3286
|
+
var ModelAliasUpdateSchema = z8.object({
|
|
3287
|
+
code: z8.string().regex(SIMING_CODE_REGEX).optional(),
|
|
3288
|
+
name: z8.string().min(1).optional(),
|
|
3289
|
+
realModel: z8.string().min(1).optional()
|
|
3185
3290
|
});
|
|
3186
3291
|
var ModelAliasWithRefCountSchema = ModelAliasShapeSchema.extend({
|
|
3187
|
-
refCount:
|
|
3292
|
+
refCount: z8.number().int().min(0)
|
|
3188
3293
|
});
|
|
3189
3294
|
|
|
3190
3295
|
// src/schemas/agent.ts
|
|
3191
|
-
var AgentScopeSchema =
|
|
3192
|
-
var AgentFunctionSchema =
|
|
3296
|
+
var AgentScopeSchema = z9.enum(["global", "project"]);
|
|
3297
|
+
var AgentFunctionSchema = z9.enum(["reviewer", "executor"]);
|
|
3193
3298
|
var AgentScopeRefine = (val, ctx) => {
|
|
3194
3299
|
if (val.scope === "project" && !val.projectId) {
|
|
3195
3300
|
ctx.addIssue({
|
|
@@ -3199,17 +3304,17 @@ var AgentScopeRefine = (val, ctx) => {
|
|
|
3199
3304
|
});
|
|
3200
3305
|
}
|
|
3201
3306
|
};
|
|
3202
|
-
var AgentShapeSchema =
|
|
3203
|
-
id:
|
|
3204
|
-
name:
|
|
3205
|
-
description:
|
|
3206
|
-
systemPrompt:
|
|
3207
|
-
boundSkills:
|
|
3208
|
-
model:
|
|
3307
|
+
var AgentShapeSchema = z9.object({
|
|
3308
|
+
id: z9.string().optional(),
|
|
3309
|
+
name: z9.string(),
|
|
3310
|
+
description: z9.string(),
|
|
3311
|
+
systemPrompt: z9.string(),
|
|
3312
|
+
boundSkills: z9.array(z9.string()).default([]),
|
|
3313
|
+
model: z9.string(),
|
|
3209
3314
|
/** 资产版本(N015 F13):install/export 版本对比依据;default 仅读侧兜底(createRepo 不做读侧解析,存量回填走 M6 迁移) */
|
|
3210
|
-
version:
|
|
3211
|
-
tools:
|
|
3212
|
-
permissions:
|
|
3315
|
+
version: z9.string().default("1.0.0"),
|
|
3316
|
+
tools: z9.array(z9.string()).default([]),
|
|
3317
|
+
permissions: z9.array(z9.string()).default([]),
|
|
3213
3318
|
/** 引用文档集合(可选——存量单文件资产无此字段,行为与升级前一致) */
|
|
3214
3319
|
references: createReferencesSchema(AGENT_MAIN_DOC).optional(),
|
|
3215
3320
|
/** 作用域:global=跨项目复用(默认,仅作存量迁移读侧兜底)/ project=项目专用(N012 D3) */
|
|
@@ -3217,15 +3322,15 @@ var AgentShapeSchema = z8.object({
|
|
|
3217
3322
|
/** 功能类型(T202608260002):default 仅创建侧归一——toEntity 直转不经 Zod parse,读侧归一在 repo 层 + 回填走 M12 */
|
|
3218
3323
|
"function": AgentFunctionSchema.default("executor"),
|
|
3219
3324
|
/** 仅 scope=project 时必填且为合法 ObjectId hex(superRefine 保证) */
|
|
3220
|
-
projectId:
|
|
3325
|
+
projectId: z9.string().regex(OBJECT_ID_HEX, "projectId must be a valid ObjectId hex").optional(),
|
|
3221
3326
|
/**
|
|
3222
3327
|
* T202608290001 资产启停(可选——存量无此字段 = 启用,零迁移)。
|
|
3223
3328
|
* 全局判断规则:enabled === false 即停用,true/缺失均启用。
|
|
3224
3329
|
* 唯一写入口是专用启停端点(POST /:name/enabled)——Create/Update/Copy 均不含此字段。
|
|
3225
3330
|
*/
|
|
3226
|
-
enabled:
|
|
3227
|
-
createdAt:
|
|
3228
|
-
updatedAt:
|
|
3331
|
+
enabled: z9.boolean().optional(),
|
|
3332
|
+
createdAt: z9.date().optional(),
|
|
3333
|
+
updatedAt: z9.date().optional()
|
|
3229
3334
|
});
|
|
3230
3335
|
var agentAggregateLimitRefine = (val, ctx) => {
|
|
3231
3336
|
const totalChars = (val.systemPrompt?.length ?? 0) + sumReferenceContentChars(val.references);
|
|
@@ -3243,28 +3348,28 @@ var AgentCreateSchema = AgentShapeSchema.omit({
|
|
|
3243
3348
|
createdAt: true,
|
|
3244
3349
|
updatedAt: true,
|
|
3245
3350
|
enabled: true
|
|
3246
|
-
}).extend({ scope: AgentScopeSchema }).extend({ model:
|
|
3351
|
+
}).extend({ scope: AgentScopeSchema }).extend({ model: z9.string().regex(SIMING_CODE_REGEX, "model \u5FC5\u987B\u662F siming code\uFF08kebab-case\uFF09") }).extend({ "function": AgentFunctionSchema.default("executor") }).superRefine(AgentScopeRefine).superRefine(agentAggregateLimitRefine);
|
|
3247
3352
|
var AgentUpdateSchema = AgentShapeSchema.omit({
|
|
3248
3353
|
id: true,
|
|
3249
3354
|
createdAt: true,
|
|
3250
3355
|
updatedAt: true,
|
|
3251
3356
|
enabled: true
|
|
3252
3357
|
}).extend({
|
|
3253
|
-
boundSkills:
|
|
3358
|
+
boundSkills: z9.array(z9.string()).optional(),
|
|
3254
3359
|
// N015:version 放行(export apply 版本递增随 PUT 携带);optional 剥离实体层 default 避免 partial 空 body 注入
|
|
3255
|
-
version:
|
|
3256
|
-
tools:
|
|
3257
|
-
permissions:
|
|
3360
|
+
version: z9.string().optional(),
|
|
3361
|
+
tools: z9.array(z9.string()).optional(),
|
|
3362
|
+
permissions: z9.array(z9.string()).optional(),
|
|
3258
3363
|
scope: AgentScopeSchema.optional(),
|
|
3259
3364
|
// N013:model 收紧为 siming code 格式(存在性校验在 handler 层;undefined = 不更新该字段)
|
|
3260
|
-
model:
|
|
3365
|
+
model: z9.string().regex(SIMING_CODE_REGEX, "model \u5FC5\u987B\u662F siming code\uFF08kebab-case\uFF09").optional(),
|
|
3261
3366
|
// T202608260002:optional 剥离实体层 default——否则 PUT 空 body 会注入 executor 覆盖 reviewer
|
|
3262
3367
|
"function": AgentFunctionSchema.optional()
|
|
3263
3368
|
}).partial().superRefine(AgentScopeRefine).superRefine(agentAggregateLimitRefine);
|
|
3264
|
-
var AgentCopySchema =
|
|
3265
|
-
newName:
|
|
3369
|
+
var AgentCopySchema = z9.object({
|
|
3370
|
+
newName: z9.string(),
|
|
3266
3371
|
newScope: AgentScopeSchema,
|
|
3267
|
-
targetProjectId:
|
|
3372
|
+
targetProjectId: z9.string().regex(OBJECT_ID_HEX, "projectId must be a valid ObjectId hex").optional()
|
|
3268
3373
|
}).superRefine((val, ctx) => {
|
|
3269
3374
|
if (val.newScope === "project" && !val.targetProjectId) {
|
|
3270
3375
|
ctx.addIssue({
|
|
@@ -3276,7 +3381,7 @@ var AgentCopySchema = z8.object({
|
|
|
3276
3381
|
});
|
|
3277
3382
|
|
|
3278
3383
|
// src/schemas/export-bundle.ts
|
|
3279
|
-
import { z as
|
|
3384
|
+
import { z as z10 } from "zod";
|
|
3280
3385
|
var EXPORT_FORMAT_VERSION = "1.0";
|
|
3281
3386
|
var TemplatePayloadSchema = DagTemplateSchema.omit({
|
|
3282
3387
|
id: true,
|
|
@@ -3286,8 +3391,8 @@ var TemplatePayloadSchema = DagTemplateSchema.omit({
|
|
|
3286
3391
|
updatedAt: true,
|
|
3287
3392
|
code: true
|
|
3288
3393
|
}).extend({
|
|
3289
|
-
version:
|
|
3290
|
-
isDefault:
|
|
3394
|
+
version: z10.string(),
|
|
3395
|
+
isDefault: z10.boolean()
|
|
3291
3396
|
});
|
|
3292
3397
|
var SkillPayloadSchema = SkillShapeSchema.omit({
|
|
3293
3398
|
id: true,
|
|
@@ -3296,7 +3401,7 @@ var SkillPayloadSchema = SkillShapeSchema.omit({
|
|
|
3296
3401
|
createdAt: true,
|
|
3297
3402
|
updatedAt: true
|
|
3298
3403
|
}).extend({
|
|
3299
|
-
version:
|
|
3404
|
+
version: z10.string(),
|
|
3300
3405
|
scope: SkillScopeSchema,
|
|
3301
3406
|
references: createReferencesSchema(SKILL_MAIN_DOC)
|
|
3302
3407
|
});
|
|
@@ -3307,12 +3412,12 @@ var AgentPayloadSchema = AgentShapeSchema.omit({
|
|
|
3307
3412
|
createdAt: true,
|
|
3308
3413
|
updatedAt: true
|
|
3309
3414
|
}).extend({
|
|
3310
|
-
version:
|
|
3415
|
+
version: z10.string(),
|
|
3311
3416
|
scope: AgentScopeSchema,
|
|
3312
3417
|
references: createReferencesSchema(AGENT_MAIN_DOC),
|
|
3313
|
-
boundSkills:
|
|
3314
|
-
tools:
|
|
3315
|
-
permissions:
|
|
3418
|
+
boundSkills: z10.array(z10.string()),
|
|
3419
|
+
tools: z10.array(z10.string()),
|
|
3420
|
+
permissions: z10.array(z10.string()),
|
|
3316
3421
|
"function": AgentFunctionSchema
|
|
3317
3422
|
});
|
|
3318
3423
|
var ModelAliasPayloadSchema = ModelAliasSchema.omit({
|
|
@@ -3320,357 +3425,357 @@ var ModelAliasPayloadSchema = ModelAliasSchema.omit({
|
|
|
3320
3425
|
createdAt: true,
|
|
3321
3426
|
updatedAt: true
|
|
3322
3427
|
});
|
|
3323
|
-
var ExportBundleSchema =
|
|
3324
|
-
exportFormatVersion:
|
|
3428
|
+
var ExportBundleSchema = z10.object({
|
|
3429
|
+
exportFormatVersion: z10.literal(EXPORT_FORMAT_VERSION, {
|
|
3325
3430
|
error: `\u5BFC\u51FA\u683C\u5F0F\u7248\u672C\u4E0D\u652F\u6301\uFF0C\u5F53\u524D\u652F\u6301 ${EXPORT_FORMAT_VERSION}`
|
|
3326
3431
|
}),
|
|
3327
|
-
exportedAt:
|
|
3432
|
+
exportedAt: z10.string(),
|
|
3328
3433
|
/** 源环境悬空提示(§2.2:悬空 skill/agent.model 不阻断导出)。导出响应恒携带;导入入参可缺省——导入侧提示由 plan 生成,不消费本字段 */
|
|
3329
|
-
warnings:
|
|
3434
|
+
warnings: z10.array(z10.string()).optional(),
|
|
3330
3435
|
template: TemplatePayloadSchema,
|
|
3331
|
-
dependencies:
|
|
3332
|
-
skills:
|
|
3333
|
-
agents:
|
|
3334
|
-
modelAliases:
|
|
3436
|
+
dependencies: z10.object({
|
|
3437
|
+
skills: z10.array(SkillPayloadSchema),
|
|
3438
|
+
agents: z10.array(AgentPayloadSchema),
|
|
3439
|
+
modelAliases: z10.array(ModelAliasPayloadSchema)
|
|
3335
3440
|
})
|
|
3336
3441
|
});
|
|
3337
|
-
var ImportPlanRequestSchema =
|
|
3338
|
-
targetProjectId:
|
|
3442
|
+
var ImportPlanRequestSchema = z10.object({
|
|
3443
|
+
targetProjectId: z10.string().regex(OBJECT_ID_HEX, "targetProjectId must be a valid ObjectId hex"),
|
|
3339
3444
|
bundle: ExportBundleSchema
|
|
3340
3445
|
});
|
|
3341
|
-
var ImportDecisionSchema =
|
|
3342
|
-
|
|
3343
|
-
kind:
|
|
3344
|
-
name:
|
|
3446
|
+
var ImportDecisionSchema = z10.discriminatedUnion("kind", [
|
|
3447
|
+
z10.object({
|
|
3448
|
+
kind: z10.literal("skill"),
|
|
3449
|
+
name: z10.string(),
|
|
3345
3450
|
scope: SkillScopeSchema,
|
|
3346
|
-
action:
|
|
3451
|
+
action: z10.enum(["overwrite", "skip"])
|
|
3347
3452
|
}),
|
|
3348
|
-
|
|
3349
|
-
kind:
|
|
3350
|
-
name:
|
|
3453
|
+
z10.object({
|
|
3454
|
+
kind: z10.literal("agent"),
|
|
3455
|
+
name: z10.string(),
|
|
3351
3456
|
scope: AgentScopeSchema,
|
|
3352
|
-
action:
|
|
3457
|
+
action: z10.enum(["overwrite", "skip"])
|
|
3353
3458
|
}),
|
|
3354
|
-
|
|
3355
|
-
kind:
|
|
3356
|
-
name:
|
|
3357
|
-
action:
|
|
3459
|
+
z10.object({
|
|
3460
|
+
kind: z10.literal("modelAlias"),
|
|
3461
|
+
name: z10.string(),
|
|
3462
|
+
action: z10.enum(["overwrite", "skip"])
|
|
3358
3463
|
})
|
|
3359
3464
|
]);
|
|
3360
3465
|
var ImportApplyRequestSchema = ImportPlanRequestSchema.extend({
|
|
3361
3466
|
/** 未列出的冲突项缺省 skip(保守默认:未决策不覆盖) */
|
|
3362
|
-
decisions:
|
|
3467
|
+
decisions: z10.array(ImportDecisionSchema).default([])
|
|
3363
3468
|
});
|
|
3364
|
-
var DependencyStatusSchema =
|
|
3365
|
-
var DependencyCheckSchema =
|
|
3366
|
-
kind:
|
|
3367
|
-
name:
|
|
3469
|
+
var DependencyStatusSchema = z10.enum(["create", "identical", "conflict"]);
|
|
3470
|
+
var DependencyCheckSchema = z10.object({
|
|
3471
|
+
kind: z10.enum(["skill", "agent", "modelAlias"]),
|
|
3472
|
+
name: z10.string(),
|
|
3368
3473
|
/** skill/agent 携带;modelAlias 无 */
|
|
3369
|
-
scope:
|
|
3474
|
+
scope: z10.enum(["global", "project"]).optional(),
|
|
3370
3475
|
status: DependencyStatusSchema,
|
|
3371
3476
|
/** status ≠ create 时目标环境现值版本(modelAlias 无 version 概念不填) */
|
|
3372
|
-
currentVersion:
|
|
3373
|
-
importVersion:
|
|
3477
|
+
currentVersion: z10.string().optional(),
|
|
3478
|
+
importVersion: z10.string().optional(),
|
|
3374
3479
|
/** status = conflict 时差异字段名清单(如 "content, references") */
|
|
3375
|
-
changeSummary:
|
|
3480
|
+
changeSummary: z10.string().optional(),
|
|
3376
3481
|
/** 影响范围(PRD F13):global 资产影响所有项目 / project 资产仅影响所属项目 */
|
|
3377
|
-
impact:
|
|
3482
|
+
impact: z10.enum(["global", "project"])
|
|
3378
3483
|
});
|
|
3379
|
-
var ImportPlanResponseSchema =
|
|
3380
|
-
template:
|
|
3381
|
-
name:
|
|
3382
|
-
willOverwrite:
|
|
3383
|
-
currentVersion:
|
|
3384
|
-
importVersion:
|
|
3385
|
-
isDefaultRequested:
|
|
3484
|
+
var ImportPlanResponseSchema = z10.object({
|
|
3485
|
+
template: z10.object({
|
|
3486
|
+
name: z10.string(),
|
|
3487
|
+
willOverwrite: z10.boolean(),
|
|
3488
|
+
currentVersion: z10.string().optional(),
|
|
3489
|
+
importVersion: z10.string(),
|
|
3490
|
+
isDefaultRequested: z10.boolean(),
|
|
3386
3491
|
/** isDefault 降级后的最终生效值(F17:项目已有默认 → false) */
|
|
3387
|
-
isDefaultEffect:
|
|
3388
|
-
downgradeReason:
|
|
3492
|
+
isDefaultEffect: z10.boolean(),
|
|
3493
|
+
downgradeReason: z10.string().optional()
|
|
3389
3494
|
}),
|
|
3390
|
-
dependencies:
|
|
3495
|
+
dependencies: z10.array(DependencyCheckSchema),
|
|
3391
3496
|
/**
|
|
3392
3497
|
* K10①:模板节点直接技能引用完整性逐项核对(node × skill 粒度)——
|
|
3393
3498
|
* ok = 在 bundle 依赖 ∪ 目标环境可见集;missing = 双侧皆无(绑定悬空,non-blocking warning)
|
|
3394
3499
|
*/
|
|
3395
|
-
directSkillChecks:
|
|
3396
|
-
|
|
3397
|
-
node:
|
|
3398
|
-
skill:
|
|
3399
|
-
status:
|
|
3500
|
+
directSkillChecks: z10.array(
|
|
3501
|
+
z10.object({
|
|
3502
|
+
node: z10.string(),
|
|
3503
|
+
skill: z10.string(),
|
|
3504
|
+
status: z10.enum(["ok", "missing"])
|
|
3400
3505
|
})
|
|
3401
3506
|
),
|
|
3402
3507
|
/**
|
|
3403
3508
|
* K10③:模板节点直接 AGENT 引用完整性逐项核对(node × agent 粒度)——
|
|
3404
3509
|
* 与 directSkillChecks 对称;ok = 在 bundle 依赖 ∪ 目标环境可见集;missing = 双侧皆无(引用悬空,non-blocking warning)
|
|
3405
3510
|
*/
|
|
3406
|
-
directAgentChecks:
|
|
3407
|
-
|
|
3408
|
-
node:
|
|
3409
|
-
agent:
|
|
3410
|
-
status:
|
|
3511
|
+
directAgentChecks: z10.array(
|
|
3512
|
+
z10.object({
|
|
3513
|
+
node: z10.string(),
|
|
3514
|
+
agent: z10.string(),
|
|
3515
|
+
status: z10.enum(["ok", "missing"])
|
|
3411
3516
|
})
|
|
3412
3517
|
),
|
|
3413
3518
|
/** 非阻断提示(源环境悬空绑定、agent.model 引用缺失、sourcePreset 来源缺失等) */
|
|
3414
|
-
warnings:
|
|
3519
|
+
warnings: z10.array(z10.string())
|
|
3415
3520
|
});
|
|
3416
|
-
var DependencyActionSchema =
|
|
3417
|
-
var ImportApplyResponseSchema =
|
|
3418
|
-
template:
|
|
3419
|
-
id:
|
|
3420
|
-
name:
|
|
3421
|
-
action:
|
|
3422
|
-
isDefaultEffect:
|
|
3521
|
+
var DependencyActionSchema = z10.enum(["created", "updated", "skipped", "identical", "failed"]);
|
|
3522
|
+
var ImportApplyResponseSchema = z10.object({
|
|
3523
|
+
template: z10.object({
|
|
3524
|
+
id: z10.string(),
|
|
3525
|
+
name: z10.string(),
|
|
3526
|
+
action: z10.enum(["created", "updated"]),
|
|
3527
|
+
isDefaultEffect: z10.boolean()
|
|
3423
3528
|
}),
|
|
3424
|
-
dependencies:
|
|
3425
|
-
|
|
3426
|
-
kind:
|
|
3427
|
-
name:
|
|
3428
|
-
scope:
|
|
3529
|
+
dependencies: z10.array(
|
|
3530
|
+
z10.object({
|
|
3531
|
+
kind: z10.enum(["skill", "agent", "modelAlias"]),
|
|
3532
|
+
name: z10.string(),
|
|
3533
|
+
scope: z10.enum(["global", "project"]).optional(),
|
|
3429
3534
|
action: DependencyActionSchema,
|
|
3430
3535
|
/** action = failed 时的错误说明 */
|
|
3431
|
-
message:
|
|
3536
|
+
message: z10.string().optional()
|
|
3432
3537
|
})
|
|
3433
3538
|
),
|
|
3434
3539
|
/** K10②:apply 时刻目标环境缺失来源而被剥除 sourcePreset 的节点 id 清单(降级自建导入) */
|
|
3435
|
-
sourceStripped:
|
|
3540
|
+
sourceStripped: z10.array(z10.string())
|
|
3436
3541
|
});
|
|
3437
3542
|
function decisionKey(kind, scope, name) {
|
|
3438
3543
|
return `${kind}:${scope ?? ""}:${name}`;
|
|
3439
3544
|
}
|
|
3440
3545
|
|
|
3441
3546
|
// src/schemas/advance.ts
|
|
3442
|
-
import { z as
|
|
3443
|
-
var AdvanceRequestSchema =
|
|
3444
|
-
note:
|
|
3547
|
+
import { z as z11 } from "zod";
|
|
3548
|
+
var AdvanceRequestSchema = z11.object({
|
|
3549
|
+
note: z11.string().optional(),
|
|
3445
3550
|
/** min(1).max(2000) 与 record summary 端点对齐(同一 $set 目标,两入口校验强度一致) */
|
|
3446
|
-
summary:
|
|
3551
|
+
summary: z11.string().min(1).max(2e3).optional(),
|
|
3447
3552
|
/**
|
|
3448
3553
|
* T202609130009 收尾确认(可选):终节点推进默认被拒
|
|
3449
3554
|
* (TASK_FINALIZE_CONFIRMATION_REQUIRED),携带 finalize=true 才完成收尾终态化;
|
|
3450
3555
|
* 中间节点传递无副作用(守卫不在其路径,宽容语义)。
|
|
3451
3556
|
*/
|
|
3452
|
-
finalize:
|
|
3557
|
+
finalize: z11.boolean().optional()
|
|
3453
3558
|
});
|
|
3454
|
-
var ApproveRequestSchema =
|
|
3455
|
-
decision:
|
|
3456
|
-
comment:
|
|
3559
|
+
var ApproveRequestSchema = z11.object({
|
|
3560
|
+
decision: z11.enum(["approved", "rejected"]),
|
|
3561
|
+
comment: z11.string().optional()
|
|
3457
3562
|
});
|
|
3458
|
-
var TaskPublicSchema =
|
|
3459
|
-
taskId:
|
|
3460
|
-
title:
|
|
3563
|
+
var TaskPublicSchema = z11.object({
|
|
3564
|
+
taskId: z11.string(),
|
|
3565
|
+
title: z11.string(),
|
|
3461
3566
|
// T202608240003:任务类型标签(缺省 = 裸任务/旧任务;模板 PRD 调研变体判定消费)
|
|
3462
|
-
type:
|
|
3567
|
+
type: z11.enum(TASK_TYPES).optional(),
|
|
3463
3568
|
/** T202609230001:归属项目(CLI advance 门禁经 context 直取 projectId 读项目 vcs 配置,免额外实体查询) */
|
|
3464
|
-
projectId:
|
|
3465
|
-
currentNode:
|
|
3466
|
-
currentPhase:
|
|
3467
|
-
status:
|
|
3468
|
-
pausedAt:
|
|
3469
|
-
track:
|
|
3569
|
+
projectId: z11.string(),
|
|
3570
|
+
currentNode: z11.string(),
|
|
3571
|
+
currentPhase: z11.string(),
|
|
3572
|
+
status: z11.string(),
|
|
3573
|
+
pausedAt: z11.string().nullable(),
|
|
3574
|
+
track: z11.string(),
|
|
3470
3575
|
/** T202610120005:组合任务匹配快照(toTaskPublic 投影;迁移前存量缺省) */
|
|
3471
|
-
trackMatch:
|
|
3576
|
+
trackMatch: z11.array(z11.string()).optional()
|
|
3472
3577
|
});
|
|
3473
|
-
var NodeInfoSchema =
|
|
3474
|
-
nodeId:
|
|
3475
|
-
label:
|
|
3578
|
+
var NodeInfoSchema = z11.object({
|
|
3579
|
+
nodeId: z11.string(),
|
|
3580
|
+
label: z11.string(),
|
|
3476
3581
|
// T202610120005 R7:节点轨道 union(多轨节点——值拷贝冻结原样形态)
|
|
3477
|
-
track:
|
|
3478
|
-
prompt:
|
|
3479
|
-
skills:
|
|
3480
|
-
agents:
|
|
3481
|
-
upcomingPause:
|
|
3582
|
+
track: z11.union([z11.string(), z11.array(z11.string())]),
|
|
3583
|
+
prompt: z11.string(),
|
|
3584
|
+
skills: z11.array(z11.string()),
|
|
3585
|
+
agents: z11.array(z11.string()),
|
|
3586
|
+
upcomingPause: z11.string().nullable(),
|
|
3482
3587
|
/**
|
|
3483
3588
|
* T202609230001:门禁项随资料包注入(四响应单源 toNodeInfo)——响应恒为数组(?? [] 归一),
|
|
3484
3589
|
* 每节点注入即红线自动重申(对抗长上下文漂移);AI 据此先自检后推进。
|
|
3485
3590
|
*/
|
|
3486
|
-
toolChecks:
|
|
3487
|
-
aiChecks:
|
|
3591
|
+
toolChecks: z11.array(ToolCheckSchema).default([]),
|
|
3592
|
+
aiChecks: z11.array(AiCheckSchema).default([])
|
|
3488
3593
|
});
|
|
3489
|
-
var AdvanceResponseSchema =
|
|
3490
|
-
|
|
3491
|
-
status:
|
|
3594
|
+
var AdvanceResponseSchema = z11.discriminatedUnion("status", [
|
|
3595
|
+
z11.object({
|
|
3596
|
+
status: z11.literal("advanced"),
|
|
3492
3597
|
task: TaskPublicSchema,
|
|
3493
3598
|
nextNode: NodeInfoSchema
|
|
3494
3599
|
}),
|
|
3495
|
-
|
|
3496
|
-
status:
|
|
3600
|
+
z11.object({
|
|
3601
|
+
status: z11.literal("paused"),
|
|
3497
3602
|
task: TaskPublicSchema,
|
|
3498
3603
|
pausePoint: EdgePausePointSchema,
|
|
3499
|
-
guidance:
|
|
3604
|
+
guidance: z11.string()
|
|
3500
3605
|
}),
|
|
3501
|
-
|
|
3502
|
-
status:
|
|
3606
|
+
z11.object({
|
|
3607
|
+
status: z11.literal("completed"),
|
|
3503
3608
|
task: TaskPublicSchema
|
|
3504
3609
|
})
|
|
3505
3610
|
]);
|
|
3506
|
-
var ApproveResponseSchema =
|
|
3507
|
-
|
|
3508
|
-
status:
|
|
3611
|
+
var ApproveResponseSchema = z11.discriminatedUnion("status", [
|
|
3612
|
+
z11.object({
|
|
3613
|
+
status: z11.literal("advanced"),
|
|
3509
3614
|
task: TaskPublicSchema,
|
|
3510
3615
|
nextNode: NodeInfoSchema
|
|
3511
3616
|
}),
|
|
3512
|
-
|
|
3513
|
-
status:
|
|
3617
|
+
z11.object({
|
|
3618
|
+
status: z11.literal("rejected"),
|
|
3514
3619
|
task: TaskPublicSchema,
|
|
3515
|
-
guidance:
|
|
3620
|
+
guidance: z11.string()
|
|
3516
3621
|
}),
|
|
3517
3622
|
// 「completed」分支当前引擎不可达(approve 从 paused 流转必有下一节点,技术方案 §2.2
|
|
3518
3623
|
// 已删 paused→completed 直达路径)——按方案 §2.1 契约保留作前向兼容预留
|
|
3519
|
-
|
|
3520
|
-
status:
|
|
3624
|
+
z11.object({
|
|
3625
|
+
status: z11.literal("completed"),
|
|
3521
3626
|
task: TaskPublicSchema
|
|
3522
3627
|
})
|
|
3523
3628
|
]);
|
|
3524
|
-
var PauseRequestSchema =
|
|
3525
|
-
reason:
|
|
3629
|
+
var PauseRequestSchema = z11.object({
|
|
3630
|
+
reason: z11.string().optional()
|
|
3526
3631
|
});
|
|
3527
|
-
var ResumeRequestSchema =
|
|
3528
|
-
decision:
|
|
3632
|
+
var ResumeRequestSchema = z11.object({
|
|
3633
|
+
decision: z11.string().optional()
|
|
3529
3634
|
});
|
|
3530
|
-
var CancelRequestSchema =
|
|
3531
|
-
reason:
|
|
3635
|
+
var CancelRequestSchema = z11.object({
|
|
3636
|
+
reason: z11.string().min(1).max(500).optional()
|
|
3532
3637
|
});
|
|
3533
|
-
var ReopenRequestSchema =
|
|
3534
|
-
reason:
|
|
3638
|
+
var ReopenRequestSchema = z11.object({
|
|
3639
|
+
reason: z11.string().min(1).max(500)
|
|
3535
3640
|
});
|
|
3536
3641
|
|
|
3537
3642
|
// src/schemas/task-doc.ts
|
|
3538
|
-
import { z as
|
|
3539
|
-
var TaskContextSchema =
|
|
3540
|
-
task:
|
|
3541
|
-
taskId:
|
|
3542
|
-
title:
|
|
3643
|
+
import { z as z12 } from "zod";
|
|
3644
|
+
var TaskContextSchema = z12.object({
|
|
3645
|
+
task: z12.object({
|
|
3646
|
+
taskId: z12.string(),
|
|
3647
|
+
title: z12.string(),
|
|
3543
3648
|
// T202608240003:与 TaskPublicSchema 同步(toTaskPublic 运行时已产出,schema 声明漂移会导致 typed 消费方 strip 掉 type)
|
|
3544
|
-
type:
|
|
3649
|
+
type: z12.enum(TASK_TYPES).optional(),
|
|
3545
3650
|
// T202609230001:与 TaskPublicSchema 同步(advance 门禁读项目 vcs 配置依赖)
|
|
3546
|
-
projectId:
|
|
3547
|
-
currentNode:
|
|
3548
|
-
currentPhase:
|
|
3549
|
-
status:
|
|
3550
|
-
pausedAt:
|
|
3551
|
-
track:
|
|
3651
|
+
projectId: z12.string(),
|
|
3652
|
+
currentNode: z12.string(),
|
|
3653
|
+
currentPhase: z12.string(),
|
|
3654
|
+
status: z12.string(),
|
|
3655
|
+
pausedAt: z12.string().nullable(),
|
|
3656
|
+
track: z12.string(),
|
|
3552
3657
|
// T202610120005:组合任务匹配快照(与 TaskPublicSchema 同步——context 读取出口)
|
|
3553
|
-
trackMatch:
|
|
3658
|
+
trackMatch: z12.array(z12.string()).optional()
|
|
3554
3659
|
}),
|
|
3555
|
-
currentNode:
|
|
3556
|
-
nodeId:
|
|
3557
|
-
label:
|
|
3558
|
-
phase:
|
|
3660
|
+
currentNode: z12.object({
|
|
3661
|
+
nodeId: z12.string(),
|
|
3662
|
+
label: z12.string(),
|
|
3663
|
+
phase: z12.string(),
|
|
3559
3664
|
// T202610120005 R7:节点轨道 union(多轨节点)
|
|
3560
|
-
track:
|
|
3665
|
+
track: z12.union([z12.string(), z12.array(z12.string())]),
|
|
3561
3666
|
/** renderPrompt 渲染后(AI 推进任务的直接输入) */
|
|
3562
|
-
prompt:
|
|
3563
|
-
skills:
|
|
3564
|
-
agents:
|
|
3667
|
+
prompt: z12.string(),
|
|
3668
|
+
skills: z12.array(z12.string()),
|
|
3669
|
+
agents: z12.array(z12.string()),
|
|
3565
3670
|
/** 完成当前节点后出边上的暂停点描述(经 findNextEdge 按轨选边) */
|
|
3566
|
-
upcomingPause:
|
|
3671
|
+
upcomingPause: z12.string().nullable(),
|
|
3567
3672
|
/**
|
|
3568
3673
|
* T202609230001:门禁项注入(与 NodeInfoSchema 同步的内联镜像——CLI 侧
|
|
3569
3674
|
* TaskContext['currentNode'] 类型取门禁项供 advance 前置校验消费)。
|
|
3570
3675
|
*/
|
|
3571
|
-
toolChecks:
|
|
3572
|
-
aiChecks:
|
|
3676
|
+
toolChecks: z12.array(ToolCheckSchema).default([]),
|
|
3677
|
+
aiChecks: z12.array(AiCheckSchema).default([])
|
|
3573
3678
|
}).nullable(),
|
|
3574
|
-
pausedAtEdge:
|
|
3575
|
-
from:
|
|
3576
|
-
to:
|
|
3679
|
+
pausedAtEdge: z12.object({
|
|
3680
|
+
from: z12.string(),
|
|
3681
|
+
to: z12.string(),
|
|
3577
3682
|
pausePoint: EdgePausePointBaseSchema
|
|
3578
3683
|
}).nullable(),
|
|
3579
3684
|
/** 全节点实时状态清单 */
|
|
3580
|
-
nodes:
|
|
3581
|
-
nodeId:
|
|
3582
|
-
label:
|
|
3583
|
-
status:
|
|
3584
|
-
enteredAt:
|
|
3585
|
-
completedAt:
|
|
3685
|
+
nodes: z12.array(z12.object({
|
|
3686
|
+
nodeId: z12.string(),
|
|
3687
|
+
label: z12.string(),
|
|
3688
|
+
status: z12.string(),
|
|
3689
|
+
enteredAt: z12.date().nullable(),
|
|
3690
|
+
completedAt: z12.date().nullable()
|
|
3586
3691
|
})),
|
|
3587
3692
|
/**
|
|
3588
3693
|
* T202609230001:实例有向边表(B6 前序闭包判定数据源——「前序」按 DAG 拓扑而非列表序,
|
|
3589
3694
|
* 后继 pending 节点不算前序)。旧 server 不携带 → 客户端 ?? [] 兜底(闭包为空 = 不拦截,
|
|
3590
3695
|
* 老组合形态本就无门禁,不构成静默放行新增面)。
|
|
3591
3696
|
*/
|
|
3592
|
-
edges:
|
|
3697
|
+
edges: z12.array(z12.object({ from: z12.string(), to: z12.string() })).default([]),
|
|
3593
3698
|
/** N020 D1:任务级结构化文档(未写时 null) */
|
|
3594
3699
|
taskDoc: TaskDocContentSchema.nullable(),
|
|
3595
3700
|
/** N020 D1:节点执行记录(仅含已写记录的 nodeId) */
|
|
3596
|
-
nodeRecords:
|
|
3701
|
+
nodeRecords: z12.record(z12.string(), NodeRecordSchema),
|
|
3597
3702
|
/** N020 D1:跨节点累积素材(架构信息收集条目) */
|
|
3598
|
-
archNotes:
|
|
3703
|
+
archNotes: z12.array(ArchNoteSchema)
|
|
3599
3704
|
});
|
|
3600
|
-
var TaskSummarySchema =
|
|
3601
|
-
taskId:
|
|
3602
|
-
title:
|
|
3705
|
+
var TaskSummarySchema = z12.object({
|
|
3706
|
+
taskId: z12.string(),
|
|
3707
|
+
title: z12.string(),
|
|
3603
3708
|
// T202608240003:任务类型标签(缺省 = 裸任务/旧任务)
|
|
3604
|
-
type:
|
|
3605
|
-
projectId:
|
|
3606
|
-
dagTemplateId:
|
|
3607
|
-
currentNode:
|
|
3608
|
-
currentPhase:
|
|
3609
|
-
status:
|
|
3610
|
-
pausedAt:
|
|
3611
|
-
track:
|
|
3709
|
+
type: z12.enum(TASK_TYPES).optional(),
|
|
3710
|
+
projectId: z12.string(),
|
|
3711
|
+
dagTemplateId: z12.string(),
|
|
3712
|
+
currentNode: z12.string(),
|
|
3713
|
+
currentPhase: z12.string(),
|
|
3714
|
+
status: z12.string(),
|
|
3715
|
+
pausedAt: z12.string().nullable(),
|
|
3716
|
+
track: z12.string(),
|
|
3612
3717
|
// T202610120005:组合任务展示数据承载(列表页拼接文案依赖;迁移前存量可能缺省)
|
|
3613
|
-
trackMatch:
|
|
3614
|
-
progress:
|
|
3615
|
-
completed:
|
|
3616
|
-
total:
|
|
3718
|
+
trackMatch: z12.array(z12.string()).optional(),
|
|
3719
|
+
progress: z12.object({
|
|
3720
|
+
completed: z12.number(),
|
|
3721
|
+
total: z12.number()
|
|
3617
3722
|
}),
|
|
3618
|
-
createdAt:
|
|
3619
|
-
updatedAt:
|
|
3723
|
+
createdAt: z12.date().optional(),
|
|
3724
|
+
updatedAt: z12.date().optional()
|
|
3620
3725
|
});
|
|
3621
3726
|
|
|
3622
3727
|
// src/schemas/write-ack.ts
|
|
3623
|
-
import { z as
|
|
3728
|
+
import { z as z13 } from "zod";
|
|
3624
3729
|
var WRITE_ACK_ENTRY_KINDS = ["check", "artifact", "decision", "confirmation", "archnote"];
|
|
3625
|
-
var WriteAckEntryKindSchema =
|
|
3626
|
-
var EchoItemSchema =
|
|
3627
|
-
path:
|
|
3628
|
-
excerpt:
|
|
3730
|
+
var WriteAckEntryKindSchema = z13.enum(WRITE_ACK_ENTRY_KINDS);
|
|
3731
|
+
var EchoItemSchema = z13.object({
|
|
3732
|
+
path: z13.string(),
|
|
3733
|
+
excerpt: z13.string()
|
|
3629
3734
|
});
|
|
3630
|
-
var TaskProgressSchema =
|
|
3631
|
-
completed:
|
|
3632
|
-
total:
|
|
3735
|
+
var TaskProgressSchema = z13.object({
|
|
3736
|
+
completed: z13.number().int(),
|
|
3737
|
+
total: z13.number().int()
|
|
3633
3738
|
});
|
|
3634
3739
|
var TaskProgressPublicSchema = TaskPublicSchema.extend({
|
|
3635
|
-
projectId:
|
|
3740
|
+
projectId: z13.string(),
|
|
3636
3741
|
progress: TaskProgressSchema
|
|
3637
3742
|
});
|
|
3638
|
-
var WriteAckSchema =
|
|
3639
|
-
taskId:
|
|
3743
|
+
var WriteAckSchema = z13.object({
|
|
3744
|
+
taskId: z13.string(),
|
|
3640
3745
|
/** 本次写入触及的字段点路径(如 doc.what / nodeRecords.PRD.checks) */
|
|
3641
|
-
updated:
|
|
3746
|
+
updated: z13.array(z13.string()),
|
|
3642
3747
|
/** 新建条目标识($push 五类对象条目;无新条目的端点缺省) */
|
|
3643
|
-
entry:
|
|
3644
|
-
id:
|
|
3748
|
+
entry: z13.object({
|
|
3749
|
+
id: z13.string(),
|
|
3645
3750
|
kind: WriteAckEntryKindSchema
|
|
3646
3751
|
}).optional(),
|
|
3647
3752
|
/** 写入内容回显(触及字段逐条;无值可回显的端点可缺省) */
|
|
3648
|
-
echo:
|
|
3649
|
-
updatedAt:
|
|
3753
|
+
echo: z13.array(EchoItemSchema).optional(),
|
|
3754
|
+
updatedAt: z13.date(),
|
|
3650
3755
|
task: TaskProgressPublicSchema
|
|
3651
3756
|
});
|
|
3652
|
-
var TaskBatchEntrySchema =
|
|
3653
|
-
index:
|
|
3654
|
-
id:
|
|
3757
|
+
var TaskBatchEntrySchema = z13.object({
|
|
3758
|
+
index: z13.number().int().min(0),
|
|
3759
|
+
id: z13.string().optional(),
|
|
3655
3760
|
kind: WriteAckEntryKindSchema.optional()
|
|
3656
3761
|
});
|
|
3657
|
-
var TaskBatchFailureSchema =
|
|
3658
|
-
index:
|
|
3659
|
-
message:
|
|
3660
|
-
hint:
|
|
3762
|
+
var TaskBatchFailureSchema = z13.object({
|
|
3763
|
+
index: z13.number().int().min(0),
|
|
3764
|
+
message: z13.string(),
|
|
3765
|
+
hint: z13.string().optional()
|
|
3661
3766
|
});
|
|
3662
|
-
var TaskBatchAckSchema =
|
|
3663
|
-
taskId:
|
|
3767
|
+
var TaskBatchAckSchema = z13.object({
|
|
3768
|
+
taskId: z13.string(),
|
|
3664
3769
|
/** 成功落库条目数(部分失败语义:成功条目保留不回滚) */
|
|
3665
|
-
applied:
|
|
3770
|
+
applied: z13.number().int().min(0),
|
|
3666
3771
|
/** 本次写入触及的字段点路径 */
|
|
3667
|
-
updated:
|
|
3668
|
-
entries:
|
|
3669
|
-
failures:
|
|
3670
|
-
updatedAt:
|
|
3772
|
+
updated: z13.array(z13.string()),
|
|
3773
|
+
entries: z13.array(TaskBatchEntrySchema),
|
|
3774
|
+
failures: z13.array(TaskBatchFailureSchema),
|
|
3775
|
+
updatedAt: z13.date(),
|
|
3671
3776
|
task: TaskProgressPublicSchema
|
|
3672
3777
|
});
|
|
3673
|
-
var CreateTaskResponseSchema =
|
|
3778
|
+
var CreateTaskResponseSchema = z13.object({
|
|
3674
3779
|
task: TaskProgressPublicSchema,
|
|
3675
3780
|
firstNode: NodeInfoSchema
|
|
3676
3781
|
});
|
|
@@ -3686,53 +3791,53 @@ function excerpt(value, max = 120) {
|
|
|
3686
3791
|
return `${chars.slice(0, max - 1).join("")}\u2026`;
|
|
3687
3792
|
}
|
|
3688
3793
|
var CONTEXT_VIEWS = ["basic", "full"];
|
|
3689
|
-
var ContextViewSchema =
|
|
3794
|
+
var ContextViewSchema = z13.enum(CONTEXT_VIEWS);
|
|
3690
3795
|
|
|
3691
3796
|
// src/schemas/project.ts
|
|
3692
|
-
import { z as
|
|
3693
|
-
var ProjectStatusSchema =
|
|
3694
|
-
var VcsConfigSchema =
|
|
3797
|
+
import { z as z14 } from "zod";
|
|
3798
|
+
var ProjectStatusSchema = z14.enum(["active", "archived"]);
|
|
3799
|
+
var VcsConfigSchema = z14.object({
|
|
3695
3800
|
/** false=项目级豁免:全部 git 类检查 N/A(纯文档/无分支模型项目不误拦) */
|
|
3696
|
-
enabled:
|
|
3801
|
+
enabled: z14.boolean().optional(),
|
|
3697
3802
|
/** 基础分支(参数解析链第 2 级;第 1 级=nodeRecords[ALIGN].baseBranch) */
|
|
3698
|
-
baseBranch:
|
|
3803
|
+
baseBranch: z14.string().min(1).max(50).optional(),
|
|
3699
3804
|
/** 仓库绝对路径(MCP 宿主 cwd 未必是任务仓库时由管理台配置;缺省=cwd 探测) */
|
|
3700
|
-
repoPath:
|
|
3805
|
+
repoPath: z14.string().min(1).optional(),
|
|
3701
3806
|
/** 任务分支前缀模式(A1 判定用) */
|
|
3702
|
-
branchPattern:
|
|
3807
|
+
branchPattern: z14.string().min(1).max(50).optional(),
|
|
3703
3808
|
/** true=worktree 并行模式(A6 停留子项 N/A——主工作区停留基础分支由主会话承载) */
|
|
3704
|
-
worktreeMode:
|
|
3809
|
+
worktreeMode: z14.boolean().optional(),
|
|
3705
3810
|
/** false=项目声明无分支归档流程(A5 N/A;表达「有分支模型但无归档流程」粒度) */
|
|
3706
|
-
archiveToBase:
|
|
3811
|
+
archiveToBase: z14.boolean().optional(),
|
|
3707
3812
|
/** B7 版本一致判定的豁免路径清单(文档/临时产物) */
|
|
3708
|
-
docPaths:
|
|
3813
|
+
docPaths: z14.array(z14.string().min(1)).max(50).optional()
|
|
3709
3814
|
});
|
|
3710
3815
|
var DEFAULT_VCS_DOC_PATHS = ["ProjectHub/", "docs/", "temp/", "*.md"];
|
|
3711
|
-
var ProjectSchema =
|
|
3712
|
-
id:
|
|
3713
|
-
key:
|
|
3714
|
-
name:
|
|
3715
|
-
description:
|
|
3816
|
+
var ProjectSchema = z14.object({
|
|
3817
|
+
id: z14.string().optional(),
|
|
3818
|
+
key: z14.string().regex(/^[a-z0-9][a-z0-9-]{1,30}$/, "key \u5FC5\u987B\u4E3A kebab-case\uFF082-31 \u5B57\u7B26\uFF09"),
|
|
3819
|
+
name: z14.string().min(1).max(50),
|
|
3820
|
+
description: z14.string().max(500).optional(),
|
|
3716
3821
|
status: ProjectStatusSchema.default("active"),
|
|
3717
3822
|
vcs: VcsConfigSchema.optional(),
|
|
3718
|
-
createdAt:
|
|
3719
|
-
updatedAt:
|
|
3823
|
+
createdAt: z14.date().optional(),
|
|
3824
|
+
updatedAt: z14.date().optional()
|
|
3720
3825
|
});
|
|
3721
|
-
var ProjectCreateSchema =
|
|
3722
|
-
key:
|
|
3723
|
-
name:
|
|
3724
|
-
description:
|
|
3826
|
+
var ProjectCreateSchema = z14.object({
|
|
3827
|
+
key: z14.string().regex(/^[a-z0-9][a-z0-9-]{1,30}$/, "key \u5FC5\u987B\u4E3A kebab-case\uFF082-31 \u5B57\u7B26\uFF09").optional(),
|
|
3828
|
+
name: z14.string().min(1).max(50),
|
|
3829
|
+
description: z14.string().max(500).optional()
|
|
3725
3830
|
});
|
|
3726
|
-
var ProjectUpdateSchema =
|
|
3727
|
-
name:
|
|
3728
|
-
description:
|
|
3831
|
+
var ProjectUpdateSchema = z14.object({
|
|
3832
|
+
name: z14.string().min(1).max(50).optional(),
|
|
3833
|
+
description: z14.string().max(500).optional(),
|
|
3729
3834
|
status: ProjectStatusSchema.optional(),
|
|
3730
3835
|
vcs: VcsConfigSchema.optional()
|
|
3731
3836
|
});
|
|
3732
3837
|
|
|
3733
3838
|
// src/schemas/enum-registry.ts
|
|
3734
|
-
import { z as
|
|
3735
|
-
var EnumRegistryCategorySchema =
|
|
3839
|
+
import { z as z15 } from "zod";
|
|
3840
|
+
var EnumRegistryCategorySchema = z15.enum([
|
|
3736
3841
|
"dag_phase",
|
|
3737
3842
|
"dag_track",
|
|
3738
3843
|
"pause_type",
|
|
@@ -3743,100 +3848,34 @@ var EnumRegistryCategorySchema = z14.enum([
|
|
|
3743
3848
|
"agent_function",
|
|
3744
3849
|
"issue_status"
|
|
3745
3850
|
]);
|
|
3746
|
-
var EnumEntrySchema =
|
|
3851
|
+
var EnumEntrySchema = z15.object({
|
|
3747
3852
|
/** 领域层存库的原始枚举值(不可臆造;builtin 值 engine/DB 强依赖;kebab 约束与 skill name 对齐,保证 DELETE /entries/:value 可寻址) */
|
|
3748
|
-
value:
|
|
3853
|
+
value: z15.string().regex(/^[a-z0-9][a-z0-9_-]*$/, "value \u4EC5\u652F\u6301\u5C0F\u5199\u5B57\u6BCD/\u6570\u5B57/\u4E0B\u5212\u7EBF/\u8FDE\u5B57\u7B26\uFF08kebab-case\uFF09"),
|
|
3749
3854
|
/** 展示文案(消费端下拉直接取用) */
|
|
3750
|
-
label:
|
|
3855
|
+
label: z15.string().min(1, "label \u4E0D\u80FD\u4E3A\u7A7A"),
|
|
3751
3856
|
/** 可选语义色 token(如 --success / --warning),消费端映射到 UI */
|
|
3752
|
-
color:
|
|
3857
|
+
color: z15.string().optional(),
|
|
3753
3858
|
/** 下拉排序(升序) */
|
|
3754
|
-
order:
|
|
3859
|
+
order: z15.number().int().default(0),
|
|
3755
3860
|
/** 内置值:禁删 + label/color 可改但 value 不可改(D8);seed 时标记 */
|
|
3756
|
-
builtin:
|
|
3861
|
+
builtin: z15.boolean().default(false),
|
|
3757
3862
|
/** 启停:false = 下拉禁用展示(历史数据仍可读,新选择不可用) */
|
|
3758
|
-
active:
|
|
3863
|
+
active: z15.boolean().default(true)
|
|
3759
3864
|
});
|
|
3760
|
-
var EnumRegistrySchema =
|
|
3761
|
-
id:
|
|
3865
|
+
var EnumRegistrySchema = z15.object({
|
|
3866
|
+
id: z15.string().optional(),
|
|
3762
3867
|
category: EnumRegistryCategorySchema,
|
|
3763
|
-
entries:
|
|
3764
|
-
updatedAt:
|
|
3868
|
+
entries: z15.array(EnumEntrySchema).default([]),
|
|
3869
|
+
updatedAt: z15.date().optional()
|
|
3765
3870
|
});
|
|
3766
|
-
var EnumRegistryUpdateSchema =
|
|
3767
|
-
entries:
|
|
3871
|
+
var EnumRegistryUpdateSchema = z15.object({
|
|
3872
|
+
entries: z15.array(EnumEntrySchema)
|
|
3768
3873
|
});
|
|
3769
3874
|
|
|
3770
3875
|
// src/schemas/asset-enabled.ts
|
|
3771
|
-
import { z as z15 } from "zod";
|
|
3772
|
-
var AssetSetEnabledSchema = z15.object({
|
|
3773
|
-
enabled: z15.boolean()
|
|
3774
|
-
});
|
|
3775
|
-
|
|
3776
|
-
// src/schemas/auth.ts
|
|
3777
3876
|
import { z as z16 } from "zod";
|
|
3778
|
-
var
|
|
3779
|
-
|
|
3780
|
-
id: z16.string().optional(),
|
|
3781
|
-
username: z16.string().min(3, "\u8D26\u53F7\u81F3\u5C11 3 \u4E2A\u5B57\u7B26").max(50).regex(/^[a-zA-Z0-9_-]+$/, "\u8D26\u53F7\u4EC5\u5141\u8BB8\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u4E0B\u5212\u7EBF\u4E0E\u8FDE\u5B57\u7B26"),
|
|
3782
|
-
/** 存储形态:scrypt$N$r$p$salt$hash(base64 段),明文仅存在于请求体 */
|
|
3783
|
-
passwordHash: z16.string().min(1),
|
|
3784
|
-
createdAt: z16.date().optional(),
|
|
3785
|
-
updatedAt: z16.date().optional()
|
|
3786
|
-
});
|
|
3787
|
-
var AuthAccountCreateSchema = z16.object({
|
|
3788
|
-
username: AuthAccountSchema.shape.username,
|
|
3789
|
-
password: z16.string().min(8, "\u5BC6\u7801\u81F3\u5C11 8 \u4E2A\u5B57\u7B26").max(128)
|
|
3790
|
-
});
|
|
3791
|
-
var PasswordChangeSchema = z16.object({
|
|
3792
|
-
currentPassword: z16.string().min(1),
|
|
3793
|
-
newPassword: z16.string().min(8, "\u5BC6\u7801\u81F3\u5C11 8 \u4E2A\u5B57\u7B26").max(128)
|
|
3794
|
-
});
|
|
3795
|
-
var LoginSchema = z16.object({
|
|
3796
|
-
username: z16.string().min(1),
|
|
3797
|
-
password: z16.string().min(1)
|
|
3798
|
-
});
|
|
3799
|
-
var AuthTokenSchema = z16.object({
|
|
3800
|
-
id: z16.string().optional(),
|
|
3801
|
-
/** sha256(token 全串含前缀) hex——明文 Token 不入库 */
|
|
3802
|
-
tokenHash: z16.string().regex(/^[a-f0-9]{64}$/),
|
|
3803
|
-
type: AuthTokenTypeSchema,
|
|
3804
|
-
/** type=project 时必填且不可缺失(superRefine 保证);指向 projects.id(24-hex) */
|
|
3805
|
-
projectId: z16.string().regex(/^[a-f0-9]{24}$/, "projectId \u5FC5\u987B\u4E3A 24-hex ObjectId").optional(),
|
|
3806
|
-
createdAt: z16.date().optional(),
|
|
3807
|
-
updatedAt: z16.date().optional()
|
|
3808
|
-
}).superRefine((data, ctx) => {
|
|
3809
|
-
if (data.type === "project" && data.projectId === void 0) {
|
|
3810
|
-
ctx.addIssue({ code: "custom", path: ["projectId"], message: "\u9879\u76EE Token \u5FC5\u987B\u7ED1\u5B9A projectId" });
|
|
3811
|
-
}
|
|
3812
|
-
});
|
|
3813
|
-
var AuthTokenGenResponseSchema = z16.object({
|
|
3814
|
-
token: z16.string().min(1),
|
|
3815
|
-
type: AuthTokenTypeSchema,
|
|
3816
|
-
projectId: z16.string().optional()
|
|
3817
|
-
});
|
|
3818
|
-
var AuthTokenStatusSchema = z16.object({
|
|
3819
|
-
type: AuthTokenTypeSchema,
|
|
3820
|
-
projectId: z16.string().optional(),
|
|
3821
|
-
hasToken: z16.boolean(),
|
|
3822
|
-
createdAt: z16.date().nullable().optional()
|
|
3823
|
-
});
|
|
3824
|
-
var AuthWhoamiSchema = z16.object({
|
|
3825
|
-
identity: z16.enum(["admin", "project", "none"]),
|
|
3826
|
-
project: z16.object({
|
|
3827
|
-
id: z16.string(),
|
|
3828
|
-
key: z16.string(),
|
|
3829
|
-
name: z16.string()
|
|
3830
|
-
}).nullable().optional(),
|
|
3831
|
-
authEnabled: z16.boolean(),
|
|
3832
|
-
server: z16.object({
|
|
3833
|
-
url: z16.string()
|
|
3834
|
-
})
|
|
3835
|
-
});
|
|
3836
|
-
var AuthStatusSchema = z16.object({
|
|
3837
|
-
authEnabled: z16.boolean(),
|
|
3838
|
-
/** 鉴权开启且无管理员账号 = 初始化引导窗口(PRD §3.2) */
|
|
3839
|
-
needsSetup: z16.boolean()
|
|
3877
|
+
var AssetSetEnabledSchema = z16.object({
|
|
3878
|
+
enabled: z16.boolean()
|
|
3840
3879
|
});
|
|
3841
3880
|
|
|
3842
3881
|
// src/schemas/node-preset.ts
|
|
@@ -4057,7 +4096,7 @@ function bumpPatchOrPassthrough(version) {
|
|
|
4057
4096
|
}
|
|
4058
4097
|
|
|
4059
4098
|
// src/content-hash.ts
|
|
4060
|
-
import { createHash
|
|
4099
|
+
import { createHash } from "crypto";
|
|
4061
4100
|
function computeNodeContentHash(node) {
|
|
4062
4101
|
const canonical = JSON.stringify({
|
|
4063
4102
|
label: node.label,
|
|
@@ -4066,7 +4105,7 @@ function computeNodeContentHash(node) {
|
|
|
4066
4105
|
prompt: node.prompt,
|
|
4067
4106
|
skills: [...node.skills].sort()
|
|
4068
4107
|
});
|
|
4069
|
-
return
|
|
4108
|
+
return createHash("sha256").update(canonical).digest("hex").slice(0, 16);
|
|
4070
4109
|
}
|
|
4071
4110
|
|
|
4072
4111
|
// src/template-content-diff.ts
|
|
@@ -4901,6 +4940,7 @@ export {
|
|
|
4901
4940
|
AGENT_MAIN_DOC,
|
|
4902
4941
|
ARTIFACT_TYPES,
|
|
4903
4942
|
AUTH_COLLECTIONS,
|
|
4943
|
+
AUTH_TOKEN_LIMIT,
|
|
4904
4944
|
AdvanceRequestSchema,
|
|
4905
4945
|
AdvanceResponseSchema,
|
|
4906
4946
|
AgentCopySchema,
|
|
@@ -4922,9 +4962,11 @@ export {
|
|
|
4922
4962
|
AuthAccountSchema,
|
|
4923
4963
|
AuthStatusSchema,
|
|
4924
4964
|
AuthTokenGenResponseSchema,
|
|
4965
|
+
AuthTokenIssueInputSchema,
|
|
4966
|
+
AuthTokenNameSchema,
|
|
4925
4967
|
AuthTokenSchema,
|
|
4926
|
-
AuthTokenStatusSchema,
|
|
4927
4968
|
AuthTokenTypeSchema,
|
|
4969
|
+
AuthTokenViewSchema,
|
|
4928
4970
|
AuthWhoamiSchema,
|
|
4929
4971
|
BIZ_CODE_MESSAGES,
|
|
4930
4972
|
BadRequestError,
|
|
@@ -5127,7 +5169,6 @@ export {
|
|
|
5127
5169
|
generateToken,
|
|
5128
5170
|
hasProjectDefault,
|
|
5129
5171
|
hashPassword,
|
|
5130
|
-
hashToken,
|
|
5131
5172
|
isLegalTemplateCode,
|
|
5132
5173
|
matchSetOf,
|
|
5133
5174
|
mkHistory,
|