@yeaft/webchat-agent 1.0.541 → 1.0.542

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.
Binary file
@@ -17,6 +17,6 @@
17
17
  </head>
18
18
  <body>
19
19
  <div id="app"></div>
20
- <script type="module" src="app.bundle.js?v=c1815bb9"></script>
20
+ <script type="module" src="app.bundle.js?v=78f185fb"></script>
21
21
  </body>
22
22
  </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yeaft/webchat-agent",
3
- "version": "1.0.541",
3
+ "version": "1.0.542",
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",
@@ -689,6 +689,44 @@ export function updateSessionAnnouncement(yeaftDir, sessionId, text) {
689
689
  return next;
690
690
  }
691
691
 
692
+ /**
693
+ * Update the project directory used to load Session-scoped project context.
694
+ * Session data remains under the Agent-owned yeaftDir; only the metadata and
695
+ * manifest projection change. An empty string intentionally clears workDir.
696
+ */
697
+ export function updateSessionWorkDir(yeaftDir, sessionId, workDir) {
698
+ if (typeof workDir !== 'string') {
699
+ throw new SessionCrudError('invalid_workdir', sessionId);
700
+ }
701
+ const normalized = normalizeWorkDir(workDir);
702
+ const ownerYeaftDir = resolveSessionYeaftDir(yeaftDir, sessionId);
703
+ const handle = requireSession(ownerYeaftDir, sessionId);
704
+ const previous = handle.getMeta();
705
+ const next = {
706
+ ...previous,
707
+ workDir: normalized,
708
+ workspaceKey: canonicalWorkspaceKey(normalized),
709
+ metadataUpdatedAt: new Date().toISOString(),
710
+ };
711
+ try {
712
+ handle.saveMeta(next);
713
+ try {
714
+ addOrUpdateManifestSession(yeaftDir, next, handle.dir);
715
+ } catch (error) {
716
+ // Keep session.json and the discovery manifest aligned when the second
717
+ // write fails. The rollback is best-effort; preserve the original error.
718
+ try {
719
+ handle.saveMeta(previous);
720
+ addOrUpdateManifestSession(yeaftDir, previous, handle.dir);
721
+ } catch {}
722
+ throw error;
723
+ }
724
+ return handle.getMeta();
725
+ } finally {
726
+ handle.close();
727
+ }
728
+ }
729
+
692
730
  /**
693
731
  * (A.2.c) Persist the model selected in the group conversation header.
694
732
  * Returns the persisted config object so the caller can broadcast it.
@@ -84,6 +84,7 @@ import {
84
84
  copySession,
85
85
  renameSession,
86
86
  updateSessionAnnouncement,
87
+ updateSessionWorkDir,
87
88
  archiveSession,
88
89
  deleteSession,
89
90
  purgeArchivedSessions,
@@ -3737,18 +3738,14 @@ export function handleYeaftRenameSession(msg) {
3737
3738
  }
3738
3739
 
3739
3740
  /**
3740
- * `yeaft_update_group` — generalised group meta patch. Currently accepts
3741
- * `name` and `announcement` keys. Empty patch is rejected; an empty/
3741
+ * `yeaft_update_session` — generalised Session metadata patch. Accepts
3742
+ * `name`, `announcement`, and `workDir`. Empty patch is rejected; an empty/
3742
3743
  * whitespace-only `name` is also rejected up front rather than letting
3743
3744
  * `renameSession` raise a less-specific error deeper in the call stack.
3744
3745
  *
3745
- * Partial-success contract: when a single patch contains BOTH `name` and
3746
- * `announcement`, the rename is committed first; if the announcement
3747
- * write throws, the rename has already persisted on disk and the client
3748
- * receives `ok:false` for the announcement error — i.e. the WS op is not
3749
- * atomic. Today's UI binds Save buttons per pane in `GroupSettingsModal`
3750
- * so this is theoretical; readers extending the patch shape should know
3751
- * the contract permits half-commits.
3746
+ * Partial-success contract: when a single patch contains multiple keys, each
3747
+ * mutator commits independently. Today's UI binds one Save button per field,
3748
+ * so the wire operation normally contains exactly one key.
3752
3749
  */
3753
3750
  export function handleYeaftUpdateSession(msg) {
3754
3751
  const requestId = msg && msg.requestId;
@@ -3758,7 +3755,8 @@ export function handleYeaftUpdateSession(msg) {
3758
3755
  try {
3759
3756
  const hasName = patch && typeof patch.name === 'string' && patch.name.trim().length > 0;
3760
3757
  const hasAnnouncement = patch && typeof patch.announcement === 'string';
3761
- if (!patch || (!hasName && !hasAnnouncement)) {
3758
+ const hasWorkDir = patch && typeof patch.workDir === 'string';
3759
+ if (!patch || (!hasName && !hasAnnouncement && !hasWorkDir)) {
3762
3760
  throw new SessionCrudError('invalid_patch', sessionId);
3763
3761
  }
3764
3762
  const yeaftDir = ctx.CONFIG?.yeaftDir;
@@ -3769,6 +3767,9 @@ export function handleYeaftUpdateSession(msg) {
3769
3767
  if (hasAnnouncement) {
3770
3768
  group = updateSessionAnnouncement(yeaftDir, sessionId, patch.announcement);
3771
3769
  }
3770
+ if (hasWorkDir) {
3771
+ group = updateSessionWorkDir(yeaftDir, sessionId, patch.workDir);
3772
+ }
3772
3773
  invalidateGroupContext(sessionId);
3773
3774
  sendSessionCrudResult({ op: 'update', requestId, ok: true, session: group });
3774
3775
  sendSessionSnapshotBroadcast();