@yeaft/webchat-agent 1.0.507 → 1.0.509

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.
@@ -393,7 +393,7 @@ export async function handleMessage(msg) {
393
393
  // LLM configuration (read/write this agent's ~/.yeaft/config.json)
394
394
  case 'get_llm_config': {
395
395
  const config = getLlmConfig(ctx.CONFIG?.yeaftDir);
396
- sendToServer({ type: 'llm_config', ...config });
396
+ sendToServer({ type: 'llm_config', requestId: msg.requestId, ...config });
397
397
  break;
398
398
  }
399
399
 
@@ -299,6 +299,7 @@ export async function handleAgentSync(agentId, agent, msg) {
299
299
  await sendToWebClient(client, {
300
300
  type: 'llm_config',
301
301
  agentId,
302
+ requestId: msg.requestId,
302
303
  providers: msg.providers,
303
304
  primaryModel: msg.primaryModel,
304
305
  fastModel: msg.fastModel,
@@ -68,6 +68,25 @@ function emptyYeaftManagedSkillResult(error = null) {
68
68
  };
69
69
  }
70
70
 
71
+ async function sendAskUserAgentUnavailable(client, msg, agentId) {
72
+ await sendToWebClient(client, {
73
+ type: 'yeaft_output',
74
+ agentId: agentId || null,
75
+ requestId: msg.requestId || null,
76
+ conversationId: msg.conversationId ?? null,
77
+ ...(msg.sessionId != null ? { sessionId: msg.sessionId } : {}),
78
+ ...(msg.vpId != null ? { vpId: msg.vpId } : {}),
79
+ ...(msg.turnId != null ? { turnId: msg.turnId } : {}),
80
+ ...(msg.threadId != null ? { threadId: msg.threadId } : {}),
81
+ event: {
82
+ type: 'ask_user_answer_rejected',
83
+ requestId: msg.requestId || null,
84
+ toolCallId: msg.toolCallId || null,
85
+ reason: 'agent_unavailable',
86
+ },
87
+ });
88
+ }
89
+
71
90
  async function sendVpSnapshotError(client, msg, error) {
72
91
  await sendToWebClient(client, {
73
92
  type: 'yeaft_output',
@@ -1663,7 +1682,9 @@ export async function handleClientConversation(clientId, client, msg, checkAgent
1663
1682
  });
1664
1683
  }
1665
1684
  if (!relayAgentId) {
1666
- if (relayType === 'yeaft_fetch_tool_stats') {
1685
+ if (relayType === 'yeaft_ask_user_answer') {
1686
+ await sendAskUserAgentUnavailable(client, msg, relayAgentId);
1687
+ } else if (relayType === 'yeaft_fetch_tool_stats') {
1667
1688
  await sendToWebClient(client, emptyYeaftToolStats('No agent selected.'));
1668
1689
  } else if (relayType === 'yeaft_dream_trigger') {
1669
1690
  await sendToWebClient(client, skippedYeaftDreamResult(msg, 'no-agent-selected'));
@@ -1678,7 +1699,9 @@ export async function handleClientConversation(clientId, client, msg, checkAgent
1678
1699
  return true; // swallow silently for legacy fire-and-forget messages
1679
1700
  }
1680
1701
  if (!await checkAgentAccess(relayAgentId)) {
1681
- if (relayType === 'yeaft_fetch_tool_stats') {
1702
+ if (relayType === 'yeaft_ask_user_answer') {
1703
+ await sendAskUserAgentUnavailable(client, msg, relayAgentId);
1704
+ } else if (relayType === 'yeaft_fetch_tool_stats') {
1682
1705
  await sendToWebClient(client, emptyYeaftToolStats('Agent is not available.'));
1683
1706
  } else if (relayType === 'yeaft_dream_trigger') {
1684
1707
  await sendToWebClient(client, skippedYeaftDreamResult(msg, 'agent-not-available'));
@@ -1707,6 +1730,10 @@ export async function handleClientConversation(clientId, client, msg, checkAgent
1707
1730
  }
1708
1731
  const relayAgent = agents.get(relayAgentId);
1709
1732
  if (!relayAgent || relayAgent.ws?.readyState !== 1) {
1733
+ if (relayType === 'yeaft_ask_user_answer') {
1734
+ await sendAskUserAgentUnavailable(client, msg, relayAgentId);
1735
+ return true;
1736
+ }
1710
1737
  if (relayType === 'yeaft_fetch_tool_stats') {
1711
1738
  await sendToWebClient(client, emptyYeaftToolStats('Agent is offline.'));
1712
1739
  return true;
@@ -1728,6 +1755,15 @@ export async function handleClientConversation(clientId, client, msg, checkAgent
1728
1755
  // router is the authoritative consumer of the payload shape.
1729
1756
  const { agentId: _discard, ...rest } = msg;
1730
1757
  rest.type = relayType;
1758
+ if (relayType === 'yeaft_ask_user_answer') {
1759
+ rest._requestClientId = clientId;
1760
+ let dispatched = false;
1761
+ try {
1762
+ dispatched = await forwardToAgent(relayAgentId, rest);
1763
+ } catch { /* the submitting card needs a correlated failure, not a generic error */ }
1764
+ if (!dispatched) await sendAskUserAgentUnavailable(client, msg, relayAgentId);
1765
+ return true;
1766
+ }
1731
1767
  // Direct catalog replies are request-scoped. Carry the browser client
1732
1768
  // identity through the Agent so another owner tab cannot accidentally
1733
1769
  // consume a response for this picker request.
@@ -244,7 +244,7 @@ export async function handleClientMisc(clientId, client, msg, checkAgentAccess)
244
244
  const llmAgentId = msg.agentId || client.currentAgent;
245
245
  if (!llmAgentId) break;
246
246
  if (!await checkAgentAccess(llmAgentId)) break;
247
- await forwardToAgent(llmAgentId, { type: 'get_llm_config' });
247
+ await forwardToAgent(llmAgentId, { type: 'get_llm_config', requestId: msg.requestId });
248
248
  break;
249
249
  }
250
250
 
@@ -50,6 +50,10 @@ async function denyWorkbenchRoute(client, msg) {
50
50
  error,
51
51
  });
52
52
  if (response) await sendToWebClient(client, response);
53
+ // History file-link previews are background requests, not failed chat turns.
54
+ // Their correlated result already terminates the request without polluting
55
+ // the conversation (or stopping an unrelated streaming answer).
56
+ if (msg?.type === 'resolve_file_references' && response) return;
53
57
  await sendToWebClient(client, { type: 'error', message: error });
54
58
  }
55
59
 
@@ -321,7 +325,9 @@ export async function handleClientWorkbench(clientId, client, msg, checkAgentAcc
321
325
  client,
322
326
  msg,
323
327
  resolved,
324
- canonical: canonicalWorkbenchMessage(msg, { ...resolved, conversationId: fileConvId }),
328
+ canonical: canonicalWorkbenchMessage(msg, { ...resolved, conversationId: fileConvId }, {
329
+ canonicalWorkDir: !resolved.legacy && msg.type === 'resolve_file_references',
330
+ }),
325
331
  });
326
332
  break;
327
333
  }
@@ -97,6 +97,15 @@ function resolveYeaftRow(client, route) {
97
97
  || null;
98
98
  }
99
99
 
100
+ // Resolve defaults only after Session ownership has been checked. An empty
101
+ // legacy Session cwd inherits the Agent's advertised execution directory,
102
+ // never the browser's cwd or the Server process cwd.
103
+ function resolveSessionWorkDir(row, route) {
104
+ if (!row) return '';
105
+ return clean(route.runtimeProvider === 'yeaft' ? row.workDir : row.work_dir, 4096)
106
+ || clean(agents.get(route.agentId)?.workDir, 4096);
107
+ }
108
+
100
109
  function resolveChatRow(client, route) {
101
110
  const row = sessionDb.get(route.sessionId);
102
111
  if (!row || row.agent_id !== route.agentId) return null;
@@ -131,7 +140,7 @@ export function currentWorkbenchWorkspaceGeneration({ route, userId, role }) {
131
140
  ? resolveYeaftRow(client, route)
132
141
  : resolveChatRow(client, route);
133
142
  if (!row || row.isArchived) return null;
134
- const workDir = clean(route.runtimeProvider === 'yeaft' ? row.workDir : row.work_dir, 4096);
143
+ const workDir = resolveSessionWorkDir(row, route);
135
144
  if (!workDir) return '';
136
145
  return workbenchWorkspaceGeneration(workbenchRouteKey(route), workDir);
137
146
  }
@@ -175,9 +184,7 @@ export function resolveWorkbenchRequest(client, msg, targetAgentId, { allowMissi
175
184
  if (msg.conversationId === '_folder_picker') scope = 'files-folder-picker';
176
185
  else if (msg.conversationId === '_git_folder_picker') scope = 'git-folder-picker';
177
186
  }
178
- const sessionWorkDir = clean(row
179
- ? (route.runtimeProvider === 'yeaft' ? row.workDir : row.work_dir)
180
- : '', 4096);
187
+ const sessionWorkDir = resolveSessionWorkDir(row, route);
181
188
  const workspaceGeneration = sessionWorkDir
182
189
  ? workbenchWorkspaceGeneration(routeKey, sessionWorkDir)
183
190
  : clean(msg.workbenchWorkspaceGeneration, 1600);
@@ -1 +1 @@
1
- {"version":"1.0.507"}
1
+ {"version":"1.0.509"}