@xeno-corporation/xeno-agent-sdk 0.5.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.
@@ -0,0 +1,1166 @@
1
+ interface ToolDefinition {
2
+ name: string;
3
+ description: string;
4
+ input_schema: {
5
+ type: "object";
6
+ properties: Record<string, unknown>;
7
+ required?: string[];
8
+ };
9
+ }
10
+ interface ImageUrlBlock {
11
+ type: "image_url";
12
+ image_url: {
13
+ url: string;
14
+ detail?: "auto" | "low" | "high";
15
+ };
16
+ }
17
+ interface ResourceContentBlock {
18
+ type: "resource";
19
+ uri?: string;
20
+ mimeType?: string;
21
+ text?: string;
22
+ data?: string;
23
+ }
24
+ type ToolAssistantContentBlock = TextBlock | ImageUrlBlock | ResourceContentBlock;
25
+ type ToolResultContent = string | ToolAssistantContentBlock[];
26
+ interface ToolResult {
27
+ success: boolean;
28
+ output: string;
29
+ error?: string;
30
+ assistantContent?: ToolAssistantContentBlock[];
31
+ assistantOnlyContent?: ToolAssistantContentBlock[];
32
+ }
33
+ type ToolExecutor = (input: Record<string, unknown>) => Promise<ToolResult>;
34
+ interface RegisteredTool {
35
+ definition: ToolDefinition;
36
+ execute: ToolExecutor;
37
+ }
38
+ interface TextBlock {
39
+ type: "text";
40
+ text: string;
41
+ }
42
+ interface ToolUseBlock {
43
+ type: "tool_use";
44
+ id: string;
45
+ name: string;
46
+ input: Record<string, unknown>;
47
+ }
48
+ interface ToolResultBlock {
49
+ type: "tool_result";
50
+ tool_use_id: string;
51
+ content: string;
52
+ assistant_content?: ToolAssistantContentBlock[];
53
+ assistant_only_content?: ToolAssistantContentBlock[];
54
+ is_error?: boolean;
55
+ }
56
+ type ContentBlock = TextBlock | ToolUseBlock;
57
+ interface Message {
58
+ role: "user" | "assistant";
59
+ content: string | ContentBlock[] | ToolResultBlock[];
60
+ }
61
+ type PermissionDecision = "allow" | "ask" | "deny";
62
+ type ExecutionMode = "agent" | "chatOnly";
63
+ interface PermissionRule {
64
+ tool: string;
65
+ pattern?: string;
66
+ decision: PermissionDecision;
67
+ }
68
+ interface PermissionConfig {
69
+ mode: "default" | "acceptEdits" | "bypassPermissions" | "plan";
70
+ rules: PermissionRule[];
71
+ }
72
+ type PermissionPromptOperation = "generic" | "filesystem" | "write" | "edit" | "bash";
73
+ interface PermissionPromptPreviewLine {
74
+ kind: "meta" | "context" | "add" | "remove";
75
+ text: string;
76
+ }
77
+ interface PermissionPromptPreview {
78
+ title: string;
79
+ summary?: string;
80
+ lines: PermissionPromptPreviewLine[];
81
+ truncated?: boolean;
82
+ }
83
+ interface PermissionPromptInfo {
84
+ toolName: string;
85
+ detail: string;
86
+ description?: string;
87
+ operation?: PermissionPromptOperation;
88
+ preview?: PermissionPromptPreview;
89
+ commandPrefix?: string;
90
+ approvalKey?: string;
91
+ requesterLabel?: string;
92
+ requesterSummary?: string;
93
+ directory?: string;
94
+ filePath?: string;
95
+ }
96
+ type PermissionPromptFn = (info: PermissionPromptInfo) => Promise<"allow" | "always" | "deny">;
97
+ type SessionStatus = "creating" | "active" | "paused" | "completed" | "abandoned" | "archived";
98
+ interface SessionMeta {
99
+ id: string;
100
+ role: string;
101
+ name?: string;
102
+ status: SessionStatus;
103
+ createdAt: string;
104
+ updatedAt: string;
105
+ lastActivity: string;
106
+ workingDirectory: string;
107
+ model: string;
108
+ parentSession?: string;
109
+ checkpoints: string[];
110
+ messageCount: number;
111
+ tokenUsage: {
112
+ input: number;
113
+ output: number;
114
+ total: number;
115
+ };
116
+ formatVersion?: number;
117
+ }
118
+ type TranscriptEventType = "session_start" | "user_message" | "assistant_message" | "tool_call" | "tool_result" | "delegation_summary" | "checkpoint" | "context_compressed" | "session_end" | "error";
119
+ interface SessionStartData {
120
+ sessionId: string;
121
+ role: string;
122
+ model: string;
123
+ workingDirectory: string;
124
+ formatVersion?: number;
125
+ }
126
+ interface ToolCallData {
127
+ toolName: string;
128
+ input: Record<string, unknown>;
129
+ }
130
+ interface ToolResultData {
131
+ toolName: string;
132
+ success: boolean;
133
+ output: string;
134
+ error?: string;
135
+ assistantContent?: ToolAssistantContentBlock[];
136
+ assistantOnlyContent?: ToolAssistantContentBlock[];
137
+ }
138
+ interface CheckpointData {
139
+ id?: string;
140
+ checkpointId?: string;
141
+ action?: "create" | "restore" | "delete";
142
+ name?: string;
143
+ trigger?: CheckpointTrigger;
144
+ messageCount: number;
145
+ }
146
+ interface DelegationSummaryData {
147
+ selectedRole?: string;
148
+ selectedTaskId?: string;
149
+ elapsedMs: number;
150
+ totalTokens: number;
151
+ okBranches: number;
152
+ errorBranches: number;
153
+ totalBranches: number;
154
+ roleSummaries: Record<string, {
155
+ status: "ok" | "error" | "timeout";
156
+ tokensUsed: number;
157
+ outputPreview?: string;
158
+ error?: string;
159
+ }>;
160
+ }
161
+ interface ContextCompressedData {
162
+ messagesRemoved: number;
163
+ tokensSaved: number;
164
+ }
165
+ interface SessionEndData {
166
+ reason: "user_exit" | "error" | "completed";
167
+ messageCount: number;
168
+ totalTokens: number;
169
+ }
170
+ interface ErrorData {
171
+ message: string;
172
+ code?: string;
173
+ stack?: string;
174
+ }
175
+ type TranscriptEventData = {
176
+ type: "session_start";
177
+ data: SessionStartData;
178
+ } | {
179
+ type: "user_message";
180
+ data: Message;
181
+ } | {
182
+ type: "assistant_message";
183
+ data: Message;
184
+ } | {
185
+ type: "tool_call";
186
+ data: ToolCallData;
187
+ } | {
188
+ type: "tool_result";
189
+ data: ToolResultData;
190
+ } | {
191
+ type: "delegation_summary";
192
+ data: DelegationSummaryData;
193
+ } | {
194
+ type: "checkpoint";
195
+ data: CheckpointData;
196
+ } | {
197
+ type: "context_compressed";
198
+ data: ContextCompressedData;
199
+ } | {
200
+ type: "session_end";
201
+ data: SessionEndData;
202
+ } | {
203
+ type: "error";
204
+ data: ErrorData;
205
+ };
206
+ interface TranscriptEvent {
207
+ id: string;
208
+ type: TranscriptEventType;
209
+ timestamp: string;
210
+ sequence: number;
211
+ data: TranscriptEventData["data"];
212
+ tokenCount?: number;
213
+ }
214
+ type CheckpointTrigger = "auto" | "manual" | "pre_dangerous" | "milestone";
215
+ interface CheckpointInfo {
216
+ id: string;
217
+ name?: string;
218
+ trigger: CheckpointTrigger;
219
+ createdAt: string;
220
+ messageCount: number;
221
+ tokenCount: number;
222
+ }
223
+ interface PermissionRequestContext {
224
+ toolName: string;
225
+ path: string;
226
+ directory: string;
227
+ reason: string;
228
+ }
229
+ interface PermissionRequestResult {
230
+ granted: boolean;
231
+ allowedDirectory?: string;
232
+ }
233
+ interface AgentCapabilities {
234
+ terminal: boolean;
235
+ fileRead: boolean;
236
+ fileWrite: boolean;
237
+ appLaunch: boolean;
238
+ }
239
+ interface AgentSandbox {
240
+ allowedDirectories: string[];
241
+ workingDirectory?: string;
242
+ capabilities: AgentCapabilities;
243
+ temporaryDirectories?: string[];
244
+ workspace?: {
245
+ id: string;
246
+ name: string;
247
+ };
248
+ team?: {
249
+ id: string;
250
+ name: string;
251
+ };
252
+ }
253
+ interface ToolRegistryOptions {
254
+ validateInputs?: boolean;
255
+ }
256
+ declare class ToolRegistry {
257
+ private tools;
258
+ private changeListeners;
259
+ private aliasNames;
260
+ private validateInputs;
261
+ constructor(options?: ToolRegistryOptions);
262
+ setValidateInputs(enabled: boolean): this;
263
+ get inputValidationEnabled(): boolean;
264
+ register(tool: RegisteredTool): void;
265
+ registerAlias(tool: RegisteredTool): void;
266
+ registerAll(tools: Iterable<RegisteredTool>): void;
267
+ unregister(name: string): boolean;
268
+ onChange(listener: () => void): () => void;
269
+ private emitChange;
270
+ get(name: string): RegisteredTool | undefined;
271
+ getDefinitions(): ToolDefinition[];
272
+ private static namespaceOf;
273
+ getDefinitionsByNamespace(namespace: string): ToolDefinition[];
274
+ listNamespaces(): string[];
275
+ execute(name: string, input: Record<string, unknown>): Promise<ToolResult>;
276
+ listNames(): string[];
277
+ has(name: string): boolean;
278
+ get size(): number;
279
+ }
280
+ interface PermissionDecisionEvent {
281
+ traceId?: string;
282
+ toolName: string;
283
+ input: Record<string, unknown>;
284
+ allowed: boolean;
285
+ reason: string;
286
+ mode: PermissionConfig["mode"];
287
+ requesterLabel?: string;
288
+ }
289
+ type PermissionDecisionHook = (event: PermissionDecisionEvent) => Promise<void> | void;
290
+ interface PersistentPermissionState {
291
+ allowedTools?: string[];
292
+ allowedDirectories?: string[];
293
+ }
294
+ interface PermissionCheckContext {
295
+ traceId?: string;
296
+ requesterLabel?: string;
297
+ }
298
+ declare class PermissionEngine {
299
+ private config;
300
+ private workingDirectory;
301
+ private sessionAllowed;
302
+ private sessionAllowedDirectories;
303
+ private persistentAllowed;
304
+ private persistentAllowedDirectories;
305
+ private promptFn?;
306
+ private decisionHook?;
307
+ constructor(config?: Partial<PermissionConfig>, promptFn?: PermissionPromptFn, decisionHook?: PermissionDecisionHook);
308
+ get mode(): PermissionConfig["mode"];
309
+ setMode(mode: PermissionConfig["mode"]): void;
310
+ setWorkingDirectory(cwd: string): void;
311
+ loadPersistentState(state: PersistentPermissionState): void;
312
+ allowDirectory(directory: string): void;
313
+ isPathInAllowedDirectory(filePath: string): boolean;
314
+ check(toolName: string, input: Record<string, unknown>, context?: PermissionCheckContext): Promise<{
315
+ allowed: boolean;
316
+ reason: string;
317
+ }>;
318
+ private finalizeDecision;
319
+ private getCacheKey;
320
+ private isPathInPersistentAllowedDirectory;
321
+ private extractFilePath;
322
+ private extractDirectory;
323
+ private normalizeDirectory;
324
+ private promptUser;
325
+ private getToolDetail;
326
+ private getCommandPrefix;
327
+ private matchesRule;
328
+ private matchesBashPattern;
329
+ private hasBashApproval;
330
+ private extractBashCommandPrefix;
331
+ private normalizeCommandText;
332
+ private resolveTargetPath;
333
+ }
334
+ type XenoRuntimeEventType = "thread.started" | "turn.started" | "turn.completed" | "turn.failed" | "turn.interrupted" | "model.text.delta" | "tool.started" | "tool.permission" | "tool.completed" | "diff.completed";
335
+ interface XenoRuntimeEventBase {
336
+ id: string;
337
+ sequence: number;
338
+ type: XenoRuntimeEventType;
339
+ timestamp: string;
340
+ threadId?: string;
341
+ turnId?: string;
342
+ }
343
+ type XenoRuntimeEvent = (XenoRuntimeEventBase & {
344
+ type: "thread.started";
345
+ cwd: string;
346
+ model: string;
347
+ }) | (XenoRuntimeEventBase & {
348
+ type: "turn.started";
349
+ model: string;
350
+ promptPreview: string;
351
+ }) | (XenoRuntimeEventBase & {
352
+ type: "turn.completed";
353
+ outputPreview: string;
354
+ tokenUsage: {
355
+ input: number;
356
+ output: number;
357
+ total: number;
358
+ };
359
+ }) | (XenoRuntimeEventBase & {
360
+ type: "turn.failed" | "turn.interrupted";
361
+ error: string;
362
+ }) | (XenoRuntimeEventBase & {
363
+ type: "model.text.delta";
364
+ text: string;
365
+ iteration?: number;
366
+ }) | (XenoRuntimeEventBase & {
367
+ type: "tool.started";
368
+ toolName: string;
369
+ inputPreview: Record<string, unknown>;
370
+ iteration?: number;
371
+ }) | (XenoRuntimeEventBase & {
372
+ type: "tool.permission";
373
+ toolName: string;
374
+ allowed: boolean;
375
+ reason: string;
376
+ layer: "sandbox" | "permission";
377
+ iteration?: number;
378
+ }) | (XenoRuntimeEventBase & {
379
+ type: "tool.completed";
380
+ toolName: string;
381
+ success: boolean;
382
+ outputPreview: string;
383
+ error?: string;
384
+ elapsedMs: number;
385
+ iteration?: number;
386
+ }) | (XenoRuntimeEventBase & {
387
+ type: "diff.completed";
388
+ filesChanged: number;
389
+ summary: string;
390
+ });
391
+ type XenoRuntimeEventSink = (event: XenoRuntimeEvent) => void | Promise<void>;
392
+ type XenoRuntimeEventDraft = XenoRuntimeEvent extends infer Event ? Event extends XenoRuntimeEvent ? Omit<Event, "id" | "sequence" | "timestamp"> & Partial<Pick<XenoRuntimeEvent, "id" | "sequence" | "timestamp">> : never : never;
393
+ declare class XenoRuntimeEventBus {
394
+ private readonly maxHistory;
395
+ private listeners;
396
+ private history;
397
+ private sequence;
398
+ constructor(maxHistory?: number);
399
+ subscribe(listener: XenoRuntimeEventSink): () => void;
400
+ nextSequence(): number;
401
+ emit(event: XenoRuntimeEventDraft): void;
402
+ snapshot(): XenoRuntimeEvent[];
403
+ }
404
+ type AuditRiskLevel = "none" | "low" | "medium" | "high" | "critical";
405
+ type AuditDecision = "allow" | "ask" | "deny";
406
+ type AuditStatus = "ok" | "error";
407
+ interface AuditEvent {
408
+ id: string;
409
+ sequence: number;
410
+ timestamp: string;
411
+ trace_id: string;
412
+ session_id?: string;
413
+ event_type: string;
414
+ actor: "user" | "assistant" | "system";
415
+ risk_level: AuditRiskLevel;
416
+ tool_name?: string;
417
+ decision?: AuditDecision;
418
+ status?: AuditStatus;
419
+ reason?: string;
420
+ metadata?: Record<string, unknown>;
421
+ }
422
+ interface AuditLoggerOptions {
423
+ filePath: string;
424
+ sessionId?: string;
425
+ }
426
+ declare class AuditLogger {
427
+ private filePath;
428
+ private sessionId?;
429
+ private sequence;
430
+ private writeQueue;
431
+ constructor(options: AuditLoggerOptions);
432
+ get path(): string;
433
+ append(event: Omit<AuditEvent, "id" | "sequence" | "timestamp" | "session_id"> & {
434
+ session_id?: string;
435
+ }): Promise<string>;
436
+ read(options?: {
437
+ limit?: number;
438
+ eventType?: string;
439
+ traceId?: string;
440
+ }): Promise<AuditEvent[]>;
441
+ tail(limit?: number): Promise<AuditEvent[]>;
442
+ exportJson(targetPath: string): Promise<number>;
443
+ flush(): Promise<void>;
444
+ }
445
+ interface FileSnapshot {
446
+ path: string;
447
+ exists: boolean;
448
+ size: number;
449
+ mtimeMs: number;
450
+ text?: string;
451
+ binary?: boolean;
452
+ truncated?: boolean;
453
+ }
454
+ interface TurnFileDiff {
455
+ path: string;
456
+ status: "created" | "modified" | "deleted" | "unchanged";
457
+ before?: FileSnapshot;
458
+ after?: FileSnapshot;
459
+ patch?: string;
460
+ }
461
+ interface TurnDiffSummary {
462
+ turnId: string;
463
+ startedAt: string;
464
+ completedAt: string;
465
+ files: TurnFileDiff[];
466
+ }
467
+ interface TurnDiffTrackerOptions {
468
+ maxFileBytes?: number;
469
+ cwd?: string;
470
+ }
471
+ declare class TurnDiffTracker {
472
+ private active?;
473
+ private readonly maxFileBytes;
474
+ private readonly cwd;
475
+ constructor(options?: TurnDiffTrackerOptions);
476
+ beginTurn(turnId: string): void;
477
+ observeBefore(paths: Iterable<string | null | undefined>): void;
478
+ observeAfter(paths: Iterable<string | null | undefined>): void;
479
+ endTurn(): TurnDiffSummary | undefined;
480
+ inferToolPaths(toolName: string, input: Record<string, unknown>): string[];
481
+ private resolvePath;
482
+ private snapshot;
483
+ }
484
+ declare class TranscriptWriter {
485
+ private sessionDir;
486
+ private sessionId;
487
+ private transcriptPath;
488
+ private markdownPath;
489
+ private workspaceMarkdownPath;
490
+ private markdownHeaderWritten;
491
+ private workspaceHeaderWritten;
492
+ private workspaceMirrorDisabled;
493
+ private sequence;
494
+ private writeQueue;
495
+ private pendingWrites;
496
+ constructor(sessionDir: string);
497
+ append(event: Omit<TranscriptEvent, "id" | "timestamp" | "sequence">): Promise<string>;
498
+ private stringify;
499
+ private formatMessageContent;
500
+ private formatEventMarkdown;
501
+ private ensureMarkdownHeader;
502
+ private resolveWorkspaceMarkdownPath;
503
+ private appendMarkdownEvent;
504
+ private buildMarkdownDocument;
505
+ read(options?: {
506
+ types?: TranscriptEventType[];
507
+ limit?: number;
508
+ offset?: number;
509
+ }): Promise<TranscriptEvent[]>;
510
+ private isMessageData;
511
+ getMessages(): Promise<Message[]>;
512
+ replaceMessages(messages: Message[]): Promise<void>;
513
+ truncateAfterMessageCount(messageCount: number): Promise<void>;
514
+ getSequence(): number;
515
+ initialize(): Promise<void>;
516
+ flush(): Promise<void>;
517
+ }
518
+ declare class CheckpointManager {
519
+ private sessionDir;
520
+ private checkpointsDir;
521
+ private autoInterval;
522
+ private lastCheckpointMessageCount;
523
+ constructor(sessionDir: string, options?: {
524
+ autoInterval?: number;
525
+ });
526
+ initialize(): Promise<void>;
527
+ create(options: {
528
+ trigger: CheckpointTrigger;
529
+ messages: Message[];
530
+ description?: string;
531
+ }): Promise<CheckpointInfo>;
532
+ list(): Promise<CheckpointInfo[]>;
533
+ restore(checkpointId: string): Promise<{
534
+ messages: Message[];
535
+ info: CheckpointInfo;
536
+ }>;
537
+ shouldAutoCheckpoint(currentMessageCount: number): boolean;
538
+ static isDangerousOperation(toolName: string, input: unknown): boolean;
539
+ delete(checkpointId: string): Promise<void>;
540
+ private estimateTokens;
541
+ }
542
+ interface SessionCreateOptions {
543
+ role?: string;
544
+ parentSession?: string;
545
+ workingDirectory: string;
546
+ model: string;
547
+ }
548
+ interface SessionResumeOptions {
549
+ sessionId: string;
550
+ fromCheckpoint?: string;
551
+ }
552
+ declare class SessionManager {
553
+ private sessionDir;
554
+ private _meta;
555
+ private _transcript;
556
+ private _checkpoints;
557
+ private _lock;
558
+ private constructor();
559
+ static create(options: SessionCreateOptions): Promise<SessionManager>;
560
+ static resume(options: SessionResumeOptions): Promise<SessionManager>;
561
+ get meta(): SessionMeta;
562
+ get transcript(): TranscriptWriter;
563
+ get checkpoints(): CheckpointManager;
564
+ updateMeta(partial: Partial<SessionMeta>): Promise<void>;
565
+ end(status?: "completed" | "abandoned"): Promise<void>;
566
+ recordUserMessage(content: string): Promise<void>;
567
+ recordAssistantMessage(content: string | ContentBlock[] | ToolResultBlock[], tokenCount?: number): Promise<void>;
568
+ recordTokenUsage(input: number, output: number): Promise<void>;
569
+ recordDelegationSummary(data: DelegationSummaryData): Promise<void>;
570
+ updateMessageCount(count: number): Promise<void>;
571
+ }
572
+ interface ApiTextContentBlock {
573
+ type: "text";
574
+ text: string;
575
+ }
576
+ interface ApiToolUseContentBlock {
577
+ type: "tool_use";
578
+ id: string;
579
+ name: string;
580
+ input: Record<string, unknown>;
581
+ }
582
+ interface ApiToolResultContentBlock {
583
+ type: "tool_result";
584
+ tool_use_id: string;
585
+ content: ToolResultContent;
586
+ assistant_content?: ToolAssistantContentBlock[];
587
+ assistant_only_content?: ToolAssistantContentBlock[];
588
+ is_error?: boolean;
589
+ }
590
+ type ApiMessage = {
591
+ role: "user" | "assistant";
592
+ content: string | Array<ApiTextContentBlock | ApiToolUseContentBlock | ApiToolResultContentBlock>;
593
+ };
594
+ type XenoChatMessage = {
595
+ role: "system" | "user" | "assistant" | "tool";
596
+ content: string | null | Array<{
597
+ type: "text";
598
+ text: string;
599
+ } | {
600
+ type: "image_url";
601
+ image_url: {
602
+ url: string;
603
+ detail?: "auto" | "low" | "high";
604
+ };
605
+ }>;
606
+ tool_call_id?: string;
607
+ tool_calls?: Array<{
608
+ id: string;
609
+ type: "function";
610
+ function: {
611
+ name: string;
612
+ arguments: string;
613
+ };
614
+ }>;
615
+ };
616
+ interface StreamResult {
617
+ content: ContentBlock[];
618
+ stopReason: "end_turn" | "tool_use" | "max_tokens" | "stop_sequence";
619
+ inputTokens: number;
620
+ outputTokens: number;
621
+ }
622
+ interface ApiRequestFailureDiagnostics {
623
+ model: string;
624
+ requestUrl: string;
625
+ stream: boolean;
626
+ messageCount: number;
627
+ toolCount: number;
628
+ requestBytes: number;
629
+ promptTokenEstimate: number;
630
+ statusCode?: number;
631
+ requestId?: string;
632
+ cfRay?: string;
633
+ retryAfterMs?: number;
634
+ detailPreview?: string;
635
+ errorMessage?: string;
636
+ }
637
+ interface LlmClientDeps {
638
+ readonly baseURL: string;
639
+ readonly ollamaBaseUrl: string;
640
+ readonly apiKey?: string;
641
+ readonly maxTokens: number;
642
+ getApiRequestTimeoutMs(): number;
643
+ buildRuntimeSystemPrompt(): string;
644
+ reportFailure(diagnostics: ApiRequestFailureDiagnostics): Promise<void>;
645
+ }
646
+ declare class LlmClient {
647
+ private readonly deps;
648
+ private ollamaMode;
649
+ constructor(deps: LlmClientDeps);
650
+ readonly id = "xeno-llm-client";
651
+ complete(model: string, messages: ApiMessage[], tools: ToolDefinition[], onText?: (text: string) => void, signal?: AbortSignal): Promise<StreamResult>;
652
+ completeLocal(model: string, messages: ApiMessage[], tools: ToolDefinition[], onText?: (text: string) => void, signal?: AbortSignal): Promise<StreamResult>;
653
+ toOllamaMessages(apiMessages: ApiMessage[]): Array<{
654
+ role: "system" | "user" | "assistant" | "tool";
655
+ content: string;
656
+ tool_call_id?: string;
657
+ tool_calls?: Array<{
658
+ id: string;
659
+ type: "function";
660
+ function: {
661
+ name: string;
662
+ arguments: string;
663
+ };
664
+ }>;
665
+ }>;
666
+ toXenoMessages(apiMessages: ApiMessage[], options?: {
667
+ allowImages?: boolean;
668
+ }): XenoChatMessage[];
669
+ private buildStructuredToolContextMessage;
670
+ private modelSupportsImageInputs;
671
+ private describeSuppressedImageBlock;
672
+ getChatCompletionsBaseUrl(): string;
673
+ private condenseToolResultForModel;
674
+ buildXenoToolDefinitions(tools: ToolDefinition[]): Array<{
675
+ type: "function";
676
+ function: {
677
+ name: string;
678
+ description: string;
679
+ parameters: ToolDefinition["input_schema"];
680
+ };
681
+ }>;
682
+ private buildChatCompletionsRequestBody;
683
+ private parseXenoCompletion;
684
+ static parseRetryAfterSeconds(value: string | null): number | undefined;
685
+ private static getHeaderValue;
686
+ private static stripHtml;
687
+ private static summarizeErrorBody;
688
+ private createApiRequestSignal;
689
+ callChatCompletionsNonStream(model: string, apiMessages: ApiMessage[], tools: ToolDefinition[], onText?: (text: string) => void, signal?: AbortSignal): Promise<StreamResult>;
690
+ callChatCompletions(model: string, apiMessages: ApiMessage[], tools: ToolDefinition[], onText?: (text: string) => void, signal?: AbortSignal): Promise<StreamResult>;
691
+ callOllama(model: string, apiMessages: ApiMessage[], tools: ToolDefinition[], onText?: (text: string) => void, signal?: AbortSignal): Promise<StreamResult>;
692
+ private callOllamaOpenAI;
693
+ private callOllamaNative;
694
+ }
695
+ interface ToolMiddlewareContext {
696
+ readonly toolName: string;
697
+ readonly toolCallId: string;
698
+ input: Record<string, unknown>;
699
+ readonly iteration: number;
700
+ readonly traceId: string;
701
+ readonly signal: AbortSignal;
702
+ addGuidance(text: string): void;
703
+ }
704
+ type ToolMiddleware = (ctx: ToolMiddlewareContext, next: () => Promise<ToolResult>) => Promise<ToolResult>;
705
+ interface PromptSectionContext {
706
+ readonly systemPrompt: string;
707
+ readonly taskPrompt?: string;
708
+ readonly iteration: number;
709
+ readonly model: string;
710
+ }
711
+ interface PromptSectionProvider {
712
+ name: string;
713
+ order?: number;
714
+ provide(ctx: PromptSectionContext): string | null | undefined;
715
+ }
716
+ type CompletionGuardStopReason = "end_turn" | "tool_use" | "max_tokens" | "stop_sequence" | "empty_response" | "progress_checkpoint";
717
+ interface CompletionGuardTurnStats {
718
+ readonly iteration: number;
719
+ readonly maxIterations: number;
720
+ readonly toolCalls: number;
721
+ readonly toolFailures: number;
722
+ readonly failuresByTool: Readonly<Record<string, number>>;
723
+ }
724
+ interface CompletionGuardEvaluationContext {
725
+ readonly finalText: string;
726
+ readonly iteration: number;
727
+ readonly maxIterations: number;
728
+ readonly messages: Message[];
729
+ readonly stopReason: CompletionGuardStopReason;
730
+ readonly stats: CompletionGuardTurnStats;
731
+ }
732
+ type CompletionGuardDecision = {
733
+ allow: true;
734
+ } | {
735
+ allow: false;
736
+ guidance: string;
737
+ stop?: boolean;
738
+ };
739
+ interface CompletionGuard {
740
+ name: string;
741
+ order?: number;
742
+ evaluate(ctx: CompletionGuardEvaluationContext): CompletionGuardDecision | null | undefined | Promise<CompletionGuardDecision | null | undefined>;
743
+ }
744
+ type LLMProviderMessage = ApiMessage;
745
+ type LLMCompletionResult = StreamResult;
746
+ interface LLMProviderCapabilities {
747
+ readonly streaming?: boolean;
748
+ readonly tools?: boolean;
749
+ readonly vision?: boolean;
750
+ readonly [capability: string]: boolean | undefined;
751
+ }
752
+ interface LLMProvider {
753
+ readonly id: string;
754
+ readonly model?: string;
755
+ readonly capabilities?: LLMProviderCapabilities;
756
+ complete(model: string, messages: LLMProviderMessage[], tools: ToolDefinition[], onText?: (text: string) => void, signal?: AbortSignal): Promise<LLMCompletionResult>;
757
+ completeLocal?(model: string, messages: LLMProviderMessage[], tools: ToolDefinition[], onText?: (text: string) => void, signal?: AbortSignal): Promise<LLMCompletionResult>;
758
+ }
759
+ interface ModeSwitchRequest {
760
+ from: ExecutionMode;
761
+ to: ExecutionMode;
762
+ requestedTools: string[];
763
+ reason: string;
764
+ }
765
+ interface AgentLoopConfig {
766
+ apiKey?: string;
767
+ baseURL: string;
768
+ ollamaBaseURL?: string;
769
+ model: string;
770
+ maxTokens: number;
771
+ maxIterations: number;
772
+ systemPrompt: string;
773
+ requesterLabel?: string;
774
+ executionMode?: ExecutionMode;
775
+ permissionEngine: PermissionEngine;
776
+ toolRegistry?: ToolRegistry;
777
+ onText?: (text: string) => void;
778
+ onToolStart?: (name: string, input: Record<string, unknown>) => void;
779
+ onToolWillExecute?: (name: string, input: Record<string, unknown>) => void | Promise<void>;
780
+ onToolEnd?: (name: string, result: ToolResult) => void;
781
+ onIteration?: (iteration: number, totalTokens: number) => void;
782
+ onError?: (error: Error, context: string) => void;
783
+ onTranscriptError?: (error: Error, context: string) => void;
784
+ onModeSwitchRequest?: (request: ModeSwitchRequest) => Promise<boolean>;
785
+ onExecutionModeChanged?: (mode: ExecutionMode, reason: string) => void;
786
+ onContextCompressed?: (messagesRemoved: number, tokensSaved: number) => void;
787
+ onRuntimeEvent?: XenoRuntimeEventSink;
788
+ runtimeEventBus?: XenoRuntimeEventBus;
789
+ turnDiffTracker?: TurnDiffTracker;
790
+ completionGuard?: (context: CompletionGuardContext) => Promise<CompletionGuardResult | null> | CompletionGuardResult | null;
791
+ maxCompletionGuardReminders?: number;
792
+ progressGuardEveryIterations?: number;
793
+ apiRequestTimeoutMs?: number;
794
+ runStartedAtMs?: number;
795
+ externalTimeoutMs?: number;
796
+ apiDeadlineFinalBufferMs?: number;
797
+ backgroundTaskDrainMaxWaitMs?: number;
798
+ backgroundTaskDrainPollIntervalMs?: number;
799
+ backgroundTaskDrainExtraIterations?: number;
800
+ sandbox?: AgentSandbox;
801
+ onPermissionRequest?: (context: PermissionRequestContext) => Promise<PermissionRequestResult> | PermissionRequestResult;
802
+ toolMiddleware?: ToolMiddleware[];
803
+ promptSections?: PromptSectionProvider[];
804
+ promptSectionsTokenBudget?: number;
805
+ completionGuards?: CompletionGuard[];
806
+ provider?: LLMProvider;
807
+ transcript?: TranscriptWriter;
808
+ checkpoints?: CheckpointManager;
809
+ sessionManager?: SessionManager;
810
+ autoCheckpointInterval?: number;
811
+ maxContextTokens?: number;
812
+ historyMarkdownPath?: string;
813
+ compressionKeepRecentMessages?: number;
814
+ auditLogger?: AuditLogger;
815
+ }
816
+ interface CompletionGuardContext {
817
+ finalText: string;
818
+ iteration: number;
819
+ messages: Message[];
820
+ stopReason: StreamResult["stopReason"] | "empty_response" | "progress_checkpoint";
821
+ }
822
+ interface RunStreamOptions {
823
+ signal?: AbortSignal;
824
+ }
825
+ interface CompletionGuardResultObject {
826
+ message: string;
827
+ blocking?: boolean;
828
+ stop?: boolean;
829
+ toolPolicy?: CompletionGuardToolPolicy;
830
+ }
831
+ type CompletionGuardResult = string | CompletionGuardResultObject;
832
+ type CompletionGuardToolPolicyMode = "require_output_checkpoint";
833
+ interface CompletionGuardToolPolicy {
834
+ mode: CompletionGuardToolPolicyMode;
835
+ requiredOutputPaths?: string[];
836
+ message?: string;
837
+ }
838
+ type AgentRunTerminationStatus = "completed" | "incomplete" | "interrupted" | "error";
839
+ type AgentRunTerminationReason = "end_turn" | "empty_response" | "max_tokens" | "completion_guard_stop" | "max_iterations" | "interrupted" | "error";
840
+ interface AgentRunTermination {
841
+ status: AgentRunTerminationStatus;
842
+ reason: AgentRunTerminationReason;
843
+ iteration: number;
844
+ maxIterations: number;
845
+ finalStateVerified: boolean;
846
+ message: string;
847
+ }
848
+ interface SessionIntegrationConfig {
849
+ transcript?: TranscriptWriter;
850
+ checkpoints?: CheckpointManager;
851
+ sessionManager?: SessionManager;
852
+ historyMarkdownPath?: string;
853
+ auditLogger?: AuditLogger;
854
+ }
855
+ declare class AgentLoop {
856
+ private config;
857
+ private toolRegistry;
858
+ private _messages;
859
+ private totalInputTokens;
860
+ private totalOutputTokens;
861
+ private lastCheckpointMessageCount;
862
+ private ollamaBaseUrl;
863
+ private activeAbortController;
864
+ private interruptionRequested;
865
+ private currentTraceId;
866
+ private lastRunTraceId;
867
+ private lastRunTerminationInfo;
868
+ private activeTaskPrompt;
869
+ private activeToolPolicy;
870
+ private apiFailureDiagnosticsLogged;
871
+ private readonly runtimeEventBus;
872
+ private readonly threadId;
873
+ private readonly turnDiffTracker?;
874
+ private readonly llm;
875
+ private readonly messageFlow;
876
+ private readonly middleware;
877
+ private readonly promptSections;
878
+ private readonly completionGuards;
879
+ private turnToolCalls;
880
+ private turnToolFailures;
881
+ private turnFailuresByTool;
882
+ private turnIteration;
883
+ constructor(config: AgentLoopConfig);
884
+ get tokenUsage(): {
885
+ input: number;
886
+ output: number;
887
+ total: number;
888
+ };
889
+ get lastTraceId(): string | null;
890
+ get lastRunTermination(): AgentRunTermination | null;
891
+ get model(): string;
892
+ set model(value: string);
893
+ get executionMode(): ExecutionMode;
894
+ set executionMode(value: ExecutionMode);
895
+ get systemPrompt(): string;
896
+ set systemPrompt(value: string);
897
+ use(middleware: ToolMiddleware): this;
898
+ registerPromptSection(provider: PromptSectionProvider): this;
899
+ registerCompletionGuard(guard: CompletionGuard): this;
900
+ attachSessionIntegration(config: SessionIntegrationConfig): void;
901
+ cancelCurrentTurn(): boolean;
902
+ private emitRuntimeEvent;
903
+ private handleTextDelta;
904
+ private handleContextCompressed;
905
+ private isAbortError;
906
+ private toolRiskLevel;
907
+ private isParallelSafeTool;
908
+ private pathAliasesForToolPolicy;
909
+ private toolPolicyMentionsRequiredPath;
910
+ private toolPolicyTargetsRequiredPath;
911
+ private bashCommandCanCreateRequiredOutput;
912
+ private toolCallSatisfiesToolPolicy;
913
+ private maybeBlockActiveToolPolicy;
914
+ private getCompressedSourceSizeLimit;
915
+ private isSourceLikePath;
916
+ private isBinaryReimplementationContractTask;
917
+ private getOriginalBinaryAliases;
918
+ private textMentionsOriginalBinary;
919
+ private sourceContainsOriginalBinaryBypass;
920
+ private sourceGenerationCommandContainsOriginalBinaryBypass;
921
+ private buildSourceIndependenceBlock;
922
+ private maybeBlockSourceIndependenceViolation;
923
+ private maybeBlockKnownInvalidWrite;
924
+ private maybeBlockKnownInvalidBashSourceGeneration;
925
+ private recordToolEventsToTranscript;
926
+ protected callChatCompletions(model: string, apiMessages: ApiMessage[], tools: ToolDefinition[], onText?: (text: string) => void, signal?: AbortSignal): Promise<StreamResult>;
927
+ protected callOllama(model: string, apiMessages: ApiMessage[], tools: ToolDefinition[], onText?: (text: string) => void, signal?: AbortSignal): Promise<StreamResult>;
928
+ protected toXenoMessages(apiMessages: ApiMessage[]): ReturnType<LlmClient["toXenoMessages"]>;
929
+ protected toOllamaMessages(apiMessages: ApiMessage[]): ReturnType<LlmClient["toOllamaMessages"]>;
930
+ private executeToolCall;
931
+ private recordTurnToolStats;
932
+ private currentTurnStats;
933
+ private appendAuditEvent;
934
+ private setExecutionModeInternal;
935
+ private maybeAppendApiRequestFailureAudit;
936
+ private static parsePositiveInteger;
937
+ private sleep;
938
+ private getApiDeadlineFinalBufferMs;
939
+ private getExternalDeadlineMs;
940
+ private getBackgroundTaskDrainMaxWaitMs;
941
+ private getBackgroundTaskDrainPollIntervalMs;
942
+ private getBackgroundTaskDrainExtraIterations;
943
+ private getBackgroundTaskDrainBudgetMs;
944
+ private getDrainableBackgroundTasks;
945
+ private summarizeBackgroundTaskSnapshot;
946
+ private maybeDrainBackgroundTasksAtIterationBudget;
947
+ private getApiRequestTimeoutMs;
948
+ private createApiRequestSignal;
949
+ private buildRuntimeSystemPrompt;
950
+ get messages(): Message[];
951
+ set messages(value: Message[]);
952
+ private shouldAutoCheckpoint;
953
+ private getApiMessagesForRequest;
954
+ private appendSyntheticUserMessage;
955
+ run(userMessage: string): Promise<string>;
956
+ runStream(prompt: string, options?: RunStreamOptions): AsyncIterable<XenoRuntimeEvent>;
957
+ private createRuntimeEventIterator;
958
+ private runInternal;
959
+ clearHistory(): void;
960
+ }
961
+ type AppType = "pixel" | "motion" | "sound";
962
+ interface DocumentContext {
963
+ name: string;
964
+ path?: string;
965
+ modified: boolean;
966
+ }
967
+ interface LayerContext {
968
+ id: string;
969
+ name: string;
970
+ type: string;
971
+ }
972
+ interface ClipContext {
973
+ id: string;
974
+ name: string;
975
+ type: string;
976
+ }
977
+ interface TrackContext {
978
+ id: string;
979
+ name: string;
980
+ }
981
+ interface CanvasSize {
982
+ width: number;
983
+ height: number;
984
+ }
985
+ interface AppContext {
986
+ app: AppType;
987
+ document?: DocumentContext;
988
+ activeLayer?: LayerContext;
989
+ selectedTool?: string;
990
+ canvasSize?: CanvasSize;
991
+ currentFrame?: number;
992
+ selectedClip?: ClipContext;
993
+ timelineLength?: number;
994
+ bpm?: number;
995
+ currentPosition?: number;
996
+ selectedTrack?: TrackContext;
997
+ isRecording?: boolean;
998
+ }
999
+ type AppContextProvider = () => AppContext;
1000
+ declare class AppContextManager {
1001
+ private provider;
1002
+ setProvider(provider: AppContextProvider): void;
1003
+ getContext(): AppContext;
1004
+ formatForPrompt(): string;
1005
+ }
1006
+ interface PermissionInfo {
1007
+ toolName: string;
1008
+ input: unknown;
1009
+ riskLevel: "low" | "medium" | "high";
1010
+ }
1011
+ interface AgentStreamCallbacks {
1012
+ onText: (text: string) => void;
1013
+ onToolStart: (name: string, input: unknown) => void;
1014
+ onToolEnd: (name: string, result: unknown) => void;
1015
+ onComplete: () => void;
1016
+ onError: (error: Error) => void;
1017
+ }
1018
+ interface ElectronAgentConfig {
1019
+ apiKey: string;
1020
+ baseURL: string;
1021
+ model: string;
1022
+ app: AppType;
1023
+ tools: RegisteredTool[];
1024
+ appContext: () => AppContext;
1025
+ onPermissionRequest?: (info: PermissionInfo) => Promise<"allow" | "deny">;
1026
+ maxTokens?: number;
1027
+ maxIterations?: number;
1028
+ }
1029
+ declare class ElectronAgentBridge {
1030
+ private agent;
1031
+ private readonly contextManager;
1032
+ private readonly config;
1033
+ private readonly toolRegistry;
1034
+ private readonly permissionEngine;
1035
+ private pendingPermissions;
1036
+ constructor(config: ElectronAgentConfig);
1037
+ private buildSystemPrompt;
1038
+ sendMessage(text: string, callbacks: AgentStreamCallbacks): Promise<void>;
1039
+ cancel(): boolean;
1040
+ getHistory(): Message[];
1041
+ clearHistory(): void;
1042
+ updateContext(): void;
1043
+ respondToPermission(id: string, decision: "allow" | "deny"): void;
1044
+ getAgentLoop(): AgentLoop;
1045
+ getContextManager(): AppContextManager;
1046
+ getToolRegistry(): ToolRegistry;
1047
+ }
1048
+ interface PermissionRequestInfo {
1049
+ id: string;
1050
+ toolName: string;
1051
+ input: unknown;
1052
+ riskLevel: "low" | "medium" | "high";
1053
+ description?: string;
1054
+ }
1055
+ interface AgentToAppMessages {
1056
+ "agent:text": {
1057
+ text: string;
1058
+ };
1059
+ "agent:tool-start": {
1060
+ name: string;
1061
+ input: unknown;
1062
+ };
1063
+ "agent:tool-end": {
1064
+ name: string;
1065
+ result: unknown;
1066
+ success: boolean;
1067
+ };
1068
+ "agent:complete": Record<string, never>;
1069
+ "agent:error": {
1070
+ message: string;
1071
+ code?: string;
1072
+ };
1073
+ "agent:permission-request": PermissionRequestInfo;
1074
+ }
1075
+ interface AppToAgentMessages {
1076
+ "agent:send-message": {
1077
+ text: string;
1078
+ };
1079
+ "agent:cancel": Record<string, never>;
1080
+ "agent:clear": Record<string, never>;
1081
+ "agent:permission-response": {
1082
+ id: string;
1083
+ decision: "allow" | "deny";
1084
+ };
1085
+ }
1086
+ type AgentToAppChannel = keyof AgentToAppMessages;
1087
+ type AppToAgentChannel = keyof AppToAgentMessages;
1088
+ type AgentIpcChannel = AgentToAppChannel | AppToAgentChannel;
1089
+ type IpcHandler<C extends string, M extends Record<string, unknown>> = C extends keyof M ? (payload: M[C]) => void : never;
1090
+ type DualLLMMode = "auto" | "local" | "cloud";
1091
+ interface ChatParams {
1092
+ messages: Array<{
1093
+ role: "system" | "user" | "assistant";
1094
+ content: string;
1095
+ }>;
1096
+ model?: string;
1097
+ maxTokens?: number;
1098
+ temperature?: number;
1099
+ systemPrompt?: string;
1100
+ jsonMode?: boolean;
1101
+ stop?: string[];
1102
+ }
1103
+ interface ChatResponse {
1104
+ success: boolean;
1105
+ content: string;
1106
+ endpoint: "local" | "cloud";
1107
+ model: string;
1108
+ usage: {
1109
+ promptTokens: number;
1110
+ completionTokens: number;
1111
+ totalTokens: number;
1112
+ };
1113
+ error?: string;
1114
+ }
1115
+ interface DualLLMStatus {
1116
+ mode: DualLLMMode;
1117
+ localAvailable: boolean;
1118
+ activeEndpoint: "local" | "cloud";
1119
+ localModel?: string;
1120
+ localUrl: string;
1121
+ cloudUrl: string;
1122
+ }
1123
+ interface DualLLMProviderConfig {
1124
+ localUrl?: string;
1125
+ cloudUrl?: string;
1126
+ cloudApiKey?: string;
1127
+ mode?: DualLLMMode;
1128
+ localModel?: string;
1129
+ cloudModel?: string;
1130
+ }
1131
+ declare class DualLLMProvider {
1132
+ private localUrl;
1133
+ private cloudUrl;
1134
+ private cloudApiKey;
1135
+ private mode;
1136
+ private defaultLocalModel;
1137
+ private defaultCloudModel;
1138
+ private localAvailable;
1139
+ private localModelName;
1140
+ private lastHealthCheck;
1141
+ constructor(config?: DualLLMProviderConfig);
1142
+ chat(params: ChatParams): Promise<ChatResponse>;
1143
+ chatStream(params: ChatParams): AsyncGenerator<string>;
1144
+ isLocalAvailable(forceRefresh?: boolean): Promise<boolean>;
1145
+ setMode(mode: DualLLMMode): void;
1146
+ getMode(): DualLLMMode;
1147
+ setLocalUrl(url: string): void;
1148
+ setCloudApiKey(apiKey: string): void;
1149
+ getStatus(): Promise<DualLLMStatus>;
1150
+ asLLMProvider(options?: {
1151
+ id?: string;
1152
+ model?: string;
1153
+ }): LLMProvider;
1154
+ private shouldUseLocal;
1155
+ private chatLocal;
1156
+ private chatCloud;
1157
+ }
1158
+ type IpcHandleFunction = (channel: string, handler: (event: unknown, ...args: unknown[]) => unknown) => void;
1159
+ interface SetupAIHandlersOptions {
1160
+ ipcHandle?: IpcHandleFunction;
1161
+ config?: DualLLMProviderConfig;
1162
+ provider?: DualLLMProvider;
1163
+ }
1164
+ declare function setupAIHandlers(options?: SetupAIHandlersOptions): DualLLMProvider;
1165
+ declare function readXenoApiKey(): string | undefined;
1166
+ export { type AgentIpcChannel, type AgentStreamCallbacks, type AgentToAppChannel, type AgentToAppMessages, type AppToAgentChannel, type AppToAgentMessages, ElectronAgentBridge, type ElectronAgentConfig, type IpcHandler, type PermissionInfo, type PermissionRequestInfo, type SetupAIHandlersOptions, readXenoApiKey, setupAIHandlers };