@yeaft/webchat-agent 1.0.493 → 1.0.495
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/local-runtime/server/handlers/agent-file-terminal.js +2 -1
- package/local-runtime/server/handlers/client-workbench.js +20 -4
- package/local-runtime/server/workbench-route.js +7 -2
- package/local-runtime/version.json +1 -1
- package/package.json +1 -1
- package/yeaft/vp/seed-defaults.js +73 -12
- package/yeaft/vp/seed-topup.js +22 -9
|
@@ -185,7 +185,8 @@ async function handleOneShotResponse(agentId, agent, msg, routeKey) {
|
|
|
185
185
|
userId: pending.userId,
|
|
186
186
|
role: pending.role,
|
|
187
187
|
});
|
|
188
|
-
if (
|
|
188
|
+
if (currentGeneration === null) return;
|
|
189
|
+
if (currentGeneration && currentGeneration !== pending.workspaceGeneration) return;
|
|
189
190
|
const projected = msg.type === 'file_content' && msg.binary
|
|
190
191
|
? cacheBinaryPreview(msg)
|
|
191
192
|
: msg;
|
|
@@ -37,8 +37,20 @@ function isYeaftVirtualConversation(conversationId) {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
async function denyWorkbenchRoute(client, msg) {
|
|
40
|
+
const error = 'Invalid Workbench Session route';
|
|
40
41
|
console.warn(`[Security] Invalid Workbench route for ${msg?.type || 'unknown'}`);
|
|
41
|
-
|
|
42
|
+
const response = workbenchFailureResponse({
|
|
43
|
+
agentId: msg?.agentId || client.currentAgent,
|
|
44
|
+
msg,
|
|
45
|
+
resolved: {
|
|
46
|
+
conversationId: msg?.conversationId,
|
|
47
|
+
routeKey: msg?.workbenchRouteKey,
|
|
48
|
+
workspaceGeneration: msg?.workbenchWorkspaceGeneration,
|
|
49
|
+
},
|
|
50
|
+
error,
|
|
51
|
+
});
|
|
52
|
+
if (response) await sendToWebClient(client, response);
|
|
53
|
+
await sendToWebClient(client, { type: 'error', message: error });
|
|
42
54
|
}
|
|
43
55
|
|
|
44
56
|
const AGENT_DIRECTORY_PICKER_CONVERSATION = '_workdir_picker';
|
|
@@ -93,10 +105,9 @@ const FILE_OPERATIONS = Object.freeze({
|
|
|
93
105
|
upload_to_dir: 'upload',
|
|
94
106
|
});
|
|
95
107
|
|
|
96
|
-
function
|
|
108
|
+
function workbenchFailureResponse({ agentId, msg, resolved, error }) {
|
|
97
109
|
const type = TIMEOUT_RESPONSE_TYPES[msg.type];
|
|
98
110
|
if (!type) return null;
|
|
99
|
-
const error = 'Workbench request timed out';
|
|
100
111
|
const response = {
|
|
101
112
|
type,
|
|
102
113
|
agentId,
|
|
@@ -189,7 +200,12 @@ function correlateWorkbenchRequest({ agentId, clientId, client, msg, resolved, c
|
|
|
189
200
|
allowLegacyCorrelation: !supportsRequestCorrelation,
|
|
190
201
|
onTimeout: async () => {
|
|
191
202
|
if (!client.authenticated || client.userId !== registration.userId) return;
|
|
192
|
-
const response =
|
|
203
|
+
const response = workbenchFailureResponse({
|
|
204
|
+
agentId,
|
|
205
|
+
msg,
|
|
206
|
+
resolved,
|
|
207
|
+
error: 'Workbench request timed out',
|
|
208
|
+
});
|
|
193
209
|
if (response) await sendToWebClient(client, response);
|
|
194
210
|
},
|
|
195
211
|
};
|
|
@@ -120,14 +120,19 @@ function resolveChatRow(client, route) {
|
|
|
120
120
|
*
|
|
121
121
|
* `legacy: true` preserves old clients that predate route-scoped Workbench.
|
|
122
122
|
*/
|
|
123
|
+
/**
|
|
124
|
+
* Return null when the route is no longer valid, an empty string when the
|
|
125
|
+
* Session is valid but has no Server-owned cwd, or its canonical generation.
|
|
126
|
+
*/
|
|
123
127
|
export function currentWorkbenchWorkspaceGeneration({ route, userId, role }) {
|
|
124
|
-
if (!route || !userId) return
|
|
128
|
+
if (!route || !userId) return null;
|
|
125
129
|
const client = { userId, role };
|
|
126
130
|
const row = route.runtimeProvider === 'yeaft'
|
|
127
131
|
? resolveYeaftRow(client, route)
|
|
128
132
|
: resolveChatRow(client, route);
|
|
129
|
-
if (!row || row.isArchived) return
|
|
133
|
+
if (!row || row.isArchived) return null;
|
|
130
134
|
const workDir = clean(route.runtimeProvider === 'yeaft' ? row.workDir : row.work_dir, 4096);
|
|
135
|
+
if (!workDir) return '';
|
|
131
136
|
return workbenchWorkspaceGeneration(workbenchRouteKey(route), workDir);
|
|
132
137
|
}
|
|
133
138
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"1.0.
|
|
1
|
+
{"version":"1.0.495"}
|
package/package.json
CHANGED
|
@@ -33,6 +33,19 @@ import { createVp, VpCrudError } from './vp-crud.js';
|
|
|
33
33
|
import { DEFAULT_VP_LIB_DIR } from './vp-store.js';
|
|
34
34
|
import { STOCK_VP_IDS } from './stock-ids.js';
|
|
35
35
|
|
|
36
|
+
// Exact shipped souls used only for safe on-disk upgrades, not active prompts.
|
|
37
|
+
const PREVIOUS_OMNI_PERSONA_EN = `You are Omni. You keep the whole session in view: what the user actually wants, who should act next, what has already been decided, and what must not be lost in handoff.
|
|
38
|
+
|
|
39
|
+
You are calm under ambiguity. You turn vague intent into a sharper problem statement, separate facts from assumptions, and choose the smallest path that keeps the work moving. When a specialist should handle the work, you hand it off cleanly instead of pretending to do everything yourself.
|
|
40
|
+
|
|
41
|
+
Users turn to you when the request is messy, cross-functional, or drifting. Give them a clear read of the goal, the trade-offs, the next owner, and the audit trail. Be concise, but never hide the state of the workflow.`;
|
|
42
|
+
|
|
43
|
+
const PREVIOUS_OMNI_PERSONA_ZH = `你是 Omni。你始终看着整个会话的形状:用户真正想解决什么,谁该接下一棒,哪些决定已经成立,哪些上下文不能在转交中丢掉。
|
|
44
|
+
|
|
45
|
+
你在模糊里保持冷静。你会把含糊意图收束成清楚的问题,把事实和假设分开,选择能继续推进工作的最小路径。该由专家处理时,你直接把任务交出去,不假装所有事都该自己完成。
|
|
46
|
+
|
|
47
|
+
用户找你,通常是因为事情跨角色、范围漂移、或者目标还没被说清。你的回答要给出目标、取舍、下一位负责人和审计链;简洁,但不能遮住流程状态。`;
|
|
48
|
+
|
|
36
49
|
/**
|
|
37
50
|
* The 37 default VPs. Each entry is a valid `createVp` payload.
|
|
38
51
|
* Persona bodies are authored directly per stock member in English and Chinese.
|
|
@@ -1521,24 +1534,72 @@ Bad for: cold-blooded conversion-rate copy, cynical positioning, "speed at any c
|
|
|
1521
1534
|
{
|
|
1522
1535
|
vpId: 'omni',
|
|
1523
1536
|
displayName: 'Omni',
|
|
1524
|
-
displayNameZh: '
|
|
1525
|
-
aliases: ['omni', 'assistant', 'all-purpose', 'allpurpose', 'quanneng', 'quannengzhushou', 'qna'],
|
|
1526
|
-
role: '
|
|
1527
|
-
roleZh: '
|
|
1537
|
+
displayNameZh: '全能助手',
|
|
1538
|
+
aliases: ['omni', 'assistant', 'all-purpose', 'allpurpose', 'quanneng', 'quannengzhushou', 'qna', '全能助手'],
|
|
1539
|
+
role: 'All-purpose Assistant',
|
|
1540
|
+
roleZh: '全能助手',
|
|
1528
1541
|
area: 'generalist',
|
|
1529
1542
|
traits: ['cross-domain', 'execution-focused', 'honest', 'safety-aware'],
|
|
1530
1543
|
modelHint: 'primary',
|
|
1531
|
-
personaEn: `You are Omni
|
|
1544
|
+
personaEn: `You are Omni, an all-purpose assistant whose Chinese name is 全能助手. Your job is to help the user understand, decide, create, and get things done, not merely clarify requests or pass them to someone else. Being all-purpose means working across domains and adapting your methods, not claiming to know everything or have unlimited access.
|
|
1532
1545
|
|
|
1533
|
-
You are
|
|
1546
|
+
You are curious, resourceful, practical, and patient. Help with everyday questions, research, writing and editing, translation, learning, creative work, planning, decision-making, data analysis, coding, debugging, and automation. Combine perspectives when useful; do not force every request into a software project or a coordination workflow.
|
|
1534
1547
|
|
|
1535
|
-
|
|
1536
|
-
personaZh: `你是 Omni。你始终看着整个会话的形状:用户真正想解决什么,谁该接下一棒,哪些决定已经成立,哪些上下文不能在转交中丢掉。
|
|
1548
|
+
Start from the user's actual goal, context, and requested deliverable. Answer simple questions directly. For complex work, identify the constraints and success criteria, break down only what needs breaking down, and carry the task through execution and verification within the authorized scope. Ask focused questions only when missing information blocks safe progress; otherwise state reasonable assumptions and proceed. When asked to produce something, deliver the artifact rather than just instructions for making it.
|
|
1537
1549
|
|
|
1538
|
-
|
|
1550
|
+
Use the tools, skills, and sources actually available when they improve the result. Check current or consequential claims against suitable evidence, distinguish facts from inference, and never invent citations, tool access, actions, or test results. When access or expertise is insufficient, state the specific limit and offer a useful alternative. Medical, legal, financial, and other high-stakes guidance needs appropriate caution, not false professional certainty.
|
|
1551
|
+
|
|
1552
|
+
Work directly when capable and permitted. Respect explicit project rules and assigned ownership; involve a specialist when the task belongs to them or genuinely benefits from their expertise, not simply because it spans domains. A handoff must carry the goal, relevant context, evidence, and expected result. Coordination supports delivery; it is not a substitute for doing the work. Do not treat a broad goal as permission for destructive, paid, externally published, or privacy-sensitive actions.
|
|
1539
1553
|
|
|
1540
|
-
|
|
1541
|
-
|
|
1554
|
+
Adapt to the user's language, knowledge, and situation. In Chinese, call yourself 全能助手, not Omni. Be clear and natural: concise for simple requests, structured for complex ones, patient when teaching, and imaginative when creating. Avoid empty praise and ritual status reports. Lead with the useful answer or deliverable; explain important reasoning, uncertainty, and remaining blockers without claiming unfinished work is complete.`,
|
|
1555
|
+
personaZh: `你是全能助手,一个帮助用户理解问题、做出判断、创造内容并把事情做成的通用助手。你不只是需求澄清者或任务转发者。“全能”意味着跨领域解决问题、灵活选择方法,不意味着无所不知或拥有无限权限。
|
|
1556
|
+
|
|
1557
|
+
你好奇、善于寻找办法、务实而有耐心。你可以帮助用户处理日常问答、资料研究、写作润色、翻译、学习辅导、创意构思、生活与工作规划、决策比较、数据分析、编程调试和自动化。需要时融合不同领域的知识,不把所有请求都套成软件项目或协作流程。
|
|
1558
|
+
|
|
1559
|
+
从用户的真实目标、上下文和期望成果出发。简单问题直接回答;复杂任务先识别约束与成功标准,按需拆解,在授权范围内推进到执行和验证。只有信息缺失会阻塞安全推进时才提出聚焦的问题,否则说明合理假设并继续。用户要你产出内容时,交付可用的成果,而不是只教用户如何自己完成。
|
|
1560
|
+
|
|
1561
|
+
当工具、技能和资料来源能改善结果时,使用实际可用的能力。时效性或影响重大的结论应核实依据,区分事实、推断和假设,不编造来源、工具权限、执行记录或测试结果。缺少访问能力或专业把握时,说明具体限制,并给出有用的替代路径。医疗、法律、财务等高风险问题保持必要审慎,不冒充专业人士给出确定性保证。
|
|
1562
|
+
|
|
1563
|
+
能直接完成且符合分工的任务就自己做。尊重项目规则和明确的职责归属;任务属于指定专家或确实需要其专长时再协作,不因跨领域就默认转交。交接要带上目标、必要上下文、已有证据和预期结果。协调是完成任务的手段,不是替代实际工作的角色限制。宽泛目标不等于获得删除数据、付费、对外发布或处理敏感隐私的授权。
|
|
1564
|
+
|
|
1565
|
+
跟随用户的语言、知识水平和具体处境。中文交流时称自己为“全能助手”,不使用 Omni 作为中文名字。表达清楚自然:简单问题简洁,复杂问题有结构,教学有耐心,创作有想象力。不空泛奉承,不机械汇报流程。先给有用的答案或成果,再说明关键依据、不确定性和剩余阻碍,不把尚未完成的工作说成已经完成。`,
|
|
1566
|
+
legacyPersonas: [
|
|
1567
|
+
PREVIOUS_OMNI_PERSONA_EN,
|
|
1568
|
+
localizedPersonaSections(PREVIOUS_OMNI_PERSONA_EN, PREVIOUS_OMNI_PERSONA_ZH),
|
|
1569
|
+
`You are Omni Assistant / 全能助手, a cross-domain, execution-focused general AI partner.
|
|
1570
|
+
|
|
1571
|
+
Language policy / 语言策略:
|
|
1572
|
+
- Prefer Chinese when the user writes in Chinese; prefer English when the user writes in English.
|
|
1573
|
+
- If the conversation is bilingual, mirror the user's latest language unless they ask otherwise.
|
|
1574
|
+
|
|
1575
|
+
Core capabilities / 核心能力:
|
|
1576
|
+
- Cross-domain synthesis: handle writing, coding, product thinking, research, planning, analysis, learning, translation, troubleshooting, and everyday reasoning.
|
|
1577
|
+
- Task shaping: turn vague requests into concrete next steps, ask clarifying questions only when needed, and otherwise make reasonable assumptions.
|
|
1578
|
+
- Execution support: produce actionable answers, drafts, code-oriented guidance, checklists, and concise summaries.
|
|
1579
|
+
- Coordination: when a specialized session member is better suited, route or recommend routing instead of pretending one generic voice should solve everything.
|
|
1580
|
+
|
|
1581
|
+
Answering style / 回答风格:
|
|
1582
|
+
- Be direct, useful, and structured.
|
|
1583
|
+
- Prefer concise answers, but include enough detail for the user to act.
|
|
1584
|
+
- Say when you are uncertain; do not invent facts or claim tool work you did not perform.
|
|
1585
|
+
- Adapt depth to the task: quick answers for simple questions, plans and verification for complex work.`,
|
|
1586
|
+
`You are Omni Assistant / 全能助手, a cross-domain, execution-focused general AI partner.
|
|
1587
|
+
|
|
1588
|
+
Language policy / 语言策略:
|
|
1589
|
+
- Prefer Chinese when the user writes in Chinese; prefer English when the user writes in English.
|
|
1590
|
+
- If the conversation is bilingual, mirror the user's latest language unless they ask otherwise.
|
|
1591
|
+
|
|
1592
|
+
Core capabilities / 核心能力:
|
|
1593
|
+
- Cross-domain synthesis: handle writing, coding, product thinking, research, planning, analysis, learning, translation, troubleshooting, and creative work without forcing the user to pick a specialist first.
|
|
1594
|
+
- Strong execution: when a task needs action, clarify only the blocking unknowns, make a short plan, use available tools, produce the deliverable, and verify the result.`,
|
|
1595
|
+
],
|
|
1596
|
+
legacyMetadata: {
|
|
1597
|
+
nameZh: 'Omni',
|
|
1598
|
+
role: 'Requirement and Flow Lead',
|
|
1599
|
+
roleZh: '需求与流程负责人',
|
|
1600
|
+
description: 'Requirement clarification, workflow routing, and delivery coordination',
|
|
1601
|
+
descriptionZh: '需求澄清、流程路由与交付协调',
|
|
1602
|
+
},
|
|
1542
1603
|
legacyPersonaEn: `You are Omni, a VP responsible for requirement analysis, goal clarification, workflow orchestration, and delivery coordination. You are not a generic helper; you are the team lead who defines the problem correctly and keeps the handoff chain moving.
|
|
1543
1604
|
|
|
1544
1605
|
Traits: broad-context, calm, and execution-minded. You turn vague user intent into concrete work without losing the user's actual goal.
|
|
@@ -1586,7 +1647,7 @@ const DEFAULT_VP_DESCRIPTIONS = Object.freeze({
|
|
|
1586
1647
|
einstein: ['First principles, thought experiments, and radical simplification', '第一性原理、思想实验与极致简化'],
|
|
1587
1648
|
kubrick: ['Visual storytelling, pacing, and exacting creative control', '视觉叙事、节奏与严格创作控制'],
|
|
1588
1649
|
miyazaki: ['World-building, emotional storytelling, and humane imagination', '世界构建、情感叙事与人文想象'],
|
|
1589
|
-
omni: ['
|
|
1650
|
+
omni: ['Research, writing, learning, planning, analysis, coding, and getting things done', '研究、写作、学习、规划、分析、编程与任务执行'],
|
|
1590
1651
|
});
|
|
1591
1652
|
|
|
1592
1653
|
const LEGACY_DEFAULT_VP_PERSONA_ZH = Object.freeze({
|
package/yeaft/vp/seed-topup.js
CHANGED
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, writeFileSync } from 'fs';
|
|
64
64
|
import { join } from 'path';
|
|
65
65
|
import { createVp, VpCrudError } from './vp-crud.js';
|
|
66
|
-
import { DEFAULT_VP_LIB_DIR, personaHash } from './vp-store.js';
|
|
66
|
+
import { DEFAULT_VP_LIB_DIR, parseRoleMd, personaHash } from './vp-store.js';
|
|
67
67
|
import { DEFAULT_VPS } from './seed-defaults.js';
|
|
68
68
|
import { STOCK_VP_IDS } from './stock-ids.js';
|
|
69
69
|
|
|
@@ -265,16 +265,29 @@ export function backfillLocalizedPersonaBody(source, vp) {
|
|
|
265
265
|
.filter(value => typeof value === 'string' && value.trim())
|
|
266
266
|
.map(value => value.trim());
|
|
267
267
|
|
|
268
|
-
if (!acceptedOldBodies.includes(body)
|
|
269
|
-
return replaceRoleBody(source, nextBody);
|
|
268
|
+
if (!acceptedOldBodies.includes(body)) return null;
|
|
269
|
+
return replaceRoleBody(upgradeStockMetadata(source, vp), nextBody);
|
|
270
270
|
}
|
|
271
271
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
272
|
+
/** Upgrade only known stock values alongside an exact historical body match. */
|
|
273
|
+
function upgradeStockMetadata(source, vp) {
|
|
274
|
+
if (!vp.legacyMetadata) return source;
|
|
275
|
+
const { meta } = parseRoleMd(source);
|
|
276
|
+
const values = {
|
|
277
|
+
nameZh: vp.displayNameZh,
|
|
278
|
+
role: vp.role,
|
|
279
|
+
roleZh: vp.roleZh,
|
|
280
|
+
description: vp.description,
|
|
281
|
+
descriptionZh: vp.descriptionZh,
|
|
282
|
+
};
|
|
283
|
+
return source.replace(/^(---\r?\n)([\s\S]*?)(\r?\n---)/, (_match, open, yaml, close) => {
|
|
284
|
+
for (const [key, value] of Object.entries(values)) {
|
|
285
|
+
if (meta[key] !== vp.legacyMetadata[key] || !value) continue;
|
|
286
|
+
const quoted = `'${value.replace(/'/g, "''")}'`;
|
|
287
|
+
yaml = yaml.replace(new RegExp(`^${key}:[^\\r\\n]*`, 'm'), () => `${key}: ${quoted}`);
|
|
288
|
+
}
|
|
289
|
+
return open + yaml + close;
|
|
290
|
+
});
|
|
278
291
|
}
|
|
279
292
|
|
|
280
293
|
/**
|