@f5-sales-demo/xcsh 21.47.3 → 21.49.2

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": "21.47.3",
4
+ "version": "21.49.2",
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",
@@ -32,7 +32,7 @@
32
32
  },
33
33
  "scripts": {
34
34
  "prebuild": "bun ../../scripts/check-installed-dependencies.ts",
35
- "build": "bun run generate-build-info && bun run generate-extension-capabilities && bun run generate-api-catalog-qmd-index && test -f src/internal-urls/api-spec-index.generated.ts && bun --cwd=../stats scripts/generate-client-bundle.ts --generate && bun --cwd=../office-pane scripts/generate-client-bundle.ts --generate && bun --cwd=../natives run embed:native && bun scripts/build-binary.ts && bun --cwd=../natives run embed:native --reset && bun --cwd=../stats scripts/generate-client-bundle.ts --reset && bun --cwd=../office-pane scripts/generate-client-bundle.ts --reset",
35
+ "build": "bun scripts/build-package.ts",
36
36
  "precheck": "bun ../../scripts/check-installed-dependencies.ts",
37
37
  "check": "biome check . && bun run format-prompts -- --check && bun run audit:tui-readability && bun run check:types",
38
38
  "audit:tui-readability": "bun scripts/audit-tui-readability.ts --check",
@@ -53,6 +53,7 @@
53
53
  "generate-docs-index": "bun scripts/generate-docs-index.ts",
54
54
  "generate-api-spec-index": "bun scripts/generate-api-spec-index.ts",
55
55
  "generate-api-catalog-qmd-index": "bun scripts/generate-api-catalog-qmd-index.ts",
56
+ "generate-documentation-index": "bun scripts/generate-documentation-index.ts",
56
57
  "generate-branding-index": "bun scripts/generate-branding-index.ts",
57
58
  "generate-sitecli-index": "bun scripts/generate-sitecli-index.ts",
58
59
  "generate-build-info": "bun scripts/generate-build-info.ts",
@@ -66,16 +67,16 @@
66
67
  },
67
68
  "dependencies": {
68
69
  "@agentclientprotocol/sdk": "1.4.0",
69
- "@f5-sales-demo/pi-agent-core": "21.47.3",
70
- "@f5-sales-demo/pi-ai": "21.47.3",
71
- "@f5-sales-demo/pi-natives": "21.47.3",
72
- "@f5-sales-demo/pi-resource-management": "21.47.3",
73
- "@f5-sales-demo/pi-tui": "21.47.3",
74
- "@f5-sales-demo/pi-utils": "21.47.3",
75
- "@f5-sales-demo/xcsh-stats": "21.47.3",
70
+ "@f5-sales-demo/pi-agent-core": "21.49.2",
71
+ "@f5-sales-demo/pi-ai": "21.49.2",
72
+ "@f5-sales-demo/pi-natives": "21.49.2",
73
+ "@f5-sales-demo/pi-resource-management": "21.49.2",
74
+ "@f5-sales-demo/pi-tui": "21.49.2",
75
+ "@f5-sales-demo/pi-utils": "21.49.2",
76
+ "@f5-sales-demo/xcsh-stats": "21.49.2",
76
77
  "@mozilla/readability": "^0.6",
78
+ "@resvg/resvg-wasm": "2.6.2",
77
79
  "@sinclair/typebox": "0.34.52",
78
- "@tobilu/qmd": "2.8.3",
79
80
  "@xterm/headless": "^6.0",
80
81
  "ajv": "^8.20",
81
82
  "chalk": "6.0.0",
@@ -86,10 +87,13 @@
86
87
  "lru-cache": "11.5.2",
87
88
  "markit-ai": "0.5.3",
88
89
  "puppeteer": "25.10.0",
90
+ "tar-stream": "3.1.7",
89
91
  "yaml": "2.9.0"
90
92
  },
91
93
  "devDependencies": {
92
94
  "@types/bun": "1.4.2",
95
+ "@types/tar-stream": "3.1.4",
96
+ "@tobilu/qmd": "2.8.3",
93
97
  "@xterm/addon-unicode11": "0.9.0",
94
98
  "handlebars": "^4.7"
95
99
  },
@@ -1,10 +1,27 @@
1
+ import * as fs from "node:fs/promises";
2
+ import * as path from "node:path";
1
3
  import { postmortem } from "@f5-sales-demo/pi-utils";
2
4
  import type { ExtensionAPI, ExtensionContext } from "@f5-sales-demo/xcsh";
3
5
 
4
6
  export const NATIVE_LIFECYCLE_CONTROL_FLAG = "--native-lifecycle-control";
5
7
  export const NATIVE_LIFECYCLE_CONTINUATION_TITLE = "Native lifecycle continuation";
8
+ export const NATIVE_LIFECYCLE_CONTROL_VALUES = ["await_user_v1", "local_operation_failure_v1"] as const;
6
9
 
7
- type NativeLifecycleControl = "await-user";
10
+ type NativeLifecycleControl = (typeof NATIVE_LIFECYCLE_CONTROL_VALUES)[number];
11
+
12
+ /**
13
+ * Fatal only for the explicit local-operation acceptance control. Extension
14
+ * errors are normally isolated; the runner recognizes this type so the actual
15
+ * failed operation settles the ordinary AgentSession turn as failed.
16
+ */
17
+ export class NativeLifecycleLocalOperationError extends Error {
18
+ readonly code = "ENOENT";
19
+
20
+ constructor(cause: Error) {
21
+ super("Native lifecycle owned local read failed with ENOENT", { cause });
22
+ this.name = "NativeLifecycleLocalOperationError";
23
+ }
24
+ }
8
25
 
9
26
  let activeManagedCancellation: ((reason: string) => void) | undefined;
10
27
 
@@ -22,7 +39,23 @@ export function requestNativeLifecycleCancellation(reason: string): boolean {
22
39
 
23
40
  function configuredControl(pi: ExtensionAPI): NativeLifecycleControl | undefined {
24
41
  const value = pi.getFlag(NATIVE_LIFECYCLE_CONTROL_FLAG);
25
- return value === "await-user" ? value : undefined;
42
+ // Preserve the version-2 spelling for already published acceptance callers.
43
+ if (value === "await-user") return "await_user_v1";
44
+ return NATIVE_LIFECYCLE_CONTROL_VALUES.find(control => control === value);
45
+ }
46
+
47
+ async function failOwnedLocalOperation(cwd: string): Promise<never> {
48
+ const ownedDirectory = await fs.mkdtemp(path.join(cwd, ".xcsh-native-lifecycle-operation-"));
49
+ await fs.chmod(ownedDirectory, 0o700);
50
+ try {
51
+ await fs.readFile(path.join(ownedDirectory, "intentionally-missing"));
52
+ throw new Error("Native lifecycle missing-file read unexpectedly succeeded");
53
+ } catch (error) {
54
+ if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") throw error;
55
+ throw new NativeLifecycleLocalOperationError(error);
56
+ } finally {
57
+ await fs.rm(ownedDirectory, { recursive: true, force: true });
58
+ }
26
59
  }
27
60
 
28
61
  /**
@@ -37,7 +70,7 @@ function configuredControl(pi: ExtensionAPI): NativeLifecycleControl | undefined
37
70
  export default function nativeLifecycleControl(pi: ExtensionAPI): void {
38
71
  pi.registerFlag(NATIVE_LIFECYCLE_CONTROL_FLAG, {
39
72
  type: "string",
40
- description: "Acceptance-only native lifecycle control (supported: await-user)",
73
+ description: `Acceptance-only native lifecycle control (supported: ${NATIVE_LIFECYCLE_CONTROL_VALUES.join(", ")})`,
41
74
  });
42
75
 
43
76
  let activeController: AbortController | undefined;
@@ -50,10 +83,12 @@ export default function nativeLifecycleControl(pi: ExtensionAPI): void {
50
83
  };
51
84
 
52
85
  pi.on("before_agent_start", async (_event, ctx) => {
53
- if (configuredControl(pi) !== "await-user") return;
86
+ const control = configuredControl(pi);
87
+ if (!control) return;
88
+ if (control === "local_operation_failure_v1") return failOwnedLocalOperation(ctx.cwd);
54
89
  if (!ctx.hasUI) {
55
90
  ctx.abort();
56
- throw new Error("--native-lifecycle-control await-user requires interactive mode");
91
+ throw new Error("--native-lifecycle-control await_user_v1 requires interactive mode");
57
92
  }
58
93
 
59
94
  const controller = new AbortController();
@@ -11,6 +11,7 @@ import type { IntegrationHandle } from "../../integrations/types";
11
11
  import { type Theme, theme } from "../../modes/theme/theme";
12
12
  import { personProfileService } from "../../person-profile/service";
13
13
  import type { SessionManager } from "../../session/session-manager";
14
+ import { NativeLifecycleLocalOperationError } from "./bundled/native-lifecycle-control";
14
15
  import type {
15
16
  BeforeAgentStartEvent,
16
17
  BeforeAgentStartEventResult,
@@ -599,6 +600,7 @@ export class ExtensionRunner {
599
600
  result = handlerResult as SessionCompactingResult;
600
601
  }
601
602
  } catch (err) {
603
+ if (err instanceof NativeLifecycleLocalOperationError) throw err;
602
604
  const message = err instanceof Error ? err.message : String(err);
603
605
  const stack = err instanceof Error ? err.stack : undefined;
604
606
  this.emitError({