@yeaft/webchat-agent 1.0.328 → 1.0.329

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.
@@ -1 +1 @@
1
- {"version":"1.0.328"}
1
+ {"version":"1.0.329"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yeaft/webchat-agent",
3
- "version": "1.0.328",
3
+ "version": "1.0.329",
4
4
  "description": "Remote worker agent for Yeaft Web Code Agent — connects the native Yeaft engine, CLI providers, and workbench tools",
5
5
  "main": "index.js",
6
6
  "type": "module",
package/yeaft/engine.js CHANGED
@@ -1201,13 +1201,14 @@ export class Engine {
1201
1201
  * @param {object} [args.activeScope] — DESIGN-PROMPT §3 ④ structured scope summary
1202
1202
  * @param {string} [args.sessionAnnouncement]
1203
1203
  * @param {string} [args.projectInstruction] — server-managed instruction shared by Project Sessions
1204
+ * @param {string} [args.projectLabel] — current Project name and id for prompt attribution
1204
1205
  * @param {string} [args.workCenterInstructions] — frozen Agent-level Work Center policy
1205
1206
  * @param {string} [args.projectDoc] — resolved CLAUDE.md / AGENTS.md text (already truncated)
1206
1207
  * @param {object} [args.taskCtx] — legacy task-context sub-block (optional)
1207
1208
  * @param {string} [args.explicitSkillName] — leading /skill:<name> command, if present
1208
1209
  * @returns {string}
1209
1210
  */
1210
- #buildSystemPrompt({ prompt, memoryInjection, vpPersona, activeScope, sessionAnnouncement, projectInstruction, workCenterInstructions, projectDoc, taskCtx, activeTasks, explicitSkillName, resolvedSkillContent = null } = {}) {
1211
+ #buildSystemPrompt({ prompt, memoryInjection, vpPersona, activeScope, sessionAnnouncement, projectInstruction, projectLabel, workCenterInstructions, projectDoc, taskCtx, activeTasks, explicitSkillName, resolvedSkillContent = null } = {}) {
1211
1212
  // Skill selection is normally resolved once by #runQuery so the prompt and
1212
1213
  // emitted protocol events describe the exact same skills. Keep the local
1213
1214
  // fallback for internal callers that do not need selection events.
@@ -1235,6 +1236,7 @@ export class Engine {
1235
1236
  activeScope,
1236
1237
  sessionAnnouncement,
1237
1238
  projectInstruction,
1239
+ projectLabel,
1238
1240
  workCenterInstructions,
1239
1241
  projectDoc,
1240
1242
  runtimePlatform: getRuntimePlatformInfo(),
@@ -1420,6 +1422,9 @@ export class Engine {
1420
1422
  projectSessionIds: Array.isArray(vpCtx?.projectSessionIds)
1421
1423
  ? vpCtx.projectSessionIds.slice()
1422
1424
  : [],
1425
+ projectLabel: typeof vpCtx?.projectLabel === 'string'
1426
+ ? vpCtx.projectLabel
1427
+ : '',
1423
1428
  projectInstruction: typeof vpCtx?.projectInstruction === 'string'
1424
1429
  ? vpCtx.projectInstruction
1425
1430
  : '',
@@ -1967,7 +1972,7 @@ export class Engine {
1967
1972
  }
1968
1973
  }
1969
1974
 
1970
- async *#queryLifecycle({ prompt, promptParts = null, messages = [], signal, userEffort = null, scenario = 'chat', vpPersona, router, senderVpId, inboundEnvelope, taskId, taskMembers, sessionId, sessionMembers, projectSessionIds = null, projectInstruction = '', sessionTopics = null, vpPlan, sessionAnnouncement, workCenterInstructions, workDir, userAlreadyPersisted = false, getCurrentTodos = null, setCurrentTodos = null, askUser = null, threadId = MAIN_THREAD_ID, vpTurnId = null, drainPendingUserMessages = null, prepareProviderRequest = null, startProviderRequest = null, finishProviderRequest = null, failProviderRequest = null, closePendingUserInput = null, collabToolPolicy = null } = {}) {
1975
+ async *#queryLifecycle({ prompt, promptParts = null, messages = [], signal, userEffort = null, scenario = 'chat', vpPersona, router, senderVpId, inboundEnvelope, taskId, taskMembers, sessionId, sessionMembers, projectSessionIds = null, projectInstruction = '', projectLabel = '', sessionTopics = null, vpPlan, sessionAnnouncement, workCenterInstructions, workDir, userAlreadyPersisted = false, getCurrentTodos = null, setCurrentTodos = null, askUser = null, threadId = MAIN_THREAD_ID, vpTurnId = null, drainPendingUserMessages = null, prepareProviderRequest = null, startProviderRequest = null, finishProviderRequest = null, failProviderRequest = null, closePendingUserInput = null, collabToolPolicy = null } = {}) {
1971
1976
  if (!prompt || typeof prompt !== 'string' || !prompt.trim()) {
1972
1977
  const error = new Error('prompt is required and must be a non-empty string');
1973
1978
  yield {
@@ -2053,7 +2058,7 @@ export class Engine {
2053
2058
  };
2054
2059
  try {
2055
2060
  this.#currentThreadId = threadId || MAIN_THREAD_ID;
2056
- yield* this.#runQuery({ prompt: effectivePrompt, promptParts: effectivePromptParts, messages, signal: runSignal, userEffort: effectiveUserEffort, scenario, vpPersona, router, senderVpId, inboundEnvelope, taskId, taskMembers, sessionId, sessionMembers, projectSessionIds, projectInstruction, sessionTopics, vpPlan, sessionAnnouncement, workCenterInstructions, workDir, userAlreadyPersisted, getCurrentTodos, setCurrentTodos, askUser, threadId: this.#currentThreadId, vpTurnId, drainPendingUserMessages, prepareProviderRequest, startProviderRequest, finishProviderRequest, failProviderRequest, closePendingUserInput, collabToolPolicy: effectiveCollabToolPolicy, explicitSkillName: parsedSkill.skillName, retryLifecycle });
2061
+ yield* this.#runQuery({ prompt: effectivePrompt, promptParts: effectivePromptParts, messages, signal: runSignal, userEffort: effectiveUserEffort, scenario, vpPersona, router, senderVpId, inboundEnvelope, taskId, taskMembers, sessionId, sessionMembers, projectSessionIds, projectInstruction, projectLabel, sessionTopics, vpPlan, sessionAnnouncement, workCenterInstructions, workDir, userAlreadyPersisted, getCurrentTodos, setCurrentTodos, askUser, threadId: this.#currentThreadId, vpTurnId, drainPendingUserMessages, prepareProviderRequest, startProviderRequest, finishProviderRequest, failProviderRequest, closePendingUserInput, collabToolPolicy: effectiveCollabToolPolicy, explicitSkillName: parsedSkill.skillName, retryLifecycle });
2057
2062
  } finally {
2058
2063
  // Closing the async generator at a visible retry boundary means the
2059
2064
  // continuation never reached a provider. Keep it out of history and
@@ -2101,7 +2106,7 @@ export class Engine {
2101
2106
  * in a try/finally without indenting the whole loop.
2102
2107
  * @private
2103
2108
  */
2104
- async *#runQuery({ prompt, promptParts = null, messages, signal, userEffort = null, scenario = 'chat', vpPersona, router, senderVpId, inboundEnvelope, taskId, taskMembers, sessionId, sessionMembers, projectSessionIds = null, projectInstruction = '', sessionTopics = null, vpPlan, sessionAnnouncement, workCenterInstructions, workDir, userAlreadyPersisted = false, getCurrentTodos = null, setCurrentTodos = null, askUser = null, threadId = MAIN_THREAD_ID, vpTurnId = null, drainPendingUserMessages = null, prepareProviderRequest = null, startProviderRequest = null, finishProviderRequest = null, failProviderRequest = null, closePendingUserInput = null, collabToolPolicy = null, explicitSkillName = null, retryLifecycle }) {
2109
+ async *#runQuery({ prompt, promptParts = null, messages, signal, userEffort = null, scenario = 'chat', vpPersona, router, senderVpId, inboundEnvelope, taskId, taskMembers, sessionId, sessionMembers, projectSessionIds = null, projectInstruction = '', projectLabel = '', sessionTopics = null, vpPlan, sessionAnnouncement, workCenterInstructions, workDir, userAlreadyPersisted = false, getCurrentTodos = null, setCurrentTodos = null, askUser = null, threadId = MAIN_THREAD_ID, vpTurnId = null, drainPendingUserMessages = null, prepareProviderRequest = null, startProviderRequest = null, finishProviderRequest = null, failProviderRequest = null, closePendingUserInput = null, collabToolPolicy = null, explicitSkillName = null, retryLifecycle }) {
2105
2110
 
2106
2111
  const effectiveCollabToolPolicy = collabToolPolicy === COLLAB_TOOL_POLICY.SINGLE_VP || collabToolPolicy === COLLAB_TOOL_POLICY.MULTI_VP
2107
2112
  ? collabToolPolicy
@@ -2303,6 +2308,7 @@ export class Engine {
2303
2308
  activeScope,
2304
2309
  sessionAnnouncement,
2305
2310
  projectInstruction,
2311
+ projectLabel,
2306
2312
  workCenterInstructions,
2307
2313
  projectDoc,
2308
2314
  activeTasks,
@@ -3706,6 +3712,7 @@ export class Engine {
3706
3712
  sessionId: runtimeSessionId,
3707
3713
  projectSessionIds,
3708
3714
  projectInstruction,
3715
+ projectLabel,
3709
3716
  threadId: runtimeThreadId,
3710
3717
  inboundEnvelope,
3711
3718
  taskId,
package/yeaft/prompts.js CHANGED
@@ -205,7 +205,9 @@ const PROMPTS = {
205
205
  multiVpRoutingHeader: '## multi_vp_routing',
206
206
  sessionAnnouncementHeader: '[Session Announcement]',
207
207
  projectInstructionHeader: '[Project Instruction]',
208
- projectInstructionIntro: 'This server-managed instruction applies to every Session in the current Project.',
208
+ projectInstructionIntro: (projectLabel) => projectLabel
209
+ ? `The current Session belongs to Project ${projectLabel}. The unified instruction for this Project is:`
210
+ : 'The current Session belongs to the current Project. The unified instruction for this Project is:',
209
211
  workCenterInstructionsHeader: '[Work Center Agent Instructions]',
210
212
  workCenterInstructionsIntro: 'These Agent-level instructions apply to every Action in this WorkItem. Follow them unless they conflict with system/tool safety rules, the authoritative project document, or the WorkItem contract.',
211
213
  // Project-doc (CLAUDE.md / AGENTS.md) header + one-liner intro. Both
@@ -229,7 +231,9 @@ const PROMPTS = {
229
231
  multiVpRoutingHeader: '## multi_vp_routing',
230
232
  sessionAnnouncementHeader: '[会话公告]',
231
233
  projectInstructionHeader: '[Project 指令]',
232
- projectInstructionIntro: '这是服务器管理的 Project 级指令,适用于当前 Project 内的所有 Session。',
234
+ projectInstructionIntro: (projectLabel) => projectLabel
235
+ ? `当前 Session 隶属于 Project ${projectLabel}。当前 Project 的统一 instruction 是:`
236
+ : '当前 Session 隶属于当前 Project。当前 Project 的统一 instruction 是:',
233
237
  workCenterInstructionsHeader: '[Work Center Agent 指令]',
234
238
  workCenterInstructionsIntro: '这些 Agent 级指令作用于当前 Work Item 的每个 Action。除非与系统/工具安全规则、权威项目文档或 Work Item 契约冲突,否则必须遵循。',
235
239
  // 项目文档块:CLAUDE.md / AGENTS.md(与 Codex 通用命名兼容)。
@@ -302,6 +306,7 @@ export function normalizePromptLanguage(language) {
302
306
  * vpPersona?: object,
303
307
  * sessionAnnouncement?: string,
304
308
  * projectInstruction?: string,
309
+ * projectLabel?: string,
305
310
  * workCenterInstructions?: string,
306
311
  * projectDoc?: string,
307
312
  * }} params
@@ -317,6 +322,7 @@ export function buildSystemPrompt({
317
322
  vpPersona,
318
323
  sessionAnnouncement = '',
319
324
  projectInstruction = '',
325
+ projectLabel = '',
320
326
  workCenterInstructions = '',
321
327
  projectDoc = '',
322
328
  runtimePlatform,
@@ -366,7 +372,10 @@ export function buildSystemPrompt({
366
372
  const projectInstructionText = typeof projectInstruction === 'string' ? projectInstruction.trim() : '';
367
373
  if (projectInstructionText) {
368
374
  const header = lang.projectInstructionHeader || '[Project Instruction]';
369
- const intro = lang.projectInstructionIntro || '';
375
+ const normalizedProjectLabel = typeof projectLabel === 'string' ? projectLabel.trim() : '';
376
+ const intro = typeof lang.projectInstructionIntro === 'function'
377
+ ? lang.projectInstructionIntro(normalizedProjectLabel)
378
+ : '';
370
379
  parts.push(`${header}\n${intro ? `${intro}\n\n` : ''}${projectInstructionText}`);
371
380
  }
372
381
 
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * @param {object} agent
8
8
  * @param {string} prompt
9
- * @param {{ projectSessionIds?: string[], projectInstruction?: string }} projectContext
9
+ * @param {{ projectSessionIds?: string[], projectLabel?: string, projectInstruction?: string }} projectContext
10
10
  */
11
11
  export function enqueueSubAgentPrompt(agent, prompt, projectContext = {}) {
12
12
  if (!Array.isArray(agent.pendingPrompts)) agent.pendingPrompts = [];
@@ -15,6 +15,9 @@ export function enqueueSubAgentPrompt(agent, prompt, projectContext = {}) {
15
15
  projectSessionIds: Array.isArray(projectContext.projectSessionIds)
16
16
  ? projectContext.projectSessionIds.slice()
17
17
  : [],
18
+ projectLabel: typeof projectContext.projectLabel === 'string'
19
+ ? projectContext.projectLabel
20
+ : '',
18
21
  projectInstruction: typeof projectContext.projectInstruction === 'string'
19
22
  ? projectContext.projectInstruction
20
23
  : '',
@@ -125,6 +125,7 @@ export function isRestrictedToolName(name) {
125
125
  * parentVpId?: string,
126
126
  * parentSessionId?: string|null,
127
127
  * projectSessionIds?: string[],
128
+ * projectLabel?: string,
128
129
  * projectInstruction?: string,
129
130
  * parentThreadId?: string|null,
130
131
  * parentVpPersona?: object,
@@ -325,6 +326,9 @@ async function driveSubAgent(agent, subEngine, vpPersona, deps) {
325
326
  projectSessionIds: Array.isArray(deps.projectSessionIds)
326
327
  ? deps.projectSessionIds.slice()
327
328
  : [],
329
+ projectLabel: typeof deps.projectLabel === 'string'
330
+ ? deps.projectLabel
331
+ : '',
328
332
  projectInstruction: typeof deps.projectInstruction === 'string'
329
333
  ? deps.projectInstruction
330
334
  : '',
@@ -336,6 +340,9 @@ async function driveSubAgent(agent, subEngine, vpPersona, deps) {
336
340
  projectSessionIds: Array.isArray(entry.projectSessionIds)
337
341
  ? entry.projectSessionIds.slice()
338
342
  : [],
343
+ projectLabel: typeof entry.projectLabel === 'string'
344
+ ? entry.projectLabel
345
+ : '',
339
346
  projectInstruction: typeof entry.projectInstruction === 'string'
340
347
  ? entry.projectInstruction
341
348
  : '',
@@ -407,6 +414,7 @@ async function driveSubAgent(agent, subEngine, vpPersona, deps) {
407
414
  vpPersona,
408
415
  sessionId: agent.parentSessionId || deps.parentSessionId || null,
409
416
  projectSessionIds: queuedPrompt.projectSessionIds,
417
+ projectLabel: queuedPrompt.projectLabel,
410
418
  projectInstruction: queuedPrompt.projectInstruction,
411
419
  });
412
420
  for await (const evt of stream) {
@@ -114,6 +114,7 @@ SpawnAgent -> (PromptAgent <-> WaitAgent)+ -> CloseAgent -> 最终回复给用
114
114
  // driver out of its idle wait and starts a new turn.
115
115
  enqueueSubAgentPrompt(agent, message, {
116
116
  projectSessionIds: ctx?.parentEngineDeps?.projectSessionIds,
117
+ projectLabel: ctx?.parentEngineDeps?.projectLabel,
117
118
  projectInstruction: ctx?.parentEngineDeps?.projectInstruction,
118
119
  });
119
120
  agent.messages.push({
@@ -5276,6 +5276,9 @@ async function runVpTurn({ prompt, promptParts = null, sessionId, vpId, threadId
5276
5276
  || legacyProjectContext(ctx.CONFIG?.yeaftDir, sessionId);
5277
5277
  const projectSessionIds = projectContext?.sessionIds || [];
5278
5278
  queryOpts.projectSessionIds = projectSessionIds;
5279
+ queryOpts.projectLabel = projectContext?.projectName
5280
+ ? `${projectContext.projectName} (${projectContext.projectId})`
5281
+ : (projectContext?.projectId || '');
5279
5282
  queryOpts.projectInstruction = projectContext?.projectInstruction || '';
5280
5283
  // Related Session summaries now enter through Engine's single AMS
5281
5284
  // memory outlet. Keep this announcement limited to Project identity and
@@ -6527,6 +6530,9 @@ export function handleYeaftSubAgentPrompt(msg) {
6527
6530
  || legacyProjectContext(ctx.CONFIG?.yeaftDir, sessionId);
6528
6531
  enqueueSubAgentPrompt(agent, message, {
6529
6532
  projectSessionIds: projectContext?.sessionIds,
6533
+ projectLabel: projectContext?.projectName
6534
+ ? `${projectContext.projectName} (${projectContext.projectId})`
6535
+ : (projectContext?.projectId || ''),
6530
6536
  projectInstruction: projectContext?.projectInstruction,
6531
6537
  });
6532
6538
  if (!Array.isArray(agent.messages)) agent.messages = [];