@yeaft/webchat-agent 0.1.892 → 0.1.894

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yeaft/webchat-agent",
3
- "version": "0.1.892",
3
+ "version": "0.1.894",
4
4
  "description": "Remote agent for Yeaft WebChat — connects worker machines to the central server",
5
5
  "main": "index.js",
6
6
  "type": "module",
package/yeaft/engine.js CHANGED
@@ -18,6 +18,7 @@
18
18
  */
19
19
 
20
20
  import { randomUUID } from 'crypto';
21
+ import { resolve as resolvePath } from 'path';
21
22
  import { buildSystemPrompt, buildWorkerPrompt } from './prompts.js';
22
23
  import { LLMContextError, LLMAbortError } from './llm/adapter.js';
23
24
  import { runMemoryPreflow, buildRelevantScopes } from './sessions/pre-flow.js';
@@ -877,7 +878,17 @@ export class Engine {
877
878
  return {
878
879
  signal,
879
880
  yeaftDir: this.#yeaftDir,
880
- cwd: process.cwd(),
881
+ // Group-scoped working directory. Threaded from #runQuery({ workDir })
882
+ // → set by web-bridge runVpTurn from sessionMeta.workDir. Tools read
883
+ // `ctx.cwd` and resolve relative paths against it. Always absolute
884
+ // (path.resolve normalizes relative inputs + trailing slashes) so
885
+ // tools that string-concatenate don't accidentally walk from
886
+ // process.cwd(). Falls back to process.cwd() in non-group / test
887
+ // contexts.
888
+ cwd: (() => {
889
+ const raw = typeof vpCtx?.workDir === 'string' ? vpCtx.workDir.trim() : '';
890
+ return raw ? resolvePath(raw) : process.cwd();
891
+ })(),
881
892
  mcpManager: this.#mcpManager,
882
893
  skillManager: this.#skillManager,
883
894
  conversationStore: this.#conversationStore,
@@ -2266,6 +2277,7 @@ export class Engine {
2266
2277
  contextWindow: currentContextWindow,
2267
2278
  getCurrentTodos,
2268
2279
  setCurrentTodos,
2280
+ workDir,
2269
2281
  requestEndTurn: (reason) => {
2270
2282
  // First call wins — preserve the kind/reason of the first tool
2271
2283
  // that asked to end the turn. Late callers (a second
@@ -2344,7 +2356,14 @@ export class Engine {
2344
2356
  output = await this.#toolRegistry.execute(tc.name, tc.input, toolCtx);
2345
2357
  } else {
2346
2358
  const tool = this.#tools.get(tc.name);
2347
- const rawOutput = await tool.execute(tc.input, { signal });
2359
+ // Pass the full toolCtx (cwd, workDir, signal, ) — not just
2360
+ // `{ signal }`. Legacy registerTool() callers historically got
2361
+ // a 1-field ctx, but that means tools like bash/file-read run
2362
+ // in the agent process cwd instead of the group's workDir.
2363
+ // Real production goes through #toolRegistry; the legacy path
2364
+ // is exercised by tests and a few standalone tools. Aligning
2365
+ // both paths keeps `ctx.cwd` semantics consistent.
2366
+ const rawOutput = await tool.execute(tc.input, toolCtx);
2348
2367
  // Legacy #tools branch must apply the same per-tool cap as
2349
2368
  // ToolRegistry.execute. Otherwise a deployment using the legacy
2350
2369
  // registration path bypasses the defense entirely.
package/yeaft/session.js CHANGED
@@ -323,11 +323,15 @@ export async function loadSession(options = {}) {
323
323
  } catch (err) {
324
324
  console.warn(`[Yeaft] topUpDefaultVps failed: ${err?.message || err}`);
325
325
  }
326
- try {
327
- ensureDefaultSessionIfEmpty(yeaftDir, { memoryRoot: join(yeaftDir, 'memory') });
328
- } catch (err) {
329
- console.warn(`[Yeaft] ensureDefaultSessionIfEmpty failed: ${err?.message || err}`);
330
- }
326
+ // fix-yeaft-session-server-persistence: stop auto-seeding a
327
+ // `grp_default` per agent. Previously every agent that booted with
328
+ // zero sessions would manufacture an empty default group, which on
329
+ // the unified sidebar shows up as a phantom row distinct from the
330
+ // user's real session — and on agent switch it stole the active-
331
+ // session slot. With server-side persistence the user's actual
332
+ // yeaft sessions are now hydrated from the DB; if they have none,
333
+ // the sidebar shows the empty state + "create session" CTA, which
334
+ // is the explicit behaviour the user asked for.
331
335
 
332
336
  // task-fix-memory-load: backfill summary.md for VPs / groups created
333
337
  // before the create-time seed was added. Without this, an existing
@@ -2223,15 +2223,13 @@ export async function handleYeaftSessionSend(msg) {
2223
2223
  const dir = join(sessionRoot, sessionId);
2224
2224
  if (existsSync(dir) && loadSessionMeta(dir)) {
2225
2225
  sessionHandle = openSession(sessionRoot, sessionId);
2226
- } else if (sessionId === 'grp_default') {
2227
- try {
2228
- const seeded = seedDefaultSession(groupYeaftDir, { memoryRoot: join(groupYeaftDir, 'memory') });
2229
- sessionHandle = seeded.group;
2230
- } catch (seedErr) {
2231
- seedFailed = true;
2232
- console.warn('[Yeaft] yeaft_group_chat: seedDefaultSession failed', seedErr?.message || seedErr);
2233
- }
2234
2226
  } else {
2227
+ // fix-yeaft-session-server-persistence: the `grp_default` on-the-
2228
+ // fly seed used to manufacture a missing session here. That
2229
+ // hid the "session not found" error and re-created the phantom
2230
+ // default-group row across agents. Now we surface the not-found
2231
+ // case so the web can show an "agent offline / session missing"
2232
+ // hint instead of silently creating a different session.
2235
2233
  console.warn('[Yeaft] yeaft_group_chat: sessionId %s not found', sessionId);
2236
2234
  }
2237
2235
  } catch (err) {