@tickernelz/paperclip-pro-adapter-grok-local 2026.925.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.
Files changed (119) hide show
  1. package/LICENSE +22 -0
  2. package/dist/cli/format-event.d.ts +2 -0
  3. package/dist/cli/format-event.d.ts.map +1 -0
  4. package/dist/cli/format-event.js +55 -0
  5. package/dist/cli/format-event.js.map +1 -0
  6. package/dist/cli/format-event.test.d.ts +2 -0
  7. package/dist/cli/format-event.test.d.ts.map +1 -0
  8. package/dist/cli/format-event.test.js +19 -0
  9. package/dist/cli/format-event.test.js.map +1 -0
  10. package/dist/cli/index.d.ts +2 -0
  11. package/dist/cli/index.d.ts.map +1 -0
  12. package/dist/cli/index.js +2 -0
  13. package/dist/cli/index.js.map +1 -0
  14. package/dist/index.d.ts +10 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +53 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/server/adapter-auth-promotion.d.ts +87 -0
  19. package/dist/server/adapter-auth-promotion.d.ts.map +1 -0
  20. package/dist/server/adapter-auth-promotion.js +294 -0
  21. package/dist/server/adapter-auth-promotion.js.map +1 -0
  22. package/dist/server/adapter-auth-promotion.test.d.ts +2 -0
  23. package/dist/server/adapter-auth-promotion.test.d.ts.map +1 -0
  24. package/dist/server/adapter-auth-promotion.test.js +563 -0
  25. package/dist/server/adapter-auth-promotion.test.js.map +1 -0
  26. package/dist/server/device-login-parse.d.ts +23 -0
  27. package/dist/server/device-login-parse.d.ts.map +1 -0
  28. package/dist/server/device-login-parse.js +148 -0
  29. package/dist/server/device-login-parse.js.map +1 -0
  30. package/dist/server/device-login-parse.test.d.ts +2 -0
  31. package/dist/server/device-login-parse.test.d.ts.map +1 -0
  32. package/dist/server/device-login-parse.test.js +146 -0
  33. package/dist/server/device-login-parse.test.js.map +1 -0
  34. package/dist/server/execute.d.ts +3 -0
  35. package/dist/server/execute.d.ts.map +1 -0
  36. package/dist/server/execute.js +572 -0
  37. package/dist/server/execute.js.map +1 -0
  38. package/dist/server/execute.test.d.ts +2 -0
  39. package/dist/server/execute.test.d.ts.map +1 -0
  40. package/dist/server/execute.test.js +731 -0
  41. package/dist/server/execute.test.js.map +1 -0
  42. package/dist/server/grok-auth-copyback.d.ts +48 -0
  43. package/dist/server/grok-auth-copyback.d.ts.map +1 -0
  44. package/dist/server/grok-auth-copyback.js +92 -0
  45. package/dist/server/grok-auth-copyback.js.map +1 -0
  46. package/dist/server/grok-auth-copyback.test.d.ts +2 -0
  47. package/dist/server/grok-auth-copyback.test.d.ts.map +1 -0
  48. package/dist/server/grok-auth-copyback.test.js +246 -0
  49. package/dist/server/grok-auth-copyback.test.js.map +1 -0
  50. package/dist/server/grok-auth-merge-decision.cjs +157 -0
  51. package/dist/server/grok-auth-merge-decision.d.ts +21 -0
  52. package/dist/server/grok-auth-merge-decision.d.ts.map +1 -0
  53. package/dist/server/grok-auth-merge-decision.js +58 -0
  54. package/dist/server/grok-auth-merge-decision.js.map +1 -0
  55. package/dist/server/grok-auth-merge-decision.test.d.ts +2 -0
  56. package/dist/server/grok-auth-merge-decision.test.d.ts.map +1 -0
  57. package/dist/server/grok-auth-merge-decision.test.js +189 -0
  58. package/dist/server/grok-auth-merge-decision.test.js.map +1 -0
  59. package/dist/server/grok-home.d.ts +57 -0
  60. package/dist/server/grok-home.d.ts.map +1 -0
  61. package/dist/server/grok-home.js +145 -0
  62. package/dist/server/grok-home.js.map +1 -0
  63. package/dist/server/grok-home.test.d.ts +2 -0
  64. package/dist/server/grok-home.test.d.ts.map +1 -0
  65. package/dist/server/grok-home.test.js +109 -0
  66. package/dist/server/grok-home.test.js.map +1 -0
  67. package/dist/server/index.d.ts +12 -0
  68. package/dist/server/index.d.ts.map +1 -0
  69. package/dist/server/index.js +67 -0
  70. package/dist/server/index.js.map +1 -0
  71. package/dist/server/parse.d.ts +15 -0
  72. package/dist/server/parse.d.ts.map +1 -0
  73. package/dist/server/parse.js +93 -0
  74. package/dist/server/parse.js.map +1 -0
  75. package/dist/server/parse.test.d.ts +2 -0
  76. package/dist/server/parse.test.d.ts.map +1 -0
  77. package/dist/server/parse.test.js +82 -0
  78. package/dist/server/parse.test.js.map +1 -0
  79. package/dist/server/skills.d.ts +4 -0
  80. package/dist/server/skills.d.ts.map +1 -0
  81. package/dist/server/skills.js +21 -0
  82. package/dist/server/skills.js.map +1 -0
  83. package/dist/server/test.d.ts +9 -0
  84. package/dist/server/test.d.ts.map +1 -0
  85. package/dist/server/test.js +362 -0
  86. package/dist/server/test.js.map +1 -0
  87. package/dist/server/test.test.d.ts +2 -0
  88. package/dist/server/test.test.d.ts.map +1 -0
  89. package/dist/server/test.test.js +293 -0
  90. package/dist/server/test.test.js.map +1 -0
  91. package/dist/shared/turn-boundary.d.ts +7 -0
  92. package/dist/shared/turn-boundary.d.ts.map +1 -0
  93. package/dist/shared/turn-boundary.js +44 -0
  94. package/dist/shared/turn-boundary.js.map +1 -0
  95. package/dist/shared/turn-boundary.test.d.ts +2 -0
  96. package/dist/shared/turn-boundary.test.d.ts.map +1 -0
  97. package/dist/shared/turn-boundary.test.js +43 -0
  98. package/dist/shared/turn-boundary.test.js.map +1 -0
  99. package/dist/ui/build-config.d.ts +3 -0
  100. package/dist/ui/build-config.d.ts.map +1 -0
  101. package/dist/ui/build-config.js +29 -0
  102. package/dist/ui/build-config.js.map +1 -0
  103. package/dist/ui/build-config.test.d.ts +2 -0
  104. package/dist/ui/build-config.test.d.ts.map +1 -0
  105. package/dist/ui/build-config.test.js +26 -0
  106. package/dist/ui/build-config.test.js.map +1 -0
  107. package/dist/ui/index.d.ts +3 -0
  108. package/dist/ui/index.d.ts.map +1 -0
  109. package/dist/ui/index.js +3 -0
  110. package/dist/ui/index.js.map +1 -0
  111. package/dist/ui/parse-stdout.d.ts +7 -0
  112. package/dist/ui/parse-stdout.d.ts.map +1 -0
  113. package/dist/ui/parse-stdout.js +76 -0
  114. package/dist/ui/parse-stdout.js.map +1 -0
  115. package/dist/ui/parse-stdout.test.d.ts +2 -0
  116. package/dist/ui/parse-stdout.test.d.ts.map +1 -0
  117. package/dist/ui/parse-stdout.test.js +62 -0
  118. package/dist/ui/parse-stdout.test.js.map +1 -0
  119. package/package.json +58 -0
@@ -0,0 +1,145 @@
1
+ import fs from "node:fs/promises";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { resolvePaperclipInstanceRootForAdapter } from "@tickernelz/paperclip-pro-adapter-utils/server-utils";
5
+ // The Grok credential home. `GROK_HOME` replaces `~/.grok` and holds one file,
6
+ // `auth.json`. Unlike Codex, a Grok `auth.json` has no fixed top-level key: it
7
+ // holds exactly one key, and that key is a composite `<issuer>::<uuid>` value.
8
+ // This module resolves the company-scoped home path and reads its usable-auth
9
+ // shape. It never writes to the managed home itself; {@link
10
+ // promoteGrokDeviceLoginCredential} in `adapter-auth-promotion.ts` owns that
11
+ // write. {@link stageGrokHomeForSync} writes only to a fresh, private staging
12
+ // directory it creates for a sandbox run.
13
+ const AUTH_FILE_NAME = "auth.json";
14
+ /**
15
+ * The allowlist of managed `GROK_HOME` entries that the grok-local adapter
16
+ * stages into the sandbox `home` asset (see {@link stageGrokHomeForSync}).
17
+ * Paperclip writes instructions and skills under the workspace, not under the
18
+ * Grok home, so the credential file is the only entry a sandbox run needs.
19
+ */
20
+ export const GROK_SYNC_ALLOWLIST = ["auth.json"];
21
+ // Matches the composite `<issuer>::<uuid>` top-level key. The issuer is a
22
+ // non-empty string — an OIDC issuer URL such as `https://issuer.x.ai` holds
23
+ // colons of its own — so this anchors on the LAST `::` before a standard
24
+ // 8-4-4-4-12 hex UUID at the end of the string (the greedy `.+` backtracks
25
+ // to that last separator).
26
+ const GROK_IDENTITY_KEY_RE = /^.+::[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
27
+ function nonEmpty(value) {
28
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
29
+ }
30
+ /**
31
+ * Parses a decoded JSON value into a {@link GrokAuthPayload}. Returns null when
32
+ * the value is not an object, holds zero or more than one top-level key, or the
33
+ * single key does not match the `<issuer>::<uuid>` shape, or its value is not an
34
+ * object. Never assumes a fixed key name.
35
+ */
36
+ export function parseGrokAuthPayload(raw) {
37
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw))
38
+ return null;
39
+ const keys = Object.keys(raw);
40
+ if (keys.length !== 1)
41
+ return null;
42
+ const [identityKey] = keys;
43
+ if (!GROK_IDENTITY_KEY_RE.test(identityKey))
44
+ return null;
45
+ const value = raw[identityKey];
46
+ if (value === null || typeof value !== "object" || Array.isArray(value))
47
+ return null;
48
+ return { identityKey, value: value };
49
+ }
50
+ /** True when the payload value holds the two fields a run needs to authenticate. */
51
+ export function hasUsableGrokAuthValue(value) {
52
+ const key = value.key;
53
+ const refreshToken = value.refresh_token;
54
+ return (typeof key === "string" &&
55
+ key.trim().length > 0 &&
56
+ typeof refreshToken === "string" &&
57
+ refreshToken.trim().length > 0);
58
+ }
59
+ /**
60
+ * True when `home` has a usable `auth.json`: a single `<issuer>::<uuid>`
61
+ * top-level key whose value holds a non-empty `key` and `refresh_token`. A
62
+ * missing file, invalid JSON, or an unusable shape all resolve false.
63
+ */
64
+ export async function grokHomeHasUsableAuth(home) {
65
+ const authPath = path.join(home, AUTH_FILE_NAME);
66
+ try {
67
+ const raw = await fs.readFile(authPath, "utf8");
68
+ const parsed = parseGrokAuthPayload(JSON.parse(raw));
69
+ return parsed !== null && hasUsableGrokAuthValue(parsed.value);
70
+ }
71
+ catch {
72
+ return false;
73
+ }
74
+ }
75
+ /**
76
+ * Resolves the managed Grok home directory. With a `companyId`, it resolves the
77
+ * company-scoped home under the Paperclip instance tree, the same isolation
78
+ * boundary `resolveManagedCodexHomeDir` uses. Without one, it resolves the
79
+ * instance-global home, which a promotion must never write.
80
+ */
81
+ export function resolveManagedGrokHomeDir(env, companyId) {
82
+ const instanceRoot = resolvePaperclipInstanceRootForAdapter({
83
+ homeDir: nonEmpty(env.PAPERCLIP_HOME) ?? undefined,
84
+ instanceId: nonEmpty(env.PAPERCLIP_INSTANCE_ID) ?? undefined,
85
+ env,
86
+ });
87
+ return companyId
88
+ ? path.resolve(instanceRoot, "companies", companyId, "grok-home")
89
+ : path.resolve(instanceRoot, "grok-home");
90
+ }
91
+ /**
92
+ * Reads `candidate` and dereferences a symlink to its target bytes. Returns
93
+ * null for a missing file or a dangling symlink (both resolve to `ENOENT`);
94
+ * any other read error propagates to the caller.
95
+ */
96
+ async function readFileBytesIfPresent(candidate) {
97
+ try {
98
+ return await fs.readFile(candidate);
99
+ }
100
+ catch (error) {
101
+ if (error.code === "ENOENT")
102
+ return null;
103
+ throw error;
104
+ }
105
+ }
106
+ /**
107
+ * Stages exactly {@link GROK_SYNC_ALLOWLIST} from `effectiveGrokHome` into a
108
+ * fresh private temp dir and returns its path, for registration as the sandbox
109
+ * `home` asset. Mirrors `stageCodexHomeForSync` in the codex-local adapter.
110
+ *
111
+ * - **The symlink is dereferenced to bytes** — the single-use `auth.json`
112
+ * credential (a symlink into the shared source home) lands as a real file,
113
+ * never a dangling link.
114
+ * - **A missing `auth.json` is not an error** — a company with no completed
115
+ * device login yet stages an empty directory.
116
+ * - **`mkdtemp` guarantees the staged dir is `0700`** on POSIX, and the staged
117
+ * `auth.json` is written `0600` (least privilege).
118
+ * - **Fail-closed** — any *unexpected* I/O error removes the partial temp dir
119
+ * and re-throws, so a run never proceeds with a partial staged home.
120
+ *
121
+ * The caller owns removing the returned dir on run teardown.
122
+ */
123
+ export async function stageGrokHomeForSync(effectiveGrokHome, options = {}) {
124
+ const runIdPart = nonEmpty(options.runId ?? undefined);
125
+ const stagedHome = await fs.mkdtemp(path.join(os.tmpdir(), `paperclip-grok-home-sync-${runIdPart ? `${runIdPart}-` : ""}`));
126
+ try {
127
+ for (const entry of GROK_SYNC_ALLOWLIST) {
128
+ const bytes = await readFileBytesIfPresent(path.join(effectiveGrokHome, entry));
129
+ if (bytes === null)
130
+ continue;
131
+ const target = path.join(stagedHome, entry);
132
+ await fs.writeFile(target, bytes, { mode: 0o600 });
133
+ // Explicit chmod so the mode is 0600 regardless of the process umask.
134
+ await fs.chmod(target, 0o600);
135
+ }
136
+ return stagedHome;
137
+ }
138
+ catch (error) {
139
+ // Fail-closed: never hand back a partial staged home. Remove the temp dir
140
+ // we created before propagating the failure.
141
+ await fs.rm(stagedHome, { recursive: true, force: true }).catch(() => { });
142
+ throw error;
143
+ }
144
+ }
145
+ //# sourceMappingURL=grok-home.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grok-home.js","sourceRoot":"","sources":["../../src/server/grok-home.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=grok-home.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grok-home.test.d.ts","sourceRoot":"","sources":["../../src/server/grok-home.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,109 @@
1
+ import fs from "node:fs/promises";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { afterEach, describe, expect, it, vi } from "vitest";
5
+ import { GROK_SYNC_ALLOWLIST, stageGrokHomeForSync } from "./grok-home.js";
6
+ describe("GROK_SYNC_ALLOWLIST", () => {
7
+ it("holds exactly one name: auth.json", () => {
8
+ expect(GROK_SYNC_ALLOWLIST).toEqual(["auth.json"]);
9
+ });
10
+ });
11
+ describe("stageGrokHomeForSync", () => {
12
+ const cleanupDirs = [];
13
+ afterEach(async () => {
14
+ vi.restoreAllMocks();
15
+ while (cleanupDirs.length > 0) {
16
+ const dir = cleanupDirs.pop();
17
+ if (!dir)
18
+ continue;
19
+ await fs.rm(dir, { recursive: true, force: true }).catch(() => undefined);
20
+ }
21
+ });
22
+ async function makeRoot(prefix) {
23
+ const root = await fs.mkdtemp(path.join(os.tmpdir(), prefix));
24
+ cleanupDirs.push(root);
25
+ return root;
26
+ }
27
+ it("stages auth.json and stages no other file", async () => {
28
+ const root = await makeRoot("paperclip-grok-stage-");
29
+ const home = path.join(root, "grok-home");
30
+ await fs.mkdir(home, { recursive: true });
31
+ await fs.writeFile(path.join(home, "auth.json"), JSON.stringify({ ok: true }), "utf8");
32
+ // A decoy runtime file the allowlist must not pick up.
33
+ await fs.writeFile(path.join(home, "sessions.sqlite"), "decoy", "utf8");
34
+ const staged = await stageGrokHomeForSync(home, { runId: "run-1" });
35
+ cleanupDirs.push(staged);
36
+ expect(await fs.readdir(staged)).toEqual(["auth.json"]);
37
+ expect(await fs.readFile(path.join(staged, "auth.json"), "utf8")).toBe(JSON.stringify({ ok: true }));
38
+ });
39
+ it("creates the staged directory with mode 0700", async () => {
40
+ const root = await makeRoot("paperclip-grok-stage-dir-");
41
+ const home = path.join(root, "grok-home");
42
+ await fs.mkdir(home, { recursive: true });
43
+ await fs.writeFile(path.join(home, "auth.json"), "{}", "utf8");
44
+ const staged = await stageGrokHomeForSync(home, { runId: "run-dir" });
45
+ cleanupDirs.push(staged);
46
+ const mode = (await fs.stat(staged)).mode & 0o777;
47
+ expect(mode).toBe(0o700);
48
+ });
49
+ it("writes the staged auth.json with mode 0600", async () => {
50
+ const root = await makeRoot("paperclip-grok-stage-mode-");
51
+ const home = path.join(root, "grok-home");
52
+ await fs.mkdir(home, { recursive: true });
53
+ // Source file at a world-readable mode; the staged copy must still land 0600.
54
+ await fs.writeFile(path.join(home, "auth.json"), "{}", { mode: 0o644 });
55
+ const staged = await stageGrokHomeForSync(home, { runId: "run-mode" });
56
+ cleanupDirs.push(staged);
57
+ const mode = (await fs.stat(path.join(staged, "auth.json"))).mode & 0o777;
58
+ expect(mode).toBe(0o600);
59
+ });
60
+ it("dereferences an auth.json symlink to bytes", async () => {
61
+ const root = await makeRoot("paperclip-grok-stage-symlink-");
62
+ const home = path.join(root, "grok-home");
63
+ await fs.mkdir(home, { recursive: true });
64
+ const authSource = path.join(root, "shared-auth.json");
65
+ await fs.writeFile(authSource, JSON.stringify({ live: "token" }), "utf8");
66
+ await fs.symlink(authSource, path.join(home, "auth.json"));
67
+ const staged = await stageGrokHomeForSync(home, { runId: "run-symlink" });
68
+ cleanupDirs.push(staged);
69
+ const stagedAuthPath = path.join(staged, "auth.json");
70
+ expect(await fs.readFile(stagedAuthPath, "utf8")).toBe(JSON.stringify({ live: "token" }));
71
+ // The staged copy is a real file, not a symlink into the shared source.
72
+ expect((await fs.lstat(stagedAuthPath)).isSymbolicLink()).toBe(false);
73
+ });
74
+ it("treats an absent auth.json as absent", async () => {
75
+ const root = await makeRoot("paperclip-grok-stage-absent-");
76
+ const home = path.join(root, "grok-home");
77
+ await fs.mkdir(home, { recursive: true });
78
+ const staged = await stageGrokHomeForSync(home, { runId: "run-absent" });
79
+ cleanupDirs.push(staged);
80
+ expect(await fs.readdir(staged)).toEqual([]);
81
+ });
82
+ it("treats a dangling auth.json symlink as absent", async () => {
83
+ const root = await makeRoot("paperclip-grok-stage-dangling-");
84
+ const home = path.join(root, "grok-home");
85
+ await fs.mkdir(home, { recursive: true });
86
+ await fs.symlink(path.join(root, "gone", "auth.json"), path.join(home, "auth.json"));
87
+ const staged = await stageGrokHomeForSync(home, { runId: "run-dangling" });
88
+ cleanupDirs.push(staged);
89
+ expect(await fs.readdir(staged)).toEqual([]);
90
+ });
91
+ it("removes the staged directory on an unexpected error", async () => {
92
+ const root = await makeRoot("paperclip-grok-stage-fail-");
93
+ const home = path.join(root, "grok-home");
94
+ await fs.mkdir(home, { recursive: true });
95
+ await fs.writeFile(path.join(home, "auth.json"), "{}", "utf8");
96
+ let createdDir = null;
97
+ const realMkdtemp = fs.mkdtemp.bind(fs);
98
+ vi.spyOn(fs, "mkdtemp").mockImplementation(async (prefix, ...rest) => {
99
+ const dir = await realMkdtemp(prefix, ...rest);
100
+ createdDir = dir;
101
+ return dir;
102
+ });
103
+ vi.spyOn(fs, "readFile").mockRejectedValue(Object.assign(new Error("boom"), { code: "EACCES" }));
104
+ await expect(stageGrokHomeForSync(home, { runId: "run-fail" })).rejects.toThrow("boom");
105
+ expect(createdDir).not.toBeNull();
106
+ await expect(fs.access(createdDir)).rejects.toMatchObject({ code: "ENOENT" });
107
+ });
108
+ });
109
+ //# sourceMappingURL=grok-home.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grok-home.test.js","sourceRoot":"","sources":["../../src/server/grok-home.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { AdapterSessionCodec } from "@tickernelz/paperclip-pro-adapter-utils";
2
+ export declare const sessionCodec: AdapterSessionCodec;
3
+ export { execute } from "./execute.js";
4
+ export { listGrokSkills, syncGrokSkills } from "./skills.js";
5
+ export { testEnvironment } from "./test.js";
6
+ export { parseGrokJsonl, isGrokUnknownSessionError } from "./parse.js";
7
+ export { GROK_DEVICE_LOGIN_COMMAND, GROK_DEVICE_LOGIN_URL_ORIGIN, GROK_DEVICE_LOGIN_URL_PATH, parseGrokDeviceLoginPrompt, type DeviceLoginPrompt as GrokDeviceLoginPrompt, } from "./device-login-parse.js";
8
+ export { resolveManagedGrokHomeDir, grokHomeHasUsableAuth } from "./grok-home.js";
9
+ export { promoteGrokDeviceLoginCredential, checkStagedGrokCredentialReadiness, DeviceLoginReadinessError as GrokDeviceLoginReadinessError, type CredentialReadinessResult as GrokCredentialReadinessResult, type PromoteGrokDeviceLoginCredentialInput, type PromoteGrokDeviceLoginCredentialOutcome, } from "./adapter-auth-promotion.js";
10
+ export { decideGrokAuthMerge } from "./grok-auth-merge-decision.js";
11
+ export { parseGrokAuthPayload, hasUsableGrokAuthValue } from "./grok-home.js";
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAMnF,eAAO,MAAM,YAAY,EAAE,mBAsD1B,CAAC;AAEF,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,EACL,yBAAyB,EACzB,4BAA4B,EAC5B,0BAA0B,EAC1B,0BAA0B,EAC1B,KAAK,iBAAiB,IAAI,qBAAqB,GAChD,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAClF,OAAO,EACL,gCAAgC,EAChC,kCAAkC,EAClC,yBAAyB,IAAI,6BAA6B,EAC1D,KAAK,yBAAyB,IAAI,6BAA6B,EAC/D,KAAK,qCAAqC,EAC1C,KAAK,uCAAuC,GAC7C,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAEpE,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,67 @@
1
+ function readNonEmptyString(value) {
2
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
3
+ }
4
+ export const sessionCodec = {
5
+ deserialize(raw) {
6
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw))
7
+ return null;
8
+ const record = raw;
9
+ const sessionId = readNonEmptyString(record.sessionId) ??
10
+ readNonEmptyString(record.session_id) ??
11
+ readNonEmptyString(record.sessionID);
12
+ if (!sessionId)
13
+ return null;
14
+ const cwd = readNonEmptyString(record.cwd) ??
15
+ readNonEmptyString(record.workdir) ??
16
+ readNonEmptyString(record.folder);
17
+ const workspaceId = readNonEmptyString(record.workspaceId) ?? readNonEmptyString(record.workspace_id);
18
+ const repoUrl = readNonEmptyString(record.repoUrl) ?? readNonEmptyString(record.repo_url);
19
+ const repoRef = readNonEmptyString(record.repoRef) ?? readNonEmptyString(record.repo_ref);
20
+ return {
21
+ sessionId,
22
+ ...(cwd ? { cwd } : {}),
23
+ ...(workspaceId ? { workspaceId } : {}),
24
+ ...(repoUrl ? { repoUrl } : {}),
25
+ ...(repoRef ? { repoRef } : {}),
26
+ };
27
+ },
28
+ serialize(params) {
29
+ if (!params)
30
+ return null;
31
+ const sessionId = readNonEmptyString(params.sessionId) ??
32
+ readNonEmptyString(params.session_id) ??
33
+ readNonEmptyString(params.sessionID);
34
+ if (!sessionId)
35
+ return null;
36
+ const cwd = readNonEmptyString(params.cwd) ??
37
+ readNonEmptyString(params.workdir) ??
38
+ readNonEmptyString(params.folder);
39
+ const workspaceId = readNonEmptyString(params.workspaceId) ?? readNonEmptyString(params.workspace_id);
40
+ const repoUrl = readNonEmptyString(params.repoUrl) ?? readNonEmptyString(params.repo_url);
41
+ const repoRef = readNonEmptyString(params.repoRef) ?? readNonEmptyString(params.repo_ref);
42
+ return {
43
+ sessionId,
44
+ ...(cwd ? { cwd } : {}),
45
+ ...(workspaceId ? { workspaceId } : {}),
46
+ ...(repoUrl ? { repoUrl } : {}),
47
+ ...(repoRef ? { repoRef } : {}),
48
+ };
49
+ },
50
+ getDisplayId(params) {
51
+ if (!params)
52
+ return null;
53
+ return (readNonEmptyString(params.sessionId) ??
54
+ readNonEmptyString(params.session_id) ??
55
+ readNonEmptyString(params.sessionID));
56
+ },
57
+ };
58
+ export { execute } from "./execute.js";
59
+ export { listGrokSkills, syncGrokSkills } from "./skills.js";
60
+ export { testEnvironment } from "./test.js";
61
+ export { parseGrokJsonl, isGrokUnknownSessionError } from "./parse.js";
62
+ export { GROK_DEVICE_LOGIN_COMMAND, GROK_DEVICE_LOGIN_URL_ORIGIN, GROK_DEVICE_LOGIN_URL_PATH, parseGrokDeviceLoginPrompt, } from "./device-login-parse.js";
63
+ export { resolveManagedGrokHomeDir, grokHomeHasUsableAuth } from "./grok-home.js";
64
+ export { promoteGrokDeviceLoginCredential, checkStagedGrokCredentialReadiness, DeviceLoginReadinessError as GrokDeviceLoginReadinessError, } from "./adapter-auth-promotion.js";
65
+ export { decideGrokAuthMerge } from "./grok-auth-merge-decision.js";
66
+ export { parseGrokAuthPayload, hasUsableGrokAuthValue } from "./grok-home.js";
67
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export interface ParsedGrokJsonl {
2
+ sessionId: string | null;
3
+ summary: string;
4
+ thought: string;
5
+ errorMessage: string | null;
6
+ stopReason: string | null;
7
+ requestId: string | null;
8
+ inputTokens: number;
9
+ outputTokens: number;
10
+ cachedInputTokens: number;
11
+ costUsd: number | null;
12
+ }
13
+ export declare function parseGrokJsonl(stdout: string): ParsedGrokJsonl;
14
+ export declare function isGrokUnknownSessionError(stdout: string, stderr: string): boolean;
15
+ //# sourceMappingURL=parse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/server/parse.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAkBD,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe,CAkE9D;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAQjF"}
@@ -0,0 +1,93 @@
1
+ import { asNumber, asString, parseJson, parseObject } from "@tickernelz/paperclip-pro-adapter-utils/server-utils";
2
+ import { applyTurnBoundary, createTurnBoundaryState } from "../shared/turn-boundary.js";
3
+ function errorText(value) {
4
+ if (typeof value === "string")
5
+ return value;
6
+ const rec = parseObject(value);
7
+ const message = asString(rec.message, "").trim() ||
8
+ asString(rec.error, "").trim() ||
9
+ asString(rec.detail, "").trim() ||
10
+ asString(rec.code, "").trim();
11
+ if (message)
12
+ return message;
13
+ try {
14
+ return JSON.stringify(rec);
15
+ }
16
+ catch {
17
+ return "";
18
+ }
19
+ }
20
+ export function parseGrokJsonl(stdout) {
21
+ let sessionId = null;
22
+ let stopReason = null;
23
+ let requestId = null;
24
+ let errorMessage = null;
25
+ let inputTokens = 0;
26
+ let outputTokens = 0;
27
+ let cachedInputTokens = 0;
28
+ let costUsd = null;
29
+ const thoughtParts = [];
30
+ const textParts = [];
31
+ const thoughtBoundary = createTurnBoundaryState();
32
+ for (const rawLine of stdout.split(/\r?\n/)) {
33
+ const line = rawLine.trim();
34
+ if (!line)
35
+ continue;
36
+ const event = parseJson(line);
37
+ if (!event)
38
+ continue;
39
+ const type = asString(event.type, "").trim();
40
+ if (type === "thought") {
41
+ const text = asString(event.data, "");
42
+ if (text)
43
+ thoughtParts.push(applyTurnBoundary(thoughtBoundary, text));
44
+ continue;
45
+ }
46
+ if (type === "text") {
47
+ const text = asString(event.data, "");
48
+ if (text)
49
+ textParts.push(text);
50
+ continue;
51
+ }
52
+ if (type === "end") {
53
+ sessionId = asString(event.sessionId, "").trim() || sessionId;
54
+ stopReason = asString(event.stopReason, "").trim() || stopReason;
55
+ requestId = asString(event.requestId, "").trim() || requestId;
56
+ const usage = parseObject(event.usage);
57
+ inputTokens = asNumber(usage.input_tokens, inputTokens);
58
+ outputTokens = asNumber(usage.output_tokens, outputTokens);
59
+ cachedInputTokens = asNumber(usage.cache_read_input_tokens, cachedInputTokens);
60
+ const totalCostUsd = event.total_cost_usd;
61
+ if (typeof totalCostUsd === "number" && Number.isFinite(totalCostUsd)) {
62
+ costUsd = totalCostUsd;
63
+ }
64
+ continue;
65
+ }
66
+ if (type === "error") {
67
+ const text = errorText(event.error ?? event.message ?? event.detail ?? event.data).trim();
68
+ if (text)
69
+ errorMessage = text;
70
+ }
71
+ }
72
+ return {
73
+ sessionId,
74
+ summary: textParts.join("").trim(),
75
+ thought: thoughtParts.join("").trim(),
76
+ errorMessage,
77
+ stopReason,
78
+ requestId,
79
+ inputTokens,
80
+ outputTokens,
81
+ cachedInputTokens,
82
+ costUsd,
83
+ };
84
+ }
85
+ export function isGrokUnknownSessionError(stdout, stderr) {
86
+ const haystack = `${stdout}\n${stderr}`
87
+ .split(/\r?\n/)
88
+ .map((line) => line.trim())
89
+ .filter(Boolean)
90
+ .join("\n");
91
+ return /unknown\s+session|session(?:\s+.*)?\s+not\s+found|resume\s+.*\s+not\s+found|invalid\s+session/i.test(haystack);
92
+ }
93
+ //# sourceMappingURL=parse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/server/parse.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=parse.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.test.d.ts","sourceRoot":"","sources":["../../src/server/parse.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,82 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { isGrokUnknownSessionError, parseGrokJsonl } from "./parse.js";
3
+ describe("parseGrokJsonl", () => {
4
+ it("collects streamed thought/text content and final session metadata", () => {
5
+ const parsed = parseGrokJsonl([
6
+ JSON.stringify({ type: "thought", data: "Plan" }),
7
+ JSON.stringify({ type: "thought", data: " first." }),
8
+ JSON.stringify({ type: "text", data: "hel" }),
9
+ JSON.stringify({ type: "text", data: "lo" }),
10
+ JSON.stringify({ type: "end", stopReason: "EndTurn", sessionId: "sess-1", requestId: "req-1" }),
11
+ ].join("\n"));
12
+ expect(parsed).toEqual({
13
+ sessionId: "sess-1",
14
+ summary: "hello",
15
+ thought: "Plan first.",
16
+ errorMessage: null,
17
+ stopReason: "EndTurn",
18
+ requestId: "req-1",
19
+ inputTokens: 0,
20
+ outputTokens: 0,
21
+ cachedInputTokens: 0,
22
+ costUsd: null,
23
+ });
24
+ });
25
+ it("extracts token usage and cost from the end event", () => {
26
+ const parsed = parseGrokJsonl([
27
+ JSON.stringify({ type: "text", data: "hi" }),
28
+ JSON.stringify({
29
+ type: "end",
30
+ stopReason: "EndTurn",
31
+ sessionId: "sess-1",
32
+ requestId: "req-1",
33
+ usage: { input_tokens: 21560, output_tokens: 960, cache_read_input_tokens: 25216 },
34
+ total_cost_usd: 0.0564448,
35
+ }),
36
+ ].join("\n"));
37
+ expect(parsed.inputTokens).toBe(21560);
38
+ expect(parsed.outputTokens).toBe(960);
39
+ expect(parsed.cachedInputTokens).toBe(25216);
40
+ expect(parsed.costUsd).toBe(0.0564448);
41
+ });
42
+ it("reads structured error payloads", () => {
43
+ const parsed = parseGrokJsonl([
44
+ JSON.stringify({ type: "error", error: { message: "Authentication required" } }),
45
+ ].join("\n"));
46
+ expect(parsed.errorMessage).toBe("Authentication required");
47
+ });
48
+ it("separates reasoning turns that grok streaming-json glues together", () => {
49
+ // PAPA-349: at turn boundaries grok drops the newline between turns; the
50
+ // aggregated thought should still read as two paragraphs.
51
+ const parsed = parseGrokJsonl([
52
+ JSON.stringify({ type: "thought", data: "The user uses `" }),
53
+ JSON.stringify({ type: "thought", data: "ls" }),
54
+ JSON.stringify({ type: "thought", data: "`" }),
55
+ JSON.stringify({ type: "thought", data: "The" }),
56
+ JSON.stringify({ type: "thought", data: " `" }),
57
+ JSON.stringify({ type: "thought", data: "ls" }),
58
+ JSON.stringify({ type: "thought", data: "`" }),
59
+ JSON.stringify({ type: "thought", data: " returned" }),
60
+ JSON.stringify({ type: "end", stopReason: "EndTurn", sessionId: "sess-1" }),
61
+ ].join("\n"));
62
+ expect(parsed.thought).toBe("The user uses `ls`\nThe `ls` returned");
63
+ });
64
+ it("preserves assistant `text` chunks verbatim (no boundary heuristic)", () => {
65
+ // PAPA-349 review feedback: the turn-boundary helper is scoped to the
66
+ // reasoning stream only. Final assistant text is stored unmodified so
67
+ // user-visible responses cannot be reshaped by the heuristic.
68
+ const parsed = parseGrokJsonl([
69
+ JSON.stringify({ type: "text", data: "Done." }),
70
+ JSON.stringify({ type: "text", data: "Next" }),
71
+ JSON.stringify({ type: "end", stopReason: "EndTurn", sessionId: "sess-1" }),
72
+ ].join("\n"));
73
+ expect(parsed.summary).toBe("Done.Next");
74
+ });
75
+ });
76
+ describe("isGrokUnknownSessionError", () => {
77
+ it("detects stale resume failures", () => {
78
+ expect(isGrokUnknownSessionError("", "session not found")).toBe(true);
79
+ expect(isGrokUnknownSessionError("", "everything fine")).toBe(false);
80
+ });
81
+ });
82
+ //# sourceMappingURL=parse.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.test.js","sourceRoot":"","sources":["../../src/server/parse.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { AdapterSkillContext, AdapterSkillSnapshot } from "@tickernelz/paperclip-pro-adapter-utils";
2
+ export declare function listGrokSkills(ctx: AdapterSkillContext): Promise<AdapterSkillSnapshot>;
3
+ export declare function syncGrokSkills(ctx: AdapterSkillContext, _desiredSkills: string[]): Promise<AdapterSkillSnapshot>;
4
+ //# sourceMappingURL=skills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/server/skills.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EACrB,MAAM,yCAAyC,CAAC;AAsBjD,wBAAsB,cAAc,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAE5F;AAED,wBAAsB,cAAc,CAClC,GAAG,EAAE,mBAAmB,EACxB,cAAc,EAAE,MAAM,EAAE,GACvB,OAAO,CAAC,oBAAoB,CAAC,CAE/B"}
@@ -0,0 +1,21 @@
1
+ import path from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import { buildRuntimeMountedSkillSnapshot, readPaperclipRuntimeSkillEntries, resolveLegacyPaperclipDesiredSkillNames, } from "@tickernelz/paperclip-pro-adapter-utils/server-utils";
4
+ const __moduleDir = path.dirname(fileURLToPath(import.meta.url));
5
+ async function buildGrokSkillSnapshot(config) {
6
+ const availableEntries = await readPaperclipRuntimeSkillEntries(config, __moduleDir);
7
+ const desiredSkills = resolveLegacyPaperclipDesiredSkillNames(config, availableEntries);
8
+ return buildRuntimeMountedSkillSnapshot({
9
+ adapterType: "grok_local",
10
+ availableEntries,
11
+ desiredSkills,
12
+ configuredDetail: "Will be copied into `.claude/skills` in the execution workspace on the next run.",
13
+ });
14
+ }
15
+ export async function listGrokSkills(ctx) {
16
+ return buildGrokSkillSnapshot(ctx.config);
17
+ }
18
+ export async function syncGrokSkills(ctx, _desiredSkills) {
19
+ return buildGrokSkillSnapshot(ctx.config);
20
+ }
21
+ //# sourceMappingURL=skills.js.map