@musnows/scriverse 0.5.2 → 0.5.4
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/LICENSE +661 -21
- package/README.en.md +8 -0
- package/README.md +12 -3
- package/dist/ai-protocol.js +216 -0
- package/dist/ai-protocol.js.map +1 -0
- package/dist/ai.js +1082 -187
- package/dist/ai.js.map +1 -1
- package/dist/app.js +51 -6
- package/dist/app.js.map +1 -1
- package/dist/database.js +339 -0
- package/dist/database.js.map +1 -1
- package/dist/public/app.js +77 -16
- package/dist/public/display-labels.d.ts +1 -0
- package/dist/public/display-labels.js +8 -0
- package/dist/public/index.html +13 -7
- package/dist/public/styles.css +17 -0
- package/dist/relationship-search.js +196 -0
- package/dist/relationship-search.js.map +1 -0
- package/dist/store.js +59 -8
- package/dist/store.js.map +1 -1
- package/dist/user-auth.js +23 -6
- package/dist/user-auth.js.map +1 -1
- package/dist/utils.js +1 -1
- package/dist/utils.js.map +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -2
package/dist/app.js
CHANGED
|
@@ -28,7 +28,7 @@ import { currentRequestActor, runWithRequestActor } from "./request-context.js";
|
|
|
28
28
|
import { APP_VERSION } from "./version.js";
|
|
29
29
|
import { fullWorkModulePermissions, proseReplacementPermissionModules } from "./work-permissions.js";
|
|
30
30
|
import { CollaborationPresence, editorPageKey, entityEditorPageKey, modulePageKey, pageLabelForKey, presencePageKinds } from "./collaboration-presence.js";
|
|
31
|
-
import { clearSessionCookie, createCliApiScopeMiddleware, createUserSessionMiddleware, createWorkAuthorizationMiddleware, setSessionCookie, UserAuthService } from "./user-auth.js";
|
|
31
|
+
import { clearSessionCookie, createCliApiScopeMiddleware, createUserSessionMiddleware, createWorkAuthorizationMiddleware, relationshipAnalysisReadModules, setSessionCookie, UserAuthService } from "./user-auth.js";
|
|
32
32
|
const nonEmpty = z.string().trim().min(1);
|
|
33
33
|
const identifier = z.string().trim().min(1).max(200);
|
|
34
34
|
const optionalStrings = z.array(z.string()).optional();
|
|
@@ -274,6 +274,7 @@ const providerSchema = z.object({
|
|
|
274
274
|
name: nonEmpty.max(200),
|
|
275
275
|
baseUrl: z.string().url().refine((value) => value.startsWith("http://") || value.startsWith("https://"), "接口地址必须使用 HTTP 或 HTTPS"),
|
|
276
276
|
apiKey: nonEmpty.max(10_000),
|
|
277
|
+
protocol: z.enum(["openai-chat-completions", "anthropic-messages"]).optional(),
|
|
277
278
|
status: z.enum(["enabled", "disabled"]).optional(),
|
|
278
279
|
note: z.string().max(10_000).optional(),
|
|
279
280
|
concurrencyLimit: z.number().int().min(1).max(100).optional(),
|
|
@@ -379,8 +380,8 @@ const relationshipAnalysisScopeSchema = z.object({
|
|
|
379
380
|
}
|
|
380
381
|
});
|
|
381
382
|
const analysisTaskSchema = z.union([
|
|
382
|
-
z.object({ taskType: z.literal("relationship-analysis"), scope: relationshipAnalysisScopeSchema.optional() }).strict(),
|
|
383
|
-
z.object({ taskType: analysisTaskTypeSchema, scope: jsonObject.optional() }).strict().superRefine((input, context) => {
|
|
383
|
+
z.object({ taskType: z.literal("relationship-analysis"), scope: relationshipAnalysisScopeSchema.optional(), modelId: identifier.optional() }).strict(),
|
|
384
|
+
z.object({ taskType: analysisTaskTypeSchema, scope: jsonObject.optional(), modelId: identifier.optional() }).strict().superRefine((input, context) => {
|
|
384
385
|
if (input.scope?.includeAllSettings !== undefined) {
|
|
385
386
|
context.addIssue({ code: z.ZodIssueCode.custom, path: ["scope", "includeAllSettings"], message: "包含所有设定仅支持人物关系分析" });
|
|
386
387
|
}
|
|
@@ -570,7 +571,24 @@ export function createRuntime(options) {
|
|
|
570
571
|
return auth.workModulePermissions(request.authUser, resolvedWorkId, request.authMethod !== "api-key") ?? fullWorkModulePermissions();
|
|
571
572
|
};
|
|
572
573
|
const captcha = new ImageCaptchaService({ revealAnswer: options.revealCaptchaAnswer === true });
|
|
573
|
-
const ai = new AiManager(store, new CredentialVault(options.masterSecret), options.fetchImpl ?? fetch, options.security ? (url) => assertSafeAiEndpoint(url, options.security?.allowPrivateAiEndpoints) : undefined)
|
|
574
|
+
const ai = new AiManager(store, new CredentialVault(options.masterSecret), options.fetchImpl ?? fetch, options.security ? (url) => assertSafeAiEndpoint(url, options.security?.allowPrivateAiEndpoints) : undefined, (task, actor) => {
|
|
575
|
+
if (task.taskType !== "relationship-analysis")
|
|
576
|
+
return;
|
|
577
|
+
const requiredModules = relationshipAnalysisReadModules(task.scope);
|
|
578
|
+
if (requiredModules.length === 0)
|
|
579
|
+
return;
|
|
580
|
+
const creator = actor ? null : database.get("SELECT created_by_user_id FROM analysis_tasks WHERE id = ?", String(task.id));
|
|
581
|
+
const userId = actor?.userId ?? (typeof creator?.created_by_user_id === "string" ? creator.created_by_user_id : null);
|
|
582
|
+
if (!userId)
|
|
583
|
+
return;
|
|
584
|
+
const user = auth.getUser(userId);
|
|
585
|
+
if (user.status !== "active")
|
|
586
|
+
throw new AppError(403, "WORK_ACCESS_DENIED", "任务创建者已无法访问这部作品");
|
|
587
|
+
auth.assertWorkAccess(user, String(task.workId), {
|
|
588
|
+
read: requiredModules,
|
|
589
|
+
write: ["ai-analysis"]
|
|
590
|
+
}, false, actor?.allowAdminAccess ?? false);
|
|
591
|
+
});
|
|
574
592
|
const app = express();
|
|
575
593
|
const upload = multer({
|
|
576
594
|
storage: multer.memoryStorage(),
|
|
@@ -601,6 +619,7 @@ export function createRuntime(options) {
|
|
|
601
619
|
status: "ok",
|
|
602
620
|
version: APP_VERSION,
|
|
603
621
|
protocol: "openai-chat-completions",
|
|
622
|
+
protocols: ["openai-chat-completions", "anthropic-messages"],
|
|
604
623
|
development: options.developmentServer === true
|
|
605
624
|
});
|
|
606
625
|
});
|
|
@@ -1417,9 +1436,22 @@ export function createRuntime(options) {
|
|
|
1417
1436
|
});
|
|
1418
1437
|
app.post("/api/works/:workId/tasks", (request, response) => {
|
|
1419
1438
|
const input = parse(analysisTaskSchema, request.body);
|
|
1420
|
-
data(response, redactTaskCharacterNames(
|
|
1439
|
+
data(response, redactTaskCharacterNames(ai.createTask(request.params.workId, input), requestPermissions(request, request.params.workId)), 201);
|
|
1421
1440
|
});
|
|
1422
1441
|
app.post("/api/works/:workId/tasks/auto-run", (request, response) => {
|
|
1442
|
+
const permissions = requestPermissions(request, request.params.workId);
|
|
1443
|
+
for (const taskId of store.listOldestPendingTaskIds(request.params.workId, store.countPendingTasks(request.params.workId))) {
|
|
1444
|
+
const task = store.getTask(taskId);
|
|
1445
|
+
if (task.taskType !== "relationship-analysis")
|
|
1446
|
+
continue;
|
|
1447
|
+
const deniedModules = relationshipAnalysisReadModules(task.scope).filter((module) => permissions[module] === "none");
|
|
1448
|
+
if (deniedModules.length > 0) {
|
|
1449
|
+
throw new AppError(403, "WORK_MODULE_READ_DENIED", "你没有读取待运行定向人物关系分析所需资料模块的权限", {
|
|
1450
|
+
taskId,
|
|
1451
|
+
modules: deniedModules
|
|
1452
|
+
});
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1423
1455
|
data(response, ai.startAutoRunBatch(request.params.workId));
|
|
1424
1456
|
});
|
|
1425
1457
|
app.get("/api/tasks/:taskId/detail", (request, response) => data(response, redactTaskCharacterNames(store.getTaskDetail(request.params.taskId), requestPermissions(request))));
|
|
@@ -1438,7 +1470,20 @@ export function createRuntime(options) {
|
|
|
1438
1470
|
app.get("/api/tasks/:taskId/trace/calls/:callId", (request, response) => data(response, ai.getTaskTraceCall(request.params.taskId, request.params.callId)));
|
|
1439
1471
|
app.post("/api/tasks/:taskId/run", async (request, response) => {
|
|
1440
1472
|
const input = parse(z.object({ modelId: identifier.optional() }), request.body ?? {});
|
|
1441
|
-
|
|
1473
|
+
const task = store.getTask(request.params.taskId);
|
|
1474
|
+
if (task.taskType === "relationship-analysis") {
|
|
1475
|
+
const permissions = requestPermissions(request, String(task.workId));
|
|
1476
|
+
const deniedModules = relationshipAnalysisReadModules(task.scope).filter((module) => permissions[module] === "none");
|
|
1477
|
+
if (deniedModules.length > 0) {
|
|
1478
|
+
throw new AppError(403, "WORK_MODULE_READ_DENIED", "你没有读取本次定向人物关系分析所需资料模块的权限", {
|
|
1479
|
+
modules: deniedModules
|
|
1480
|
+
});
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
data(response, redactTaskCharacterNames(await ai.runTask(request.params.taskId, input.modelId, request.authUser ? {
|
|
1484
|
+
userId: request.authUser.userId,
|
|
1485
|
+
allowAdminAccess: request.authMethod !== "api-key"
|
|
1486
|
+
} : undefined), requestPermissions(request)));
|
|
1442
1487
|
});
|
|
1443
1488
|
app.post("/api/tasks/:taskId/cancel", (request, response) => data(response, redactTaskCharacterNames(ai.cancelTask(request.params.taskId), requestPermissions(request))));
|
|
1444
1489
|
app.get("/api/platform/ai/providers", (request, response) => {
|