grok-bot-cli 0.2.1 → 0.2.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,6 +1,6 @@
1
1
  {
2
2
  "name": "grok-bot-cli",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "CLI for Grok Bot agents and groups: create, update, message, inspect threads, and automate cleanup",
5
5
  "type": "module",
6
6
  "bin": {
@@ -43,6 +43,6 @@
43
43
  "LICENSE"
44
44
  ],
45
45
  "devDependencies": {
46
- "@changesets/cli": "2.31.1"
46
+ "@changesets/cli": "3.0.1"
47
47
  }
48
48
  }
@@ -6,6 +6,49 @@ import { join } from "node:path";
6
6
 
7
7
  const SAFE_STORAGE_PREFIX = Buffer.from("v10");
8
8
 
9
+ export class GrokBotGatewaySessionError extends Error {
10
+ constructor(code, message) {
11
+ super(message);
12
+ this.name = "GrokBotGatewaySessionError";
13
+ this.code = code;
14
+ }
15
+ }
16
+
17
+ function encryptedPayload(wrapped) {
18
+ if (wrapped.version != null && wrapped.version !== 1 && wrapped.version !== 2) {
19
+ throw new GrokBotGatewaySessionError(
20
+ "UNSUPPORTED_VERSION",
21
+ `Unsupported Grok Bot gateway descriptor version ${wrapped.version}.`,
22
+ );
23
+ }
24
+ let encrypted;
25
+ if (wrapped.version === 2) {
26
+ const entries = Object.values(wrapped.entries ?? {});
27
+ if (entries.length === 0) {
28
+ throw new GrokBotGatewaySessionError(
29
+ "EMPTY_ENTRIES",
30
+ "Grok Bot gateway descriptor has no saved gateway entries.",
31
+ );
32
+ }
33
+ if (entries.length > 1) {
34
+ throw new GrokBotGatewaySessionError(
35
+ "AMBIGUOUS_ENTRIES",
36
+ "Grok Bot gateway descriptor has multiple saved gateway entries and no active entry selection.",
37
+ );
38
+ }
39
+ encrypted = entries[0]?.encrypted;
40
+ } else {
41
+ encrypted = wrapped.encrypted;
42
+ }
43
+ if (typeof encrypted !== "string" || !encrypted) {
44
+ throw new GrokBotGatewaySessionError(
45
+ "MISSING_ENCRYPTED_PAYLOAD",
46
+ "Grok Bot gateway descriptor is missing an encrypted payload.",
47
+ );
48
+ }
49
+ return encrypted;
50
+ }
51
+
9
52
  export function decryptSafeStorageString(encryptedBase64, password) {
10
53
  const encrypted = Buffer.from(encryptedBase64, "base64");
11
54
  if (!encrypted.subarray(0, 3).equals(SAFE_STORAGE_PREFIX)) {
@@ -57,13 +100,17 @@ export function loadGrokBotGatewaySession({
57
100
  if (!existsSync(path)) return null;
58
101
 
59
102
  const wrapped = JSON.parse(readFileSync(path, "utf8"));
103
+ const encrypted = encryptedPayload(wrapped);
60
104
  const clear = decryptSafeStorageString(
61
- wrapped.encrypted,
105
+ encrypted,
62
106
  getKeychainPassword(),
63
107
  );
64
108
  const descriptor = JSON.parse(clear);
65
109
  if (!descriptor.baseUrl || !descriptor.token) {
66
- throw new Error("Grok Bot gateway descriptor is incomplete.");
110
+ throw new GrokBotGatewaySessionError(
111
+ "INCOMPLETE_DESCRIPTOR",
112
+ "Decrypted Grok Bot gateway descriptor is incomplete.",
113
+ );
67
114
  }
68
115
 
69
116
  return {
@@ -72,3 +119,20 @@ export function loadGrokBotGatewaySession({
72
119
  headers: descriptor.headers ?? {},
73
120
  };
74
121
  }
122
+
123
+ export function inspectGrokBotGatewaySession(options = {}) {
124
+ if (!hasGrokBotGatewaySession(options)) {
125
+ return { present: false, usable: false };
126
+ }
127
+ try {
128
+ loadGrokBotGatewaySession(options);
129
+ return { present: true, usable: true };
130
+ } catch (error) {
131
+ return {
132
+ present: true,
133
+ usable: false,
134
+ code: error instanceof GrokBotGatewaySessionError ? error.code : "UNUSABLE_SESSION",
135
+ error: error instanceof Error ? error.message : String(error),
136
+ };
137
+ }
138
+ }
package/src/cli.js CHANGED
@@ -2,6 +2,7 @@
2
2
  import { AVATAR_COLORS, AVATAR_SHAPES, MAX_GROUP_MEMBERS, StoreError, defaultCandidateRoots, looksLikeAgentsRoot, resolveAgentsRoot } from "./store.js";
3
3
  import { hasGatewayAuth } from "./gateway.js";
4
4
  import { openBackend } from "./commands.js";
5
+ import { inspectGrokBotGatewaySession } from "./app-session.js";
5
6
 
6
7
  function print(value) {
7
8
  if (typeof value === "string") process.stdout.write(value + "\n");
@@ -247,11 +248,16 @@ async function main(argv) {
247
248
  if (!(err instanceof StoreError)) throw err;
248
249
  }
249
250
  const note = "Live roster is on the box. Prefer CURSOR_ACCESS_TOKEN then EnsureSandBox then POST gateway /api/*.";
250
- const payload = { resolved, found, candidates, gatewayAuthPresent: hasGatewayAuth(), note };
251
+ const gatewayAuthPresent = hasGatewayAuth();
252
+ const grokBotAppSession = inspectGrokBotGatewaySession();
253
+ const payload = { resolved, found, candidates, gatewayAuthPresent, grokBotAppSession, note };
251
254
  if (json) print(payload);
252
255
  else {
253
256
  print("resolved: " + (resolved ?? "(none)"));
254
- print("gateway auth: " + (hasGatewayAuth() ? "yes (env)" : "no"));
257
+ print("gateway auth: " + (gatewayAuthPresent ? "present" : "no"));
258
+ if (grokBotAppSession.usable) print("Grok Bot app session: usable");
259
+ else if (grokBotAppSession.present) print("Grok Bot app session: present but unusable: " + grokBotAppSession.error);
260
+ else print("Grok Bot app session: not found");
255
261
  print("found:");
256
262
  print(found.length ? found.map((p) => " " + p).join("\n") : " (none)");
257
263
  print("candidates:");