@f5-sales-demo/xcsh 19.85.4 → 19.85.5

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,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@f5-sales-demo/xcsh",
4
- "version": "19.85.4",
4
+ "version": "19.85.5",
5
5
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://github.com/f5-sales-demo/xcsh",
7
7
  "author": "Can Boluk",
@@ -56,13 +56,13 @@
56
56
  "dependencies": {
57
57
  "@agentclientprotocol/sdk": "0.16.1",
58
58
  "@mozilla/readability": "^0.6",
59
- "@f5-sales-demo/xcsh-stats": "19.85.4",
60
- "@f5-sales-demo/pi-agent-core": "19.85.4",
61
- "@f5-sales-demo/pi-ai": "19.85.4",
62
- "@f5-sales-demo/pi-natives": "19.85.4",
63
- "@f5-sales-demo/pi-resource-management": "19.85.4",
64
- "@f5-sales-demo/pi-tui": "19.85.4",
65
- "@f5-sales-demo/pi-utils": "19.85.4",
59
+ "@f5-sales-demo/xcsh-stats": "19.85.5",
60
+ "@f5-sales-demo/pi-agent-core": "19.85.5",
61
+ "@f5-sales-demo/pi-ai": "19.85.5",
62
+ "@f5-sales-demo/pi-natives": "19.85.5",
63
+ "@f5-sales-demo/pi-resource-management": "19.85.5",
64
+ "@f5-sales-demo/pi-tui": "19.85.5",
65
+ "@f5-sales-demo/pi-utils": "19.85.5",
66
66
  "@sinclair/typebox": "^0.34",
67
67
  "@xterm/headless": "^6.0",
68
68
  "ajv": "^8.20",
@@ -8,6 +8,8 @@
8
8
  * mirroring `stats-cli.ts` / `chrome-cli.ts`.
9
9
  */
10
10
  import { spawnSync } from "node:child_process";
11
+ import * as fs from "node:fs";
12
+ import * as os from "node:os";
11
13
  import * as path from "node:path";
12
14
  import { LOCALIP_HOST } from "../browser/bridge-cert";
13
15
  import { type HeadlessChatBridge, startHeadlessChatBridge } from "../browser/headless-bridge";
@@ -133,7 +135,49 @@ async function runServe(): Promise<void> {
133
135
  });
134
136
  }
135
137
 
136
- /** Run the Office sideload against the embedded bundle (best-effort). */
138
+ /** The macOS Office desktop containers whose `wef` folder holds sideloaded manifests. */
139
+ const OFFICE_WEF_CONTAINERS = ["com.microsoft.Excel", "com.microsoft.Powerpoint", "com.microsoft.Word"];
140
+
141
+ /** The `wef` sideload directories for the desktop Office apps under `homeDir`. */
142
+ export function officeWefDirs(homeDir: string): string[] {
143
+ return OFFICE_WEF_CONTAINERS.map(c => path.join(homeDir, "Library", "Containers", c, "Data", "Documents", "wef"));
144
+ }
145
+
146
+ /**
147
+ * `office-addin-debugging` symlinks the add-in manifest into each Office container's
148
+ * `wef` folder as `<manifestId>.manifest.json` and fails `EEXIST` if a link from a
149
+ * prior sideload is already there — so a repeat sideload errors even though the
150
+ * add-in registered fine. Remove any stale copy for our id so `office sideload` is
151
+ * idempotent. Best-effort per dir (a missing file or container is a no-op). Returns
152
+ * the paths actually removed.
153
+ */
154
+ export function removeStaleWefManifests(manifestId: string, homeDir: string = os.homedir()): string[] {
155
+ const removed: string[] = [];
156
+ for (const dir of officeWefDirs(homeDir)) {
157
+ const p = path.join(dir, `${manifestId}.manifest.json`);
158
+ try {
159
+ if (fs.existsSync(p)) {
160
+ fs.rmSync(p);
161
+ removed.push(p);
162
+ }
163
+ } catch {
164
+ /* best-effort: a permission error or race here must not block the sideload */
165
+ }
166
+ }
167
+ return removed;
168
+ }
169
+
170
+ /** The add-in manifest id from the bundled manifest.json (the `wef` link's basename). */
171
+ function manifestIdFrom(manifestText: string): string | undefined {
172
+ try {
173
+ const id = (JSON.parse(manifestText) as { id?: unknown }).id;
174
+ return typeof id === "string" && id.length > 0 ? id : undefined;
175
+ } catch {
176
+ return undefined;
177
+ }
178
+ }
179
+
180
+ /** Run the Office sideload against the embedded bundle (idempotent + best-effort). */
137
181
  async function runSideload(app: OfficeApp): Promise<void> {
138
182
  // Point office-addin-debugging at the extracted bundle dir, which has
139
183
  // manifest.json AND its referenced `assets/` icons colocated. A bare temp
@@ -141,6 +185,21 @@ async function runSideload(app: OfficeApp): Promise<void> {
141
185
  // step: `File to zip ".../assets/color.png" does not exist`.
142
186
  const dir = await getOfficePaneDir();
143
187
  const manifestPath = path.join(dir, "manifest.json");
188
+
189
+ // Idempotency: office-addin-debugging fails EEXIST if a prior sideload left a
190
+ // `<id>.manifest.json` link in a container's wef folder. Clear stale copies first.
191
+ const manifestId = manifestIdFrom(
192
+ await Bun.file(manifestPath)
193
+ .text()
194
+ .catch(() => ""),
195
+ );
196
+ if (manifestId) {
197
+ const removed = removeStaleWefManifests(manifestId);
198
+ if (removed.length > 0) {
199
+ console.log(`Cleared ${removed.length} stale sideload manifest link(s) from a previous sideload.`);
200
+ }
201
+ }
202
+
144
203
  console.log(`Sideloading ${manifestPath} into ${app} (requires the office-addin-debugging / atk tool on PATH)...`);
145
204
 
146
205
  const result = spawnSync("office-addin-debugging", ["start", manifestPath, "desktop", "--app", app], {
@@ -17,17 +17,17 @@ export interface BuildInfo {
17
17
  }
18
18
 
19
19
  export const BUILD_INFO: BuildInfo = {
20
- "version": "19.85.4",
21
- "commit": "d014668cc60902dc4545082fc2c4c2062dff4046",
22
- "shortCommit": "d014668",
20
+ "version": "19.85.5",
21
+ "commit": "78846ea460721267f0fda099042fba2390dd6887",
22
+ "shortCommit": "78846ea",
23
23
  "branch": "main",
24
- "tag": "v19.85.4",
25
- "commitDate": "2026-07-23T21:02:17Z",
26
- "buildDate": "2026-07-23T21:25:20.917Z",
24
+ "tag": "v19.85.5",
25
+ "commitDate": "2026-07-23T22:07:14Z",
26
+ "buildDate": "2026-07-23T22:31:05.353Z",
27
27
  "dirty": true,
28
28
  "prNumber": "",
29
29
  "repoUrl": "https://github.com/f5-sales-demo/xcsh",
30
30
  "repoSlug": "f5-sales-demo/xcsh",
31
- "commitUrl": "https://github.com/f5-sales-demo/xcsh/commit/d014668cc60902dc4545082fc2c4c2062dff4046",
32
- "releaseUrl": "https://github.com/f5-sales-demo/xcsh/releases/tag/v19.85.4"
31
+ "commitUrl": "https://github.com/f5-sales-demo/xcsh/commit/78846ea460721267f0fda099042fba2390dd6887",
32
+ "releaseUrl": "https://github.com/f5-sales-demo/xcsh/releases/tag/v19.85.5"
33
33
  };