@cleocode/adapters 2026.4.60 → 2026.4.63
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/dist/index.js +282 -221
- package/dist/index.js.map +3 -3
- package/dist/providers/claude-code/hooks.d.ts +8 -4
- package/dist/providers/claude-code/hooks.d.ts.map +1 -1
- package/dist/providers/claude-sdk/spawn.d.ts +10 -4
- package/dist/providers/claude-sdk/spawn.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/claude-code-adapter.test.ts +5 -5
- package/src/__tests__/cursor-adapter.test.ts +4 -4
- package/src/__tests__/opencode-adapter.test.ts +5 -5
- package/src/providers/claude-code/__tests__/hooks-get-transcript.test.ts +183 -0
- package/src/providers/claude-code/hooks.ts +69 -32
- package/src/providers/claude-sdk/__tests__/spawn.test.ts +52 -3
- package/src/providers/claude-sdk/spawn.ts +69 -5
|
@@ -9,20 +9,79 @@
|
|
|
9
9
|
* - Awaits full completion before returning (synchronous output capture)
|
|
10
10
|
* - Session IDs from the SDK enable future multi-turn resumption
|
|
11
11
|
* - No temp files, no OS PIDs — tracking is purely in-memory session IDs
|
|
12
|
-
* - `canSpawn()`
|
|
12
|
+
* - `canSpawn()` uses 3-tier key resolution (env var → stored key → Claude Code OAuth)
|
|
13
13
|
*
|
|
14
14
|
* CANT enrichment is identical to the CLI provider: `buildCantEnrichedPrompt()`
|
|
15
15
|
* is called before `query()` and the result is passed as the SDK prompt string.
|
|
16
16
|
*
|
|
17
17
|
* @task T581
|
|
18
|
+
* @see T752 — canSpawn() OAuth fix
|
|
18
19
|
*/
|
|
19
20
|
|
|
21
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
22
|
+
import { homedir } from 'node:os';
|
|
23
|
+
import { join } from 'node:path';
|
|
20
24
|
import type { AdapterSpawnProvider, SpawnContext, SpawnResult } from '@cleocode/contracts';
|
|
21
25
|
import { getErrorMessage } from '@cleocode/contracts';
|
|
22
26
|
import { getServers } from './mcp-registry.js';
|
|
23
27
|
import { SessionStore } from './session-store.js';
|
|
24
28
|
import { resolveTools } from './tool-bridge.js';
|
|
25
29
|
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// Inline 3-tier Anthropic key resolver
|
|
32
|
+
// NOTE: Cannot import from @cleocode/core — circular dependency
|
|
33
|
+
// (@cleocode/core depends on @cleocode/adapters). This is a deliberate
|
|
34
|
+
// inline copy of the resolution logic from anthropic-key-resolver.ts.
|
|
35
|
+
// Keep in sync with packages/core/src/memory/anthropic-key-resolver.ts.
|
|
36
|
+
// T752 — OAuth fix for canSpawn()
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Resolve the Anthropic API key using a 3-tier priority chain:
|
|
41
|
+
* 1. `ANTHROPIC_API_KEY` environment variable
|
|
42
|
+
* 2. `~/.local/share/cleo/anthropic-key` (user-stored via cleo config)
|
|
43
|
+
* 3. `~/.claude/.credentials.json` → claudeAiOauth.accessToken (Claude Code OAuth)
|
|
44
|
+
*
|
|
45
|
+
* @returns The key/token string, or null if unavailable.
|
|
46
|
+
*/
|
|
47
|
+
function resolveAnthropicApiKey(): string | null {
|
|
48
|
+
// 1. Explicit env var
|
|
49
|
+
const envKey = process.env.ANTHROPIC_API_KEY;
|
|
50
|
+
if (envKey?.trim()) return envKey;
|
|
51
|
+
|
|
52
|
+
// 2. CLEO global stored key
|
|
53
|
+
try {
|
|
54
|
+
const xdg = process.env.XDG_DATA_HOME || join(homedir(), '.local', 'share');
|
|
55
|
+
const keyFile = join(xdg, 'cleo', 'anthropic-key');
|
|
56
|
+
if (existsSync(keyFile)) {
|
|
57
|
+
const stored = readFileSync(keyFile, 'utf-8').trim();
|
|
58
|
+
if (stored) return stored;
|
|
59
|
+
}
|
|
60
|
+
} catch {
|
|
61
|
+
// Not available — continue
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// 3. Claude Code OAuth token (free for Claude Code users)
|
|
65
|
+
try {
|
|
66
|
+
const credPath = join(homedir(), '.claude', '.credentials.json');
|
|
67
|
+
if (!existsSync(credPath)) return null;
|
|
68
|
+
const raw = readFileSync(credPath, 'utf-8');
|
|
69
|
+
const creds = JSON.parse(raw) as {
|
|
70
|
+
claudeAiOauth?: { accessToken?: string; expiresAt?: number };
|
|
71
|
+
};
|
|
72
|
+
const token = creds.claudeAiOauth?.accessToken;
|
|
73
|
+
if (token?.trim()) {
|
|
74
|
+
const expiresAt = creds.claudeAiOauth?.expiresAt;
|
|
75
|
+
if (expiresAt && Date.now() > expiresAt) return null;
|
|
76
|
+
return token;
|
|
77
|
+
}
|
|
78
|
+
} catch {
|
|
79
|
+
// Credentials file missing or unreadable — not an error
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
|
|
26
85
|
/** Model used when no model is specified in spawn options. */
|
|
27
86
|
const DEFAULT_MODEL = 'claude-sonnet-4-5';
|
|
28
87
|
|
|
@@ -48,13 +107,18 @@ export class ClaudeSDKSpawnProvider implements AdapterSpawnProvider {
|
|
|
48
107
|
/**
|
|
49
108
|
* Check whether the SDK can be used in the current environment.
|
|
50
109
|
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
110
|
+
* Uses 3-tier key resolution so the provider works with:
|
|
111
|
+
* - `ANTHROPIC_API_KEY` environment variable (explicit)
|
|
112
|
+
* - `~/.local/share/cleo/anthropic-key` (user-stored via cleo config)
|
|
113
|
+
* - Claude Code OAuth token (zero-config for Claude Code users)
|
|
114
|
+
*
|
|
115
|
+
* No binary check is needed because the SDK manages the Claude Code
|
|
116
|
+
* subprocess internally.
|
|
53
117
|
*
|
|
54
|
-
* @returns `true` when
|
|
118
|
+
* @returns `true` when any Anthropic credential is available
|
|
55
119
|
*/
|
|
56
120
|
async canSpawn(): Promise<boolean> {
|
|
57
|
-
return !!
|
|
121
|
+
return !!resolveAnthropicApiKey();
|
|
58
122
|
}
|
|
59
123
|
|
|
60
124
|
/**
|