koishi-plugin-chatluna-studio 1.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/LICENSE +21 -0
- package/README.md +38 -0
- package/dist/index.js +45313 -0
- package/dist/style.css +1 -0
- package/lib/chatluna/error.d.ts +15 -0
- package/lib/chatluna/runtime.d.ts +25 -0
- package/lib/chatluna/session-tracker.d.ts +98 -0
- package/lib/chatluna/usage.d.ts +46 -0
- package/lib/console-contract.d.ts +61 -0
- package/lib/console.d.ts +39 -0
- package/lib/evidence-kind.d.ts +61 -0
- package/lib/evidence-preview-text.d.ts +13 -0
- package/lib/index.d.ts +42 -0
- package/lib/index.js +4579 -0
- package/lib/model-evidence/index.d.ts +15 -0
- package/lib/model-evidence/metrics.d.ts +11 -0
- package/lib/model-evidence/request.d.ts +7 -0
- package/lib/model-evidence/response.d.ts +7 -0
- package/lib/model-evidence/shared.d.ts +37 -0
- package/lib/model-evidence/transport.d.ts +13 -0
- package/lib/model-evidence/types.d.ts +104 -0
- package/lib/model-evidence/usage.d.ts +10 -0
- package/lib/model-request-collector.d.ts +32 -0
- package/lib/model-request-trajectory.d.ts +21 -0
- package/lib/model-request-variables.d.ts +16 -0
- package/lib/model-request.d.ts +158 -0
- package/lib/persistence.d.ts +85 -0
- package/lib/presets/evidence-match.d.ts +9 -0
- package/lib/presets/index.d.ts +6 -0
- package/lib/presets/repository.d.ts +86 -0
- package/lib/presets/runtime-correlation.d.ts +16 -0
- package/lib/presets/service.d.ts +69 -0
- package/lib/presets/source-document.d.ts +2 -0
- package/lib/presets/types.d.ts +63 -0
- package/lib/record-store.d.ts +85 -0
- package/lib/types.d.ts +270 -0
- package/package.json +110 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { type StudioModelRequestStore } from '../model-request';
|
|
2
|
+
import { type CreatePresetInput, type DeletePresetInput, type PresetRepository, type RenamePresetInput, type SavePresetInput } from './repository';
|
|
3
|
+
import type { PresetDocumentKind, PresetSourceDiagnostic, PresetSourcePath, PresetSourceRange, PresetTemplateExpression, PresetTemplateField } from './types';
|
|
4
|
+
export interface StudioPresetExpression extends PresetTemplateExpression {
|
|
5
|
+
stableId: string;
|
|
6
|
+
}
|
|
7
|
+
export interface StudioPresetDocument {
|
|
8
|
+
kind: PresetDocumentKind;
|
|
9
|
+
fileName: string;
|
|
10
|
+
displayName?: string;
|
|
11
|
+
source: string;
|
|
12
|
+
revision: string;
|
|
13
|
+
size: number;
|
|
14
|
+
modifiedAt: string;
|
|
15
|
+
templateFields: PresetTemplateField[];
|
|
16
|
+
expressions: StudioPresetExpression[];
|
|
17
|
+
diagnostics: PresetSourceDiagnostic[];
|
|
18
|
+
}
|
|
19
|
+
export interface ReadStudioPresetInput {
|
|
20
|
+
kind: PresetDocumentKind;
|
|
21
|
+
fileName: string;
|
|
22
|
+
}
|
|
23
|
+
export interface StudioPresetDocumentIdentity extends ReadStudioPresetInput {
|
|
24
|
+
revision: string;
|
|
25
|
+
}
|
|
26
|
+
export type StudioPresetExpressionIdentity = {
|
|
27
|
+
stableId: string;
|
|
28
|
+
} | {
|
|
29
|
+
path: PresetSourcePath;
|
|
30
|
+
range: PresetSourceRange;
|
|
31
|
+
occurrence: number;
|
|
32
|
+
};
|
|
33
|
+
export interface LocateStudioPresetExpressionInput {
|
|
34
|
+
document: StudioPresetDocumentIdentity;
|
|
35
|
+
expression: StudioPresetExpressionIdentity;
|
|
36
|
+
}
|
|
37
|
+
export type StudioPresetLocateFailureCode = 'document-not-found' | 'document-stale' | 'document-identity-unavailable' | 'expression-not-found' | 'request-not-observed' | 'expression-stale' | 'expression-not-observed' | 'expression-ambiguous' | 'expression-unsupported';
|
|
38
|
+
export type LocateStudioPresetExpressionResult = {
|
|
39
|
+
status: 'matched';
|
|
40
|
+
recordId: string;
|
|
41
|
+
evidenceId: string;
|
|
42
|
+
range: PresetSourceRange;
|
|
43
|
+
} | {
|
|
44
|
+
status: 'failed';
|
|
45
|
+
code: StudioPresetLocateFailureCode;
|
|
46
|
+
message: string;
|
|
47
|
+
reason?: 'control-tag' | 'template-field';
|
|
48
|
+
};
|
|
49
|
+
export interface StudioPresetServiceOptions {
|
|
50
|
+
baseDir: string;
|
|
51
|
+
modelRequests: StudioModelRequestStore;
|
|
52
|
+
repository?: PresetRepository;
|
|
53
|
+
}
|
|
54
|
+
export declare class StudioPresetService {
|
|
55
|
+
private readonly options;
|
|
56
|
+
private readonly repository;
|
|
57
|
+
constructor(options: StudioPresetServiceOptions);
|
|
58
|
+
catalog(kind?: PresetDocumentKind): Promise<StudioPresetDocument[]>;
|
|
59
|
+
read(input: ReadStudioPresetInput): Promise<StudioPresetDocument>;
|
|
60
|
+
create(input: CreatePresetInput): Promise<StudioPresetDocument>;
|
|
61
|
+
save(input: SavePresetInput): Promise<StudioPresetDocument>;
|
|
62
|
+
rename(input: RenamePresetInput): Promise<StudioPresetDocument>;
|
|
63
|
+
delete(input: DeletePresetInput): Promise<{
|
|
64
|
+
deleted: true;
|
|
65
|
+
}>;
|
|
66
|
+
locateExpression(input: LocateStudioPresetExpressionInput): Promise<LocateStudioPresetExpressionResult>;
|
|
67
|
+
private present;
|
|
68
|
+
}
|
|
69
|
+
export declare function expressionStableId(expression: Pick<PresetTemplateExpression, 'path' | 'occurrence'>): string;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { StudioPresetRuntimeSnapshot, StudioPresetRuntimeTemplate, StudioPresetTemplateRole } from '../types';
|
|
2
|
+
export type PresetDocumentKind = 'core' | 'character';
|
|
3
|
+
export type PresetRuntimeSnapshot = StudioPresetRuntimeSnapshot;
|
|
4
|
+
export type PresetRuntimeTemplate = StudioPresetRuntimeTemplate;
|
|
5
|
+
export type PresetTemplateRole = StudioPresetTemplateRole;
|
|
6
|
+
export type PresetSourcePath = readonly (string | number)[];
|
|
7
|
+
export interface PresetSourceRange {
|
|
8
|
+
start: number;
|
|
9
|
+
end: number;
|
|
10
|
+
}
|
|
11
|
+
export type PresetTemplateExpressionKind = 'value' | 'control';
|
|
12
|
+
export interface PresetTemplateExpression {
|
|
13
|
+
path: PresetSourcePath;
|
|
14
|
+
range: PresetSourceRange;
|
|
15
|
+
content: string;
|
|
16
|
+
kind: PresetTemplateExpressionKind;
|
|
17
|
+
clickable: boolean;
|
|
18
|
+
occurrence: number;
|
|
19
|
+
}
|
|
20
|
+
export interface PresetTemplateField {
|
|
21
|
+
path: PresetSourcePath;
|
|
22
|
+
range: PresetSourceRange;
|
|
23
|
+
value: string;
|
|
24
|
+
}
|
|
25
|
+
export type PresetSourceDiagnosticCode = 'yaml-parse-error' | 'template-field-not-string';
|
|
26
|
+
export interface PresetSourceDiagnostic {
|
|
27
|
+
code: PresetSourceDiagnosticCode;
|
|
28
|
+
message: string;
|
|
29
|
+
severity: 'error';
|
|
30
|
+
path?: PresetSourcePath;
|
|
31
|
+
range?: PresetSourceRange;
|
|
32
|
+
}
|
|
33
|
+
export interface PresetSourceDocument {
|
|
34
|
+
kind: PresetDocumentKind;
|
|
35
|
+
source: string;
|
|
36
|
+
displayName?: string;
|
|
37
|
+
templateFields: PresetTemplateField[];
|
|
38
|
+
expressions: PresetTemplateExpression[];
|
|
39
|
+
diagnostics: PresetSourceDiagnostic[];
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* 一次对话轮的归属目标。
|
|
43
|
+
*
|
|
44
|
+
* 真实环境里(机器人,会话)就是完整身份,不再有把同一对参与者分到不同记录域的空间概念。
|
|
45
|
+
*/
|
|
46
|
+
export interface PresetRuntimeSessionTarget {
|
|
47
|
+
botId: string;
|
|
48
|
+
conversationId: string;
|
|
49
|
+
}
|
|
50
|
+
export type PresetEvidenceMatchResult = {
|
|
51
|
+
status: 'matched';
|
|
52
|
+
evidenceId: string;
|
|
53
|
+
range: PresetSourceRange;
|
|
54
|
+
} | {
|
|
55
|
+
status: 'stale';
|
|
56
|
+
} | {
|
|
57
|
+
status: 'not-observed';
|
|
58
|
+
} | {
|
|
59
|
+
status: 'ambiguous';
|
|
60
|
+
} | {
|
|
61
|
+
status: 'unsupported';
|
|
62
|
+
reason: 'control-tag' | 'template-field';
|
|
63
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 证据记录行库的共享机制。OneBot 调试记录与模型请求记录都按行持久化,两者的
|
|
3
|
+
* 「作用域摘要 + 按最旧回收」和「串行写入队列」语义完全一致,差异只在记录类型与过滤谓词;
|
|
4
|
+
* 这些机制放在这里,内存适配器、数据库适配器与两个 Store 共用同一份实现。
|
|
5
|
+
*/
|
|
6
|
+
export interface StudioRecordScopeSummary {
|
|
7
|
+
/** 作用域内下一个可用序号;不因回收或清理而回退。 */
|
|
8
|
+
nextSequence: number;
|
|
9
|
+
recordCount: number;
|
|
10
|
+
/** 全部记录完整持久化内容的字节数之和。 */
|
|
11
|
+
totalBytes: number;
|
|
12
|
+
earliestSequence?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface StudioRecordCapacityLimits {
|
|
15
|
+
maxRecords: number;
|
|
16
|
+
maxBytes: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 作用域行索引:只保存每行的序号与体积。容量统计与回收决策只需要这两列,缓存后追加
|
|
20
|
+
* 就不必回表统计,否则「一次追加一行」会换来「一次追加扫一遍元数据」。
|
|
21
|
+
* 每个作用域只有一个适配器实例在写,索引因此可以作为权威值维护。
|
|
22
|
+
*/
|
|
23
|
+
export declare class ScopeRowIndex {
|
|
24
|
+
private rows;
|
|
25
|
+
private nextSequence;
|
|
26
|
+
reset(rows: Array<{
|
|
27
|
+
sequence: number;
|
|
28
|
+
bytes: number;
|
|
29
|
+
}>, persistedNextSequence: number): void;
|
|
30
|
+
put(sequence: number, bytes: number, nextSequence?: number): void;
|
|
31
|
+
has(sequence: number): boolean;
|
|
32
|
+
clear(nextSequence: number): void;
|
|
33
|
+
/** 从最旧开始试算,返回需要一并删除的最大序号;索引在删除成功后才由 dropThrough 收敛。 */
|
|
34
|
+
resolveCutoff(limits: StudioRecordCapacityLimits): number | undefined;
|
|
35
|
+
dropThrough(cutoff: number): void;
|
|
36
|
+
readNextSequence(): number;
|
|
37
|
+
summary(): StudioRecordScopeSummary;
|
|
38
|
+
private totalBytes;
|
|
39
|
+
}
|
|
40
|
+
export interface StudioRecordRowsQuery {
|
|
41
|
+
order: 'asc' | 'desc';
|
|
42
|
+
limit: number;
|
|
43
|
+
}
|
|
44
|
+
interface StudioRecordRow {
|
|
45
|
+
id: string;
|
|
46
|
+
sequence: number;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* 进程内记录行库。内存持久化模式与数据库不可用时的降级路径共用这一份语义,
|
|
50
|
+
* 容量与回收决策复用 ScopeRowIndex,因此与数据库适配器给出一致的摘要。
|
|
51
|
+
*/
|
|
52
|
+
export declare class InMemoryRecordRows<Record extends StudioRecordRow, Query extends StudioRecordRowsQuery> {
|
|
53
|
+
private matches;
|
|
54
|
+
private bodies;
|
|
55
|
+
private index;
|
|
56
|
+
constructor(matches: (record: Record, query: Query) => boolean);
|
|
57
|
+
summarize(): Promise<StudioRecordScopeSummary>;
|
|
58
|
+
append(record: Record, bytes: number, nextSequence: number): Promise<StudioRecordScopeSummary>;
|
|
59
|
+
find(recordId: string): Promise<Record | undefined>;
|
|
60
|
+
replace(record: Record, bytes: number): Promise<StudioRecordScopeSummary>;
|
|
61
|
+
query(query: Query): Promise<Record[]>;
|
|
62
|
+
/**
|
|
63
|
+
* 只读出记录的一部分。投影先在存有的行上执行,再拷贝投影结果,因此读取路径不需要的子树
|
|
64
|
+
* (模型请求的请求体与响应原文)既不会被深拷贝,也不会被交给调用方。
|
|
65
|
+
*/
|
|
66
|
+
queryProjected<Projected>(query: Query, project: (record: Record) => Projected): Promise<Projected[]>;
|
|
67
|
+
private select;
|
|
68
|
+
reclaim(limits: StudioRecordCapacityLimits): Promise<StudioRecordScopeSummary>;
|
|
69
|
+
clear(nextSequence: number): Promise<StudioRecordScopeSummary>;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* 串行写入队列。所有写入都排在首次恢复之后并依次执行,读取等待同一条队列稳定,
|
|
73
|
+
* 因此读取总能看到已提交状态,而 append 仍可以同步返回记录。
|
|
74
|
+
*/
|
|
75
|
+
export declare class SerialWriteQueue {
|
|
76
|
+
private ready;
|
|
77
|
+
private queue;
|
|
78
|
+
constructor(ready: Promise<void>);
|
|
79
|
+
/** 队列任务可能在等待期间继续追加(例如 append 之后的容量回收),必须等到队列稳定。 */
|
|
80
|
+
settle(): Promise<void>;
|
|
81
|
+
/** 写入失败不能变成未处理的 Promise 拒绝:证据落盘是旁路能力,不应影响调用方。 */
|
|
82
|
+
push(task: () => Promise<void>): void;
|
|
83
|
+
run<T>(task: () => Promise<T>): Promise<T>;
|
|
84
|
+
}
|
|
85
|
+
export {};
|
package/lib/types.d.ts
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import type { StudioEvidenceCompositionKind, StudioEvidenceKind } from './evidence-kind';
|
|
2
|
+
export type StudioPersistenceMode = 'memory' | 'database';
|
|
3
|
+
export interface StudioPersistenceStatus {
|
|
4
|
+
mode: StudioPersistenceMode;
|
|
5
|
+
available: boolean;
|
|
6
|
+
persisted: boolean;
|
|
7
|
+
message?: string;
|
|
8
|
+
}
|
|
9
|
+
/** 工作室外观:颜色模式、强调色、毛玻璃与头像来源,由插件全局配置统一控制。 */
|
|
10
|
+
export interface StudioAppearance {
|
|
11
|
+
enableStudioFrostedGlass: boolean;
|
|
12
|
+
studioColorMode: 'auto' | 'light' | 'dark';
|
|
13
|
+
studioAccentColor: string;
|
|
14
|
+
/** 开启时列表与详情向 QQ 头像 CDN 取真实头像;关闭时只用首字母色块,不发起外部请求。 */
|
|
15
|
+
studioUseQQAvatars: boolean;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* 可预期的领域业务拒绝:参数不合法、实体不存在、游标过期这类由领域规则主动作出的判定。
|
|
19
|
+
*
|
|
20
|
+
* 它存在的唯一理由是让上层能把「领域说不」与「实现出错」分开:Console 端点把领域拒绝的消息
|
|
21
|
+
* 原样透出给前端,而基础设施故障(数据库不可用)与内部不变量违背不属于此类,应继续抛普通 `Error`。
|
|
22
|
+
*/
|
|
23
|
+
export declare class StudioDomainError extends Error {
|
|
24
|
+
constructor(message: string);
|
|
25
|
+
}
|
|
26
|
+
export declare class StudioModelRequestCursorExpiredError extends StudioDomainError {
|
|
27
|
+
readonly earliestCursor?: number | undefined;
|
|
28
|
+
readonly code: "cursor_expired";
|
|
29
|
+
constructor(message: string, earliestCursor?: number | undefined);
|
|
30
|
+
}
|
|
31
|
+
export type StudioModelRequestStatus = 'pending' | 'success' | 'error';
|
|
32
|
+
export type StudioModelResponseBodyStatus = 'pending' | 'complete' | 'unavailable' | 'error';
|
|
33
|
+
export type StudioModelResponseBodyFormat = 'json' | 'text' | 'sse';
|
|
34
|
+
export type StudioModelRequestAttribution = 'attributed' | 'unattributed';
|
|
35
|
+
export interface StudioModelRequestError {
|
|
36
|
+
code: string;
|
|
37
|
+
message: string;
|
|
38
|
+
retryable: boolean;
|
|
39
|
+
traceId: string;
|
|
40
|
+
}
|
|
41
|
+
export interface StudioChatLunaRequestError {
|
|
42
|
+
code?: number;
|
|
43
|
+
message?: string;
|
|
44
|
+
originMessage?: string;
|
|
45
|
+
isTimeout?: boolean;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* 一条模型请求归属到的真实 OneBot 会话。
|
|
49
|
+
*
|
|
50
|
+
* 名称随请求一起快照,而不是读取时再查目录:群名与昵称会变,而记录要能复盘当时的现场;
|
|
51
|
+
* 会话被解散或机器人下线后,目录里也已经查不到它们。
|
|
52
|
+
*/
|
|
53
|
+
export interface StudioModelRequestEntities {
|
|
54
|
+
platform?: string;
|
|
55
|
+
botId?: string;
|
|
56
|
+
botName?: string;
|
|
57
|
+
conversationId?: string;
|
|
58
|
+
conversationName?: string;
|
|
59
|
+
conversationType?: StudioConversationType;
|
|
60
|
+
guildId?: string;
|
|
61
|
+
userId?: string;
|
|
62
|
+
userName?: string;
|
|
63
|
+
}
|
|
64
|
+
/** 私聊与群聊是真实 OneBot 会话的全部形态;频道等其他平台概念不在本插件范围内。 */
|
|
65
|
+
export type StudioConversationType = 'private' | 'group';
|
|
66
|
+
export type StudioPresetDocumentKind = 'core' | 'character';
|
|
67
|
+
export type StudioPresetTemplateRole = 'system' | 'user' | 'assistant' | 'tool';
|
|
68
|
+
export interface StudioPresetRuntimeTemplate {
|
|
69
|
+
path: readonly (string | number)[];
|
|
70
|
+
role: StudioPresetTemplateRole;
|
|
71
|
+
template: string;
|
|
72
|
+
}
|
|
73
|
+
export interface StudioPresetRuntimeSnapshot {
|
|
74
|
+
kind: StudioPresetDocumentKind;
|
|
75
|
+
presetName: string;
|
|
76
|
+
capturedAt: string;
|
|
77
|
+
source?: string;
|
|
78
|
+
templates: readonly StudioPresetRuntimeTemplate[];
|
|
79
|
+
}
|
|
80
|
+
export interface StudioPresetRuntimeSnapshotSummary {
|
|
81
|
+
kind: StudioPresetDocumentKind;
|
|
82
|
+
presetName: string;
|
|
83
|
+
capturedAt: string;
|
|
84
|
+
templateCount: number;
|
|
85
|
+
}
|
|
86
|
+
export type StudioModelRequestVariableStatus = 'observed' | 'stale' | 'not-observed' | 'ambiguous' | 'unsupported';
|
|
87
|
+
export interface StudioModelRequestVariable {
|
|
88
|
+
id: string;
|
|
89
|
+
name: string;
|
|
90
|
+
presetKind: StudioPresetDocumentKind;
|
|
91
|
+
presetName: string;
|
|
92
|
+
path: readonly (string | number)[];
|
|
93
|
+
occurrence: number;
|
|
94
|
+
status: StudioModelRequestVariableStatus;
|
|
95
|
+
value?: string;
|
|
96
|
+
evidenceId?: string;
|
|
97
|
+
range?: {
|
|
98
|
+
start: number;
|
|
99
|
+
end: number;
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* 一条模型请求记录被共享模型证据投影读出的计数。
|
|
104
|
+
*
|
|
105
|
+
* 两个字段都是投影派生事实,与模型请求对话视图、模型请求轨迹使用完全相同的消息边界和工具展平规则。
|
|
106
|
+
* 原始请求体的字段数与模型名称不属于这里:它们不是协议事实,见 StudioModelRequestDetail。
|
|
107
|
+
*/
|
|
108
|
+
export interface StudioModelEvidenceCounts {
|
|
109
|
+
requestMessageCount: number;
|
|
110
|
+
toolDefinitionCount: number;
|
|
111
|
+
}
|
|
112
|
+
export interface StudioModelRequestUsage {
|
|
113
|
+
inputTokens?: number;
|
|
114
|
+
outputTokens?: number;
|
|
115
|
+
reasoningTokens?: number;
|
|
116
|
+
cachedTokens?: number;
|
|
117
|
+
totalTokens?: number;
|
|
118
|
+
ttftMs?: number;
|
|
119
|
+
totalMs?: number;
|
|
120
|
+
tps?: number;
|
|
121
|
+
estimated?: boolean;
|
|
122
|
+
source: 'chatluna-usage' | 'response';
|
|
123
|
+
}
|
|
124
|
+
export interface StudioModelRequestRecord {
|
|
125
|
+
id: string;
|
|
126
|
+
sequence: number;
|
|
127
|
+
createdAt: string;
|
|
128
|
+
status: StudioModelRequestStatus;
|
|
129
|
+
durationMs: number;
|
|
130
|
+
method?: string;
|
|
131
|
+
url?: string;
|
|
132
|
+
provider?: string;
|
|
133
|
+
model?: string;
|
|
134
|
+
headers?: Record<string, string>;
|
|
135
|
+
attribution: StudioModelRequestAttribution;
|
|
136
|
+
entities: StudioModelRequestEntities;
|
|
137
|
+
requestBodyAvailable: boolean;
|
|
138
|
+
requestBody?: unknown;
|
|
139
|
+
responseBodyStatus: StudioModelResponseBodyStatus;
|
|
140
|
+
responseBodyFormat?: StudioModelResponseBodyFormat;
|
|
141
|
+
responseStatus?: number;
|
|
142
|
+
responseBodyRaw?: string;
|
|
143
|
+
responseBodyError?: string;
|
|
144
|
+
interactionId?: string;
|
|
145
|
+
chatlunaRequestId?: string;
|
|
146
|
+
presetSnapshots?: readonly StudioPresetRuntimeSnapshot[];
|
|
147
|
+
usage?: StudioModelRequestUsage;
|
|
148
|
+
error?: StudioModelRequestError;
|
|
149
|
+
chatlunaError?: StudioChatLunaRequestError;
|
|
150
|
+
}
|
|
151
|
+
export type StudioModelRequestListItem = Omit<StudioModelRequestRecord, 'requestBody' | 'responseBodyRaw' | 'presetSnapshots'> & {
|
|
152
|
+
presetSnapshotSummaries?: readonly StudioPresetRuntimeSnapshotSummary[];
|
|
153
|
+
};
|
|
154
|
+
export type StudioModelRequestDetail = StudioModelRequestRecord & {
|
|
155
|
+
/** 原始请求体的顶层键数量。这是原始 JSON 事实而不是投影产物;请求体未采集或不是对象时缺省。 */
|
|
156
|
+
requestBodyKeyCount?: number;
|
|
157
|
+
/** 共享模型证据投影派生的计数。请求体未采集时缺省,采集到但不是对象时两项均为 0。 */
|
|
158
|
+
evidenceCounts?: StudioModelEvidenceCounts;
|
|
159
|
+
variables: readonly StudioModelRequestVariable[];
|
|
160
|
+
};
|
|
161
|
+
export interface GetStudioModelRequestRecordsInput {
|
|
162
|
+
attribution?: StudioModelRequestAttribution;
|
|
163
|
+
botId?: string;
|
|
164
|
+
conversationId?: string;
|
|
165
|
+
interactionId?: string;
|
|
166
|
+
model?: string;
|
|
167
|
+
errorsOnly?: boolean;
|
|
168
|
+
order?: 'asc' | 'desc';
|
|
169
|
+
limit?: number;
|
|
170
|
+
beforeSequence?: number;
|
|
171
|
+
beforeCreatedAt?: string;
|
|
172
|
+
beforeId?: string;
|
|
173
|
+
}
|
|
174
|
+
export interface StudioModelRequestCapacity {
|
|
175
|
+
recordCount: number;
|
|
176
|
+
totalBytes: number;
|
|
177
|
+
maxRecords: number;
|
|
178
|
+
maxBytes: number;
|
|
179
|
+
}
|
|
180
|
+
export interface StudioModelRequestRecordsPage<T extends StudioModelRequestListItem = StudioModelRequestListItem> {
|
|
181
|
+
records: T[];
|
|
182
|
+
hasMore: boolean;
|
|
183
|
+
nextCursor?: number;
|
|
184
|
+
nextCreatedAt?: string;
|
|
185
|
+
nextId?: string;
|
|
186
|
+
earliestCursor?: number;
|
|
187
|
+
capacity: StudioModelRequestCapacity;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* 轨迹账本的行种类:一维基础证据种类,外加视图特有的请求边界行。
|
|
191
|
+
*
|
|
192
|
+
* 请求边界不是证据,而是「一次模型请求从这里开始」的结构标记;
|
|
193
|
+
* 隐藏全部证据种类后仍要能看出有哪些请求,因此它不并入基础证据种类。
|
|
194
|
+
*/
|
|
195
|
+
export type StudioModelRequestTrajectoryKind = StudioEvidenceKind | 'request';
|
|
196
|
+
export interface StudioModelRequestTrajectoryRow {
|
|
197
|
+
id: string;
|
|
198
|
+
index: number;
|
|
199
|
+
kind: StudioModelRequestTrajectoryKind;
|
|
200
|
+
preview: string;
|
|
201
|
+
/** 模型证据投影身份。请求边界行没有对应的原始模型证据,因此不带此字段。 */
|
|
202
|
+
evidenceId?: string;
|
|
203
|
+
callId?: string;
|
|
204
|
+
toolName?: string;
|
|
205
|
+
variableId?: string;
|
|
206
|
+
variableName?: string;
|
|
207
|
+
variablePresetName?: string;
|
|
208
|
+
variableStatus?: StudioModelRequestVariableStatus;
|
|
209
|
+
variableValue?: string;
|
|
210
|
+
source?: 'request' | 'response';
|
|
211
|
+
durationMs?: number;
|
|
212
|
+
startedAt?: string;
|
|
213
|
+
requestId?: string;
|
|
214
|
+
status?: StudioModelRequestStatus;
|
|
215
|
+
}
|
|
216
|
+
/** 请求组成项的种类:基础证据种类的子集加工具交互聚合,聚合成员由证据种类 module 声明。 */
|
|
217
|
+
export type StudioModelRequestPromptKind = StudioEvidenceCompositionKind;
|
|
218
|
+
export interface StudioModelRequestPromptCompositionItem {
|
|
219
|
+
kind: StudioModelRequestPromptKind;
|
|
220
|
+
/** 点击组成分段时定位的轨迹行身份;变量片段使用变量证据身份。 */
|
|
221
|
+
evidenceId: string;
|
|
222
|
+
characters: number;
|
|
223
|
+
variableId?: string;
|
|
224
|
+
variableName?: string;
|
|
225
|
+
requestId?: string;
|
|
226
|
+
}
|
|
227
|
+
export interface StudioModelRequestTrajectory {
|
|
228
|
+
mode: 'request' | 'conversation';
|
|
229
|
+
conversationId?: string;
|
|
230
|
+
records: readonly StudioModelRequestListItem[];
|
|
231
|
+
rows: readonly StudioModelRequestTrajectoryRow[];
|
|
232
|
+
promptComposition: readonly StudioModelRequestPromptCompositionItem[];
|
|
233
|
+
complete: boolean;
|
|
234
|
+
}
|
|
235
|
+
export interface GetStudioModelRequestRecordInput {
|
|
236
|
+
recordId: string;
|
|
237
|
+
}
|
|
238
|
+
export interface ClearStudioModelRequestRecordsResult {
|
|
239
|
+
cleared: number;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* 记录读取的归属范围。
|
|
243
|
+
*
|
|
244
|
+
* 全部记录住在同一个记录库里,范围只是一道归属过滤:真实环境没有互相隔离的记录域,
|
|
245
|
+
* 「未归属」也不是另一个库,而是采集时无法判定是哪一个会话在请求模型的那些记录。
|
|
246
|
+
*/
|
|
247
|
+
export type StudioModelRequestScope = {
|
|
248
|
+
scope: 'all' | 'attributed' | 'unattributed';
|
|
249
|
+
};
|
|
250
|
+
export type ListStudioModelRequestRecordsInput = StudioModelRequestScope & GetStudioModelRequestRecordsInput;
|
|
251
|
+
export type ReadStudioModelRequestRecordInput = GetStudioModelRequestRecordInput;
|
|
252
|
+
export type ReadStudioModelRequestTrajectoryInput = {
|
|
253
|
+
recordId: string;
|
|
254
|
+
mode: 'request' | 'conversation';
|
|
255
|
+
};
|
|
256
|
+
/** 筛选下拉的可选值,由记录库里已经出现过的机器人、会话与模型聚合而成。 */
|
|
257
|
+
export interface StudioModelRequestFacets {
|
|
258
|
+
bots: readonly {
|
|
259
|
+
id: string;
|
|
260
|
+
name?: string;
|
|
261
|
+
platform?: string;
|
|
262
|
+
}[];
|
|
263
|
+
conversations: readonly {
|
|
264
|
+
id: string;
|
|
265
|
+
name?: string;
|
|
266
|
+
type?: StudioConversationType;
|
|
267
|
+
botId?: string;
|
|
268
|
+
}[];
|
|
269
|
+
models: readonly string[];
|
|
270
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "koishi-plugin-chatluna-studio",
|
|
3
|
+
"description": "在 Koishi 控制台中查看 ChatLuna 真实模型请求并编辑预设",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"type": "commonjs",
|
|
6
|
+
"main": "lib/index.js",
|
|
7
|
+
"typings": "lib/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./lib/index.d.ts",
|
|
11
|
+
"require": "./lib/index.js",
|
|
12
|
+
"default": "./lib/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./package.json": "./package.json"
|
|
15
|
+
},
|
|
16
|
+
"imports": {
|
|
17
|
+
"#client/*": "./client/*"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"lib",
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"homepage": "https://github.com/Sor85/koishi-plugin-chatluna-studio",
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "https://github.com/Sor85/koishi-plugin-chatluna-studio.git"
|
|
27
|
+
},
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"scripts": {
|
|
30
|
+
"clean": "shx rm -rf lib dist",
|
|
31
|
+
"build": "yarn clean && yarn build:server && yarn build:client",
|
|
32
|
+
"build:types": "tsc -p tsconfig.json --emitDeclarationOnly",
|
|
33
|
+
"build:server": "yarn build:types && tsup src/index.ts --format cjs --out-dir lib --clean false",
|
|
34
|
+
"watch:server": "node scripts/watch-server.mjs",
|
|
35
|
+
"build:client": "yarn build:css && vite build",
|
|
36
|
+
"build:css": "node scripts/build-css.mjs",
|
|
37
|
+
"typecheck": "vue-tsc -p tsconfig.typecheck.json --noEmit",
|
|
38
|
+
"test": "vitest run",
|
|
39
|
+
"test:watch": "vitest",
|
|
40
|
+
"prepublishOnly": "yarn test && yarn typecheck && yarn build"
|
|
41
|
+
},
|
|
42
|
+
"keywords": [
|
|
43
|
+
"chatbot",
|
|
44
|
+
"chatluna",
|
|
45
|
+
"koishi",
|
|
46
|
+
"onebot",
|
|
47
|
+
"preset"
|
|
48
|
+
],
|
|
49
|
+
"koishi": {
|
|
50
|
+
"browser": true,
|
|
51
|
+
"public": [
|
|
52
|
+
"dist"
|
|
53
|
+
],
|
|
54
|
+
"description": {
|
|
55
|
+
"zh": "查看 ChatLuna 真实模型请求并编辑预设"
|
|
56
|
+
},
|
|
57
|
+
"service": {
|
|
58
|
+
"required": [
|
|
59
|
+
"console"
|
|
60
|
+
],
|
|
61
|
+
"optional": [
|
|
62
|
+
"database"
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"peerDependencies": {
|
|
67
|
+
"@koishijs/plugin-console": "^5.30.11",
|
|
68
|
+
"koishi": "^4.18.10",
|
|
69
|
+
"koishi-plugin-chatluna": "*"
|
|
70
|
+
},
|
|
71
|
+
"peerDependenciesMeta": {
|
|
72
|
+
"koishi-plugin-chatluna": {
|
|
73
|
+
"optional": true
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"dependencies": {
|
|
77
|
+
"@codemirror/lang-yaml": "^6.1.3",
|
|
78
|
+
"@codemirror/state": "^6.7.1",
|
|
79
|
+
"@codemirror/view": "^6.43.9",
|
|
80
|
+
"@koishijs/console": "^5.30.11",
|
|
81
|
+
"codemirror": "^6.0.2",
|
|
82
|
+
"fast-xml-parser": "^5.3.6",
|
|
83
|
+
"yaml": "^2.9.0"
|
|
84
|
+
},
|
|
85
|
+
"devDependencies": {
|
|
86
|
+
"@koishijs/client": "^5.30.11",
|
|
87
|
+
"@koishijs/core": "^4.18.10",
|
|
88
|
+
"@koishijs/plugin-console": "^5.30.11",
|
|
89
|
+
"@tabler/icons-vue": "^3.45.0",
|
|
90
|
+
"@tailwindcss/cli": "^4.3.3",
|
|
91
|
+
"@types/node": "^24.0.0",
|
|
92
|
+
"@vitejs/plugin-vue": "^6.0.2",
|
|
93
|
+
"@vueuse/core": "^14.3.0",
|
|
94
|
+
"class-variance-authority": "^0.7.1",
|
|
95
|
+
"clsx": "^2.1.1",
|
|
96
|
+
"koishi": "^4.18.10",
|
|
97
|
+
"postcss": "8.5.19",
|
|
98
|
+
"reka-ui": "^2.10.1",
|
|
99
|
+
"shx": "^0.4.0",
|
|
100
|
+
"tailwind-merge": "^3.6.0",
|
|
101
|
+
"tailwindcss": "^4.1.11",
|
|
102
|
+
"tsup": "^8.0.0",
|
|
103
|
+
"typescript": "5.7.2",
|
|
104
|
+
"vite": "^6.0.0",
|
|
105
|
+
"vitest": "^3.2.4",
|
|
106
|
+
"vue": "^3.5.21",
|
|
107
|
+
"vue-tsc": "^3.0.0"
|
|
108
|
+
},
|
|
109
|
+
"packageManager": "yarn@4.15.0"
|
|
110
|
+
}
|