@f5-sales-demo/xcsh 21.46.11 → 21.47.0

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.46.11",
4
+ "version": "21.47.0",
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",
@@ -66,13 +66,13 @@
66
66
  },
67
67
  "dependencies": {
68
68
  "@agentclientprotocol/sdk": "1.4.0",
69
- "@f5-sales-demo/pi-agent-core": "21.46.11",
70
- "@f5-sales-demo/pi-ai": "21.46.11",
71
- "@f5-sales-demo/pi-natives": "21.46.11",
72
- "@f5-sales-demo/pi-resource-management": "21.46.11",
73
- "@f5-sales-demo/pi-tui": "21.46.11",
74
- "@f5-sales-demo/pi-utils": "21.46.11",
75
- "@f5-sales-demo/xcsh-stats": "21.46.11",
69
+ "@f5-sales-demo/pi-agent-core": "21.47.0",
70
+ "@f5-sales-demo/pi-ai": "21.47.0",
71
+ "@f5-sales-demo/pi-natives": "21.47.0",
72
+ "@f5-sales-demo/pi-resource-management": "21.47.0",
73
+ "@f5-sales-demo/pi-tui": "21.47.0",
74
+ "@f5-sales-demo/pi-utils": "21.47.0",
75
+ "@f5-sales-demo/xcsh-stats": "21.47.0",
76
76
  "@mozilla/readability": "^0.6",
77
77
  "@sinclair/typebox": "0.34.52",
78
78
  "@tobilu/qmd": "2.8.3",
@@ -0,0 +1,38 @@
1
+ import { AuthCredentialStore } from "@f5-sales-demo/pi-ai/auth-storage";
2
+ import { loginOpenAICodex, type OpenAICodexLoginOptions } from "@f5-sales-demo/pi-ai/utils/oauth/openai-codex";
3
+ import type { OAuthAuthInfo, OAuthCredentials, OAuthPrompt } from "@f5-sales-demo/pi-ai/utils/oauth/types";
4
+
5
+ type CredentialStore = Pick<AuthCredentialStore, "close" | "saveOAuth">;
6
+
7
+ export type OpenAIDeviceAuthDependencies = {
8
+ openStore?: () => Promise<CredentialStore>;
9
+ login?: (options: OpenAICodexLoginOptions) => Promise<OAuthCredentials>;
10
+ onAuth?: (info: OAuthAuthInfo) => void;
11
+ onProgress?: (message: string) => void;
12
+ onPrompt?: (prompt: OAuthPrompt) => Promise<string>;
13
+ };
14
+
15
+ function reportAuth(info: OAuthAuthInfo): void {
16
+ if (info.kind === "device" && info.userCode) {
17
+ process.stdout.write(`Open ${info.url} and enter the one-time code: ${info.userCode}\n`);
18
+ return;
19
+ }
20
+ process.stdout.write(`Open this URL in your browser:\n${info.url}\n`);
21
+ }
22
+
23
+ /** Run the ChatGPT device-code flow without starting a local callback listener. */
24
+ export async function runOpenAIDeviceAuthLogin(dependencies: OpenAIDeviceAuthDependencies = {}): Promise<void> {
25
+ const store = await (dependencies.openStore ?? (() => AuthCredentialStore.open()))();
26
+ try {
27
+ const credentials = await (dependencies.login ?? loginOpenAICodex)({
28
+ method: "device",
29
+ onAuth: dependencies.onAuth ?? reportAuth,
30
+ onProgress: dependencies.onProgress ?? (message => process.stdout.write(`${message}\n`)),
31
+ onPrompt: dependencies.onPrompt,
32
+ });
33
+ store.saveOAuth("openai-codex", credentials);
34
+ process.stdout.write("ChatGPT credentials saved.\n");
35
+ } finally {
36
+ store.close();
37
+ }
38
+ }
package/src/cli.ts CHANGED
@@ -75,6 +75,7 @@ const commands: CommandEntry[] = [
75
75
  },
76
76
  { name: "jupyter", load: () => import("./commands/jupyter").then(m => m.default) },
77
77
  { name: "lifecycle", load: () => import("./commands/lifecycle").then(m => m.default) },
78
+ { name: "login", load: () => import("./commands/login").then(m => m.default) },
78
79
  { name: "manager", load: () => import("./commands/manager").then(m => m.default) },
79
80
  { name: "office", load: () => import("./commands/office").then(m => m.default) },
80
81
  { name: "plugin", load: () => import("./commands/plugin").then(m => m.default) },
@@ -0,0 +1,18 @@
1
+ import { Command, Flags } from "@f5-sales-demo/pi-utils/cli";
2
+ import { runOpenAIDeviceAuthLogin } from "../cli/openai-device-auth";
3
+
4
+ /** Authenticate ChatGPT through a device-code flow suitable for SSH and headless terminals. */
5
+ export default class Login extends Command {
6
+ static description = "Authenticate ChatGPT using a device code";
7
+ static flags = {
8
+ "device-auth": Flags.boolean({ description: "Use ChatGPT device-code authentication", default: false }),
9
+ };
10
+
11
+ async run(): Promise<void> {
12
+ const { flags } = await this.parse(Login);
13
+ if (!flags["device-auth"]) {
14
+ throw new Error("Use xcsh login --device-auth to authenticate ChatGPT with a device code.");
15
+ }
16
+ await runOpenAIDeviceAuthLogin();
17
+ }
18
+ }