@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
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Paperclip AI
4
+ Copyright (c) 2026 Zhafron Adani Kautsar (paperclip-pro fork modifications)
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
@@ -0,0 +1,2 @@
1
+ export declare function printGrokStreamEvent(raw: string, _debug: boolean): void;
2
+ //# sourceMappingURL=format-event.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-event.d.ts","sourceRoot":"","sources":["../../src/cli/format-event.ts"],"names":[],"mappings":"AAWA,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CA+CvE"}
@@ -0,0 +1,55 @@
1
+ import pc from "picocolors";
2
+ function asRecord(value) {
3
+ if (typeof value !== "object" || value === null || Array.isArray(value))
4
+ return null;
5
+ return value;
6
+ }
7
+ function asString(value, fallback = "") {
8
+ return typeof value === "string" ? value : fallback;
9
+ }
10
+ export function printGrokStreamEvent(raw, _debug) {
11
+ const line = raw.trim();
12
+ if (!line)
13
+ return;
14
+ let parsed = null;
15
+ try {
16
+ parsed = JSON.parse(line);
17
+ }
18
+ catch {
19
+ console.log(line);
20
+ return;
21
+ }
22
+ const type = asString(parsed.type).trim();
23
+ if (type === "thought") {
24
+ const text = asString(parsed.data);
25
+ if (text)
26
+ console.log(pc.gray(`thinking: ${text}`));
27
+ return;
28
+ }
29
+ if (type === "text") {
30
+ const text = asString(parsed.data);
31
+ if (text)
32
+ console.log(pc.green(`assistant: ${text}`));
33
+ return;
34
+ }
35
+ if (type === "end") {
36
+ const stopReason = asString(parsed.stopReason);
37
+ const sessionId = asString(parsed.sessionId);
38
+ const details = [stopReason ? `stopReason=${stopReason}` : "", sessionId ? `session=${sessionId}` : ""]
39
+ .filter(Boolean)
40
+ .join(" ");
41
+ console.log(pc.blue(`Grok run completed${details ? ` (${details})` : ""}`));
42
+ return;
43
+ }
44
+ if (type === "error") {
45
+ const text = asString(parsed.data) ||
46
+ asString(parsed.message) ||
47
+ asString(parsed.error) ||
48
+ "Grok error";
49
+ console.log(pc.red(`error: ${text}`));
50
+ return;
51
+ }
52
+ const payload = asRecord(parsed);
53
+ console.log(pc.gray(`event: ${type || "unknown"} ${payload ? JSON.stringify(payload) : line}`));
54
+ }
55
+ //# sourceMappingURL=format-event.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-event.js","sourceRoot":"","sources":["../../src/cli/format-event.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=format-event.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-event.test.d.ts","sourceRoot":"","sources":["../../src/cli/format-event.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,19 @@
1
+ import { afterEach, describe, expect, it, vi } from "vitest";
2
+ import { printGrokStreamEvent } from "./format-event.js";
3
+ describe("printGrokStreamEvent", () => {
4
+ const spy = vi.spyOn(console, "log").mockImplementation(() => { });
5
+ afterEach(() => {
6
+ spy.mockClear();
7
+ });
8
+ it("prints thought/text/end events", () => {
9
+ printGrokStreamEvent(JSON.stringify({ type: "thought", data: "Plan" }), false);
10
+ printGrokStreamEvent(JSON.stringify({ type: "text", data: "hello" }), false);
11
+ printGrokStreamEvent(JSON.stringify({ type: "end", stopReason: "EndTurn", sessionId: "sess-1" }), false);
12
+ expect(spy.mock.calls.flat()).toEqual(expect.arrayContaining([
13
+ expect.stringContaining("thinking: Plan"),
14
+ expect.stringContaining("assistant: hello"),
15
+ expect.stringContaining("Grok run completed"),
16
+ ]));
17
+ });
18
+ });
19
+ //# sourceMappingURL=format-event.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-event.test.js","sourceRoot":"","sources":["../../src/cli/format-event.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAEzD,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,MAAM,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAElE,SAAS,CAAC,GAAG,EAAE;QACb,GAAG,CAAC,SAAS,EAAE,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,oBAAoB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;QAC/E,oBAAoB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;QAC7E,oBAAoB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;QAEzG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CACnC,MAAM,CAAC,eAAe,CAAC;YACrB,MAAM,CAAC,gBAAgB,CAAC,gBAAgB,CAAC;YACzC,MAAM,CAAC,gBAAgB,CAAC,kBAAkB,CAAC;YAC3C,MAAM,CAAC,gBAAgB,CAAC,oBAAoB,CAAC;SAC9C,CAAC,CACH,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { printGrokStreamEvent } from "./format-event.js";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { printGrokStreamEvent } from "./format-event.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,10 @@
1
+ export declare const type = "grok_local";
2
+ export declare const label = "Grok Build";
3
+ export declare const DEFAULT_GROK_LOCAL_MODEL = "grok-build";
4
+ export declare const models: {
5
+ id: string;
6
+ label: string;
7
+ }[];
8
+ export declare function grokLocalReasoningEffortsForModel(model: string): readonly string[];
9
+ export declare const agentConfigurationDoc = "# grok_local agent configuration\n\nAdapter: grok_local\n\nUse when:\n- You want Paperclip to run the native Grok Build CLI locally on the host machine\n- You want resumable Grok sessions across heartbeats via `--resume`\n- You want Paperclip-managed instructions and skills staged into the execution workspace using Grok's native discovery paths (`Agents.md` and `.claude/skills`)\n\nDon't use when:\n- You need a webhook-style external invocation (use http or openclaw_gateway)\n- You only need a one-shot script without an AI coding agent loop (use process)\n- Grok CLI is not installed or authenticated on the machine that runs Paperclip\n\nCore fields:\n- cwd (string, optional): default absolute working directory fallback for the agent process (created if missing when possible)\n- instructionsFilePath (string, optional): absolute path to a markdown instructions file. Paperclip stages it into the execution workspace as `Agents.md` when safe, otherwise falls back to `--rules @file`\n- promptTemplate (string, optional): run prompt template\n- model (string, optional): Grok model id. Defaults to grok-build.\n- permissionMode (string, optional): Grok permission mode passed via `--permission-mode`. Unset by default: Grok >= 1.0 enforces `dontAsk` as deny-by-default and it overrides `--always-approve`, so unattended runs rely on `--always-approve` alone unless you explicitly need a mode\n- reasoningEffort (string, optional): Grok reasoning effort (low|medium|high; grok-4.7 and grok-4.6 also accept xhigh) passed via `--reasoning-effort`\n- maxTurns (number, optional): maximum agent turns for the run\n- command (string, optional): defaults to \"grok\"\n- extraArgs (string[], optional): additional CLI args\n- env (object, optional): KEY=VALUE environment variables\n\nOperational fields:\n- timeoutSec (number, optional): run timeout in seconds\n- graceSec (number, optional): SIGTERM grace period in seconds\n\nNotes:\n- Runs use `grok --single` with `--output-format streaming-json`.\n- Sessions resume with `--resume <sessionId>` when the saved session cwd matches the current cwd.\n- Paperclip stages desired runtime skills into `.claude/skills` inside the execution workspace so Grok discovers them as project skills.\n- Use `grok models` to inspect authentication and available models on the host.\n- Local subscription runs use the host `grok login` (`~/.grok`) until the company Grok home has a usable `auth.json` (sandbox device login). `XAI_API_KEY` authenticates without a home. Remote/sandbox runs never fall back to the host login.\n- Without a usable company login, local runs preserve an inherited or configured `GROK_HOME`. Managed AI connections keep their selected home. An explicit empty `XAI_API_KEY` clears an inherited key and selects subscription authentication.\n";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,IAAI,eAAe,CAAC;AACjC,eAAO,MAAM,KAAK,eAAe,CAAC;AAElC,eAAO,MAAM,wBAAwB,eAAe,CAAC;AAErD,eAAO,MAAM,MAAM;;;GAKlB,CAAC;AAEF,wBAAgB,iCAAiC,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAIlF;AAED,eAAO,MAAM,qBAAqB,yvFAqCjC,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,53 @@
1
+ export const type = "grok_local";
2
+ export const label = "Grok Build";
3
+ export const DEFAULT_GROK_LOCAL_MODEL = "grok-build";
4
+ export const models = [
5
+ { id: DEFAULT_GROK_LOCAL_MODEL, label: DEFAULT_GROK_LOCAL_MODEL },
6
+ { id: "grok-4.7", label: "Grok 4.7" },
7
+ { id: "grok-4.6", label: "Grok 4.6" },
8
+ { id: "grok-4.5", label: "Grok 4.5" },
9
+ ];
10
+ export function grokLocalReasoningEffortsForModel(model) {
11
+ return model.trim() === "grok-4.7" || model.trim() === "grok-4.6"
12
+ ? ["low", "medium", "high", "xhigh"]
13
+ : ["low", "medium", "high"];
14
+ }
15
+ export const agentConfigurationDoc = `# grok_local agent configuration
16
+
17
+ Adapter: grok_local
18
+
19
+ Use when:
20
+ - You want Paperclip to run the native Grok Build CLI locally on the host machine
21
+ - You want resumable Grok sessions across heartbeats via \`--resume\`
22
+ - You want Paperclip-managed instructions and skills staged into the execution workspace using Grok's native discovery paths (\`Agents.md\` and \`.claude/skills\`)
23
+
24
+ Don't use when:
25
+ - You need a webhook-style external invocation (use http or openclaw_gateway)
26
+ - You only need a one-shot script without an AI coding agent loop (use process)
27
+ - Grok CLI is not installed or authenticated on the machine that runs Paperclip
28
+
29
+ Core fields:
30
+ - cwd (string, optional): default absolute working directory fallback for the agent process (created if missing when possible)
31
+ - instructionsFilePath (string, optional): absolute path to a markdown instructions file. Paperclip stages it into the execution workspace as \`Agents.md\` when safe, otherwise falls back to \`--rules @file\`
32
+ - promptTemplate (string, optional): run prompt template
33
+ - model (string, optional): Grok model id. Defaults to grok-build.
34
+ - permissionMode (string, optional): Grok permission mode passed via \`--permission-mode\`. Unset by default: Grok >= 1.0 enforces \`dontAsk\` as deny-by-default and it overrides \`--always-approve\`, so unattended runs rely on \`--always-approve\` alone unless you explicitly need a mode
35
+ - reasoningEffort (string, optional): Grok reasoning effort (low|medium|high; grok-4.7 and grok-4.6 also accept xhigh) passed via \`--reasoning-effort\`
36
+ - maxTurns (number, optional): maximum agent turns for the run
37
+ - command (string, optional): defaults to "grok"
38
+ - extraArgs (string[], optional): additional CLI args
39
+ - env (object, optional): KEY=VALUE environment variables
40
+
41
+ Operational fields:
42
+ - timeoutSec (number, optional): run timeout in seconds
43
+ - graceSec (number, optional): SIGTERM grace period in seconds
44
+
45
+ Notes:
46
+ - Runs use \`grok --single\` with \`--output-format streaming-json\`.
47
+ - Sessions resume with \`--resume <sessionId>\` when the saved session cwd matches the current cwd.
48
+ - Paperclip stages desired runtime skills into \`.claude/skills\` inside the execution workspace so Grok discovers them as project skills.
49
+ - Use \`grok models\` to inspect authentication and available models on the host.
50
+ - Local subscription runs use the host \`grok login\` (\`~/.grok\`) until the company Grok home has a usable \`auth.json\` (sandbox device login). \`XAI_API_KEY\` authenticates without a home. Remote/sandbox runs never fall back to the host login.
51
+ - Without a usable company login, local runs preserve an inherited or configured \`GROK_HOME\`. Managed AI connections keep their selected home. An explicit empty \`XAI_API_KEY\` clears an inherited key and selects subscription authentication.
52
+ `;
53
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,IAAI,GAAG,YAAY,CAAC;AACjC,MAAM,CAAC,MAAM,KAAK,GAAG,YAAY,CAAC;AAElC,MAAM,CAAC,MAAM,wBAAwB,GAAG,YAAY,CAAC;AAErD,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,EAAE,EAAE,EAAE,wBAAwB,EAAE,KAAK,EAAE,wBAAwB,EAAE;IACjE,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE;IACrC,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE;IACrC,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE;CACtC,CAAC;AAEF,MAAM,UAAU,iCAAiC,CAAC,KAAa;IAC7D,OAAO,KAAK,CAAC,IAAI,EAAE,KAAK,UAAU,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,UAAU;QAC/D,CAAC,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC;QACpC,CAAC,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,CAAC,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqCpC,CAAC"}
@@ -0,0 +1,87 @@
1
+ import { type GrokAuthPayload } from "./grok-home.js";
2
+ /** The independent readiness result for the exact staged credential. */
3
+ export interface CredentialReadinessResult {
4
+ /** True when a run launched now with this exact credential would authenticate. */
5
+ ready: boolean;
6
+ /** An optional non-secret reason code for a non-ready result. */
7
+ reason?: string;
8
+ }
9
+ /** Thrown when the independent readiness check does not return a ready result.
10
+ * The service maps this to a failed session and still deletes the sandbox. */
11
+ export declare class DeviceLoginReadinessError extends Error {
12
+ readonly reason: string;
13
+ constructor(reason: string);
14
+ }
15
+ /**
16
+ * The independent readiness check for a staged Grok device-login credential. It
17
+ * runs on the exact staged bytes, before any promotion write. It writes the
18
+ * bytes to a throwaway private home and runs the same usable-auth predicate the
19
+ * execute path uses. It always removes the throwaway home before it returns.
20
+ *
21
+ * It never uses the `grok models` exit code: that command exits `0` whether or
22
+ * not the user is authenticated, so it is not a usable auth signal.
23
+ */
24
+ export declare function checkStagedGrokCredentialReadiness(authBytes: Buffer): Promise<CredentialReadinessResult>;
25
+ /**
26
+ * Validates the bounded-size, single-identity-key auth shape. Rejects an
27
+ * empty, an oversized, an invalid-JSON, a no-key, a multi-key, and an
28
+ * unusable-value payload. Never puts credential bytes into the thrown error.
29
+ */
30
+ export declare function assertUsableGrokAuthShape(authBytes: Buffer): GrokAuthPayload;
31
+ /**
32
+ * The promotion outcome.
33
+ *
34
+ * - `promoted`: the helper wrote the company home, either seeding an empty home
35
+ * or installing a strictly-newer same-account credential.
36
+ * - `kept`: the login carried the SAME account as the company home, and the
37
+ * home already held a same-identity credential that is not older than the
38
+ * one this login produced (a tie, or the home credential is newer), so the
39
+ * helper kept the home. This IS a successful authentication: a later run
40
+ * vends and uses the same account.
41
+ * - `kept_foreign_identity`: the company home is occupied and this step could
42
+ * not confirm it holds the same account — either a DIFFERENT account already
43
+ * occupies it, or the existing file is present but this step cannot read it
44
+ * as a usable Grok credential (an unreadable or unparseable file fails
45
+ * closed the same way). The helper never clobbers an occupied home, so it
46
+ * wrote nothing. This is NOT a successful authentication; the caller must
47
+ * fail the session.
48
+ * - `not_sole_owner`: the sole-active-owner gate rejected the write. Nothing
49
+ * was written.
50
+ * - `background_skipped`: the user-initiated gate rejected the write (an
51
+ * automatic background path never seeds a company slot). Nothing was written.
52
+ */
53
+ export type PromoteGrokDeviceLoginCredentialOutcome = "promoted" | "kept" | "kept_foreign_identity" | "not_sole_owner" | "background_skipped";
54
+ export interface PromoteGrokDeviceLoginCredentialInput {
55
+ /** The exact staged credential bytes the login sandbox produced. */
56
+ authBytes: Buffer;
57
+ /** The company that owns this login. It must be a single safe path segment. */
58
+ companyId: string;
59
+ /**
60
+ * True when a user started this login. Only a user-initiated login seeds the
61
+ * company slot; an automatic background path never seeds it.
62
+ */
63
+ userInitiated: boolean;
64
+ /**
65
+ * The independent, machine-readable readiness check. It runs on the exact
66
+ * staged credential before any write. A non-ready result rejects the
67
+ * promotion (the session fails), and the helper writes nothing.
68
+ */
69
+ checkReadiness: (authBytes: Buffer) => Promise<CredentialReadinessResult> | CredentialReadinessResult;
70
+ /**
71
+ * Resolves true only while this session still holds the sole active claim on
72
+ * `(company_id, adapter_type)`. The helper writes only when it resolves true.
73
+ */
74
+ isSoleActiveOwner: () => Promise<boolean> | boolean;
75
+ /** A non-leaking progress sink. It receives only fixed status lines. */
76
+ log: (line: string) => void | Promise<void>;
77
+ env?: NodeJS.ProcessEnv;
78
+ }
79
+ /**
80
+ * Promotes a Grok device-login credential into the company scope. The order is
81
+ * fixed: readiness check, credential validation, the user-initiated gate, the
82
+ * sole-active-owner gate, then the write. The readiness check and the write run
83
+ * while the caller still holds the active claim, so a second session cannot
84
+ * race the same slot.
85
+ */
86
+ export declare function promoteGrokDeviceLoginCredential(input: PromoteGrokDeviceLoginCredentialInput): Promise<PromoteGrokDeviceLoginCredentialOutcome>;
87
+ //# sourceMappingURL=adapter-auth-promotion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter-auth-promotion.d.ts","sourceRoot":"","sources":["../../src/server/adapter-auth-promotion.ts"],"names":[],"mappings":"AAKA,OAAO,EAKL,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AA8CxB,wEAAwE;AACxE,MAAM,WAAW,yBAAyB;IACxC,kFAAkF;IAClF,KAAK,EAAE,OAAO,CAAC;IACf,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;+EAC+E;AAC/E,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,YAAY,MAAM,EAAE,MAAM,EAIzB;CACF;AAOD;;;;;;;;GAQG;AACH,wBAAsB,kCAAkC,CACtD,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,yBAAyB,CAAC,CAepC;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,CAyB5E;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,MAAM,uCAAuC,GAC/C,UAAU,GACV,MAAM,GACN,uBAAuB,GACvB,gBAAgB,GAChB,oBAAoB,CAAC;AAEzB,MAAM,WAAW,qCAAqC;IACpD,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,aAAa,EAAE,OAAO,CAAC;IACvB;;;;OAIG;IACH,cAAc,EAAE,CACd,SAAS,EAAE,MAAM,KACd,OAAO,CAAC,yBAAyB,CAAC,GAAG,yBAAyB,CAAC;IACpE;;;OAGG;IACH,iBAAiB,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IACpD,wEAAwE;IACxE,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAyHD;;;;;;GAMG;AACH,wBAAsB,gCAAgC,CACpD,KAAK,EAAE,qCAAqC,GAC3C,OAAO,CAAC,uCAAuC,CAAC,CAgGlD"}
@@ -0,0 +1,294 @@
1
+ import { chmod, mkdir, mkdtemp, open, readFile, rename, rm, writeFile } from "node:fs/promises";
2
+ import { randomUUID } from "node:crypto";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import { withDirectoryMergeLock } from "@tickernelz/paperclip-pro-adapter-utils/workspace-restore-merge";
6
+ import { grokHomeHasUsableAuth, parseGrokAuthPayload, hasUsableGrokAuthValue, resolveManagedGrokHomeDir, } from "./grok-home.js";
7
+ import { USE_SOURCE_EXIT, decideGrokAuthMerge } from "./grok-auth-merge-decision.js";
8
+ // The Grok device-login credential promotion. It runs after a successful
9
+ // device login, on the exact credential the login sandbox produced. It mirrors
10
+ // the fixed order the Codex promotion uses (see
11
+ // `packages/adapters/codex-local/src/server/adapter-auth-promotion.ts`):
12
+ // readiness check, credential validation, a user-initiated gate, a
13
+ // sole-active-owner gate, then the write.
14
+ //
15
+ // Grok needs no per-identity cache, but it does need a "strictly newer" merge
16
+ // decision: a completed device login is NOT always the newest state for the
17
+ // account it logs in, because a teardown copy-back can install a fresher
18
+ // same-identity credential (see `grok-auth-copyback.ts`) while this session
19
+ // is still logging in. So the write step seeds an empty home, keeps the home
20
+ // untouched when a DIFFERENT account already occupies it, and for the SAME
21
+ // account runs the shared freshness predicate (`grok-auth-merge-decision.ts`)
22
+ // so it replaces the existing credential only when the login is strictly
23
+ // newer. The helper never writes the instance-global home, only the
24
+ // company-scoped one.
25
+ //
26
+ // The comparison-and-install step runs under `withDirectoryMergeLock` on the
27
+ // company Grok home, the same lock `copyBackGrokAuth` (see
28
+ // `grok-auth-copyback.ts`) takes on the same directory at teardown. Both
29
+ // resolve the lock key from the directory's canonical real path, so a
30
+ // promotion and a teardown copy-back for the same company can never
31
+ // interleave their read-decide-write sections.
32
+ //
33
+ // The helper treats the whole credential value as a secret: it never logs a
34
+ // token, a refresh token, or a personal field (email, name, user id).
35
+ const AUTH_FILE_NAME = "auth.json";
36
+ // A private directory (owner rwx only), reused from
37
+ // packages/adapters/codex-local/src/server/adapter-auth-promotion.ts:37-38.
38
+ const PRIVATE_DIR_MODE = 0o700;
39
+ // A private file (owner rw only). The write calls `chmod` after the write, so
40
+ // the process umask can never widen it — the same pattern
41
+ // packages/adapters/codex-local/src/server/codex-home.ts:524-526 uses for a
42
+ // staged credential file.
43
+ const PRIVATE_FILE_MODE = 0o600;
44
+ // A bounded size for the credential payload, mirroring
45
+ // packages/adapters/codex-local/src/server/device-login-export.ts's
46
+ // `MAX_AUTH_JSON_BYTES`. A real `auth.json` is a few kilobytes.
47
+ const MAX_AUTH_JSON_BYTES = 64 * 1024;
48
+ /** Thrown when the independent readiness check does not return a ready result.
49
+ * The service maps this to a failed session and still deletes the sandbox. */
50
+ export class DeviceLoginReadinessError extends Error {
51
+ reason;
52
+ constructor(reason) {
53
+ super(`grok device-login promotion: the readiness check did not pass (${reason})`);
54
+ this.name = "DeviceLoginReadinessError";
55
+ this.reason = reason;
56
+ }
57
+ }
58
+ // A private directory (owner rwx only) for the throwaway readiness home.
59
+ const READINESS_HOME_DIR_MODE = 0o700;
60
+ // A private file (owner rw only) for the throwaway readiness credential.
61
+ const READINESS_AUTH_FILE_MODE = 0o600;
62
+ /**
63
+ * The independent readiness check for a staged Grok device-login credential. It
64
+ * runs on the exact staged bytes, before any promotion write. It writes the
65
+ * bytes to a throwaway private home and runs the same usable-auth predicate the
66
+ * execute path uses. It always removes the throwaway home before it returns.
67
+ *
68
+ * It never uses the `grok models` exit code: that command exits `0` whether or
69
+ * not the user is authenticated, so it is not a usable auth signal.
70
+ */
71
+ export async function checkStagedGrokCredentialReadiness(authBytes) {
72
+ if (authBytes.length === 0) {
73
+ return { ready: false, reason: "empty_credential" };
74
+ }
75
+ const scratchHome = await mkdtemp(path.join(os.tmpdir(), "paperclip-grok-login-readiness-"));
76
+ try {
77
+ await mkdir(scratchHome, { recursive: true, mode: READINESS_HOME_DIR_MODE });
78
+ await writeFile(path.join(scratchHome, AUTH_FILE_NAME), authBytes, {
79
+ mode: READINESS_AUTH_FILE_MODE,
80
+ });
81
+ const ready = await grokHomeHasUsableAuth(scratchHome);
82
+ return ready ? { ready: true } : { ready: false, reason: "no_usable_auth" };
83
+ }
84
+ finally {
85
+ await rm(scratchHome, { recursive: true, force: true }).catch(() => { });
86
+ }
87
+ }
88
+ /**
89
+ * Validates the bounded-size, single-identity-key auth shape. Rejects an
90
+ * empty, an oversized, an invalid-JSON, a no-key, a multi-key, and an
91
+ * unusable-value payload. Never puts credential bytes into the thrown error.
92
+ */
93
+ export function assertUsableGrokAuthShape(authBytes) {
94
+ if (authBytes.length === 0) {
95
+ throw new Error("grok device-login promotion: refused an empty auth payload");
96
+ }
97
+ if (authBytes.length > MAX_AUTH_JSON_BYTES) {
98
+ throw new Error("grok device-login promotion: refused an oversized auth payload");
99
+ }
100
+ let parsedJson;
101
+ try {
102
+ parsedJson = JSON.parse(authBytes.toString("utf8"));
103
+ }
104
+ catch {
105
+ throw new Error("grok device-login promotion: refused invalid JSON");
106
+ }
107
+ const payload = parseGrokAuthPayload(parsedJson);
108
+ if (!payload) {
109
+ throw new Error("grok device-login promotion: refused a payload with no single <issuer>::<uuid> key");
110
+ }
111
+ if (!hasUsableGrokAuthValue(payload.value)) {
112
+ throw new Error("grok device-login promotion: refused a credential with no usable key and refresh_token");
113
+ }
114
+ return payload;
115
+ }
116
+ /** Rejects an empty or unsafe `companyId`, so a promotion can never resolve the
117
+ * instance-global home (`resolveManagedGrokHomeDir` with no `companyId`) or
118
+ * escape the company tree. */
119
+ function requireSafeCompanyId(companyId) {
120
+ const trimmed = typeof companyId === "string" ? companyId.trim() : "";
121
+ if (trimmed.length === 0) {
122
+ throw new Error("grok device-login promotion: companyId is empty");
123
+ }
124
+ if (trimmed === "." || trimmed === "..") {
125
+ throw new Error("grok device-login promotion: companyId is a relative path segment");
126
+ }
127
+ if (trimmed.includes("/") || trimmed.includes("\\") || trimmed.includes("\0")) {
128
+ throw new Error("grok device-login promotion: companyId contains a path separator");
129
+ }
130
+ return trimmed;
131
+ }
132
+ function isEnoentError(error) {
133
+ return typeof error === "object" && error !== null && error.code === "ENOENT";
134
+ }
135
+ /** Reads the existing home's state at `authPath`. A read failure other than
136
+ * a missing file, an invalid-JSON payload, or a non-Grok payload all
137
+ * resolve to `unreadable`, so the caller fails closed on any of them. Only
138
+ * a missing file resolves to `absent`. */
139
+ async function readExistingHomeState(authPath) {
140
+ let existingBytes;
141
+ try {
142
+ existingBytes = await readFile(authPath);
143
+ }
144
+ catch (error) {
145
+ return isEnoentError(error) ? { kind: "absent" } : { kind: "unreadable" };
146
+ }
147
+ let existingJson;
148
+ try {
149
+ existingJson = JSON.parse(existingBytes.toString("utf8"));
150
+ }
151
+ catch {
152
+ return { kind: "unreadable" };
153
+ }
154
+ const payload = parseGrokAuthPayload(existingJson);
155
+ return payload ? { kind: "identity", identityKey: payload.identityKey } : { kind: "unreadable" };
156
+ }
157
+ /**
158
+ * Writes `authBytes` to `authPath` atomically. It stages the bytes into a
159
+ * private (0600) temporary file in the same directory, then renames that
160
+ * file over `authPath`. The rename is an atomic same-directory swap, so a
161
+ * reader never observes a torn file, and a process that stops mid-write
162
+ * leaves the destination untouched. The temporary file is always removed,
163
+ * so a failed write never leaves stray bytes behind.
164
+ */
165
+ async function writeAuthFileAtomically(authPath, authBytes) {
166
+ const stagedTempPath = path.join(path.dirname(authPath), `.auth-${process.pid}-${randomUUID()}.tmp`);
167
+ // `wx` + explicit mode create the temp file private (0600) and fail if it
168
+ // already exists, so the write never goes through a pre-existing symlink.
169
+ const handle = await open(stagedTempPath, "wx", PRIVATE_FILE_MODE);
170
+ try {
171
+ await handle.writeFile(authBytes);
172
+ await handle.close();
173
+ await rename(stagedTempPath, authPath);
174
+ await chmod(authPath, PRIVATE_FILE_MODE);
175
+ }
176
+ finally {
177
+ await handle.close().catch(() => undefined);
178
+ await rm(stagedTempPath, { force: true }).catch(() => undefined);
179
+ }
180
+ }
181
+ /**
182
+ * Runs the shared freshness predicate (the same one `copyBackGrokAuth` uses)
183
+ * and installs `authBytes` over `authPath` only on a use-source decision. It
184
+ * stages `authBytes` into a private (0600) temporary file next to `authPath`,
185
+ * so the predicate can compare both sides by path, then renames that file
186
+ * over `authPath` on a use-source decision. The staged temp is always
187
+ * removed: the rename consumes it on the write path, and the `finally`
188
+ * removes it otherwise. Returns true when it wrote, false when it kept the
189
+ * existing file.
190
+ */
191
+ async function writeSameIdentityCredentialIfFresher(authBytes, authPath) {
192
+ const stagedTempPath = path.join(path.dirname(authPath), `.auth-${process.pid}-${randomUUID()}.tmp`);
193
+ const handle = await open(stagedTempPath, "wx", PRIVATE_FILE_MODE);
194
+ try {
195
+ await handle.writeFile(authBytes);
196
+ await handle.close();
197
+ const decision = await decideGrokAuthMerge(stagedTempPath, authPath, {
198
+ errorLabel: "grok device-login promotion",
199
+ });
200
+ if (decision !== USE_SOURCE_EXIT) {
201
+ return false;
202
+ }
203
+ await rename(stagedTempPath, authPath);
204
+ await chmod(authPath, PRIVATE_FILE_MODE);
205
+ return true;
206
+ }
207
+ finally {
208
+ await handle.close().catch(() => undefined);
209
+ await rm(stagedTempPath, { force: true }).catch(() => undefined);
210
+ }
211
+ }
212
+ /**
213
+ * Promotes a Grok device-login credential into the company scope. The order is
214
+ * fixed: readiness check, credential validation, the user-initiated gate, the
215
+ * sole-active-owner gate, then the write. The readiness check and the write run
216
+ * while the caller still holds the active claim, so a second session cannot
217
+ * race the same slot.
218
+ */
219
+ export async function promoteGrokDeviceLoginCredential(input) {
220
+ const { authBytes, userInitiated, checkReadiness, isSoleActiveOwner, log } = input;
221
+ const env = input.env ?? process.env;
222
+ const companyId = requireSafeCompanyId(input.companyId);
223
+ // 1. Independent readiness check on the exact staged credential. A non-ready
224
+ // result rejects the promotion before any validation or write.
225
+ const readiness = await checkReadiness(authBytes);
226
+ if (!readiness.ready) {
227
+ throw new DeviceLoginReadinessError(readiness.reason ?? "not_ready");
228
+ }
229
+ // 2. Validate the credential shape: the single `<issuer>::<uuid>` key, and a
230
+ // usable `key` and `refresh_token` in its value.
231
+ const payload = assertUsableGrokAuthShape(authBytes);
232
+ // 3. Only a user-initiated login seeds the company slot.
233
+ if (!userInitiated) {
234
+ await log("[paperclip] Grok device-login promotion: skipped (an automatic background login never seeds a company slot).");
235
+ return "background_skipped";
236
+ }
237
+ // 4. Write only while the session still owns the active slot.
238
+ const soleOwner = await isSoleActiveOwner();
239
+ if (!soleOwner) {
240
+ await log("[paperclip] Grok device-login promotion: skipped (the session no longer holds the sole active claim on the slot).");
241
+ return "not_sole_owner";
242
+ }
243
+ // 5. Never clobber an occupied home. A present file that this step cannot
244
+ // read as the same identity — absent from a read failure, invalid JSON,
245
+ // or a non-Grok payload — is treated as a foreign identity, so the
246
+ // promotion fails closed and writes nothing.
247
+ //
248
+ // 6. Write the company credential home. `mkdir` applies `mode` only when it
249
+ // creates the directory, so an explicit `chmod` follows it. This keeps
250
+ // the directory mode exact both for a new home and for a home that
251
+ // already existed at a broader mode. An empty home is always seeded. A
252
+ // home that already holds the SAME identity is refreshed only when the
253
+ // login is strictly newer than the existing credential — the shared
254
+ // freshness predicate in `grok-auth-merge-decision.ts` decides this, the
255
+ // same predicate the teardown copy-back uses, so a fresher remote
256
+ // copy-back credential can never lose to an older device login. Every
257
+ // write is atomic: it stages the bytes into a private temporary file in
258
+ // the same directory, then renames that file over `auth.json`.
259
+ //
260
+ // Steps 5 and 6 run under `withDirectoryMergeLock` on the company home, the
261
+ // same lock the teardown copy-back takes on the same directory (see
262
+ // `grok-auth-copyback.ts`). The directory must exist before the lock can
263
+ // resolve a canonical real path, so `mkdir` runs once, up front, at the
264
+ // final private mode; a home that already exists keeps its current mode
265
+ // until the write path below re-asserts it.
266
+ const companyHome = resolveManagedGrokHomeDir(env, companyId);
267
+ await mkdir(companyHome, { recursive: true, mode: PRIVATE_DIR_MODE });
268
+ return await withDirectoryMergeLock(companyHome, async (canonicalCompanyHome) => {
269
+ const authPath = path.join(canonicalCompanyHome, AUTH_FILE_NAME);
270
+ const existingState = await readExistingHomeState(authPath);
271
+ if (existingState.kind === "unreadable") {
272
+ await log("[paperclip] Grok device-login promotion: kept the company credential home (the existing file is present but this step cannot read it as a usable Grok credential).");
273
+ return "kept_foreign_identity";
274
+ }
275
+ if (existingState.kind === "identity" && existingState.identityKey !== payload.identityKey) {
276
+ await log("[paperclip] Grok device-login promotion: kept the company credential home (the login is a different account than the one already set for this company).");
277
+ return "kept_foreign_identity";
278
+ }
279
+ await chmod(canonicalCompanyHome, PRIVATE_DIR_MODE);
280
+ if (existingState.kind === "identity") {
281
+ const wrote = await writeSameIdentityCredentialIfFresher(authBytes, authPath);
282
+ if (!wrote) {
283
+ await log("[paperclip] Grok device-login promotion: kept the company credential home (the existing same-identity credential is not older than the device-login credential).");
284
+ return "kept";
285
+ }
286
+ await log("[paperclip] Grok device-login promotion: wrote the company credential home at mode 0600.");
287
+ return "promoted";
288
+ }
289
+ await writeAuthFileAtomically(authPath, authBytes);
290
+ await log("[paperclip] Grok device-login promotion: wrote the company credential home at mode 0600.");
291
+ return "promoted";
292
+ }, env);
293
+ }
294
+ //# sourceMappingURL=adapter-auth-promotion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter-auth-promotion.js","sourceRoot":"","sources":["../../src/server/adapter-auth-promotion.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=adapter-auth-promotion.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter-auth-promotion.test.d.ts","sourceRoot":"","sources":["../../src/server/adapter-auth-promotion.test.ts"],"names":[],"mappings":""}