@yss123/cage-ai 0.0.0-stage → 0.3.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 +77 -2
- package/dist/budget.d.ts +64 -0
- package/dist/budget.js +54 -0
- package/dist/budget.js.map +1 -0
- package/dist/context-read.d.ts +38 -0
- package/dist/context-read.js +124 -0
- package/dist/context-read.js.map +1 -0
- package/dist/context-schema.d.ts +9 -0
- package/dist/context-schema.js +16 -0
- package/dist/context-schema.js.map +1 -0
- package/dist/context.d.ts +27 -0
- package/dist/context.js +83 -0
- package/dist/context.js.map +1 -0
- package/dist/execution-schema.d.ts +9 -0
- package/dist/execution-schema.js +20 -0
- package/dist/execution-schema.js.map +1 -0
- package/dist/history.d.ts +43 -0
- package/dist/history.js +139 -0
- package/dist/history.js.map +1 -0
- package/dist/http.d.ts +15 -0
- package/dist/http.js +197 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +97 -0
- package/dist/index.js.map +1 -0
- package/dist/model-failure.d.ts +66 -0
- package/dist/model-failure.js +85 -0
- package/dist/model-failure.js.map +1 -0
- package/dist/model.d.ts +50 -0
- package/dist/model.js +93 -0
- package/dist/model.js.map +1 -0
- package/dist/models.d.ts +75 -0
- package/dist/models.js +241 -0
- package/dist/models.js.map +1 -0
- package/dist/personalities.d.ts +87 -0
- package/dist/personalities.js +191 -0
- package/dist/personalities.js.map +1 -0
- package/dist/personality-presets.d.ts +14 -0
- package/dist/personality-presets.js +24 -0
- package/dist/personality-presets.js.map +1 -0
- package/dist/prompt.d.ts +67 -0
- package/dist/prompt.js +148 -0
- package/dist/prompt.js.map +1 -0
- package/dist/query.d.ts +13 -0
- package/dist/query.js +82 -0
- package/dist/query.js.map +1 -0
- package/dist/request-plan.d.ts +59 -0
- package/dist/request-plan.js +168 -0
- package/dist/request-plan.js.map +1 -0
- package/dist/responses.d.ts +29 -0
- package/dist/responses.js +134 -0
- package/dist/responses.js.map +1 -0
- package/dist/runtime.d.ts +172 -0
- package/dist/runtime.js +1188 -0
- package/dist/runtime.js.map +1 -0
- package/dist/schema.d.ts +11 -0
- package/dist/schema.js +51 -0
- package/dist/schema.js.map +1 -0
- package/dist/security.d.ts +23 -0
- package/dist/security.js +73 -0
- package/dist/security.js.map +1 -0
- package/dist/state.d.ts +238 -0
- package/dist/state.js +11 -0
- package/dist/state.js.map +1 -0
- package/dist/store.d.ts +113 -0
- package/dist/store.js +456 -0
- package/dist/store.js.map +1 -0
- package/dist/text-stream.d.ts +62 -0
- package/dist/text-stream.js +99 -0
- package/dist/text-stream.js.map +1 -0
- package/dist/tool-catalog.d.ts +23 -0
- package/dist/tool-catalog.js +53 -0
- package/dist/tool-catalog.js.map +1 -0
- package/dist/tools.d.ts +54 -0
- package/dist/tools.js +250 -0
- package/dist/tools.js.map +1 -0
- package/dist/types.d.ts +283 -0
- package/dist/types.js +16 -0
- package/dist/types.js.map +1 -0
- package/package.json +41 -3
package/dist/store.js
ADDED
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 持久化用户助理会话、运行提交、交互回复、事件和偏好。
|
|
3
|
+
* HTTP 调用此层验证归属与当前指纹,worker 运行时继承此层推进任务;数据库中接受提交只表示 queued,不等于模型或业务动作已完成。
|
|
4
|
+
*/
|
|
5
|
+
import { randomUUID } from 'node:crypto';
|
|
6
|
+
import { cageError } from '@yss123/cage-kernel';
|
|
7
|
+
import { sql } from 'kysely';
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
import { messageInputSchema, interactionResponseSchema, personalitySelectionSchema, } from '@yss123/cage-ai-protocol';
|
|
10
|
+
import { authFingerprint, digest, needUser, parse } from './security.js';
|
|
11
|
+
import { DEFAULT_LIMITS, TERMINAL } from './types.js';
|
|
12
|
+
import { PersonalityManager, personalitySummary } from './personalities.js';
|
|
13
|
+
import { reservedTokens } from './budget.js';
|
|
14
|
+
/**
|
|
15
|
+
* 将值序列化为数据库 JSON 字段文本;调用方须先完成结构校验,不在此隐藏不可序列化错误。
|
|
16
|
+
*/
|
|
17
|
+
export const json = (value) => JSON.stringify(value);
|
|
18
|
+
/**
|
|
19
|
+
* 把数据库时间值转为 UTC ISO 字符串供协议 DTO 使用;无效时间直接抛错,不用本机时间静默替代。
|
|
20
|
+
*/
|
|
21
|
+
export const iso = (value) => new Date(value).toISOString();
|
|
22
|
+
/**
|
|
23
|
+
* 把会话数据库行转换为公开 DTO,保留性格选择版本供并发切换校验,不暴露租户/用户存储字段。
|
|
24
|
+
*/
|
|
25
|
+
const sessionDto = (r) => ({
|
|
26
|
+
id: r.id,
|
|
27
|
+
title: r.title,
|
|
28
|
+
createdAt: iso(r.created_at),
|
|
29
|
+
updatedAt: iso(r.updated_at),
|
|
30
|
+
personalityKey: r.personality_key,
|
|
31
|
+
personalityVersion: r.personality_version,
|
|
32
|
+
});
|
|
33
|
+
/** 所有流事件在持有 run 行锁的事务内编号;断线可以按 sequence 重放。 */
|
|
34
|
+
/**
|
|
35
|
+
* 在持有运行行锁的事务内递增 sequence 并插入事件,运行更新时间同步刷新。
|
|
36
|
+
* 调用方必须把业务状态变更放在同一事务,使重连按序重放时不会看见未提交状态;此函数不负责 HTTP 推送。
|
|
37
|
+
*/
|
|
38
|
+
export async function event(tx, runId, type, data) {
|
|
39
|
+
const row = await tx
|
|
40
|
+
.updateTable('sys.ai_run')
|
|
41
|
+
.set({ next_seq: sql `next_seq + 1`, updated_at: sql `now()` })
|
|
42
|
+
.where('id', '=', runId)
|
|
43
|
+
.returning('next_seq')
|
|
44
|
+
.executeTakeFirstOrThrow();
|
|
45
|
+
await tx
|
|
46
|
+
.insertInto('sys.ai_event')
|
|
47
|
+
.values({ run_id: runId, sequence: row.next_seq, type, data: json(data) })
|
|
48
|
+
.execute();
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* 用户助理持久化服务,也是 AiRuntime 的状态存取基础。
|
|
52
|
+
* 公开读取先验证用户归属、注册表与授权指纹;提交、取消及互动用事务协调并发,模型执行和业务工具调用由运行时承担。
|
|
53
|
+
*/
|
|
54
|
+
export class AiStore {
|
|
55
|
+
kernel;
|
|
56
|
+
options;
|
|
57
|
+
fingerprint;
|
|
58
|
+
/**
|
|
59
|
+
* 会话创建、切换和运行快照共用的租户性格服务。
|
|
60
|
+
*/
|
|
61
|
+
personalities;
|
|
62
|
+
/**
|
|
63
|
+
* 绑定内核、AI 声明选项及注册表指纹,并创建共用性格服务;构造时不创建会话或启动 worker。
|
|
64
|
+
*/
|
|
65
|
+
constructor(kernel, options, fingerprint) {
|
|
66
|
+
this.kernel = kernel;
|
|
67
|
+
this.options = options;
|
|
68
|
+
this.fingerprint = fingerprint;
|
|
69
|
+
this.personalities = new PersonalityManager(kernel);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* 验证助理用户及标题,在事务中确认指定或默认性格存在且启用,再创建归属当前租户/用户的会话。
|
|
73
|
+
* null 性格 key 表示跟随租户默认项;本步骤不调用模型。
|
|
74
|
+
*/
|
|
75
|
+
async createSession(ctx, title = '新会话', personalityKey = null) {
|
|
76
|
+
needUser(ctx);
|
|
77
|
+
parse(z.string().trim().min(1).max(160), title);
|
|
78
|
+
return this.kernel.app.transaction().execute(async (tx) => {
|
|
79
|
+
await this.personalities.resolve(ctx, personalityKey, tx);
|
|
80
|
+
return sessionDto(await tx
|
|
81
|
+
.insertInto('sys.ai_session')
|
|
82
|
+
.values({
|
|
83
|
+
id: randomUUID(),
|
|
84
|
+
tenant_id: ctx.tenantId,
|
|
85
|
+
user_id: ctx.userId,
|
|
86
|
+
title,
|
|
87
|
+
personality_key: personalityKey,
|
|
88
|
+
})
|
|
89
|
+
.returningAll()
|
|
90
|
+
.executeTakeFirstOrThrow());
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* 返回当前租户用户最近更新的至多 100 个会话;不提供跨用户管理视图或全量导出。
|
|
95
|
+
*/
|
|
96
|
+
async sessions(ctx) {
|
|
97
|
+
needUser(ctx);
|
|
98
|
+
const rows = await this.kernel.app
|
|
99
|
+
.selectFrom('sys.ai_session')
|
|
100
|
+
.selectAll()
|
|
101
|
+
.where('tenant_id', '=', ctx.tenantId)
|
|
102
|
+
.where('user_id', '=', ctx.userId)
|
|
103
|
+
.orderBy('updated_at', 'desc')
|
|
104
|
+
.limit(100)
|
|
105
|
+
.execute();
|
|
106
|
+
return rows.map(sessionDto);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* 锁定本人会话并比较 personality_version 后切换性格,递增版本。
|
|
110
|
+
* 目标必须启用,null 表示默认项;只影响以后提交的轮次,不修改运行已经保存的性格快照。
|
|
111
|
+
*/
|
|
112
|
+
async selectPersonality(ctx, sessionId, raw) {
|
|
113
|
+
needUser(ctx);
|
|
114
|
+
const input = parse(personalitySelectionSchema, raw);
|
|
115
|
+
return this.kernel.app.transaction().execute(async (tx) => {
|
|
116
|
+
const session = await this.ownedSession(ctx, sessionId, tx, true);
|
|
117
|
+
if (session.personality_version !== input.version)
|
|
118
|
+
throw cageError('CONFLICT');
|
|
119
|
+
await this.personalities.resolve(ctx, input.key, tx);
|
|
120
|
+
return sessionDto(await tx
|
|
121
|
+
.updateTable('sys.ai_session')
|
|
122
|
+
.set({ personality_key: input.key, personality_version: input.version + 1, updated_at: new Date() })
|
|
123
|
+
.where('id', '=', sessionId)
|
|
124
|
+
.returningAll()
|
|
125
|
+
.executeTakeFirstOrThrow());
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* 验证 UUID、登录身份和租户/用户归属后读取会话;不存在或无归属统一 NOT_FOUND。
|
|
130
|
+
* 可在调用方事务中加行锁,用于提交与性格切换的并发协调。
|
|
131
|
+
*/
|
|
132
|
+
async ownedSession(ctx, id, db = this.kernel.app, lock = false) {
|
|
133
|
+
needUser(ctx);
|
|
134
|
+
parse(z.uuid(), id);
|
|
135
|
+
let query = db
|
|
136
|
+
.selectFrom('sys.ai_session')
|
|
137
|
+
.selectAll()
|
|
138
|
+
.where('id', '=', id)
|
|
139
|
+
.where('tenant_id', '=', ctx.tenantId)
|
|
140
|
+
.where('user_id', '=', ctx.userId);
|
|
141
|
+
if (lock)
|
|
142
|
+
query = query.forUpdate();
|
|
143
|
+
const r = await query.executeTakeFirst();
|
|
144
|
+
if (!r)
|
|
145
|
+
throw cageError('NOT_FOUND');
|
|
146
|
+
return r;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* 验证运行归属,并拒绝注册声明或授权指纹已变化的旧记录。
|
|
150
|
+
* 旧回答和事件也可能包含现在不该看到的信息,因此读取同样执行指纹复核;返回内部行供本层转换,不直接作为公开 DTO。
|
|
151
|
+
*/
|
|
152
|
+
async ownedRun(ctx, id, db = this.kernel.app) {
|
|
153
|
+
needUser(ctx);
|
|
154
|
+
parse(z.uuid(), id);
|
|
155
|
+
const r = await db
|
|
156
|
+
.selectFrom('sys.ai_run')
|
|
157
|
+
.selectAll()
|
|
158
|
+
.where('id', '=', id)
|
|
159
|
+
.where('tenant_id', '=', ctx.tenantId)
|
|
160
|
+
.where('user_id', '=', ctx.userId)
|
|
161
|
+
.executeTakeFirst();
|
|
162
|
+
if (!r)
|
|
163
|
+
throw cageError('NOT_FOUND');
|
|
164
|
+
// 声明可能新增隐藏字段或改变查询含义,旧版本生成的回答和事件也必须停止交付。
|
|
165
|
+
if (r.fingerprint !== this.fingerprint)
|
|
166
|
+
throw cageError('CONFLICT', '注册声明已变化,请重新发起任务');
|
|
167
|
+
if (r.auth_fingerprint && r.auth_fingerprint !== authFingerprint(ctx))
|
|
168
|
+
throw cageError('FORBIDDEN', '授权已变化,请开启新会话');
|
|
169
|
+
return r;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* 校验启用状态、消息/页面快照及最多 80 KiB 输入,按用户事务锁执行幂等提交。
|
|
173
|
+
* 相同请求键与内容复用已有运行,不重复占队列;同键不同内容冲突。锁会话后冻结性格、权限和注册表快照,非终态队列默认最多 8 个。
|
|
174
|
+
* 创建 queued 运行、首个状态事件和会话更新时间共同提交,默认委托期限 30 分钟;返回状态快照,实际工作由 worker 异步执行。
|
|
175
|
+
*/
|
|
176
|
+
async submit(ctx, sessionId, input, requestKey, authSession) {
|
|
177
|
+
needUser(ctx);
|
|
178
|
+
if (!this.options.assistant)
|
|
179
|
+
throw cageError('NOT_FOUND');
|
|
180
|
+
const body = parse(messageInputSchema, input);
|
|
181
|
+
parse(z.string().min(1).max(160), requestKey);
|
|
182
|
+
if (Buffer.byteLength(json(body)) > 80 * 1024)
|
|
183
|
+
throw cageError('INVALID_INPUT', '消息上下文超过限制');
|
|
184
|
+
const hash = digest({ sessionId, body });
|
|
185
|
+
const id = await this.kernel.app.transaction().execute(async (tx) => {
|
|
186
|
+
// 同一用户并发请求共享配额锁;幂等键不会因重试消耗第二个队列名额。
|
|
187
|
+
await sql `select pg_advisory_xact_lock(hashtext(${ctx.tenantId}), hashtext(${ctx.userId}))`.execute(tx);
|
|
188
|
+
const old = await tx
|
|
189
|
+
.selectFrom('sys.ai_run')
|
|
190
|
+
.selectAll()
|
|
191
|
+
.where('tenant_id', '=', ctx.tenantId)
|
|
192
|
+
.where('user_id', '=', ctx.userId)
|
|
193
|
+
.where('request_key', '=', requestKey)
|
|
194
|
+
.executeTakeFirst();
|
|
195
|
+
if (old) {
|
|
196
|
+
if (old.request_hash !== hash)
|
|
197
|
+
throw cageError('CONFLICT');
|
|
198
|
+
return old.id;
|
|
199
|
+
}
|
|
200
|
+
const session = await this.ownedSession(ctx, sessionId, tx, true);
|
|
201
|
+
const personality = await this.personalities.resolve(ctx, session.personality_key, tx);
|
|
202
|
+
const count = await tx
|
|
203
|
+
.selectFrom('sys.ai_run')
|
|
204
|
+
.select(sql `count(*)::int`.as('n'))
|
|
205
|
+
.where('tenant_id', '=', ctx.tenantId)
|
|
206
|
+
.where('user_id', '=', ctx.userId)
|
|
207
|
+
.where('status', 'not in', TERMINAL)
|
|
208
|
+
.executeTakeFirstOrThrow();
|
|
209
|
+
if (count.n >= (this.options.maxQueuedPerUser ?? 8))
|
|
210
|
+
throw cageError('RATE_LIMITED');
|
|
211
|
+
const id = randomUUID(), assistant = this.options.assistant;
|
|
212
|
+
await tx
|
|
213
|
+
.insertInto('sys.ai_run')
|
|
214
|
+
.values({
|
|
215
|
+
id,
|
|
216
|
+
tenant_id: ctx.tenantId,
|
|
217
|
+
user_id: ctx.userId,
|
|
218
|
+
session_id: sessionId,
|
|
219
|
+
mode: 'assistant',
|
|
220
|
+
status: 'queued',
|
|
221
|
+
input: body.message,
|
|
222
|
+
page_context: body.pageContext ? json(body.pageContext) : null,
|
|
223
|
+
personality: json(personality),
|
|
224
|
+
model: assistant.model,
|
|
225
|
+
instructions: assistant.instructions ?? '',
|
|
226
|
+
limits: json({ ...DEFAULT_LIMITS, ...assistant.limits }),
|
|
227
|
+
fingerprint: this.fingerprint,
|
|
228
|
+
auth_fingerprint: authFingerprint(ctx),
|
|
229
|
+
auth_session: authSession ?? null,
|
|
230
|
+
delegated_until: new Date(Date.now() + (this.options.delegationTtlMs ?? 30 * 60_000)),
|
|
231
|
+
step_up_at: ctx.stepUpAt ?? null,
|
|
232
|
+
request_key: requestKey,
|
|
233
|
+
request_hash: hash,
|
|
234
|
+
})
|
|
235
|
+
.execute();
|
|
236
|
+
await event(tx, id, 'run.status', { status: 'queued' });
|
|
237
|
+
await tx
|
|
238
|
+
.updateTable('sys.ai_session')
|
|
239
|
+
.set({ updated_at: sql `now()` })
|
|
240
|
+
.where('id', '=', sessionId)
|
|
241
|
+
.execute();
|
|
242
|
+
return id;
|
|
243
|
+
});
|
|
244
|
+
return this.run(ctx, id);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* 读取经归属/指纹复核的运行 DTO及未回复互动。
|
|
248
|
+
* 终态一律不再交付待处理互动,避免客户端继续确认已结束任务;不返回内部模型历史、租约或凭据。
|
|
249
|
+
*/
|
|
250
|
+
async run(ctx, id) {
|
|
251
|
+
const r = await this.ownedRun(ctx, id);
|
|
252
|
+
const interactions = await this.kernel.app
|
|
253
|
+
.selectFrom('sys.ai_interaction')
|
|
254
|
+
.selectAll()
|
|
255
|
+
.where('run_id', '=', id)
|
|
256
|
+
.where('answered_at', 'is', null)
|
|
257
|
+
.orderBy('created_at')
|
|
258
|
+
.execute();
|
|
259
|
+
return {
|
|
260
|
+
id,
|
|
261
|
+
sessionId: r.session_id,
|
|
262
|
+
status: r.status,
|
|
263
|
+
phase: r.phase,
|
|
264
|
+
answer: r.answer,
|
|
265
|
+
error: r.error,
|
|
266
|
+
steps: r.steps,
|
|
267
|
+
toolCalls: r.tool_calls,
|
|
268
|
+
tokens: r.tokens,
|
|
269
|
+
createdAt: iso(r.created_at),
|
|
270
|
+
updatedAt: iso(r.updated_at),
|
|
271
|
+
...(r.personality ? { personality: personalitySummary(r.personality) } : {}),
|
|
272
|
+
interactions: TERMINAL.includes(r.status)
|
|
273
|
+
? []
|
|
274
|
+
: interactions.map((i) => ({
|
|
275
|
+
id: i.id,
|
|
276
|
+
kind: i.kind,
|
|
277
|
+
prompt: i.prompt,
|
|
278
|
+
data: i.data,
|
|
279
|
+
expiresAt: iso(i.expires_at),
|
|
280
|
+
})),
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* 验证本人会话后取最近 100 个运行,再按时间正序逐个执行 run 的指纹检查。
|
|
285
|
+
* 任一旧记录授权不再匹配时拒绝交付,不把旧敏感答案当作普通会话缓存返回。
|
|
286
|
+
*/
|
|
287
|
+
async runs(ctx, sessionId) {
|
|
288
|
+
await this.ownedSession(ctx, sessionId);
|
|
289
|
+
const rows = await this.kernel.app
|
|
290
|
+
.selectFrom('sys.ai_run')
|
|
291
|
+
.select('id')
|
|
292
|
+
.where('session_id', '=', sessionId)
|
|
293
|
+
.orderBy('created_at', 'desc')
|
|
294
|
+
.orderBy('id', 'desc')
|
|
295
|
+
.limit(100)
|
|
296
|
+
.execute();
|
|
297
|
+
const runs = [];
|
|
298
|
+
for (const r of rows.reverse())
|
|
299
|
+
runs.push(await this.run(ctx, r.id));
|
|
300
|
+
return runs;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* 读取指定序号之后的单页事件,默认从 0 开始;授权与每页数量规则由 eventPage 统一执行。
|
|
304
|
+
*/
|
|
305
|
+
async events(ctx, id, after = 0) {
|
|
306
|
+
return (await this.eventPage(ctx, id, after)).events;
|
|
307
|
+
}
|
|
308
|
+
/** SSE 同时读取状态与事件,避免每次追赶都再次查询完整运行及互动列表。 */
|
|
309
|
+
/**
|
|
310
|
+
* 验证归属与当前指纹,读取 after 之后最多 200 条有序事件及运行状态/最新序号。
|
|
311
|
+
* SSE 据此判断是否追平或终止;状态和事件不是额外长事务快照,下一页继续通过序号追赶。
|
|
312
|
+
*/
|
|
313
|
+
async eventPage(ctx, id, after = 0) {
|
|
314
|
+
const run = await this.ownedRun(ctx, id);
|
|
315
|
+
parse(z.number().int().nonnegative(), after);
|
|
316
|
+
const rows = await this.kernel.app
|
|
317
|
+
.selectFrom('sys.ai_event')
|
|
318
|
+
.selectAll()
|
|
319
|
+
.where('run_id', '=', id)
|
|
320
|
+
.where('sequence', '>', after)
|
|
321
|
+
.orderBy('sequence')
|
|
322
|
+
.limit(200)
|
|
323
|
+
.execute();
|
|
324
|
+
return {
|
|
325
|
+
status: run.status,
|
|
326
|
+
nextSequence: run.next_seq,
|
|
327
|
+
events: rows.map((r) => ({
|
|
328
|
+
runId: id,
|
|
329
|
+
sequence: r.sequence,
|
|
330
|
+
type: r.type,
|
|
331
|
+
data: r.data,
|
|
332
|
+
createdAt: iso(r.created_at),
|
|
333
|
+
})),
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* 锁定本人运行后标记取消并清除租约,终态重复取消不做变更。
|
|
338
|
+
* 尚未结算的模型预留按估算一次性计入累计 Token,同时写失败和取消事件;取消阻止后续租约提交,但不会撤销之前已完成的业务命令。
|
|
339
|
+
*/
|
|
340
|
+
async cancel(ctx, id) {
|
|
341
|
+
await this.kernel.app.transaction().execute(async (tx) => {
|
|
342
|
+
await this.ownedRun(ctx, id, tx);
|
|
343
|
+
const run = await tx
|
|
344
|
+
.selectFrom('sys.ai_run')
|
|
345
|
+
.selectAll()
|
|
346
|
+
.where('id', '=', id)
|
|
347
|
+
.forUpdate()
|
|
348
|
+
.executeTakeFirstOrThrow();
|
|
349
|
+
if (TERMINAL.includes(run.status))
|
|
350
|
+
return;
|
|
351
|
+
const charged = run.model_reservation ? reservedTokens(run.model_reservation) : 0;
|
|
352
|
+
await tx
|
|
353
|
+
.updateTable('sys.ai_run')
|
|
354
|
+
.set({
|
|
355
|
+
cancelled: true,
|
|
356
|
+
status: 'cancelled',
|
|
357
|
+
lease_token: null,
|
|
358
|
+
lease_until: null,
|
|
359
|
+
model_reservation: null,
|
|
360
|
+
tokens: run.tokens + charged,
|
|
361
|
+
})
|
|
362
|
+
.where('id', '=', id)
|
|
363
|
+
.execute();
|
|
364
|
+
if (run.model_reservation)
|
|
365
|
+
await event(tx, id, 'model.failed', {
|
|
366
|
+
attempt: run.model_reservation.attempt,
|
|
367
|
+
reason: 'cancelled',
|
|
368
|
+
chargedTokens: charged,
|
|
369
|
+
usageSource: 'estimate',
|
|
370
|
+
retryable: false,
|
|
371
|
+
});
|
|
372
|
+
await event(tx, id, 'run.status', { status: 'cancelled' });
|
|
373
|
+
});
|
|
374
|
+
return this.run(ctx, id);
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* 在运行行锁内保存确认、补充输入或页面快照回复,再把等待运行排回 queued。
|
|
378
|
+
* 相同已回答内容幂等返回,不同内容冲突;拒绝过期、类型不符、其他页面实例或倒退版本快照。
|
|
379
|
+
* 只记录用户回复,不在 HTTP 事务直接执行工具,worker 恢复时仍重新核验权限与业务状态。
|
|
380
|
+
*/
|
|
381
|
+
async respond(ctx, id, interactionId, input) {
|
|
382
|
+
parse(z.uuid(), interactionId);
|
|
383
|
+
const body = parse(interactionResponseSchema, input);
|
|
384
|
+
await this.kernel.app.transaction().execute(async (tx) => {
|
|
385
|
+
await this.ownedRun(ctx, id, tx);
|
|
386
|
+
const run = await tx
|
|
387
|
+
.selectFrom('sys.ai_run')
|
|
388
|
+
.selectAll()
|
|
389
|
+
.where('id', '=', id)
|
|
390
|
+
.forUpdate()
|
|
391
|
+
.executeTakeFirstOrThrow();
|
|
392
|
+
const interaction = await tx
|
|
393
|
+
.selectFrom('sys.ai_interaction')
|
|
394
|
+
.selectAll()
|
|
395
|
+
.where('id', '=', interactionId)
|
|
396
|
+
.where('run_id', '=', id)
|
|
397
|
+
.executeTakeFirst();
|
|
398
|
+
if (!interaction)
|
|
399
|
+
throw cageError('NOT_FOUND');
|
|
400
|
+
if (interaction.answered_at) {
|
|
401
|
+
if (digest(interaction.response) !== digest(body))
|
|
402
|
+
throw cageError('CONFLICT');
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
if (!['waiting_confirmation', 'waiting_input'].includes(run.status) ||
|
|
406
|
+
new Date(interaction.expires_at).getTime() <= Date.now())
|
|
407
|
+
throw cageError('CONFLICT');
|
|
408
|
+
if ((interaction.kind === 'confirmation' && body.approved === undefined) ||
|
|
409
|
+
(interaction.kind === 'input' && body.answer === undefined) ||
|
|
410
|
+
(interaction.kind === 'page_context' && !body.pageContext))
|
|
411
|
+
throw cageError('INVALID_INPUT');
|
|
412
|
+
if (body.pageContext &&
|
|
413
|
+
run.page_context &&
|
|
414
|
+
(body.pageContext.pageInstanceId !== run.page_context.pageInstanceId ||
|
|
415
|
+
body.pageContext.revision < run.page_context.revision))
|
|
416
|
+
throw cageError('CONFLICT', '页面快照来自其他页面或旧版本');
|
|
417
|
+
await tx
|
|
418
|
+
.updateTable('sys.ai_interaction')
|
|
419
|
+
.set({ response: json(body), answered_at: sql `now()` })
|
|
420
|
+
.where('id', '=', interactionId)
|
|
421
|
+
.execute();
|
|
422
|
+
await tx.updateTable('sys.ai_run').set({ status: 'queued', deadline: null }).where('id', '=', id).execute();
|
|
423
|
+
await event(tx, id, 'run.status', { status: 'queued' });
|
|
424
|
+
});
|
|
425
|
+
return this.run(ctx, id);
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* 返回当前租户用户最近更新的最多 50 条偏好;只读本人数据,内容不因被记忆就获得指令优先级。
|
|
429
|
+
*/
|
|
430
|
+
async memories(ctx) {
|
|
431
|
+
needUser(ctx);
|
|
432
|
+
const rows = await this.kernel.app
|
|
433
|
+
.selectFrom('sys.ai_memory')
|
|
434
|
+
.selectAll()
|
|
435
|
+
.where('tenant_id', '=', ctx.tenantId)
|
|
436
|
+
.where('user_id', '=', ctx.userId)
|
|
437
|
+
.orderBy('updated_at', 'desc')
|
|
438
|
+
.limit(50)
|
|
439
|
+
.execute();
|
|
440
|
+
return rows.map((r) => ({ id: r.id, key: r.key, value: r.value, updatedAt: iso(r.updated_at) }));
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* 按 UUID 和当前租户/用户归属删除偏好;目标不存在时也完成,重复删除不产生额外副作用。
|
|
444
|
+
*/
|
|
445
|
+
async deleteMemory(ctx, id) {
|
|
446
|
+
needUser(ctx);
|
|
447
|
+
parse(z.uuid(), id);
|
|
448
|
+
await this.kernel.app
|
|
449
|
+
.deleteFrom('sys.ai_memory')
|
|
450
|
+
.where('id', '=', id)
|
|
451
|
+
.where('tenant_id', '=', ctx.tenantId)
|
|
452
|
+
.where('user_id', '=', ctx.userId)
|
|
453
|
+
.execute();
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 将模型零碎文本合并为有序、可等待的持久事件提交。
|
|
3
|
+
* 运行时传入带租约检查的 emit;首段尽快提交,后续短片段合并 40 毫秒,完成和取消时分别冲刷或丢弃尾段,避免迟到文本越过运行终态。
|
|
4
|
+
*/
|
|
5
|
+
/** 首段立即提交,后续最多合并 40ms;持久化不再阻塞每一个模型 token。 */
|
|
6
|
+
/**
|
|
7
|
+
* 有序文本批处理器,串行等待 emit 并记住首次提交失败。
|
|
8
|
+
* 普通 token 不逐个阻塞数据库往返,累计到 2048 字符时主动施加背压;不负责网络重试或重建已经丢弃的文本。
|
|
9
|
+
*/
|
|
10
|
+
export declare class TextStream {
|
|
11
|
+
private readonly emit;
|
|
12
|
+
private readonly signal;
|
|
13
|
+
/**
|
|
14
|
+
* 尚未交给 emit 的文本缓冲,按字符长度触发批次阈值。
|
|
15
|
+
*/
|
|
16
|
+
private pending;
|
|
17
|
+
/**
|
|
18
|
+
* 短片段合并定时器;冲刷、完成或销毁时清理。
|
|
19
|
+
*/
|
|
20
|
+
private timer;
|
|
21
|
+
/**
|
|
22
|
+
* 已排队提交的串行尾 Promise,保证事件顺序。
|
|
23
|
+
*/
|
|
24
|
+
private tail;
|
|
25
|
+
/**
|
|
26
|
+
* 最近捕获的提交失败;后续 push/finish 重新抛出。
|
|
27
|
+
*/
|
|
28
|
+
private failure;
|
|
29
|
+
/**
|
|
30
|
+
* 是否曾提交过非空批次,确保首段不等待定时器。
|
|
31
|
+
*/
|
|
32
|
+
private started;
|
|
33
|
+
/**
|
|
34
|
+
* 是否已完成或销毁,阻止继续追加。
|
|
35
|
+
*/
|
|
36
|
+
private closed;
|
|
37
|
+
/**
|
|
38
|
+
* 绑定异步提交回调和运行取消信号;回调负责实际持久化与租约验证,本类不创建事务。
|
|
39
|
+
*/
|
|
40
|
+
constructor(emit: (text: string) => Promise<void>, signal: AbortSignal);
|
|
41
|
+
/**
|
|
42
|
+
* 追加文本;先检查取消及此前提交失败,再按首段、2048 字符阈值或 40 毫秒定时器触发冲刷。
|
|
43
|
+
* 关闭后及空文本不再入队;长片段等待提交形成背压,短片段可能先返回。
|
|
44
|
+
*/
|
|
45
|
+
push(text: string): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* 取走当前缓冲并链接到同一提交 Promise,确保各批次顺序不交错。
|
|
48
|
+
* 清理定时器,捕获异步失败供本次和后续调用重新抛出,失败后不继续发送排队文本。
|
|
49
|
+
*/
|
|
50
|
+
private flush;
|
|
51
|
+
/** 完成事件必须排在最后一段文字提交之后。 */
|
|
52
|
+
/**
|
|
53
|
+
* 关闭输入并等待尾段提交;调用方必须在此成功后发布模型完成事件,否则界面可能先看到完成再收到文字。
|
|
54
|
+
*/
|
|
55
|
+
finish(): Promise<void>;
|
|
56
|
+
/** 失败/取消后丢弃未提交的尾段,等待已开始的事务退出,杜绝迟到文本。 */
|
|
57
|
+
/**
|
|
58
|
+
* 取消/失败时丢弃尚未提交的尾段并清理定时器,等待已开始的提交退出。
|
|
59
|
+
* 不会撤销已提交数据库事件;关闭后 push 不再接收新文字。
|
|
60
|
+
*/
|
|
61
|
+
dispose(): Promise<void>;
|
|
62
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 将模型零碎文本合并为有序、可等待的持久事件提交。
|
|
3
|
+
* 运行时传入带租约检查的 emit;首段尽快提交,后续短片段合并 40 毫秒,完成和取消时分别冲刷或丢弃尾段,避免迟到文本越过运行终态。
|
|
4
|
+
*/
|
|
5
|
+
/** 首段立即提交,后续最多合并 40ms;持久化不再阻塞每一个模型 token。 */
|
|
6
|
+
/**
|
|
7
|
+
* 有序文本批处理器,串行等待 emit 并记住首次提交失败。
|
|
8
|
+
* 普通 token 不逐个阻塞数据库往返,累计到 2048 字符时主动施加背压;不负责网络重试或重建已经丢弃的文本。
|
|
9
|
+
*/
|
|
10
|
+
export class TextStream {
|
|
11
|
+
emit;
|
|
12
|
+
signal;
|
|
13
|
+
/**
|
|
14
|
+
* 尚未交给 emit 的文本缓冲,按字符长度触发批次阈值。
|
|
15
|
+
*/
|
|
16
|
+
pending = '';
|
|
17
|
+
/**
|
|
18
|
+
* 短片段合并定时器;冲刷、完成或销毁时清理。
|
|
19
|
+
*/
|
|
20
|
+
timer;
|
|
21
|
+
/**
|
|
22
|
+
* 已排队提交的串行尾 Promise,保证事件顺序。
|
|
23
|
+
*/
|
|
24
|
+
tail = Promise.resolve();
|
|
25
|
+
/**
|
|
26
|
+
* 最近捕获的提交失败;后续 push/finish 重新抛出。
|
|
27
|
+
*/
|
|
28
|
+
failure;
|
|
29
|
+
/**
|
|
30
|
+
* 是否曾提交过非空批次,确保首段不等待定时器。
|
|
31
|
+
*/
|
|
32
|
+
started = false;
|
|
33
|
+
/**
|
|
34
|
+
* 是否已完成或销毁,阻止继续追加。
|
|
35
|
+
*/
|
|
36
|
+
closed = false;
|
|
37
|
+
/**
|
|
38
|
+
* 绑定异步提交回调和运行取消信号;回调负责实际持久化与租约验证,本类不创建事务。
|
|
39
|
+
*/
|
|
40
|
+
constructor(emit, signal) {
|
|
41
|
+
this.emit = emit;
|
|
42
|
+
this.signal = signal;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* 追加文本;先检查取消及此前提交失败,再按首段、2048 字符阈值或 40 毫秒定时器触发冲刷。
|
|
46
|
+
* 关闭后及空文本不再入队;长片段等待提交形成背压,短片段可能先返回。
|
|
47
|
+
*/
|
|
48
|
+
async push(text) {
|
|
49
|
+
this.signal.throwIfAborted();
|
|
50
|
+
if (this.failure)
|
|
51
|
+
throw this.failure;
|
|
52
|
+
if (this.closed || !text)
|
|
53
|
+
return;
|
|
54
|
+
this.pending += text;
|
|
55
|
+
// 长片段施加背压,普通 token 则留给短定时器合并,避免数据库往返降低生成速度。
|
|
56
|
+
if (!this.started || this.pending.length >= 2048)
|
|
57
|
+
return this.flush();
|
|
58
|
+
this.timer ??= setTimeout(() => { void this.flush().catch(() => { }); }, 40);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 取走当前缓冲并链接到同一提交 Promise,确保各批次顺序不交错。
|
|
62
|
+
* 清理定时器,捕获异步失败供本次和后续调用重新抛出,失败后不继续发送排队文本。
|
|
63
|
+
*/
|
|
64
|
+
flush() {
|
|
65
|
+
clearTimeout(this.timer);
|
|
66
|
+
this.timer = undefined;
|
|
67
|
+
const text = this.pending;
|
|
68
|
+
this.pending = '';
|
|
69
|
+
if (text) {
|
|
70
|
+
this.started = true;
|
|
71
|
+
this.tail = this.tail.then(async () => {
|
|
72
|
+
if (this.failure)
|
|
73
|
+
return;
|
|
74
|
+
this.signal.throwIfAborted();
|
|
75
|
+
await this.emit(text);
|
|
76
|
+
}).catch(error => { this.failure = error; });
|
|
77
|
+
}
|
|
78
|
+
return this.tail.then(() => { if (this.failure)
|
|
79
|
+
throw this.failure; });
|
|
80
|
+
}
|
|
81
|
+
/** 完成事件必须排在最后一段文字提交之后。 */
|
|
82
|
+
/**
|
|
83
|
+
* 关闭输入并等待尾段提交;调用方必须在此成功后发布模型完成事件,否则界面可能先看到完成再收到文字。
|
|
84
|
+
*/
|
|
85
|
+
async finish() { this.closed = true; await this.flush(); }
|
|
86
|
+
/** 失败/取消后丢弃未提交的尾段,等待已开始的事务退出,杜绝迟到文本。 */
|
|
87
|
+
/**
|
|
88
|
+
* 取消/失败时丢弃尚未提交的尾段并清理定时器,等待已开始的提交退出。
|
|
89
|
+
* 不会撤销已提交数据库事件;关闭后 push 不再接收新文字。
|
|
90
|
+
*/
|
|
91
|
+
async dispose() {
|
|
92
|
+
this.closed = true;
|
|
93
|
+
this.pending = '';
|
|
94
|
+
clearTimeout(this.timer);
|
|
95
|
+
this.timer = undefined;
|
|
96
|
+
await this.tail;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=text-stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-stream.js","sourceRoot":"","sources":["../src/text-stream.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,6CAA6C;AAC7C;;;GAGG;AACH,MAAM,OAAO,UAAU;IA4BQ;IAAwD;IA3BrF;;OAEG;IACK,OAAO,GAAG,EAAE,CAAC;IACrB;;OAEG;IACK,KAAK,CAA4C;IACzD;;OAEG;IACK,IAAI,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;IAChD;;OAEG;IACK,OAAO,CAAU;IACzB;;OAEG;IACK,OAAO,GAAG,KAAK,CAAC;IACxB;;OAEG;IACK,MAAM,GAAG,KAAK,CAAC;IACvB;;OAEG;IACH,YAA6B,IAAqC,EAAmB,MAAmB;QAA3E,SAAI,GAAJ,IAAI,CAAiC;QAAmB,WAAM,GAAN,MAAM,CAAa;IAAG,CAAC;IAE5G;;;OAGG;IACH,KAAK,CAAC,IAAI,CAAC,IAAY;QACrB,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;QAC7B,IAAI,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,CAAC,OAAO,CAAC;QACrC,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI;YAAE,OAAO;QACjC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC;QACrB,4CAA4C;QAC5C,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC;QACtE,IAAI,CAAC,KAAK,KAAK,UAAU,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC9E,CAAC;IACD;;;OAGG;IACK,KAAK;QACX,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAAC,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;QACjD,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC;QAAC,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAC7C,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACpB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;gBACpC,IAAI,IAAI,CAAC,OAAO;oBAAE,OAAO;gBACzB,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;gBAC7B,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACxB,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/C,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACzE,CAAC;IACD,0BAA0B;IAC1B;;OAEG;IACH,KAAK,CAAC,MAAM,KAAoB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACzE,wCAAwC;IACxC;;;OAGG;IACH,KAAK,CAAC,OAAO;QACX,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QAAC,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAAC,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;QACxF,MAAM,IAAI,CAAC,IAAI,CAAC;IAClB,CAAC;CACF"}
|