opencode-claude-auth 0.5.2 → 0.5.4

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAY,MAAM,qBAAqB,CAAA;AAqF3D,QAAA,MAAM,MAAM,EAAE,MAuDb,CAAA;AAED,eAAe,MAAM,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAqEjD,QAAA,MAAM,MAAM,EAAE,MAmCb,CAAA;AAED,eAAe,MAAM,CAAA"}
package/dist/index.js CHANGED
@@ -1,28 +1,39 @@
1
1
  import { execSync } from "node:child_process";
2
- import { existsSync, readFileSync, writeFileSync } from "node:fs";
3
- import { fileURLToPath } from "node:url";
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
4
3
  import { dirname, join } from "node:path";
5
4
  import { homedir } from "node:os";
6
5
  import { readClaudeCredentials } from "./keychain.js";
7
- function clearOpencodeAuth() {
8
- const authPaths = [
9
- join(homedir(), ".local", "share", "opencode", "auth.json"),
10
- join(process.env.APPDATA ?? homedir(), "opencode", "auth.json"),
11
- join(homedir(), ".opencode", "auth.json"),
12
- ];
13
- for (const path of authPaths) {
14
- try {
15
- if (existsSync(path)) {
16
- const raw = readFileSync(path, "utf-8");
17
- const auth = JSON.parse(raw);
18
- delete auth.anthropic;
19
- writeFileSync(path, JSON.stringify(auth), "utf-8");
6
+ function getAuthJsonPath() {
7
+ if (process.platform === "win32") {
8
+ return join(process.env.USERPROFILE ?? homedir(), ".local", "share", "opencode", "auth.json");
9
+ }
10
+ return join(homedir(), ".local", "share", "opencode", "auth.json");
11
+ }
12
+ function syncAuthJson(creds) {
13
+ const authPath = getAuthJsonPath();
14
+ let auth = {};
15
+ if (existsSync(authPath)) {
16
+ const raw = readFileSync(authPath, "utf-8").trim();
17
+ if (raw) {
18
+ try {
19
+ auth = JSON.parse(raw);
20
+ }
21
+ catch {
22
+ // Malformed file, start fresh
20
23
  }
21
- }
22
- catch {
23
- // Non-fatal: may not have write permissions
24
24
  }
25
25
  }
26
+ auth.anthropic = {
27
+ type: "oauth",
28
+ access: creds.accessToken,
29
+ refresh: creds.refreshToken,
30
+ expires: creds.expiresAt,
31
+ };
32
+ const dir = dirname(authPath);
33
+ if (!existsSync(dir)) {
34
+ mkdirSync(dir, { recursive: true });
35
+ }
36
+ writeFileSync(authPath, JSON.stringify(auth, null, 2), "utf-8");
26
37
  }
27
38
  function refreshViaCli() {
28
39
  try {
@@ -37,92 +48,49 @@ function refreshViaCli() {
37
48
  // Non-fatal: Claude CLI may not be available
38
49
  }
39
50
  }
40
- function loadSessionPrompt() {
41
- try {
42
- const dir = dirname(fileURLToPath(import.meta.url));
43
- const promptPath = join(dir, "anthropic-prompt.txt");
44
- return readFileSync(promptPath, "utf-8");
51
+ function refreshIfNeeded() {
52
+ let creds = readClaudeCredentials();
53
+ if (creds && creds.expiresAt > Date.now() + 60_000) {
54
+ return creds;
45
55
  }
46
- catch {
47
- return "You are Claude Code, Anthropic's official CLI for Claude.";
56
+ // Token is expired or near expiry, try CLI refresh
57
+ refreshViaCli();
58
+ creds = readClaudeCredentials();
59
+ if (creds && creds.expiresAt > Date.now() + 60_000) {
60
+ return creds;
48
61
  }
62
+ return null;
49
63
  }
50
- function createAuthFetch(initial, onRefresh) {
51
- let current = initial;
52
- return async (fetchInput, init) => {
53
- if (current.expiresAt < Date.now() + 60_000) {
54
- const fresh = readClaudeCredentials();
55
- if (fresh && fresh.expiresAt > Date.now() + 60_000) {
56
- current = fresh;
57
- onRefresh(current);
58
- }
59
- else {
60
- refreshViaCli();
61
- const afterRefresh = readClaudeCredentials();
62
- if (afterRefresh && afterRefresh.expiresAt > Date.now() + 60_000) {
63
- current = afterRefresh;
64
- onRefresh(current);
65
- }
66
- else {
67
- throw new Error("opencode-claude-auth: Token expired and refresh failed. " +
68
- "Re-authenticate with Claude Code by running `claude` in your terminal.");
69
- }
70
- }
71
- }
72
- const headers = new Headers(init?.headers);
73
- headers.set("Authorization", `Bearer ${current.accessToken}`);
74
- return fetch(fetchInput, { ...init, headers });
75
- };
76
- }
77
- const plugin = async (input) => {
78
- const creds = readClaudeCredentials();
64
+ const SYNC_INTERVAL = 5 * 60 * 1000; // 5 minutes
65
+ const plugin = async () => {
66
+ let creds = null;
67
+ try {
68
+ creds = readClaudeCredentials();
69
+ }
70
+ catch (err) {
71
+ console.warn("opencode-claude-auth: Failed to read Claude Code credentials:", err instanceof Error ? err.message : err);
72
+ return {};
73
+ }
79
74
  if (!creds) {
75
+ console.warn("opencode-claude-auth: No Claude Code credentials found. " +
76
+ "Plugin disabled. Run `claude` to authenticate.");
80
77
  return {};
81
78
  }
82
- const auth = {
83
- provider: "anthropic",
84
- loader: async (_getAuth, _provider) => {
85
- clearOpencodeAuth();
86
- const initialCreds = readClaudeCredentials();
87
- if (!initialCreds) {
88
- throw new Error("opencode-claude-auth: Claude Code credentials not found. " +
89
- "Please authenticate with Claude Code first by running `claude` in your terminal.");
79
+ // Sync credentials to auth.json on startup
80
+ syncAuthJson(creds);
81
+ // Keep auth.json synced, refreshing via CLI if token is near expiry
82
+ setInterval(() => {
83
+ try {
84
+ const fresh = refreshIfNeeded();
85
+ if (fresh) {
86
+ syncAuthJson(fresh);
90
87
  }
91
- await input.client.auth.set({
92
- path: { id: "anthropic" },
93
- body: {
94
- type: "oauth",
95
- access: initialCreds.accessToken,
96
- refresh: initialCreds.refreshToken,
97
- expires: initialCreds.expiresAt,
98
- },
99
- });
100
- return {
101
- apiKey: "oauth",
102
- fetch: createAuthFetch(initialCreds, (updated) => {
103
- void input.client.auth.set({
104
- path: { id: "anthropic" },
105
- body: {
106
- type: "oauth",
107
- access: updated.accessToken,
108
- refresh: updated.refreshToken,
109
- expires: updated.expiresAt,
110
- },
111
- });
112
- }),
113
- };
114
- },
115
- methods: [],
116
- };
117
- return {
118
- auth,
119
- async "experimental.chat.system.transform"(hookInput, output) {
120
- if (hookInput.model.providerID !== "anthropic")
121
- return;
122
- const prompt = loadSessionPrompt();
123
- output.system.unshift(prompt);
124
- },
125
- };
88
+ }
89
+ catch {
90
+ // Non-fatal
91
+ }
92
+ }, SYNC_INTERVAL);
93
+ return {};
126
94
  };
127
95
  export default plugin;
128
96
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-claude-auth",
3
- "version": "0.5.2",
3
+ "version": "0.5.4",
4
4
  "description": "OpenCode plugin that uses your Claude Code credentials — no separate login needed.",
5
5
  "preferGlobal": true,
6
6
  "main": "dist/index.js",