osborn 0.5.3 → 0.8.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.
- package/.claude/settings.local.json +9 -0
- package/.claude/skills/markdown-to-pdf/SKILL.md +29 -0
- package/.claude/skills/pdf-to-markdown/SKILL.md +28 -0
- package/.claude/skills/playwright-browser/SKILL.md +90 -0
- package/.claude/skills/shadcn/SKILL.md +232 -0
- package/.claude/skills/shadcn/image.png +0 -0
- package/.claude/skills/youtube-transcript/SKILL.md +24 -0
- package/.dockerignore +13 -0
- package/Dockerfile +103 -0
- package/deploy.sh +70 -0
- package/dist/claude-auth.d.ts +60 -0
- package/dist/claude-auth.js +334 -0
- package/dist/claude-llm.d.ts +51 -2
- package/dist/claude-llm.js +619 -86
- package/dist/config.d.ts +5 -1
- package/dist/config.js +4 -1
- package/dist/fast-brain.d.ts +70 -16
- package/dist/fast-brain.js +662 -99
- package/dist/index-3-2-26-legacy.d.ts +1 -0
- package/dist/index-3-2-26-legacy.js +2233 -0
- package/dist/index.js +979 -429
- package/dist/jsonl-search.d.ts +66 -0
- package/dist/jsonl-search.js +274 -0
- package/dist/leagcyprompts2.d.ts +0 -0
- package/dist/leagcyprompts2.js +573 -0
- package/dist/pipeline-direct-llm.d.ts +77 -0
- package/dist/pipeline-direct-llm.js +221 -0
- package/dist/pipeline-fastbrain.d.ts +45 -0
- package/dist/pipeline-fastbrain.js +373 -0
- package/dist/prompts-2-25-26.d.ts +0 -0
- package/dist/prompts-2-25-26.js +518 -0
- package/dist/prompts-3-2-26.d.ts +78 -0
- package/dist/prompts-3-2-26.js +1319 -0
- package/dist/prompts.d.ts +83 -12
- package/dist/prompts.js +2064 -587
- package/dist/recall-client.d.ts +33 -0
- package/dist/recall-client.js +101 -0
- package/dist/session-access.d.ts +24 -0
- package/dist/session-access.js +74 -0
- package/dist/summary-index.d.ts +87 -0
- package/dist/summary-index.js +570 -0
- package/dist/turn-detector-shim.d.ts +24 -0
- package/dist/turn-detector-shim.js +83 -0
- package/dist/voice-io.d.ts +15 -5
- package/dist/voice-io.js +52 -20
- package/fly.toml +30 -0
- package/package.json +18 -13
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* claude-auth.ts — Claude Code CLI OAuth flow
|
|
3
|
+
*
|
|
4
|
+
* Handles authentication for Claude Code in headless/cloud environments.
|
|
5
|
+
* Learned from claudebox (etokarev/claude-code-docker, vutran1710/claudebox).
|
|
6
|
+
*
|
|
7
|
+
* Auth priority:
|
|
8
|
+
* 1. CLAUDE_CODE_OAUTH_TOKEN env var (set via `claude setup-token` on local machine)
|
|
9
|
+
* 2. ~/.claude/.credentials.json file (persisted on Fly.io volume)
|
|
10
|
+
* 3. `claude auth status --json` CLI check
|
|
11
|
+
* 4. Interactive OAuth flow via `claude setup-token` + pty
|
|
12
|
+
*
|
|
13
|
+
* On Linux/Docker, credentials go to ~/.claude/.credentials.json (file-based, no keyring).
|
|
14
|
+
* The Fly.io volume at /workspace/.claude is symlinked to ~/.claude for persistence.
|
|
15
|
+
*/
|
|
16
|
+
import * as pty from 'node-pty';
|
|
17
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
18
|
+
import { homedir } from 'os';
|
|
19
|
+
import { join } from 'path';
|
|
20
|
+
// ─────────────────────────────────────────
|
|
21
|
+
// Constants
|
|
22
|
+
// ─────────────────────────────────────────
|
|
23
|
+
const CREDENTIALS_PATH = join(homedir(), '.claude', '.credentials.json');
|
|
24
|
+
// URL matching: strip all whitespace first (like claudebox), then match
|
|
25
|
+
// Handles Ink UI wrapping URLs across multiple lines
|
|
26
|
+
const URL_REGEX = /https:\/\/claude\.(com|ai)\/cai\/oauth\/authorize[^\s]*/;
|
|
27
|
+
// Matches successful login/token creation
|
|
28
|
+
const SUCCESS_PATTERN = /Long-lived authentication token created|Login successful|Logged in as|Successfully authenticated|auth.*success/i;
|
|
29
|
+
// How long to wait for auth before timing out (5 minutes)
|
|
30
|
+
const AUTH_TIMEOUT_MS = 5 * 60 * 1000;
|
|
31
|
+
// ─────────────────────────────────────────
|
|
32
|
+
// Auth Check
|
|
33
|
+
// ─────────────────────────────────────────
|
|
34
|
+
/**
|
|
35
|
+
* Check if CLAUDE_CODE_OAUTH_TOKEN env var is set (highest priority).
|
|
36
|
+
* This is the recommended approach for cloud deployments.
|
|
37
|
+
* Token generated via `claude setup-token` on local machine.
|
|
38
|
+
*/
|
|
39
|
+
function hasOAuthTokenEnv() {
|
|
40
|
+
return !!process.env.CLAUDE_CODE_OAUTH_TOKEN;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Check if credentials file exists with a valid access token.
|
|
44
|
+
* On Linux/Docker, Claude Code stores OAuth creds at ~/.claude/.credentials.json
|
|
45
|
+
*/
|
|
46
|
+
export function isClaudeAuthenticated() {
|
|
47
|
+
// Env var takes highest priority
|
|
48
|
+
if (hasOAuthTokenEnv())
|
|
49
|
+
return true;
|
|
50
|
+
if (!existsSync(CREDENTIALS_PATH))
|
|
51
|
+
return false;
|
|
52
|
+
try {
|
|
53
|
+
const raw = readFileSync(CREDENTIALS_PATH, 'utf-8');
|
|
54
|
+
const creds = JSON.parse(raw);
|
|
55
|
+
const oauth = creds?.claudeAiOauth;
|
|
56
|
+
if (!oauth?.accessToken)
|
|
57
|
+
return false;
|
|
58
|
+
// Check expiry with 60s buffer
|
|
59
|
+
if (oauth.expiresAt && Date.now() > oauth.expiresAt - 60_000) {
|
|
60
|
+
console.log('⚠️ Claude credentials exist but access token is expired');
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
console.warn('⚠️ Failed to read Claude credentials:', err);
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Check auth via `claude auth status --json` (most reliable).
|
|
72
|
+
* Uses execSync to avoid node-pty PATH issues on macOS.
|
|
73
|
+
*/
|
|
74
|
+
export async function checkClaudeAuthStatus() {
|
|
75
|
+
try {
|
|
76
|
+
const { execSync } = await import('child_process');
|
|
77
|
+
const output = execSync('claude auth status', {
|
|
78
|
+
encoding: 'utf-8',
|
|
79
|
+
timeout: 10_000,
|
|
80
|
+
env: { ...process.env },
|
|
81
|
+
});
|
|
82
|
+
if (output.includes('"loggedIn": true') || output.includes('"loggedIn":true')) {
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
return /logged in|authenticated|active/i.test(output);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// ─────────────────────────────────────────
|
|
92
|
+
// URL Extraction (claudebox pattern)
|
|
93
|
+
// ─────────────────────────────────────────
|
|
94
|
+
/**
|
|
95
|
+
* Extract OAuth URL from CLI output.
|
|
96
|
+
* Strips ALL whitespace first (like vutran1710/claudebox) to handle
|
|
97
|
+
* Ink UI wrapping the URL across multiple lines.
|
|
98
|
+
* Also cleans trailing "Pastecodehereifprompted" that Ink appends.
|
|
99
|
+
*/
|
|
100
|
+
function extractOAuthUrl(text) {
|
|
101
|
+
// Strip ANSI codes
|
|
102
|
+
const noAnsi = text.replace(/\x1B\[[0-9;]*[A-Za-z]/g, '')
|
|
103
|
+
.replace(/\x1B\][^\x07]*\x07/g, '');
|
|
104
|
+
// Strip all whitespace (claudebox pattern: strings.Join(strings.Fields(pane), ""))
|
|
105
|
+
const stripped = noAnsi.replace(/\s+/g, '');
|
|
106
|
+
const match = stripped.match(URL_REGEX);
|
|
107
|
+
if (!match)
|
|
108
|
+
return null;
|
|
109
|
+
let url = match[0];
|
|
110
|
+
// Clean trailing Ink artifacts (claudebox pattern)
|
|
111
|
+
const trailingJunk = ['Pastecodehereifprompted', 'Pastecodehereifprompted>'];
|
|
112
|
+
for (const junk of trailingJunk) {
|
|
113
|
+
const idx = url.indexOf(junk);
|
|
114
|
+
if (idx > 0)
|
|
115
|
+
url = url.substring(0, idx);
|
|
116
|
+
}
|
|
117
|
+
return url;
|
|
118
|
+
}
|
|
119
|
+
// ─────────────────────────────────────────
|
|
120
|
+
// Auth Flow
|
|
121
|
+
// ─────────────────────────────────────────
|
|
122
|
+
/**
|
|
123
|
+
* Run the Claude CLI OAuth flow via `claude setup-token` in a pseudo-terminal.
|
|
124
|
+
*
|
|
125
|
+
* setup-token provides the Ink UI with a "Paste code here if prompted >" input.
|
|
126
|
+
* Unlike `auth login` which ignores pty stdin, setup-token accepts typed input.
|
|
127
|
+
*
|
|
128
|
+
* Code is written in chunks to simulate real typing (Ink reads raw keypresses).
|
|
129
|
+
*/
|
|
130
|
+
export function runClaudeAuthFlow(callbacks) {
|
|
131
|
+
let procRef = null;
|
|
132
|
+
const handle = {
|
|
133
|
+
submitCode: (code) => {
|
|
134
|
+
if (procRef) {
|
|
135
|
+
const trimmed = code.trim();
|
|
136
|
+
console.log(`🔑 Submitting auth code to Claude CLI (${trimmed.length} chars)`);
|
|
137
|
+
// Ink reads raw keypresses. Write in chunks to simulate typing.
|
|
138
|
+
const CHUNK_SIZE = 10;
|
|
139
|
+
let offset = 0;
|
|
140
|
+
const writeChunk = () => {
|
|
141
|
+
if (!procRef || offset >= trimmed.length) {
|
|
142
|
+
if (procRef) {
|
|
143
|
+
console.log('🔑 Auth code fully written, sending Enter');
|
|
144
|
+
procRef.write('\r');
|
|
145
|
+
}
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
procRef.write(trimmed.slice(offset, offset + CHUNK_SIZE));
|
|
149
|
+
offset += CHUNK_SIZE;
|
|
150
|
+
setTimeout(writeChunk, 50);
|
|
151
|
+
};
|
|
152
|
+
writeChunk();
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
console.error('❌ Cannot submit code — Claude CLI process not running');
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
const done = new Promise((resolve, reject) => {
|
|
160
|
+
console.log('🔑 Starting Claude Code authentication flow (setup-token)...');
|
|
161
|
+
const proc = pty.spawn('claude', ['setup-token'], {
|
|
162
|
+
name: 'xterm-color',
|
|
163
|
+
cols: 500, // Wide to prevent Ink URL wrapping
|
|
164
|
+
rows: 30,
|
|
165
|
+
cwd: homedir(),
|
|
166
|
+
env: { ...process.env, TERM: 'xterm-color' },
|
|
167
|
+
});
|
|
168
|
+
procRef = proc;
|
|
169
|
+
let fullBuffer = ''; // Accumulates ALL output for URL extraction
|
|
170
|
+
let recentBuffer = ''; // Recent output for pattern matching
|
|
171
|
+
let urlSent = false;
|
|
172
|
+
let codeSolicited = false;
|
|
173
|
+
let completed = false;
|
|
174
|
+
const timeout = setTimeout(() => {
|
|
175
|
+
if (!completed) {
|
|
176
|
+
proc.kill();
|
|
177
|
+
procRef = null;
|
|
178
|
+
const msg = 'Claude authentication timed out after 5 minutes';
|
|
179
|
+
console.error('❌', msg);
|
|
180
|
+
callbacks.onError(msg);
|
|
181
|
+
reject(new Error(msg));
|
|
182
|
+
}
|
|
183
|
+
}, AUTH_TIMEOUT_MS);
|
|
184
|
+
proc.onData((data) => {
|
|
185
|
+
const clean = data.replace(/\x1B\[[0-9;]*[A-Za-z]/g, '')
|
|
186
|
+
.replace(/\x1B\][^\x07]*\x07/g, '');
|
|
187
|
+
fullBuffer += clean;
|
|
188
|
+
recentBuffer += clean;
|
|
189
|
+
// Debug log (truncated)
|
|
190
|
+
const logLine = clean.trim();
|
|
191
|
+
if (logLine)
|
|
192
|
+
console.log(`🔑 [claude-cli] ${logLine.substring(0, 200)}`);
|
|
193
|
+
callbacks.onOutput?.(data);
|
|
194
|
+
// Extract OAuth URL from accumulated output (claudebox whitespace-strip pattern)
|
|
195
|
+
if (!urlSent) {
|
|
196
|
+
const url = extractOAuthUrl(fullBuffer);
|
|
197
|
+
if (url && url.length > 100) { // Valid URLs are >100 chars
|
|
198
|
+
console.log(`🔗 Claude auth URL captured (${url.length} chars)`);
|
|
199
|
+
urlSent = true;
|
|
200
|
+
callbacks.onUrl(url);
|
|
201
|
+
recentBuffer = '';
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
// Detect code prompt
|
|
205
|
+
if (urlSent && !codeSolicited && /paste|enter.*code|Paste code/i.test(recentBuffer)) {
|
|
206
|
+
codeSolicited = true;
|
|
207
|
+
console.log('🔑 Claude CLI waiting for auth code');
|
|
208
|
+
callbacks.onWaitingForCode();
|
|
209
|
+
recentBuffer = '';
|
|
210
|
+
}
|
|
211
|
+
// Detect the OAuth token in output (sk-ant-oat01-...)
|
|
212
|
+
// setup-token prints it AFTER "created successfully!" — we must NOT kill before capturing it
|
|
213
|
+
const tokenMatch = fullBuffer.match(/sk-ant-oat01-[A-Za-z0-9_-]+/);
|
|
214
|
+
if (tokenMatch && !completed) {
|
|
215
|
+
completed = true;
|
|
216
|
+
clearTimeout(timeout);
|
|
217
|
+
const token = tokenMatch[0];
|
|
218
|
+
console.log(`✅ OAuth token captured (${token.length} chars, starts with ${token.substring(0, 20)}...)`);
|
|
219
|
+
// Set as env var so Claude Agent SDK picks it up immediately
|
|
220
|
+
process.env.CLAUDE_CODE_OAUTH_TOKEN = token;
|
|
221
|
+
// Persist to volume for future restarts
|
|
222
|
+
try {
|
|
223
|
+
const tokenDir = join(homedir(), '.claude');
|
|
224
|
+
mkdirSync(tokenDir, { recursive: true });
|
|
225
|
+
// Write as credentials file
|
|
226
|
+
writeFileSync(CREDENTIALS_PATH, JSON.stringify({
|
|
227
|
+
claudeAiOauth: { accessToken: token }
|
|
228
|
+
}), { mode: 0o600 });
|
|
229
|
+
// Also write token to a simple file for easy env var restore on restart
|
|
230
|
+
writeFileSync(join(tokenDir, '.oauth-token'), token, { mode: 0o600 });
|
|
231
|
+
console.log('✅ Token persisted to volume');
|
|
232
|
+
}
|
|
233
|
+
catch (err) {
|
|
234
|
+
console.warn('⚠️ Failed to persist token to file:', err);
|
|
235
|
+
}
|
|
236
|
+
procRef = null;
|
|
237
|
+
callbacks.onComplete();
|
|
238
|
+
proc.kill();
|
|
239
|
+
resolve();
|
|
240
|
+
}
|
|
241
|
+
// Detect errors
|
|
242
|
+
if (/OAuth error|Invalid code|expired/i.test(recentBuffer)) {
|
|
243
|
+
const errMsg = recentBuffer.replace(/\x1B\[[0-9;]*[A-Za-z]/g, '').trim().substring(0, 200);
|
|
244
|
+
console.log('⚠️ Claude auth error:', errMsg);
|
|
245
|
+
callbacks.onError(errMsg);
|
|
246
|
+
recentBuffer = '';
|
|
247
|
+
}
|
|
248
|
+
// Keep recentBuffer from growing unbounded
|
|
249
|
+
if (recentBuffer.length > 5000)
|
|
250
|
+
recentBuffer = recentBuffer.slice(-2000);
|
|
251
|
+
});
|
|
252
|
+
proc.onExit(({ exitCode }) => {
|
|
253
|
+
clearTimeout(timeout);
|
|
254
|
+
procRef = null;
|
|
255
|
+
if (!completed) {
|
|
256
|
+
const msg = `Claude CLI exited with code ${exitCode} before auth completed`;
|
|
257
|
+
console.error('❌', msg);
|
|
258
|
+
callbacks.onError(msg);
|
|
259
|
+
reject(new Error(msg));
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
});
|
|
263
|
+
return { handle, done };
|
|
264
|
+
}
|
|
265
|
+
// ─────────────────────────────────────────
|
|
266
|
+
// Startup Gate
|
|
267
|
+
// ─────────────────────────────────────────
|
|
268
|
+
/**
|
|
269
|
+
* Ensure Claude is authenticated before proceeding.
|
|
270
|
+
*
|
|
271
|
+
* Check order:
|
|
272
|
+
* 1. CLAUDE_CODE_OAUTH_TOKEN env var
|
|
273
|
+
* 2. ~/.claude/.credentials.json file
|
|
274
|
+
* 3. `claude auth status --json`
|
|
275
|
+
* 4. Interactive OAuth flow (setup-token)
|
|
276
|
+
*/
|
|
277
|
+
export async function ensureClaudeAuth(sendToFrontend) {
|
|
278
|
+
// Check 0: Restore token from volume if previously persisted
|
|
279
|
+
if (!hasOAuthTokenEnv()) {
|
|
280
|
+
try {
|
|
281
|
+
const tokenFile = join(homedir(), '.claude', '.oauth-token');
|
|
282
|
+
if (existsSync(tokenFile)) {
|
|
283
|
+
const token = readFileSync(tokenFile, 'utf-8').trim();
|
|
284
|
+
if (token.startsWith('sk-ant-')) {
|
|
285
|
+
process.env.CLAUDE_CODE_OAUTH_TOKEN = token;
|
|
286
|
+
console.log('✅ Restored CLAUDE_CODE_OAUTH_TOKEN from persisted volume');
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
catch { }
|
|
291
|
+
}
|
|
292
|
+
// Check 1: Env var (cloud best practice — set via Fly secrets or persisted from setup-token)
|
|
293
|
+
if (hasOAuthTokenEnv()) {
|
|
294
|
+
console.log('✅ Claude authenticated via CLAUDE_CODE_OAUTH_TOKEN env var');
|
|
295
|
+
return {};
|
|
296
|
+
}
|
|
297
|
+
// Check 2: Credentials file
|
|
298
|
+
if (isClaudeAuthenticated()) {
|
|
299
|
+
console.log('✅ Claude authenticated via credentials file');
|
|
300
|
+
return {};
|
|
301
|
+
}
|
|
302
|
+
// Check 3: CLI status (handles Keychain on macOS, other storage backends)
|
|
303
|
+
const cliStatus = await checkClaudeAuthStatus();
|
|
304
|
+
if (cliStatus) {
|
|
305
|
+
console.log('✅ Claude authenticated (CLI status confirmed)');
|
|
306
|
+
return {};
|
|
307
|
+
}
|
|
308
|
+
// Check 4: Need interactive OAuth flow
|
|
309
|
+
console.log('🔑 Claude not authenticated — starting OAuth flow');
|
|
310
|
+
sendToFrontend('claude_auth_required', {
|
|
311
|
+
message: 'Claude authentication required. A login URL will appear shortly.',
|
|
312
|
+
});
|
|
313
|
+
const { handle, done } = runClaudeAuthFlow({
|
|
314
|
+
onUrl: (url) => {
|
|
315
|
+
console.log('📤 Sending Claude auth URL to frontend');
|
|
316
|
+
sendToFrontend('claude_auth_url', { url });
|
|
317
|
+
},
|
|
318
|
+
onWaitingForCode: () => {
|
|
319
|
+
console.log('📤 Sending code prompt to frontend');
|
|
320
|
+
sendToFrontend('claude_auth_waiting_code', {
|
|
321
|
+
message: 'Paste the authentication code from the browser.',
|
|
322
|
+
});
|
|
323
|
+
},
|
|
324
|
+
onComplete: () => {
|
|
325
|
+
sendToFrontend('claude_auth_complete', {
|
|
326
|
+
message: 'Claude authenticated successfully. Starting voice session...',
|
|
327
|
+
});
|
|
328
|
+
},
|
|
329
|
+
onError: (message) => {
|
|
330
|
+
sendToFrontend('claude_auth_error', { message });
|
|
331
|
+
},
|
|
332
|
+
});
|
|
333
|
+
return { submitCode: handle.submitCode, done };
|
|
334
|
+
}
|
package/dist/claude-llm.d.ts
CHANGED
|
@@ -7,10 +7,11 @@
|
|
|
7
7
|
* Flow: User speaks → STT → ClaudeLLM (Agent SDK) → TTS → User hears
|
|
8
8
|
*/
|
|
9
9
|
import { llm, type APIConnectOptions } from '@livekit/agents';
|
|
10
|
-
import { type McpServerConfig } from '@anthropic-ai/claude-agent-sdk';
|
|
10
|
+
import { type Options, type McpServerConfig } from '@anthropic-ai/claude-agent-sdk';
|
|
11
11
|
import { EventEmitter } from 'events';
|
|
12
12
|
export interface ClaudeLLMOptions {
|
|
13
13
|
workingDirectory?: string;
|
|
14
|
+
sessionBaseDir?: string;
|
|
14
15
|
permissionMode?: 'default' | 'acceptEdits' | 'bypassPermissions';
|
|
15
16
|
allowedTools?: string[];
|
|
16
17
|
eventEmitter?: EventEmitter;
|
|
@@ -18,6 +19,8 @@ export interface ClaudeLLMOptions {
|
|
|
18
19
|
continueSession?: boolean;
|
|
19
20
|
mcpServers?: Record<string, McpServerConfig>;
|
|
20
21
|
model?: string;
|
|
22
|
+
voiceMode?: 'direct' | 'realtime';
|
|
23
|
+
skipTTSQueue?: boolean;
|
|
21
24
|
}
|
|
22
25
|
/**
|
|
23
26
|
* Claude LLM - Wraps Claude Agent SDK for LiveKit
|
|
@@ -113,13 +116,59 @@ export declare class ClaudeLLM extends llm.LLM {
|
|
|
113
116
|
* Check if checkpoints are available
|
|
114
117
|
*/
|
|
115
118
|
hasCheckpoints(): boolean;
|
|
116
|
-
|
|
119
|
+
/**
|
|
120
|
+
* Interrupt the current Claude query gracefully (like pressing Esc).
|
|
121
|
+
* Stops current tool execution but keeps the process alive.
|
|
122
|
+
* Returns true if interrupted, false if no active query.
|
|
123
|
+
*/
|
|
124
|
+
interruptQuery(): Promise<boolean>;
|
|
125
|
+
/**
|
|
126
|
+
* Hard abort all active queries (like Ctrl+C).
|
|
127
|
+
* Kills subprocesses. Next message will spawn new processes.
|
|
128
|
+
*/
|
|
129
|
+
abortQuery(): void;
|
|
130
|
+
/**
|
|
131
|
+
* Rewind file changes to a specific checkpoint.
|
|
132
|
+
* Uses the most recently added query (most likely to have the rewind capability).
|
|
133
|
+
*/
|
|
134
|
+
rewindToCheckpoint(checkpointId?: string): Promise<boolean>;
|
|
135
|
+
/**
|
|
136
|
+
* Check if there are active queries that can be interrupted
|
|
137
|
+
*/
|
|
138
|
+
hasActiveQuery(): boolean;
|
|
139
|
+
/** Add an active query (called from ClaudeLLMStream when query starts) */
|
|
140
|
+
setActiveQuery(q: any): void;
|
|
141
|
+
/** Remove an active query (called from ClaudeLLMStream when query completes) */
|
|
142
|
+
removeActiveQuery(q: any): void;
|
|
143
|
+
/** Whether a persistent session is alive and consuming messages */
|
|
144
|
+
hasSession(): boolean;
|
|
145
|
+
/**
|
|
146
|
+
* Close the persistent session (kills subprocess).
|
|
147
|
+
* Call on disconnect, session switch, or recovery.
|
|
148
|
+
*/
|
|
149
|
+
closeSession(): void;
|
|
150
|
+
/**
|
|
151
|
+
* Push a user message into the persistent session.
|
|
152
|
+
* If no session exists yet, creates one (cold start with JSONL replay).
|
|
153
|
+
* If a session exists, instantly delivers the message (no replay).
|
|
154
|
+
*
|
|
155
|
+
* @param userText - The user's message text
|
|
156
|
+
* @param sdkOptions - Full V1 Options (only used on first call to create the query)
|
|
157
|
+
* @param callbacks - Event callbacks for the background consumer
|
|
158
|
+
*/
|
|
159
|
+
pushMessage(userText: string, sdkOptions: Options, callbacks: {
|
|
160
|
+
onSessionId: (id: string) => void;
|
|
161
|
+
onCheckpoint: (checkpointId: string) => void;
|
|
162
|
+
eventEmitter: EventEmitter;
|
|
163
|
+
}): void;
|
|
164
|
+
chat({ chatCtx, toolCtx, connOptions, abortController, }: {
|
|
117
165
|
chatCtx: llm.ChatContext;
|
|
118
166
|
toolCtx?: llm.ToolContext;
|
|
119
167
|
connOptions?: APIConnectOptions;
|
|
120
168
|
parallelToolCalls?: boolean;
|
|
121
169
|
toolChoice?: llm.ToolChoice;
|
|
122
170
|
extraKwargs?: Record<string, unknown>;
|
|
171
|
+
abortController?: AbortController;
|
|
123
172
|
}): llm.LLMStream;
|
|
124
173
|
}
|
|
125
174
|
/**
|