@yfwu2020/dsh-selection-explain 0.13.1 → 0.14.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/lib/client.js +344 -42
- package/lib/client.js.map +3 -3
- package/lib/host/promote-seed.js +111 -0
- package/lib/host/promote-seed.js.map +1 -0
- package/lib/host/promote.js +53 -153
- package/lib/host/promote.js.map +1 -1
- package/lib/types/host/promote-seed.d.ts +24 -0
- package/package.json +1 -1
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { PLUGIN_SOURCE_KIND } from './constants.js';
|
|
2
|
+
/**
|
|
3
|
+
* 去掉小窗正文里那行 `【本条消息带了附件】…`。
|
|
4
|
+
*
|
|
5
|
+
* 那行是**小窗**的说法(历史里给模型看的锚点)。升格时附件是**真带过来**的,
|
|
6
|
+
* 再留着它,主会话里就会同时出现"一行字说带了附件"和"附件本身",
|
|
7
|
+
* 而且措辞("本条消息")在主会话语境下也不通顺。
|
|
8
|
+
*
|
|
9
|
+
* 只在**确实带上了附件**时才去(`hasAttachments`):没有附件时那行是唯一的信息,不能抹。
|
|
10
|
+
*/
|
|
11
|
+
function attachmentMarkerStripped(text, hasAttachments) {
|
|
12
|
+
if (!hasAttachments)
|
|
13
|
+
return text;
|
|
14
|
+
return text.replace(/^【本条消息带了附件】[^\n]*\n?/, '');
|
|
15
|
+
}
|
|
16
|
+
/** Build balanced, contiguous history before the host constructs its agent. */
|
|
17
|
+
export function buildPromoteSeed({ text, label, contextText, translation, detail, sourceSessionId, turns }) {
|
|
18
|
+
const events = [];
|
|
19
|
+
const time = Date.now();
|
|
20
|
+
const stamp = time.toString(36);
|
|
21
|
+
const append = (type, data, options) => {
|
|
22
|
+
events.push({ type, seq: events.length, time, data, ...options });
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* 一轮升格后的**内容块**:附件在前、正文在后。
|
|
26
|
+
*
|
|
27
|
+
* 顺序与主会话、与 /analyze 完全一致(先给材料,再读问题)——
|
|
28
|
+
* 形状也是主会话真实使用的那一种(`{type:'image', attachment:{…}}`),
|
|
29
|
+
* 所以升格后客户端能画出缩略图、模型也能真的看到图。
|
|
30
|
+
*/
|
|
31
|
+
const contentOfTurn = (turn) => {
|
|
32
|
+
const blocks = [];
|
|
33
|
+
for (const item of turn.attachments) {
|
|
34
|
+
blocks.push(item.kind === 'image'
|
|
35
|
+
? { type: 'image', attachment: item.ref }
|
|
36
|
+
: { type: 'file', attachment: item.ref });
|
|
37
|
+
}
|
|
38
|
+
blocks.push({ type: 'text', text: attachmentMarkerStripped(turn.text, turn.attachments.length > 0) });
|
|
39
|
+
return blocks;
|
|
40
|
+
};
|
|
41
|
+
let turnNo = 0;
|
|
42
|
+
const appendTurn = (userEvent, assistantText) => {
|
|
43
|
+
turnNo += 1;
|
|
44
|
+
const turn = turnNo;
|
|
45
|
+
append('turn/start', { turn });
|
|
46
|
+
append('step/start', { turn, step: 1 });
|
|
47
|
+
if (userEvent)
|
|
48
|
+
append('user/message', userEvent, { surfaceOp: 'append' });
|
|
49
|
+
append('assistant/message', {
|
|
50
|
+
turn,
|
|
51
|
+
step: 1,
|
|
52
|
+
stream: [],
|
|
53
|
+
message: {
|
|
54
|
+
id: `sel-a-${stamp}-${turn}`,
|
|
55
|
+
role: 'assistant',
|
|
56
|
+
source: { kind: 'model', provider: 'dsh-selection-explain', model: '划词解读小窗' },
|
|
57
|
+
content: [{ type: 'text', text: assistantText }],
|
|
58
|
+
},
|
|
59
|
+
}, { surfaceOp: 'append' });
|
|
60
|
+
append('step/end', { turn, step: 1 });
|
|
61
|
+
append('turn/end', { turn, reason: { kind: 'completed' } });
|
|
62
|
+
};
|
|
63
|
+
// 第 1 轮:上下文消息(生产者自有的 source.kind + snapshot 呈现)+ 首轮解读
|
|
64
|
+
// ⚠️ kind 必须是 PLUGIN_SOURCE_KIND(`plugin:<插件名>`):会话格式 v4 起不再
|
|
65
|
+
// 接受退役的 `plugin` 包装(`kind: 'plugin'` 加一个 `plugin` 字段),否则整场升格
|
|
66
|
+
// 会死在 "format v4 message requires a producer-owned source kind" 上(见文件头常量注释)。
|
|
67
|
+
const contextBody = [
|
|
68
|
+
`选中文字:${text}`,
|
|
69
|
+
`所在位置:${label}`,
|
|
70
|
+
`来源:划词解读小窗${sourceSessionId ? `(来源会话 ${sourceSessionId})` : ''}`,
|
|
71
|
+
'',
|
|
72
|
+
'选中处的上下文片段:',
|
|
73
|
+
contextText,
|
|
74
|
+
].join('\n');
|
|
75
|
+
const explanation = ['翻译', translation || '(未记录)', '', '详解', detail || '(未记录)'].join('\n');
|
|
76
|
+
appendTurn({
|
|
77
|
+
id: `sel-ctx-${stamp}`,
|
|
78
|
+
role: 'user',
|
|
79
|
+
source: {
|
|
80
|
+
kind: PLUGIN_SOURCE_KIND,
|
|
81
|
+
form: 'snapshot',
|
|
82
|
+
sections: [
|
|
83
|
+
{ name: '划词解读 · 选中文字', text },
|
|
84
|
+
{ name: '划词解读 · 所在位置', text: label },
|
|
85
|
+
{ name: '划词解读 · 上下文片段', text: contextText },
|
|
86
|
+
],
|
|
87
|
+
},
|
|
88
|
+
content: [{ type: 'text', text: contextBody }],
|
|
89
|
+
}, explanation);
|
|
90
|
+
// 后续轮:小窗里的追问逐轮写成真实问答
|
|
91
|
+
for (let i = 0; i < turns.length; i += 1) {
|
|
92
|
+
const turn = turns[i];
|
|
93
|
+
if (!turn)
|
|
94
|
+
continue;
|
|
95
|
+
if (turn.role === 'user') {
|
|
96
|
+
appendTurn({
|
|
97
|
+
id: `sel-u-${stamp}-${i}`,
|
|
98
|
+
role: 'user',
|
|
99
|
+
source: { kind: 'user' },
|
|
100
|
+
content: contentOfTurn(turn),
|
|
101
|
+
}, turns[i + 1] && turns[i + 1]?.role === 'assistant' ? (turns[i + 1]?.text ?? '') : '(未记录)');
|
|
102
|
+
i += 1; // 助手回答已随本轮写入
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
// 落单的助手消息(历史里没有对应提问):单独成一轮
|
|
106
|
+
appendTurn(null, turn.text);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return events;
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=promote-seed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promote-seed.js","sourceRoot":"","sources":["../../src/host/promote-seed.ts"],"names":[],"mappings":"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"}
|
package/lib/host/promote.js
CHANGED
|
@@ -1,30 +1,15 @@
|
|
|
1
1
|
import { sendJson, readBody, BODY_LIMIT } from './http.js';
|
|
2
2
|
import { sessionIdOf } from './context.js';
|
|
3
|
-
import { name
|
|
3
|
+
import { name } from './constants.js';
|
|
4
|
+
import { randomUUID } from 'node:crypto';
|
|
5
|
+
import { buildPromoteSeed } from './promote-seed.js';
|
|
4
6
|
import { readHistoryAttachments } from './history-attachments.js';
|
|
5
|
-
/**
|
|
6
|
-
* 去掉小窗正文里那行 `【本条消息带了附件】…`。
|
|
7
|
-
*
|
|
8
|
-
* 那行是**小窗**的说法(历史里给模型看的锚点)。升格时附件是**真带过来**的,
|
|
9
|
-
* 再留着它,主会话里就会同时出现"一行字说带了附件"和"附件本身",
|
|
10
|
-
* 而且措辞("本条消息")在主会话语境下也不通顺。
|
|
11
|
-
*
|
|
12
|
-
* 只在**确实带上了附件**时才去(`hasAttachments`):没有附件时那行是唯一的信息,不能抹。
|
|
13
|
-
*/
|
|
14
|
-
function attachmentMarkerStripped(text, hasAttachments) {
|
|
15
|
-
if (!hasAttachments)
|
|
16
|
-
return text;
|
|
17
|
-
return text.replace(/^【本条消息带了附件】[^\n]*\n?/, '');
|
|
18
|
-
}
|
|
19
7
|
/** Owns promote state for one plugin instance. */
|
|
20
8
|
export function createPromote(ctx, config, sessions, historyStore) {
|
|
21
9
|
/**
|
|
22
10
|
* 把划词解读小窗「升格」成正式会话(建在来源会话同一个项目下):
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* → ⑤ 送一条短开场消息让 agent 接手(这样整段历史才会落盘)。
|
|
26
|
-
* 这样新会话里看到的就是一段真实的多轮对话,而不是一大坨打包文本。
|
|
27
|
-
* live 会话对象拿不到时,退回「打包成一条消息」的老路径,保证升格不会整体失败。
|
|
11
|
+
* 先构造真实多轮历史,再作为 seed 创建 agent;内核从历史初始化下一轮编号。
|
|
12
|
+
* 不支持 seed 或无法复用宿主的 agent 配置时,退回打包 prompt。
|
|
28
13
|
*/
|
|
29
14
|
const handlePromote = async (req, res) => {
|
|
30
15
|
if (req.method !== 'POST') {
|
|
@@ -66,10 +51,52 @@ export function createPromote(ctx, config, sessions, historyStore) {
|
|
|
66
51
|
}
|
|
67
52
|
}
|
|
68
53
|
try {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const
|
|
72
|
-
const
|
|
54
|
+
const label = historyStore.clampText(body.label, 80) || '页面内容';
|
|
55
|
+
const contextText = historyStore.clampText(body.context, config.maxContextChars) || '(未记录)';
|
|
56
|
+
const translation = historyStore.clampText(body.translation, 8000);
|
|
57
|
+
const detail = historyStore.clampText(body.detail, 12000);
|
|
58
|
+
const turns = (Array.isArray(body.turns) ? body.turns : [])
|
|
59
|
+
.map((turn) => turn)
|
|
60
|
+
.filter((turn) => turn.seed !== true && typeof turn.text === 'string' && turn.text.trim().length > 0)
|
|
61
|
+
.map((turn) => ({
|
|
62
|
+
role: turn.role === 'assistant' ? 'assistant' : 'user',
|
|
63
|
+
text: turn.text.trim(),
|
|
64
|
+
// 附件(图片/文件)随轮次一起带过来 —— 走的是和 /analyze、历史落盘**同一个收敛器**。
|
|
65
|
+
// 客户端本来就在发它们(exportTurns 带 attachments),是这里以前只认 role/text 把它们丢了,
|
|
66
|
+
// 于是升格出来的会话「声称带了附件、却看不到图」。
|
|
67
|
+
attachments: readHistoryAttachments(turn.attachments),
|
|
68
|
+
}));
|
|
69
|
+
const agents = ctx.get('agents');
|
|
70
|
+
// The composer moved under controller.agents in newer hosts. Preserve its
|
|
71
|
+
// preset mounting and model-selection setup, as the host's fork path does.
|
|
72
|
+
const composer = typeof controller.composeAgent === 'function' ? controller : controller.agents;
|
|
73
|
+
// Without cwd only normal creation can supply the host's default workspace.
|
|
74
|
+
// A cwd-less seeded session is omitted from the sidebar and cannot be resumed.
|
|
75
|
+
const seeded = !!cwd && typeof agents?.create === 'function' && typeof composer?.composeAgent === 'function';
|
|
76
|
+
let newSessionId;
|
|
77
|
+
if (seeded) {
|
|
78
|
+
const composition = await composer.composeAgent(undefined);
|
|
79
|
+
const seed = buildPromoteSeed({ text, label, contextText, translation, detail, sourceSessionId, turns });
|
|
80
|
+
newSessionId = `session-${randomUUID()}`;
|
|
81
|
+
const selection = ctx.get('agentDefaultModel')?.currentSelection?.();
|
|
82
|
+
await agents.create({
|
|
83
|
+
sessionId: newSessionId,
|
|
84
|
+
seed,
|
|
85
|
+
inheritedEventCount: seed.length,
|
|
86
|
+
meta: {
|
|
87
|
+
isSeeded: true,
|
|
88
|
+
...(cwd ? { cwd } : {}),
|
|
89
|
+
...(composition.agentPreset ? { agentPreset: composition.agentPreset } : {}),
|
|
90
|
+
},
|
|
91
|
+
...(selection ? { agentOptions: { provider: selection.provider, model: selection.model } } : {}),
|
|
92
|
+
setup: composition.setup,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
// session.create accepts workspaceId or cwd, never both.
|
|
97
|
+
const created = await controller.create(workspaceId ? { workspaceId } : cwd ? { cwd } : {});
|
|
98
|
+
newSessionId = typeof created?.sessionId === 'string' ? created.sessionId : '';
|
|
99
|
+
}
|
|
73
100
|
if (!newSessionId) {
|
|
74
101
|
sendJson(res, 500, { error: '创建会话失败:未返回会话 id' });
|
|
75
102
|
return;
|
|
@@ -93,135 +120,8 @@ export function createPromote(ctx, config, sessions, historyStore) {
|
|
|
93
120
|
catch {
|
|
94
121
|
/* 标题失败不影响升格 */
|
|
95
122
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const translation = historyStore.clampText(body.translation, 8000);
|
|
99
|
-
const detail = historyStore.clampText(body.detail, 12000);
|
|
100
|
-
const turns = (Array.isArray(body.turns) ? body.turns : [])
|
|
101
|
-
.map((turn) => turn)
|
|
102
|
-
.filter((turn) => turn.seed !== true && typeof turn.text === 'string' && turn.text.trim().length > 0)
|
|
103
|
-
.map((turn) => ({
|
|
104
|
-
role: turn.role === 'assistant' ? 'assistant' : 'user',
|
|
105
|
-
text: turn.text.trim(),
|
|
106
|
-
// 附件(图片/文件)随轮次一起带过来 —— 走的是和 /analyze、历史落盘**同一个收敛器**。
|
|
107
|
-
// 客户端本来就在发它们(exportTurns 带 attachments),是这里以前只认 role/text 把它们丢了,
|
|
108
|
-
// 于是升格出来的会话「声称带了附件、却看不到图」。
|
|
109
|
-
attachments: readHistoryAttachments(turn.attachments),
|
|
110
|
-
}));
|
|
111
|
-
const live = ctx.get('sessions')?.get?.(newSessionId);
|
|
112
|
-
let seeded = false;
|
|
113
|
-
if (live && typeof live.append === 'function') {
|
|
114
|
-
const stamp = Date.now().toString(36);
|
|
115
|
-
/**
|
|
116
|
-
* 把一轮写进日志:turn/start → step/start → 消息 → step/end → turn/end。
|
|
117
|
-
* ⚠️ 必须带这层骨架:客户端会话视图是按 turn/step 事件给消息定位的,
|
|
118
|
-
* 裸写 user/message、assistant/message 会因为拿不到坐标而不显示成历史对话。
|
|
119
|
-
*/
|
|
120
|
-
// 轮号从 1000 起:客户端按「轮号」分组(Map<number>),而新建会话里 agent 的第一轮
|
|
121
|
-
// 一定从 1 开始(phase.turn 初始为 0),所以历史轮必须避开低位号段,
|
|
122
|
-
// 否则历史的 turn 1 会和真实的 turn 1 并成同一组、看起来"历史没进去"。
|
|
123
|
-
// 同时这也是 resume 语义安全的:resume 时 phase.turn = lastTurn + 1 = 1000+N+1,仍不与历史重号。
|
|
124
|
-
/**
|
|
125
|
-
* 一轮升格后的**内容块**:附件在前、正文在后。
|
|
126
|
-
*
|
|
127
|
-
* 顺序与主会话、与 /analyze 完全一致(先给材料,再读问题)——
|
|
128
|
-
* 形状也是主会话真实使用的那一种(`{type:'image', attachment:{…}}`),
|
|
129
|
-
* 所以升格后客户端能画出缩略图、模型也能真的看到图。
|
|
130
|
-
*/
|
|
131
|
-
const contentOfTurn = (turn) => {
|
|
132
|
-
const blocks = [];
|
|
133
|
-
for (const item of turn.attachments) {
|
|
134
|
-
blocks.push(item.kind === 'image'
|
|
135
|
-
? { type: 'image', attachment: item.ref }
|
|
136
|
-
: { type: 'file', attachment: item.ref });
|
|
137
|
-
}
|
|
138
|
-
blocks.push({ type: 'text', text: attachmentMarkerStripped(turn.text, turn.attachments.length > 0) });
|
|
139
|
-
return blocks;
|
|
140
|
-
};
|
|
141
|
-
let turnNo = 1000;
|
|
142
|
-
const appendTurn = (userEvent, assistantText) => {
|
|
143
|
-
turnNo += 1;
|
|
144
|
-
const turn = turnNo;
|
|
145
|
-
live.append?.('turn/start', { turn });
|
|
146
|
-
live.append?.('step/start', { turn, step: 1 });
|
|
147
|
-
if (userEvent)
|
|
148
|
-
live.append?.('user/message', userEvent, { surfaceOp: 'append' });
|
|
149
|
-
live.append?.('assistant/message', {
|
|
150
|
-
turn,
|
|
151
|
-
step: 1,
|
|
152
|
-
stream: [],
|
|
153
|
-
message: {
|
|
154
|
-
id: `sel-a-${stamp}-${turn}`,
|
|
155
|
-
role: 'assistant',
|
|
156
|
-
source: { kind: 'model', provider: 'dsh-selection-explain', model: '划词解读小窗' },
|
|
157
|
-
content: [{ type: 'text', text: assistantText }],
|
|
158
|
-
},
|
|
159
|
-
}, { surfaceOp: 'append' });
|
|
160
|
-
live.append?.('step/end', { turn, step: 1 });
|
|
161
|
-
live.append?.('turn/end', { turn, reason: { kind: 'completed' } });
|
|
162
|
-
};
|
|
163
|
-
// 第 1 轮:上下文消息(生产者自有的 source.kind + snapshot 呈现)+ 首轮解读
|
|
164
|
-
// ⚠️ kind 必须是 PLUGIN_SOURCE_KIND(`plugin:<插件名>`):会话格式 v4 起不再
|
|
165
|
-
// 接受退役的 `plugin` 包装(`kind: 'plugin'` 加一个 `plugin` 字段),否则整场升格
|
|
166
|
-
// 会死在 "format v4 message requires a producer-owned source kind" 上(见文件头常量注释)。
|
|
167
|
-
const contextBody = [
|
|
168
|
-
`选中文字:${text}`,
|
|
169
|
-
`所在位置:${label}`,
|
|
170
|
-
`来源:划词解读小窗${sourceSessionId ? `(来源会话 ${sourceSessionId})` : ''}`,
|
|
171
|
-
'',
|
|
172
|
-
'选中处的上下文片段:',
|
|
173
|
-
contextText,
|
|
174
|
-
].join('\n');
|
|
175
|
-
const explanation = ['翻译', translation || '(未记录)', '', '详解', detail || '(未记录)'].join('\n');
|
|
176
|
-
appendTurn({
|
|
177
|
-
id: `sel-ctx-${stamp}`,
|
|
178
|
-
role: 'user',
|
|
179
|
-
source: {
|
|
180
|
-
kind: PLUGIN_SOURCE_KIND,
|
|
181
|
-
form: 'snapshot',
|
|
182
|
-
sections: [
|
|
183
|
-
{ name: '划词解读 · 选中文字', text },
|
|
184
|
-
{ name: '划词解读 · 所在位置', text: label },
|
|
185
|
-
{ name: '划词解读 · 上下文片段', text: contextText },
|
|
186
|
-
],
|
|
187
|
-
},
|
|
188
|
-
content: [{ type: 'text', text: contextBody }],
|
|
189
|
-
}, explanation);
|
|
190
|
-
// 后续轮:小窗里的追问逐轮写成真实问答
|
|
191
|
-
for (let i = 0; i < turns.length; i += 1) {
|
|
192
|
-
const turn = turns[i];
|
|
193
|
-
if (!turn)
|
|
194
|
-
continue;
|
|
195
|
-
if (turn.role === 'user') {
|
|
196
|
-
appendTurn({
|
|
197
|
-
id: `sel-u-${stamp}-${i}`,
|
|
198
|
-
role: 'user',
|
|
199
|
-
source: { kind: 'user' },
|
|
200
|
-
content: contentOfTurn(turn),
|
|
201
|
-
}, turns[i + 1] && turns[i + 1]?.role === 'assistant' ? (turns[i + 1]?.text ?? '') : '(未记录)');
|
|
202
|
-
i += 1; // 助手回答已随本轮写入
|
|
203
|
-
}
|
|
204
|
-
else {
|
|
205
|
-
// 落单的助手消息(历史里没有对应提问):单独成一轮
|
|
206
|
-
appendTurn(null, turn.text);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
seeded = true;
|
|
210
|
-
}
|
|
211
|
-
// ⑤ 开场消息
|
|
212
|
-
//
|
|
213
|
-
// ⚠️ 这个 prompt **只在打包回退路径下需要** —— 那时它本身就是"背景"的载体
|
|
214
|
-
//(一整段打包文字),不发就等于背景没进去。
|
|
215
|
-
// history 模式下历史已经是真实的 user/assistant 事件,来源也写在第一条上下文消息里
|
|
216
|
-
//(`选中文字:… / 所在位置:… / 来源:划词解读小窗(来源会话 …)`),
|
|
217
|
-
// 再发一句"请用一句话确认"没有任何作用,只剩代价:
|
|
218
|
-
// · 每次升格白烧一次模型调用(升格时模型往往正忙);
|
|
219
|
-
// · 升格出来的会话顶部多一条"好的,我确认"的噪声;
|
|
220
|
-
// · 把 agent 的第 1 轮占掉 —— 用户自己问的第一句变成第 2 轮。
|
|
221
|
-
//
|
|
222
|
-
// 曾经的理由是「整段历史落盘的触发点」。**实测否掉了**(2026-10-19):
|
|
223
|
-
// 种子事件 +328ms 就写进磁盘,模型回复 +2863ms 才出现 ——
|
|
224
|
-
// 落盘靠的是 `live.append`(当场写盘),与这次 prompt 无关。
|
|
123
|
+
// A host without seeded creation gets a normal prompt carrying the
|
|
124
|
+
// background. Never inject execution events into an already-created agent.
|
|
225
125
|
if (!seeded) {
|
|
226
126
|
const opener = [
|
|
227
127
|
'【划词解读 · 升格为会话】',
|
package/lib/host/promote.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"promote.js","sourceRoot":"","sources":["../../src/host/promote.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAE1D,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,EAAE,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"promote.js","sourceRoot":"","sources":["../../src/host/promote.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { HistoryAttachment } from './history-attachments.js';
|
|
2
|
+
export interface PromoteTurn {
|
|
3
|
+
role: 'user' | 'assistant';
|
|
4
|
+
text: string;
|
|
5
|
+
attachments: HistoryAttachment[];
|
|
6
|
+
}
|
|
7
|
+
/** The durable event envelope accepted by the host's seeded agent factory. */
|
|
8
|
+
export interface PromoteSeedEvent {
|
|
9
|
+
type: string;
|
|
10
|
+
seq: number;
|
|
11
|
+
time: number;
|
|
12
|
+
data: unknown;
|
|
13
|
+
surfaceOp?: 'append';
|
|
14
|
+
}
|
|
15
|
+
/** Build balanced, contiguous history before the host constructs its agent. */
|
|
16
|
+
export declare function buildPromoteSeed({ text, label, contextText, translation, detail, sourceSessionId, turns }: {
|
|
17
|
+
text: string;
|
|
18
|
+
label: string;
|
|
19
|
+
contextText: string;
|
|
20
|
+
translation: string;
|
|
21
|
+
detail: string;
|
|
22
|
+
sourceSessionId: string;
|
|
23
|
+
turns: PromoteTurn[];
|
|
24
|
+
}): PromoteSeedEvent[];
|