@a3s-lab/code 0.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/client.js ADDED
@@ -0,0 +1,830 @@
1
+ /**
2
+ * A3S Code Agent gRPC Client
3
+ *
4
+ * Full implementation of the CodeAgentService interface.
5
+ */
6
+ import * as grpc from '@grpc/grpc-js';
7
+ import * as protoLoader from '@grpc/proto-loader';
8
+ import { fileURLToPath } from 'url';
9
+ import { dirname, join } from 'path';
10
+ import { loadConfigFromFile, loadConfigFromDir } from './config.js';
11
+ import { normalizeMessages, a3sResponseToOpenAI, a3sChunkToOpenAI, } from './openai-compat.js';
12
+ // Get the directory of this module
13
+ const __filename = fileURLToPath(import.meta.url);
14
+ const __dirname = dirname(__filename);
15
+ // Proto file path
16
+ const PROTO_PATH = join(__dirname, '..', 'proto', 'code_agent.proto');
17
+ // Numeric enum values
18
+ export const StorageType = {
19
+ STORAGE_TYPE_UNSPECIFIED: 0,
20
+ STORAGE_TYPE_MEMORY: 1,
21
+ STORAGE_TYPE_FILE: 2,
22
+ };
23
+ export const SessionLane = {
24
+ SESSION_LANE_UNKNOWN: 0,
25
+ SESSION_LANE_CONTROL: 1,
26
+ SESSION_LANE_QUERY: 2,
27
+ SESSION_LANE_EXECUTE: 3,
28
+ SESSION_LANE_GENERATE: 4,
29
+ };
30
+ export const TimeoutAction = {
31
+ TIMEOUT_ACTION_UNKNOWN: 0,
32
+ TIMEOUT_ACTION_REJECT: 1,
33
+ TIMEOUT_ACTION_AUTO_APPROVE: 2,
34
+ };
35
+ export const TaskHandlerMode = {
36
+ TASK_HANDLER_MODE_UNKNOWN: 0,
37
+ TASK_HANDLER_MODE_INTERNAL: 1,
38
+ TASK_HANDLER_MODE_EXTERNAL: 2,
39
+ TASK_HANDLER_MODE_HYBRID: 3,
40
+ };
41
+ export const CronJobStatusEnum = {
42
+ UNKNOWN: 0,
43
+ ACTIVE: 1,
44
+ PAUSED: 2,
45
+ RUNNING: 3,
46
+ };
47
+ export const CronExecutionStatusEnum = {
48
+ UNKNOWN: 0,
49
+ SUCCESS: 1,
50
+ FAILED: 2,
51
+ TIMEOUT: 3,
52
+ CANCELLED: 4,
53
+ };
54
+ // ============================================================================
55
+ // A3sClient Class
56
+ // ============================================================================
57
+ /**
58
+ * A3S Code Agent gRPC Client
59
+ *
60
+ * Provides a TypeScript interface to all CodeAgentService RPCs.
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * // Create client with config directory
65
+ * const client = new A3sClient({ configDir: '/path/to/a3s' });
66
+ *
67
+ * // Create client with config file
68
+ * const client = new A3sClient({ configPath: '/path/to/config.json' });
69
+ *
70
+ * // Create client with explicit address
71
+ * const client = new A3sClient({ address: 'localhost:4088' });
72
+ * ```
73
+ */
74
+ export class A3sClient {
75
+ client;
76
+ address;
77
+ configDir;
78
+ constructor(options = {}) {
79
+ this.configDir = options.configDir;
80
+ // Load config from file if specified
81
+ let fileConfig;
82
+ if (options.configPath) {
83
+ fileConfig = loadConfigFromFile(options.configPath);
84
+ }
85
+ else if (options.configDir) {
86
+ fileConfig = loadConfigFromDir(options.configDir);
87
+ }
88
+ // Determine address: explicit > config file > default
89
+ this.address = options.address || fileConfig?.address || 'localhost:4088';
90
+ // Load proto definition
91
+ const packageDefinition = protoLoader.loadSync(PROTO_PATH, {
92
+ keepCase: false,
93
+ longs: String,
94
+ enums: String,
95
+ defaults: true,
96
+ oneofs: true,
97
+ });
98
+ const protoDescriptor = grpc.loadPackageDefinition(packageDefinition);
99
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
100
+ const a3s = protoDescriptor.a3s;
101
+ const CodeAgentService = a3s.code.agent.v1.CodeAgentService;
102
+ // Create credentials
103
+ const credentials = options.useTls
104
+ ? grpc.credentials.createSsl()
105
+ : grpc.credentials.createInsecure();
106
+ // Create client
107
+ this.client = new CodeAgentService(this.address, credentials);
108
+ }
109
+ /**
110
+ * Get the config directory path
111
+ */
112
+ getConfigDir() {
113
+ return this.configDir;
114
+ }
115
+ /**
116
+ * Get the server address
117
+ */
118
+ getAddress() {
119
+ return this.address;
120
+ }
121
+ /**
122
+ * Close the client connection
123
+ */
124
+ close() {
125
+ this.client.close();
126
+ }
127
+ // ==========================================================================
128
+ // Helper method for promisifying unary calls
129
+ // ==========================================================================
130
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
131
+ promisify(method, request) {
132
+ return new Promise((resolve, reject) => {
133
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
134
+ this.client[method](request, (error, response) => {
135
+ if (error) {
136
+ reject(error);
137
+ }
138
+ else {
139
+ resolve(response);
140
+ }
141
+ });
142
+ });
143
+ }
144
+ // ==========================================================================
145
+ // Lifecycle Management
146
+ // ==========================================================================
147
+ /**
148
+ * Check the health status of the agent
149
+ */
150
+ async healthCheck() {
151
+ return this.promisify('healthCheck', {});
152
+ }
153
+ /**
154
+ * Get agent capabilities
155
+ */
156
+ async getCapabilities() {
157
+ return this.promisify('getCapabilities', {});
158
+ }
159
+ /**
160
+ * Initialize the agent with workspace and environment
161
+ */
162
+ async initialize(workspace, env) {
163
+ return this.promisify('initialize', { workspace, env: env || {} });
164
+ }
165
+ /**
166
+ * Shutdown the agent
167
+ */
168
+ async shutdown() {
169
+ return this.promisify('shutdown', {});
170
+ }
171
+ // ==========================================================================
172
+ // Session Management
173
+ // ==========================================================================
174
+ /**
175
+ * Create a new session
176
+ */
177
+ async createSession(config, sessionId, initialContext) {
178
+ return this.promisify('createSession', {
179
+ sessionId,
180
+ config,
181
+ initialContext: initialContext || [],
182
+ });
183
+ }
184
+ /**
185
+ * Destroy a session
186
+ */
187
+ async destroySession(sessionId) {
188
+ return this.promisify('destroySession', { sessionId });
189
+ }
190
+ /**
191
+ * List all sessions
192
+ */
193
+ async listSessions() {
194
+ return this.promisify('listSessions', {});
195
+ }
196
+ /**
197
+ * Get a specific session
198
+ */
199
+ async getSession(sessionId) {
200
+ return this.promisify('getSession', { sessionId });
201
+ }
202
+ /**
203
+ * Configure a session
204
+ */
205
+ async configureSession(sessionId, config) {
206
+ return this.promisify('configureSession', { sessionId, config });
207
+ }
208
+ /**
209
+ * Get messages from a session
210
+ */
211
+ async getMessages(sessionId, limit, offset) {
212
+ return this.promisify('getMessages', { sessionId, limit, offset });
213
+ }
214
+ // ==========================================================================
215
+ // Code Generation
216
+ // ==========================================================================
217
+ /**
218
+ * Generate a response (unary)
219
+ *
220
+ * Supports both A3S and OpenAI message formats:
221
+ * - A3S: { role: 'ROLE_USER', content: '...' }
222
+ * - OpenAI: { role: 'user', content: '...' }
223
+ */
224
+ async generate(sessionId, messages) {
225
+ const normalizedMessages = normalizeMessages(messages);
226
+ return this.promisify('generate', { sessionId, messages: normalizedMessages });
227
+ }
228
+ /**
229
+ * Generate a response (streaming)
230
+ *
231
+ * Supports both A3S and OpenAI message formats.
232
+ */
233
+ streamGenerate(sessionId, messages) {
234
+ const normalizedMessages = normalizeMessages(messages);
235
+ const call = this.client.streamGenerate({ sessionId, messages: normalizedMessages });
236
+ return this.streamToAsyncIterable(call);
237
+ }
238
+ /**
239
+ * Generate structured output (unary)
240
+ *
241
+ * Supports both A3S and OpenAI message formats.
242
+ */
243
+ async generateStructured(sessionId, messages, schema) {
244
+ const normalizedMessages = normalizeMessages(messages);
245
+ return this.promisify('generateStructured', { sessionId, messages: normalizedMessages, schema });
246
+ }
247
+ /**
248
+ * Generate structured output (streaming)
249
+ *
250
+ * Supports both A3S and OpenAI message formats.
251
+ */
252
+ streamGenerateStructured(sessionId, messages, schema) {
253
+ const normalizedMessages = normalizeMessages(messages);
254
+ const call = this.client.streamGenerateStructured({
255
+ sessionId,
256
+ messages: normalizedMessages,
257
+ schema,
258
+ });
259
+ return this.streamToAsyncIterable(call);
260
+ }
261
+ // ==========================================================================
262
+ // OpenAI-Compatible Methods
263
+ // ==========================================================================
264
+ /**
265
+ * Generate a response in OpenAI ChatCompletion format
266
+ *
267
+ * This method provides full OpenAI API compatibility.
268
+ *
269
+ * @example
270
+ * ```typescript
271
+ * const completion = await client.chatCompletion(sessionId, [
272
+ * { role: 'user', content: 'Hello!' }
273
+ * ]);
274
+ * console.log(completion.choices[0].message.content);
275
+ * ```
276
+ */
277
+ async chatCompletion(sessionId, messages, options) {
278
+ const response = await this.generate(sessionId, messages);
279
+ return a3sResponseToOpenAI(response, options?.model);
280
+ }
281
+ /**
282
+ * Stream a response in OpenAI ChatCompletionChunk format
283
+ *
284
+ * This method provides full OpenAI API compatibility for streaming.
285
+ *
286
+ * @example
287
+ * ```typescript
288
+ * for await (const chunk of client.streamChatCompletion(sessionId, [
289
+ * { role: 'user', content: 'Hello!' }
290
+ * ])) {
291
+ * const content = chunk.choices[0].delta.content;
292
+ * if (content) process.stdout.write(content);
293
+ * }
294
+ * ```
295
+ */
296
+ async *streamChatCompletion(sessionId, messages, options) {
297
+ for await (const chunk of this.streamGenerate(sessionId, messages)) {
298
+ yield a3sChunkToOpenAI(chunk, options?.model);
299
+ }
300
+ }
301
+ // ==========================================================================
302
+ // Skill Management
303
+ // ==========================================================================
304
+ /**
305
+ * Load a skill into a session
306
+ */
307
+ async loadSkill(sessionId, skillName, skillContent) {
308
+ return this.promisify('loadSkill', { sessionId, skillName, skillContent });
309
+ }
310
+ /**
311
+ * Unload a skill from a session
312
+ */
313
+ async unloadSkill(sessionId, skillName) {
314
+ return this.promisify('unloadSkill', { sessionId, skillName });
315
+ }
316
+ /**
317
+ * List available skills
318
+ */
319
+ async listSkills(sessionId) {
320
+ return this.promisify('listSkills', { sessionId });
321
+ }
322
+ /**
323
+ * Get Claude Code skills
324
+ */
325
+ async getClaudeCodeSkills(name) {
326
+ return this.promisify('getClaudeCodeSkills', { name });
327
+ }
328
+ // ==========================================================================
329
+ // Context Management
330
+ // ==========================================================================
331
+ /**
332
+ * Get context usage for a session
333
+ */
334
+ async getContextUsage(sessionId) {
335
+ return this.promisify('getContextUsage', { sessionId });
336
+ }
337
+ /**
338
+ * Compact context for a session
339
+ */
340
+ async compactContext(sessionId) {
341
+ return this.promisify('compactContext', { sessionId });
342
+ }
343
+ /**
344
+ * Clear context for a session
345
+ */
346
+ async clearContext(sessionId) {
347
+ return this.promisify('clearContext', { sessionId });
348
+ }
349
+ // ==========================================================================
350
+ // Event Streaming
351
+ // ==========================================================================
352
+ /**
353
+ * Subscribe to agent events
354
+ */
355
+ subscribeEvents(sessionId, eventTypes) {
356
+ const call = this.client.subscribeEvents({
357
+ sessionId,
358
+ eventTypes: eventTypes || [],
359
+ });
360
+ return this.streamToAsyncIterable(call);
361
+ }
362
+ // ==========================================================================
363
+ // Control Operations
364
+ // ==========================================================================
365
+ /**
366
+ * Cancel an operation
367
+ */
368
+ async cancel(sessionId, operationId) {
369
+ return this.promisify('cancel', { sessionId, operationId });
370
+ }
371
+ /**
372
+ * Pause a session
373
+ */
374
+ async pause(sessionId) {
375
+ return this.promisify('pause', { sessionId });
376
+ }
377
+ /**
378
+ * Resume a session
379
+ */
380
+ async resume(sessionId) {
381
+ return this.promisify('resume', { sessionId });
382
+ }
383
+ // ==========================================================================
384
+ // Human-in-the-Loop (HITL)
385
+ // ==========================================================================
386
+ /**
387
+ * Confirm or reject tool execution
388
+ */
389
+ async confirmToolExecution(sessionId, toolId, approved, reason) {
390
+ return this.promisify('confirmToolExecution', {
391
+ sessionId,
392
+ toolId,
393
+ approved,
394
+ reason,
395
+ });
396
+ }
397
+ /**
398
+ * Set confirmation policy for a session
399
+ */
400
+ async setConfirmationPolicy(sessionId, policy) {
401
+ return this.promisify('setConfirmationPolicy', { sessionId, policy });
402
+ }
403
+ /**
404
+ * Get confirmation policy for a session
405
+ */
406
+ async getConfirmationPolicy(sessionId) {
407
+ return this.promisify('getConfirmationPolicy', { sessionId });
408
+ }
409
+ // ==========================================================================
410
+ // External Task Handling
411
+ // ==========================================================================
412
+ /**
413
+ * Set lane handler configuration
414
+ */
415
+ async setLaneHandler(sessionId, lane, config) {
416
+ return this.promisify('setLaneHandler', { sessionId, lane, config });
417
+ }
418
+ /**
419
+ * Get lane handler configuration
420
+ */
421
+ async getLaneHandler(sessionId, lane) {
422
+ return this.promisify('getLaneHandler', { sessionId, lane });
423
+ }
424
+ /**
425
+ * Complete an external task
426
+ */
427
+ async completeExternalTask(sessionId, taskId, success, result, error) {
428
+ return this.promisify('completeExternalTask', {
429
+ sessionId,
430
+ taskId,
431
+ success,
432
+ result: result || '',
433
+ error: error || '',
434
+ });
435
+ }
436
+ /**
437
+ * List pending external tasks
438
+ */
439
+ async listPendingExternalTasks(sessionId) {
440
+ return this.promisify('listPendingExternalTasks', { sessionId });
441
+ }
442
+ // ==========================================================================
443
+ // Permission System
444
+ // ==========================================================================
445
+ /**
446
+ * Set permission policy for a session
447
+ */
448
+ async setPermissionPolicy(sessionId, policy) {
449
+ return this.promisify('setPermissionPolicy', { sessionId, policy });
450
+ }
451
+ /**
452
+ * Get permission policy for a session
453
+ */
454
+ async getPermissionPolicy(sessionId) {
455
+ return this.promisify('getPermissionPolicy', { sessionId });
456
+ }
457
+ /**
458
+ * Check permission for a tool call
459
+ */
460
+ async checkPermission(sessionId, toolName, args) {
461
+ return this.promisify('checkPermission', {
462
+ sessionId,
463
+ toolName,
464
+ arguments: args,
465
+ });
466
+ }
467
+ /**
468
+ * Add a permission rule
469
+ */
470
+ async addPermissionRule(sessionId, ruleType, rule) {
471
+ return this.promisify('addPermissionRule', { sessionId, ruleType, rule });
472
+ }
473
+ // ==========================================================================
474
+ // Todo/Task Tracking
475
+ // ==========================================================================
476
+ /**
477
+ * Get todos for a session
478
+ */
479
+ async getTodos(sessionId) {
480
+ return this.promisify('getTodos', { sessionId });
481
+ }
482
+ /**
483
+ * Set todos for a session
484
+ */
485
+ async setTodos(sessionId, todos) {
486
+ return this.promisify('setTodos', { sessionId, todos });
487
+ }
488
+ // ==========================================================================
489
+ // Provider Configuration
490
+ // ==========================================================================
491
+ /**
492
+ * List all providers
493
+ */
494
+ async listProviders() {
495
+ return this.promisify('listProviders', {});
496
+ }
497
+ /**
498
+ * Get a specific provider
499
+ */
500
+ async getProvider(name) {
501
+ return this.promisify('getProvider', { name });
502
+ }
503
+ /**
504
+ * Add a new provider
505
+ */
506
+ async addProvider(provider) {
507
+ return this.promisify('addProvider', { provider });
508
+ }
509
+ /**
510
+ * Update an existing provider
511
+ */
512
+ async updateProvider(provider) {
513
+ return this.promisify('updateProvider', { provider });
514
+ }
515
+ /**
516
+ * Remove a provider
517
+ */
518
+ async removeProvider(name) {
519
+ return this.promisify('removeProvider', { name });
520
+ }
521
+ /**
522
+ * Set the default model
523
+ */
524
+ async setDefaultModel(provider, model) {
525
+ return this.promisify('setDefaultModel', { provider, model });
526
+ }
527
+ /**
528
+ * Get the default model
529
+ */
530
+ async getDefaultModel() {
531
+ return this.promisify('getDefaultModel', {});
532
+ }
533
+ // ==========================================================================
534
+ // Planning & Goal Tracking
535
+ // ==========================================================================
536
+ /**
537
+ * Create an execution plan
538
+ */
539
+ async createPlan(sessionId, prompt, context) {
540
+ return this.promisify('createPlan', { sessionId, prompt, context });
541
+ }
542
+ /**
543
+ * Get an existing plan
544
+ */
545
+ async getPlan(sessionId, planId) {
546
+ return this.promisify('getPlan', { sessionId, planId });
547
+ }
548
+ /**
549
+ * Extract goal from prompt
550
+ */
551
+ async extractGoal(sessionId, prompt) {
552
+ return this.promisify('extractGoal', { sessionId, prompt });
553
+ }
554
+ /**
555
+ * Check if goal is achieved
556
+ */
557
+ async checkGoalAchievement(sessionId, goal, currentState) {
558
+ return this.promisify('checkGoalAchievement', {
559
+ sessionId,
560
+ goal,
561
+ currentState,
562
+ });
563
+ }
564
+ // ==========================================================================
565
+ // Memory System
566
+ // ==========================================================================
567
+ /**
568
+ * Store a memory item
569
+ */
570
+ async storeMemory(sessionId, memory) {
571
+ return this.promisify('storeMemory', { sessionId, memory });
572
+ }
573
+ /**
574
+ * Retrieve a memory by ID
575
+ */
576
+ async retrieveMemory(sessionId, memoryId) {
577
+ return this.promisify('retrieveMemory', { sessionId, memoryId });
578
+ }
579
+ /**
580
+ * Search memories
581
+ */
582
+ async searchMemories(sessionId, query, tags, limit, recentOnly, minImportance) {
583
+ return this.promisify('searchMemories', {
584
+ sessionId,
585
+ query,
586
+ tags: tags || [],
587
+ limit: limit || 10,
588
+ recentOnly: recentOnly || false,
589
+ minImportance,
590
+ });
591
+ }
592
+ /**
593
+ * Get memory statistics
594
+ */
595
+ async getMemoryStats(sessionId) {
596
+ return this.promisify('getMemoryStats', { sessionId });
597
+ }
598
+ /**
599
+ * Clear memories
600
+ */
601
+ async clearMemories(sessionId, clearLongTerm, clearShortTerm, clearWorking) {
602
+ return this.promisify('clearMemories', {
603
+ sessionId,
604
+ clearLongTerm: clearLongTerm || false,
605
+ clearShortTerm: clearShortTerm || false,
606
+ clearWorking: clearWorking || false,
607
+ });
608
+ }
609
+ // ==========================================================================
610
+ // MCP (Model Context Protocol) Methods
611
+ // ==========================================================================
612
+ /**
613
+ * Register an MCP server
614
+ */
615
+ async registerMcpServer(config) {
616
+ return this.promisify('registerMcpServer', { config });
617
+ }
618
+ /**
619
+ * Connect to an MCP server
620
+ */
621
+ async connectMcpServer(name) {
622
+ return this.promisify('connectMcpServer', { name });
623
+ }
624
+ /**
625
+ * Disconnect from an MCP server
626
+ */
627
+ async disconnectMcpServer(name) {
628
+ return this.promisify('disconnectMcpServer', { name });
629
+ }
630
+ /**
631
+ * List all MCP servers
632
+ */
633
+ async listMcpServers() {
634
+ return this.promisify('listMcpServers', {});
635
+ }
636
+ /**
637
+ * Get MCP tools
638
+ */
639
+ async getMcpTools(serverName) {
640
+ return this.promisify('getMcpTools', { serverName });
641
+ }
642
+ // ==========================================================================
643
+ // LSP (Language Server Protocol) Methods
644
+ // ==========================================================================
645
+ /**
646
+ * Start a language server for a specific language
647
+ */
648
+ async startLspServer(language, rootUri) {
649
+ return this.promisify('startLspServer', {
650
+ language,
651
+ rootUri: rootUri || '',
652
+ });
653
+ }
654
+ /**
655
+ * Stop a running language server
656
+ */
657
+ async stopLspServer(language) {
658
+ return this.promisify('stopLspServer', { language });
659
+ }
660
+ /**
661
+ * List all running language servers
662
+ */
663
+ async listLspServers() {
664
+ return this.promisify('listLspServers', {});
665
+ }
666
+ /**
667
+ * Get hover information at a specific position
668
+ */
669
+ async lspHover(filePath, line, column) {
670
+ return this.promisify('lspHover', {
671
+ filePath,
672
+ line,
673
+ column,
674
+ });
675
+ }
676
+ /**
677
+ * Go to definition at a specific position
678
+ */
679
+ async lspDefinition(filePath, line, column) {
680
+ return this.promisify('lspDefinition', {
681
+ filePath,
682
+ line,
683
+ column,
684
+ });
685
+ }
686
+ /**
687
+ * Find all references at a specific position
688
+ */
689
+ async lspReferences(filePath, line, column, includeDeclaration) {
690
+ return this.promisify('lspReferences', {
691
+ filePath,
692
+ line,
693
+ column,
694
+ includeDeclaration: includeDeclaration || false,
695
+ });
696
+ }
697
+ /**
698
+ * Search for symbols in the workspace
699
+ */
700
+ async lspSymbols(query, limit) {
701
+ return this.promisify('lspSymbols', {
702
+ query,
703
+ limit: limit || 20,
704
+ });
705
+ }
706
+ /**
707
+ * Get diagnostics for a file
708
+ */
709
+ async lspDiagnostics(filePath) {
710
+ return this.promisify('lspDiagnostics', {
711
+ filePath: filePath || '',
712
+ });
713
+ }
714
+ // ==========================================================================
715
+ // Cron (Scheduled Tasks)
716
+ // ==========================================================================
717
+ /**
718
+ * List all cron jobs
719
+ */
720
+ async listCronJobs() {
721
+ return this.promisify('listCronJobs', {});
722
+ }
723
+ /**
724
+ * Create a new cron job
725
+ * @param name Job name
726
+ * @param schedule Schedule expression (cron syntax or natural language)
727
+ * @param command Command to execute
728
+ * @param timeoutMs Execution timeout in milliseconds (default: 60000)
729
+ */
730
+ async createCronJob(name, schedule, command, timeoutMs) {
731
+ return this.promisify('createCronJob', {
732
+ name,
733
+ schedule,
734
+ command,
735
+ timeoutMs,
736
+ });
737
+ }
738
+ /**
739
+ * Get a cron job by ID or name
740
+ * @param id Job ID
741
+ * @param name Job name (alternative to ID)
742
+ */
743
+ async getCronJob(id, name) {
744
+ return this.promisify('getCronJob', { id, name });
745
+ }
746
+ /**
747
+ * Update a cron job
748
+ * @param id Job ID
749
+ * @param schedule New schedule expression
750
+ * @param command New command
751
+ * @param timeoutMs New timeout
752
+ */
753
+ async updateCronJob(id, schedule, command, timeoutMs) {
754
+ return this.promisify('updateCronJob', {
755
+ id,
756
+ schedule,
757
+ command,
758
+ timeoutMs,
759
+ });
760
+ }
761
+ /**
762
+ * Pause a cron job
763
+ * @param id Job ID
764
+ */
765
+ async pauseCronJob(id) {
766
+ return this.promisify('pauseCronJob', { id });
767
+ }
768
+ /**
769
+ * Resume a paused cron job
770
+ * @param id Job ID
771
+ */
772
+ async resumeCronJob(id) {
773
+ return this.promisify('resumeCronJob', { id });
774
+ }
775
+ /**
776
+ * Delete a cron job
777
+ * @param id Job ID
778
+ */
779
+ async deleteCronJob(id) {
780
+ return this.promisify('deleteCronJob', { id });
781
+ }
782
+ /**
783
+ * Get execution history for a cron job
784
+ * @param id Job ID
785
+ * @param limit Max records to return (default: 10)
786
+ */
787
+ async getCronHistory(id, limit) {
788
+ return this.promisify('getCronHistory', { id, limit });
789
+ }
790
+ /**
791
+ * Manually run a cron job
792
+ * @param id Job ID
793
+ */
794
+ async runCronJob(id) {
795
+ return this.promisify('runCronJob', { id });
796
+ }
797
+ /**
798
+ * Parse natural language schedule to cron expression
799
+ * @param input Natural language or cron expression
800
+ */
801
+ async parseCronSchedule(input) {
802
+ return this.promisify('parseCronSchedule', { input });
803
+ }
804
+ // ==========================================================================
805
+ // Helper: Convert gRPC stream to AsyncIterable
806
+ // ==========================================================================
807
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
808
+ streamToAsyncIterable(call) {
809
+ return {
810
+ [Symbol.asyncIterator]() {
811
+ return {
812
+ next() {
813
+ return new Promise((resolve, reject) => {
814
+ call.once('data', (data) => {
815
+ resolve({ value: data, done: false });
816
+ });
817
+ call.once('end', () => {
818
+ resolve({ value: undefined, done: true });
819
+ });
820
+ call.once('error', (error) => {
821
+ reject(error);
822
+ });
823
+ });
824
+ },
825
+ };
826
+ },
827
+ };
828
+ }
829
+ }
830
+ //# sourceMappingURL=client.js.map