@musnows/scriverse 0.5.0 → 0.5.1
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/ai.js +112 -8
- package/dist/ai.js.map +1 -1
- package/dist/app.js +4 -0
- package/dist/app.js.map +1 -1
- package/dist/public/app.js +93 -24
- package/dist/public/index.html +2 -2
- package/dist/public/styles.css +37 -5
- package/dist/user-auth.js +1 -1
- package/dist/user-auth.js.map +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/ai.js
CHANGED
|
@@ -33,6 +33,66 @@ function thinkingParameters(provider, model) {
|
|
|
33
33
|
return { thinking: { type: boolValue(model, "thinking_enabled") ? "enabled" : "disabled" } };
|
|
34
34
|
}
|
|
35
35
|
const AGENT_TOOL_IDS = ["story_index", "read_chapters", "grep", "search_story_entities", "read_character_sections"];
|
|
36
|
+
const TASK_TRACE_PREVIEW_CHARACTER_LIMIT = 3_000;
|
|
37
|
+
function traceRecord(value) {
|
|
38
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
39
|
+
}
|
|
40
|
+
function previewTaskTraceMessages(messages) {
|
|
41
|
+
const records = messages.map(traceRecord);
|
|
42
|
+
const contents = records.map((message) => message.content === null ? "" : String(message.content ?? ""));
|
|
43
|
+
const allocations = contents.map(() => 0);
|
|
44
|
+
let remaining = TASK_TRACE_PREVIEW_CHARACTER_LIMIT;
|
|
45
|
+
let active = contents.map((_, index) => index).filter((index) => contents[index].length > 0);
|
|
46
|
+
while (remaining > 0 && active.length > 0) {
|
|
47
|
+
const share = Math.max(1, Math.floor(remaining / active.length));
|
|
48
|
+
const next = [];
|
|
49
|
+
for (const index of active) {
|
|
50
|
+
if (remaining <= 0)
|
|
51
|
+
break;
|
|
52
|
+
const available = contents[index].length - allocations[index];
|
|
53
|
+
const granted = Math.min(available, share, remaining);
|
|
54
|
+
allocations[index] = allocations[index] + granted;
|
|
55
|
+
remaining -= granted;
|
|
56
|
+
if (allocations[index] < contents[index].length)
|
|
57
|
+
next.push(index);
|
|
58
|
+
}
|
|
59
|
+
active = next;
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
messages: records.map((message, index) => {
|
|
63
|
+
const content = contents[index];
|
|
64
|
+
const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : [];
|
|
65
|
+
return {
|
|
66
|
+
role: typeof message.role === "string" ? message.role : "user",
|
|
67
|
+
content: content.slice(0, allocations[index]),
|
|
68
|
+
contentChars: content.length,
|
|
69
|
+
contentTruncated: allocations[index] < content.length,
|
|
70
|
+
toolCallCount: toolCalls.length,
|
|
71
|
+
...(typeof message.tool_call_id === "string" ? { tool_call_id: message.tool_call_id } : {})
|
|
72
|
+
};
|
|
73
|
+
}),
|
|
74
|
+
totalChars: contents.reduce((total, content) => total + content.length, 0),
|
|
75
|
+
truncated: contents.some((content, index) => allocations[index] < content.length)
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function summarizeTaskTraceRound(value) {
|
|
79
|
+
const round = traceRecord(value);
|
|
80
|
+
const request = traceRecord(round.request);
|
|
81
|
+
const messages = Array.isArray(request.messages) ? request.messages : [];
|
|
82
|
+
const attempts = Array.isArray(round.attempts) ? round.attempts : [];
|
|
83
|
+
const toolExecutions = Array.isArray(round.toolExecutions) ? round.toolExecutions : [];
|
|
84
|
+
return {
|
|
85
|
+
round: typeof round.round === "number" ? round.round : 1,
|
|
86
|
+
requestedAt: typeof round.requestedAt === "string" ? round.requestedAt : "",
|
|
87
|
+
messageCount: messages.length,
|
|
88
|
+
promptChars: messages.reduce((total, message) => {
|
|
89
|
+
const content = traceRecord(message).content;
|
|
90
|
+
return total + (content === null ? 0 : String(content ?? "").length);
|
|
91
|
+
}, 0),
|
|
92
|
+
attemptCount: attempts.length,
|
|
93
|
+
toolExecutionCount: toolExecutions.length
|
|
94
|
+
};
|
|
95
|
+
}
|
|
36
96
|
function redactProviderSecret(value, apiKey) {
|
|
37
97
|
if (!apiKey)
|
|
38
98
|
return value;
|
|
@@ -1313,8 +1373,12 @@ export class AiManager {
|
|
|
1313
1373
|
}
|
|
1314
1374
|
getTaskTrace(taskId) {
|
|
1315
1375
|
this.store.getTask(taskId);
|
|
1316
|
-
const rows = this.store.db.all(`SELECT call
|
|
1317
|
-
|
|
1376
|
+
const rows = this.store.db.all(`SELECT call.id, call.task_type, call.provider_id, call.model_id, call.status, call.failure,
|
|
1377
|
+
call.input_chars, call.output_chars, call.created_at, call.completed_at, trace.call_id AS trace_call_id,
|
|
1378
|
+
CASE WHEN trace.call_id IS NULL THEN 0 ELSE json_array_length(trace.initial_messages_json) END AS initial_message_count,
|
|
1379
|
+
CASE WHEN trace.call_id IS NULL THEN 0 ELSE json_array_length(trace.rounds_json) END AS round_count,
|
|
1380
|
+
CASE WHEN trace.call_id IS NULL THEN 0 ELSE length(trace.initial_messages_json) + length(trace.rounds_json) END AS trace_chars,
|
|
1381
|
+
trace.created_at AS trace_created_at, trace.updated_at AS trace_updated_at, provider.name AS provider_name,
|
|
1318
1382
|
model.display_name AS model_display_name, model.model_id AS external_model_id
|
|
1319
1383
|
FROM ai_calls call
|
|
1320
1384
|
LEFT JOIN ai_call_traces trace ON trace.call_id = call.id
|
|
@@ -1323,7 +1387,8 @@ export class AiManager {
|
|
|
1323
1387
|
WHERE call.task_id = ?
|
|
1324
1388
|
ORDER BY call.created_at ASC, call.id ASC`, taskId);
|
|
1325
1389
|
const calls = rows.map((row) => {
|
|
1326
|
-
const hasTrace = row.
|
|
1390
|
+
const hasTrace = row.trace_call_id !== null && row.trace_call_id !== undefined;
|
|
1391
|
+
const failure = row.failure === null ? null : stringValue(row, "failure");
|
|
1327
1392
|
return {
|
|
1328
1393
|
id: stringValue(row, "id"),
|
|
1329
1394
|
taskType: stringValue(row, "task_type"),
|
|
@@ -1338,17 +1403,18 @@ export class AiManager {
|
|
|
1338
1403
|
modelId: row.external_model_id === null ? null : stringValue(row, "external_model_id"),
|
|
1339
1404
|
deleted: row.model_display_name === null
|
|
1340
1405
|
},
|
|
1341
|
-
contextScope: json(stringValue(row, "context_scope_json"), {}),
|
|
1342
|
-
parameters: json(stringValue(row, "parameters_json"), {}),
|
|
1343
1406
|
status: stringValue(row, "status"),
|
|
1344
|
-
failure:
|
|
1407
|
+
failure: failure === null ? null : failure.slice(0, 1_000),
|
|
1408
|
+
failureTruncated: failure !== null && failure.length > 1_000,
|
|
1345
1409
|
inputChars: numberValue(row, "input_chars"),
|
|
1346
1410
|
outputChars: numberValue(row, "output_chars"),
|
|
1347
1411
|
createdAt: stringValue(row, "created_at"),
|
|
1348
1412
|
completedAt: row.completed_at === null ? null : stringValue(row, "completed_at"),
|
|
1349
1413
|
trace: hasTrace ? {
|
|
1350
|
-
|
|
1351
|
-
|
|
1414
|
+
available: true,
|
|
1415
|
+
initialMessageCount: numberValue(row, "initial_message_count"),
|
|
1416
|
+
roundCount: numberValue(row, "round_count"),
|
|
1417
|
+
serializedChars: numberValue(row, "trace_chars"),
|
|
1352
1418
|
createdAt: stringValue(row, "trace_created_at"),
|
|
1353
1419
|
updatedAt: stringValue(row, "trace_updated_at")
|
|
1354
1420
|
} : null
|
|
@@ -1360,6 +1426,44 @@ export class AiManager {
|
|
|
1360
1426
|
calls
|
|
1361
1427
|
};
|
|
1362
1428
|
}
|
|
1429
|
+
getTaskTraceCall(taskId, callId, full = false) {
|
|
1430
|
+
this.store.getTask(taskId);
|
|
1431
|
+
const row = this.store.db.get(`SELECT trace.initial_messages_json, trace.rounds_json, trace.created_at, trace.updated_at
|
|
1432
|
+
FROM ai_calls call JOIN ai_call_traces trace ON trace.call_id = call.id AND trace.task_id = call.task_id
|
|
1433
|
+
WHERE call.id = ? AND call.task_id = ?`, callId, taskId);
|
|
1434
|
+
if (!row)
|
|
1435
|
+
throw notFound("AI 调用追踪");
|
|
1436
|
+
const initialMessages = json(stringValue(row, "initial_messages_json"), []);
|
|
1437
|
+
const rounds = json(stringValue(row, "rounds_json"), []);
|
|
1438
|
+
if (full) {
|
|
1439
|
+
return {
|
|
1440
|
+
taskId,
|
|
1441
|
+
callId,
|
|
1442
|
+
mode: "full",
|
|
1443
|
+
trace: {
|
|
1444
|
+
initialMessages,
|
|
1445
|
+
rounds,
|
|
1446
|
+
createdAt: stringValue(row, "created_at"),
|
|
1447
|
+
updatedAt: stringValue(row, "updated_at")
|
|
1448
|
+
}
|
|
1449
|
+
};
|
|
1450
|
+
}
|
|
1451
|
+
const preview = previewTaskTraceMessages(initialMessages);
|
|
1452
|
+
return {
|
|
1453
|
+
taskId,
|
|
1454
|
+
callId,
|
|
1455
|
+
mode: "preview",
|
|
1456
|
+
previewLimit: TASK_TRACE_PREVIEW_CHARACTER_LIMIT,
|
|
1457
|
+
truncated: preview.truncated,
|
|
1458
|
+
totalPromptChars: preview.totalChars,
|
|
1459
|
+
trace: {
|
|
1460
|
+
initialMessages: preview.messages,
|
|
1461
|
+
rounds: rounds.map(summarizeTaskTraceRound),
|
|
1462
|
+
createdAt: stringValue(row, "created_at"),
|
|
1463
|
+
updatedAt: stringValue(row, "updated_at")
|
|
1464
|
+
}
|
|
1465
|
+
};
|
|
1466
|
+
}
|
|
1363
1467
|
async runTask(taskId, modelId) {
|
|
1364
1468
|
const task = this.store.getTask(taskId);
|
|
1365
1469
|
const workId = String(task.workId);
|