@artyfacts/claude 1.0.0 → 1.1.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/dist/index.d.mts CHANGED
@@ -1,312 +1,241 @@
1
- import { EventEmitter } from 'events';
2
- import { ChildProcess } from 'child_process';
3
-
4
1
  /**
5
- * Artyfacts API Client (Simplified)
2
+ * Device authentication flow for Artyfacts Claude adapter
6
3
  *
7
- * Handles communication with the Artyfacts API for task management.
4
+ * Implements device auth flow:
5
+ * 1. Request device code from Artyfacts
6
+ * 2. Display code for user to enter on website
7
+ * 3. Poll for completion
8
+ * 4. Store credentials locally
8
9
  */
9
- interface ArtyfactsConfig {
10
+ interface Credentials {
10
11
  apiKey: string;
11
- baseUrl?: string;
12
- agentId?: string;
13
- }
14
- interface Task {
15
- id: string;
16
- sectionId: string;
17
- heading: string;
18
- content: string;
19
- artifactId: string;
20
- artifactTitle: string;
21
- artifactUrl: string;
22
- priority: 1 | 2 | 3;
23
- dependsOn: string[];
24
- createdAt: string;
12
+ agentId: string;
13
+ agentName?: string;
14
+ expiresAt?: string;
25
15
  }
26
- interface ClaimResult {
27
- success: boolean;
28
- task: Task & {
29
- claimedAt: string;
30
- claimedBy: string;
31
- };
32
- }
33
- interface CompleteResult {
34
- success: boolean;
35
- unblockedTasks: string[];
16
+ interface DeviceAuthResponse {
17
+ deviceCode: string;
18
+ userCode: string;
19
+ verificationUri: string;
20
+ expiresIn: number;
21
+ interval: number;
36
22
  }
37
- declare class ArtyfactsClient {
38
- private config;
39
- constructor(config: ArtyfactsConfig);
40
- private fetch;
41
- /**
42
- * Get claimable tasks from the queue
43
- */
44
- getTaskQueue(options?: {
45
- limit?: number;
46
- }): Promise<Task[]>;
47
- /**
48
- * Claim a task
49
- */
50
- claimTask(taskId: string): Promise<ClaimResult>;
51
- /**
52
- * Complete a task
53
- */
54
- completeTask(taskId: string, options?: {
55
- outputUrl?: string;
56
- summary?: string;
57
- }): Promise<CompleteResult>;
58
- /**
59
- * Report task as blocked
60
- */
61
- blockTask(taskId: string, reason: string): Promise<void>;
62
- /**
63
- * Get current user/org info
64
- */
65
- getMe(): Promise<{
66
- id: string;
67
- name: string;
68
- orgId: string;
69
- }>;
23
+ interface TokenResponse {
24
+ apiKey: string;
25
+ agentId: string;
26
+ agentName?: string;
27
+ expiresAt?: string;
70
28
  }
29
+ /**
30
+ * Load stored credentials from disk
31
+ */
32
+ declare function loadCredentials(): Credentials | null;
33
+ /**
34
+ * Save credentials to disk
35
+ */
36
+ declare function saveCredentials(credentials: Credentials): void;
37
+ /**
38
+ * Clear stored credentials
39
+ */
40
+ declare function clearCredentials(): void;
41
+ /**
42
+ * Run the device authentication flow
43
+ */
44
+ declare function runDeviceAuth(baseUrl?: string): Promise<Credentials>;
45
+ /**
46
+ * Prompt user for manual API key entry
47
+ */
48
+ declare function promptForApiKey(): Promise<Credentials>;
49
+ /**
50
+ * Get credentials, running auth flow if needed
51
+ */
52
+ declare function getCredentials(options?: {
53
+ baseUrl?: string;
54
+ forceAuth?: boolean;
55
+ }): Promise<Credentials>;
71
56
 
72
57
  /**
73
- * Claude Code Runner
58
+ * Claude Code executor for Artyfacts tasks
74
59
  *
75
- * Spawns and manages Claude Code CLI processes for task execution.
60
+ * Executes tasks by shelling out to the Claude Code CLI (claude).
61
+ * This uses the user's existing Claude Code authentication - no separate API key needed.
76
62
  */
77
-
78
- interface ClaudeRunnerConfig {
79
- /** Path to claude CLI (default: 'claude') */
80
- claudePath?: string;
81
- /** Model to use (default: 'sonnet') */
82
- model?: string;
83
- /** Working directory for Claude */
84
- cwd?: string;
85
- /** Timeout in ms (default: 5 minutes) */
86
- timeoutMs?: number;
87
- }
88
- interface TaskResult {
63
+ interface TaskContext {
64
+ /** Task ID (section ID) */
65
+ taskId: string;
66
+ /** Task heading/title */
67
+ heading: string;
68
+ /** Task content/description */
69
+ content: string;
70
+ /** Parent artifact ID */
71
+ artifactId: string;
72
+ /** Parent artifact title */
73
+ artifactTitle?: string;
74
+ /** Task priority (1=high, 2=medium, 3=low) */
75
+ priority?: number;
76
+ /** Additional context */
77
+ context?: Record<string, unknown>;
78
+ }
79
+ interface ExecutionResult {
80
+ /** Whether execution was successful */
89
81
  success: boolean;
82
+ /** The generated output */
90
83
  output: string;
84
+ /** Summary of what was accomplished */
85
+ summary: string;
86
+ /** Any error message if failed */
91
87
  error?: string;
92
- exitCode: number | null;
93
- durationMs: number;
94
88
  }
95
- interface RunningTask {
96
- taskId: string;
97
- process: ChildProcess;
98
- startedAt: Date;
99
- promise: Promise<TaskResult>;
89
+ interface ExecutorConfig {
90
+ /** Path to claude CLI (default: 'claude') */
91
+ claudePath?: string;
92
+ /** Timeout in milliseconds (default: 5 minutes) */
93
+ timeout?: number;
94
+ /** System prompt prefix */
95
+ systemPromptPrefix?: string;
100
96
  }
101
- declare class ClaudeRunner extends EventEmitter {
97
+ declare class ClaudeExecutor {
102
98
  private config;
103
- private runningTasks;
104
- constructor(config?: ClaudeRunnerConfig);
99
+ constructor(config?: ExecutorConfig);
105
100
  /**
106
- * Check if Claude Code is installed and authenticated
101
+ * Execute a task using Claude Code CLI
107
102
  */
108
- checkInstalled(): Promise<{
109
- installed: boolean;
110
- authenticated: boolean;
111
- version?: string;
112
- error?: string;
113
- }>;
103
+ execute(task: TaskContext): Promise<ExecutionResult>;
114
104
  /**
115
- * Run a task with Claude Code
105
+ * Run Claude Code CLI with the given prompt
116
106
  */
117
- runTask(taskId: string, prompt: string, options?: {
118
- cwd?: string;
119
- model?: string;
120
- timeoutMs?: number;
121
- }): Promise<TaskResult>;
107
+ private runClaude;
122
108
  /**
123
- * Run a raw claude command
109
+ * Build the task prompt
124
110
  */
125
- private runCommand;
111
+ private buildTaskPrompt;
126
112
  /**
127
- * Cancel a running task
113
+ * Parse the response to extract output and summary
128
114
  */
129
- cancelTask(taskId: string): boolean;
115
+ private parseResponse;
130
116
  /**
131
- * Get count of running tasks
117
+ * Test that Claude Code CLI is available and working
132
118
  */
133
- getRunningCount(): number;
119
+ testConnection(): Promise<boolean>;
134
120
  /**
135
- * Cancel all running tasks
121
+ * Check if Claude Code CLI is installed
136
122
  */
137
- cancelAll(): void;
123
+ isInstalled(): Promise<boolean>;
138
124
  }
125
+ /**
126
+ * Create a Claude executor
127
+ */
128
+ declare function createExecutor(config?: ExecutorConfig): ClaudeExecutor;
139
129
 
140
130
  /**
141
- * Claude Adapter
131
+ * SSE Event Listener for Artyfacts task assignments
142
132
  *
143
- * Main orchestration class that:
144
- * 1. Polls Artyfacts for claimable tasks
145
- * 2. Spawns Claude Code to execute them
146
- * 3. Reports results back to Artyfacts
133
+ * Connects to the Artyfacts SSE stream and listens for task_assigned events.
134
+ * Uses EventSource for automatic reconnection handling.
147
135
  */
148
-
149
- interface AdapterConfig {
136
+ interface TaskAssignedEvent {
137
+ type: 'task_assigned';
138
+ timestamp: string;
139
+ data: {
140
+ taskId: string;
141
+ sectionId: string;
142
+ heading: string;
143
+ content: string;
144
+ artifactId: string;
145
+ artifactTitle?: string;
146
+ priority?: number;
147
+ assignedTo: string;
148
+ assignedAt: string;
149
+ };
150
+ }
151
+ interface HeartbeatEvent {
152
+ type: 'heartbeat';
153
+ timestamp: string;
154
+ }
155
+ interface ConnectedEvent {
156
+ type: 'connected';
157
+ timestamp: string;
158
+ data: {
159
+ agentId: string;
160
+ };
161
+ }
162
+ type ArtyfactsEvent = TaskAssignedEvent | HeartbeatEvent | ConnectedEvent | {
163
+ type: string;
164
+ timestamp: string;
165
+ data?: Record<string, unknown>;
166
+ };
167
+ type EventCallback<T extends ArtyfactsEvent = ArtyfactsEvent> = (event: T) => void | Promise<void>;
168
+ interface ListenerConfig {
150
169
  /** Artyfacts API key */
151
170
  apiKey: string;
152
- /** Artyfacts base URL */
171
+ /** Agent ID to listen for */
172
+ agentId: string;
173
+ /** Base URL for Artyfacts API */
153
174
  baseUrl?: string;
154
- /** Agent ID for attribution */
155
- agentId?: string;
156
- /** Poll interval in ms (default: 30s) */
157
- pollIntervalMs?: number;
158
- /** Max concurrent tasks (default: 1) */
159
- maxConcurrent?: number;
160
- /** Claude model to use (default: 'sonnet') */
161
- model?: string;
162
- /** Working directory for Claude */
163
- cwd?: string;
164
- }
165
- interface AdapterEvents {
166
- 'started': () => void;
167
- 'stopped': () => void;
168
- 'poll': (tasks: Task[]) => void;
169
- 'task:claimed': (task: Task) => void;
170
- 'task:running': (task: Task) => void;
171
- 'task:completed': (task: Task, result: TaskResult) => void;
172
- 'task:failed': (task: Task, error: string) => void;
173
- 'error': (error: Error) => void;
175
+ /** Callback for state changes */
176
+ onStateChange?: (state: ConnectionState) => void;
177
+ /** Callback for errors */
178
+ onError?: (error: Error) => void;
174
179
  }
175
- declare class ClaudeAdapter extends EventEmitter {
180
+ type ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'reconnecting';
181
+ declare class ArtyfactsListener {
176
182
  private config;
177
- private client;
178
- private runner;
179
- private running;
180
- private pollTimer;
181
- private activeTasks;
182
- constructor(config: AdapterConfig);
183
+ private eventSource;
184
+ private callbacks;
185
+ private allCallbacks;
186
+ private state;
187
+ private reconnectAttempts;
188
+ private maxReconnectAttempts;
189
+ private reconnectDelay;
190
+ constructor(config: ListenerConfig);
183
191
  /**
184
- * Check if Claude Code is ready
192
+ * Get current connection state
185
193
  */
186
- checkReady(): Promise<{
187
- ready: boolean;
188
- error?: string;
189
- }>;
194
+ get connectionState(): ConnectionState;
190
195
  /**
191
- * Start the adapter
196
+ * Check if connected
192
197
  */
193
- start(): Promise<void>;
198
+ get isConnected(): boolean;
194
199
  /**
195
- * Stop the adapter
200
+ * Subscribe to all events
196
201
  */
197
- stop(): Promise<void>;
202
+ subscribe(callback: EventCallback): () => void;
198
203
  /**
199
- * Poll for and execute tasks
204
+ * Subscribe to a specific event type
200
205
  */
201
- private poll;
206
+ on<T extends ArtyfactsEvent>(type: string, callback: EventCallback<T>): () => void;
202
207
  /**
203
- * Execute a single task
208
+ * Connect to the SSE stream
204
209
  */
205
- private executeTask;
210
+ connect(): void;
206
211
  /**
207
- * Build a prompt for Claude from the task
212
+ * Disconnect from the SSE stream
208
213
  */
209
- private buildPrompt;
214
+ disconnect(): void;
210
215
  /**
211
- * Extract a summary from Claude's output
216
+ * Reconnect to the SSE stream
212
217
  */
213
- private extractSummary;
218
+ reconnect(): void;
214
219
  /**
215
- * Check if running
220
+ * Handle incoming SSE message
216
221
  */
217
- isRunning(): boolean;
222
+ private handleMessage;
218
223
  /**
219
- * Get stats
224
+ * Safely call a callback, handling async and errors
220
225
  */
221
- getStats(): {
222
- running: boolean;
223
- activeTasks: number;
224
- maxConcurrent: number;
225
- };
226
- }
227
-
228
- /**
229
- * Device Authorization Flow
230
- *
231
- * Handles browser-based authentication for the CLI.
232
- * No API keys to copy — just run the CLI and click authorize.
233
- */
234
- interface DeviceCodeResponse {
235
- deviceCode: string;
236
- userCode: string;
237
- verificationUri: string;
238
- expiresIn: number;
239
- interval: number;
240
- }
241
- interface TokenResponse {
242
- accessToken: string;
243
- refreshToken?: string;
244
- expiresAt?: number;
245
- user: {
246
- id: string;
247
- email: string;
248
- name?: string;
249
- orgId: string;
250
- };
251
- }
252
- interface StoredCredentials {
253
- accessToken: string;
254
- refreshToken?: string;
255
- expiresAt?: number;
256
- user: {
257
- id: string;
258
- email: string;
259
- name?: string;
260
- orgId: string;
261
- };
262
- savedAt: string;
263
- }
264
- declare class DeviceAuth {
265
- private baseUrl;
266
- private credentialsPath;
267
- constructor(options?: {
268
- baseUrl?: string;
269
- });
270
- /**
271
- * Check if we have stored credentials
272
- */
273
- hasCredentials(): boolean;
226
+ private safeCallCallback;
274
227
  /**
275
- * Get stored credentials
228
+ * Handle SSE error
276
229
  */
277
- getCredentials(): StoredCredentials | null;
230
+ private handleError;
278
231
  /**
279
- * Get access token (for API calls)
232
+ * Update connection state
280
233
  */
281
- getAccessToken(): string | null;
282
- /**
283
- * Clear stored credentials (logout)
284
- */
285
- logout(): void;
286
- /**
287
- * Start device authorization flow
288
- */
289
- startDeviceFlow(): Promise<DeviceCodeResponse>;
290
- /**
291
- * Poll for token after user authorizes
292
- */
293
- pollForToken(deviceCode: string, interval: number, expiresIn: number): Promise<TokenResponse>;
294
- /**
295
- * Save credentials to disk
296
- */
297
- saveCredentials(token: TokenResponse): void;
298
- /**
299
- * Open URL in browser
300
- */
301
- openBrowser(url: string): void;
302
- /**
303
- * Full login flow
304
- */
305
- login(options?: {
306
- onDeviceCode?: (response: DeviceCodeResponse) => void;
307
- onWaiting?: () => void;
308
- }): Promise<TokenResponse>;
309
- private sleep;
234
+ private setState;
310
235
  }
236
+ /**
237
+ * Create an Artyfacts event listener
238
+ */
239
+ declare function createListener(config: ListenerConfig): ArtyfactsListener;
311
240
 
312
- export { type AdapterConfig, type AdapterEvents, ArtyfactsClient, type ArtyfactsConfig, type ClaimResult, ClaudeAdapter, ClaudeRunner, type ClaudeRunnerConfig, type CompleteResult, DeviceAuth, type DeviceCodeResponse, type RunningTask, type StoredCredentials, type Task, type TaskResult, type TokenResponse };
241
+ export { type ArtyfactsEvent, ArtyfactsListener, ClaudeExecutor, type ConnectedEvent, type ConnectionState, type Credentials, type DeviceAuthResponse, type EventCallback, type ExecutionResult, type ExecutorConfig, type HeartbeatEvent, type ListenerConfig, type TaskAssignedEvent, type TaskContext, type TokenResponse, clearCredentials, createExecutor, createListener, getCredentials, loadCredentials, promptForApiKey, runDeviceAuth, saveCredentials };