@agi-cli/server 0.1.59 → 0.1.62
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agi-cli/server",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.62",
|
|
4
4
|
"description": "HTTP API server for AGI CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"typecheck": "tsc --noEmit"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@agi-cli/sdk": "0.1.
|
|
33
|
-
"@agi-cli/database": "0.1.
|
|
32
|
+
"@agi-cli/sdk": "0.1.62",
|
|
33
|
+
"@agi-cli/database": "0.1.62",
|
|
34
34
|
"drizzle-orm": "^0.44.5",
|
|
35
35
|
"hono": "^4.9.9"
|
|
36
36
|
},
|
package/src/openapi/spec.ts
CHANGED
|
@@ -14,6 +14,8 @@ export function getOpenAPISpec() {
|
|
|
14
14
|
{ name: 'messages' },
|
|
15
15
|
{ name: 'stream' },
|
|
16
16
|
{ name: 'ask' },
|
|
17
|
+
{ name: 'config' },
|
|
18
|
+
{ name: 'git' },
|
|
17
19
|
],
|
|
18
20
|
paths: {
|
|
19
21
|
'/v1/ask': {
|
|
@@ -237,6 +239,498 @@ export function getOpenAPISpec() {
|
|
|
237
239
|
},
|
|
238
240
|
},
|
|
239
241
|
},
|
|
242
|
+
'/v1/sessions/{sessionId}/abort': {
|
|
243
|
+
delete: {
|
|
244
|
+
tags: ['sessions'],
|
|
245
|
+
operationId: 'abortSession',
|
|
246
|
+
summary: 'Abort a running session',
|
|
247
|
+
description:
|
|
248
|
+
'Aborts any currently running assistant generation for the session',
|
|
249
|
+
parameters: [
|
|
250
|
+
{
|
|
251
|
+
in: 'path',
|
|
252
|
+
name: 'sessionId',
|
|
253
|
+
required: true,
|
|
254
|
+
schema: { type: 'string' },
|
|
255
|
+
description: 'Session ID to abort',
|
|
256
|
+
},
|
|
257
|
+
],
|
|
258
|
+
responses: {
|
|
259
|
+
200: {
|
|
260
|
+
description: 'OK',
|
|
261
|
+
content: {
|
|
262
|
+
'application/json': {
|
|
263
|
+
schema: {
|
|
264
|
+
type: 'object',
|
|
265
|
+
properties: { success: { type: 'boolean' } },
|
|
266
|
+
required: ['success'],
|
|
267
|
+
},
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
},
|
|
274
|
+
'/v1/config': {
|
|
275
|
+
get: {
|
|
276
|
+
tags: ['config'],
|
|
277
|
+
operationId: 'getConfig',
|
|
278
|
+
summary: 'Get full configuration',
|
|
279
|
+
description:
|
|
280
|
+
'Returns agents, authorized providers, models, and defaults',
|
|
281
|
+
parameters: [projectQueryParam()],
|
|
282
|
+
responses: {
|
|
283
|
+
200: {
|
|
284
|
+
description: 'OK',
|
|
285
|
+
content: {
|
|
286
|
+
'application/json': {
|
|
287
|
+
schema: { $ref: '#/components/schemas/Config' },
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
'/v1/config/cwd': {
|
|
295
|
+
get: {
|
|
296
|
+
tags: ['config'],
|
|
297
|
+
operationId: 'getCwd',
|
|
298
|
+
summary: 'Get current working directory info',
|
|
299
|
+
responses: {
|
|
300
|
+
200: {
|
|
301
|
+
description: 'OK',
|
|
302
|
+
content: {
|
|
303
|
+
'application/json': {
|
|
304
|
+
schema: {
|
|
305
|
+
type: 'object',
|
|
306
|
+
properties: {
|
|
307
|
+
cwd: { type: 'string' },
|
|
308
|
+
dirName: { type: 'string' },
|
|
309
|
+
},
|
|
310
|
+
required: ['cwd', 'dirName'],
|
|
311
|
+
},
|
|
312
|
+
},
|
|
313
|
+
},
|
|
314
|
+
},
|
|
315
|
+
},
|
|
316
|
+
},
|
|
317
|
+
},
|
|
318
|
+
'/v1/config/agents': {
|
|
319
|
+
get: {
|
|
320
|
+
tags: ['config'],
|
|
321
|
+
operationId: 'getAgents',
|
|
322
|
+
summary: 'Get available agents',
|
|
323
|
+
parameters: [projectQueryParam()],
|
|
324
|
+
responses: {
|
|
325
|
+
200: {
|
|
326
|
+
description: 'OK',
|
|
327
|
+
content: {
|
|
328
|
+
'application/json': {
|
|
329
|
+
schema: {
|
|
330
|
+
type: 'object',
|
|
331
|
+
properties: {
|
|
332
|
+
agents: {
|
|
333
|
+
type: 'array',
|
|
334
|
+
items: { type: 'string' },
|
|
335
|
+
},
|
|
336
|
+
default: { type: 'string' },
|
|
337
|
+
},
|
|
338
|
+
required: ['agents', 'default'],
|
|
339
|
+
},
|
|
340
|
+
},
|
|
341
|
+
},
|
|
342
|
+
},
|
|
343
|
+
},
|
|
344
|
+
},
|
|
345
|
+
},
|
|
346
|
+
'/v1/config/providers': {
|
|
347
|
+
get: {
|
|
348
|
+
tags: ['config'],
|
|
349
|
+
operationId: 'getProviders',
|
|
350
|
+
summary: 'Get available providers',
|
|
351
|
+
description: 'Returns only providers that have been authorized',
|
|
352
|
+
parameters: [projectQueryParam()],
|
|
353
|
+
responses: {
|
|
354
|
+
200: {
|
|
355
|
+
description: 'OK',
|
|
356
|
+
content: {
|
|
357
|
+
'application/json': {
|
|
358
|
+
schema: {
|
|
359
|
+
type: 'object',
|
|
360
|
+
properties: {
|
|
361
|
+
providers: {
|
|
362
|
+
type: 'array',
|
|
363
|
+
items: { $ref: '#/components/schemas/Provider' },
|
|
364
|
+
},
|
|
365
|
+
default: { $ref: '#/components/schemas/Provider' },
|
|
366
|
+
},
|
|
367
|
+
required: ['providers', 'default'],
|
|
368
|
+
},
|
|
369
|
+
},
|
|
370
|
+
},
|
|
371
|
+
},
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
},
|
|
375
|
+
'/v1/config/providers/{provider}/models': {
|
|
376
|
+
get: {
|
|
377
|
+
tags: ['config'],
|
|
378
|
+
operationId: 'getProviderModels',
|
|
379
|
+
summary: 'Get available models for a provider',
|
|
380
|
+
parameters: [
|
|
381
|
+
projectQueryParam(),
|
|
382
|
+
{
|
|
383
|
+
in: 'path',
|
|
384
|
+
name: 'provider',
|
|
385
|
+
required: true,
|
|
386
|
+
schema: { $ref: '#/components/schemas/Provider' },
|
|
387
|
+
},
|
|
388
|
+
],
|
|
389
|
+
responses: {
|
|
390
|
+
200: {
|
|
391
|
+
description: 'OK',
|
|
392
|
+
content: {
|
|
393
|
+
'application/json': {
|
|
394
|
+
schema: {
|
|
395
|
+
type: 'object',
|
|
396
|
+
properties: {
|
|
397
|
+
models: {
|
|
398
|
+
type: 'array',
|
|
399
|
+
items: { $ref: '#/components/schemas/Model' },
|
|
400
|
+
},
|
|
401
|
+
default: { type: 'string', nullable: true },
|
|
402
|
+
},
|
|
403
|
+
required: ['models'],
|
|
404
|
+
},
|
|
405
|
+
},
|
|
406
|
+
},
|
|
407
|
+
},
|
|
408
|
+
403: {
|
|
409
|
+
description: 'Provider not authorized',
|
|
410
|
+
content: {
|
|
411
|
+
'application/json': {
|
|
412
|
+
schema: {
|
|
413
|
+
type: 'object',
|
|
414
|
+
properties: { error: { type: 'string' } },
|
|
415
|
+
required: ['error'],
|
|
416
|
+
},
|
|
417
|
+
},
|
|
418
|
+
},
|
|
419
|
+
},
|
|
420
|
+
404: {
|
|
421
|
+
description: 'Provider not found',
|
|
422
|
+
content: {
|
|
423
|
+
'application/json': {
|
|
424
|
+
schema: {
|
|
425
|
+
type: 'object',
|
|
426
|
+
properties: { error: { type: 'string' } },
|
|
427
|
+
required: ['error'],
|
|
428
|
+
},
|
|
429
|
+
},
|
|
430
|
+
},
|
|
431
|
+
},
|
|
432
|
+
},
|
|
433
|
+
},
|
|
434
|
+
},
|
|
435
|
+
'/v1/git/status': {
|
|
436
|
+
get: {
|
|
437
|
+
tags: ['git'],
|
|
438
|
+
operationId: 'getGitStatus',
|
|
439
|
+
summary: 'Get git status',
|
|
440
|
+
description:
|
|
441
|
+
'Returns current git status including staged, unstaged, and untracked files',
|
|
442
|
+
parameters: [projectQueryParam()],
|
|
443
|
+
responses: {
|
|
444
|
+
200: {
|
|
445
|
+
description: 'OK',
|
|
446
|
+
content: {
|
|
447
|
+
'application/json': {
|
|
448
|
+
schema: {
|
|
449
|
+
type: 'object',
|
|
450
|
+
properties: {
|
|
451
|
+
status: { type: 'string', enum: ['ok'] },
|
|
452
|
+
data: { $ref: '#/components/schemas/GitStatus' },
|
|
453
|
+
},
|
|
454
|
+
required: ['status', 'data'],
|
|
455
|
+
},
|
|
456
|
+
},
|
|
457
|
+
},
|
|
458
|
+
},
|
|
459
|
+
400: gitErrorResponse(),
|
|
460
|
+
500: gitErrorResponse(),
|
|
461
|
+
},
|
|
462
|
+
},
|
|
463
|
+
},
|
|
464
|
+
'/v1/git/diff': {
|
|
465
|
+
get: {
|
|
466
|
+
tags: ['git'],
|
|
467
|
+
operationId: 'getGitDiff',
|
|
468
|
+
summary: 'Get git diff for a file',
|
|
469
|
+
parameters: [
|
|
470
|
+
projectQueryParam(),
|
|
471
|
+
{
|
|
472
|
+
in: 'query',
|
|
473
|
+
name: 'file',
|
|
474
|
+
required: true,
|
|
475
|
+
schema: { type: 'string' },
|
|
476
|
+
description: 'File path to get diff for',
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
in: 'query',
|
|
480
|
+
name: 'staged',
|
|
481
|
+
required: false,
|
|
482
|
+
schema: { type: 'string', enum: ['true', 'false'] },
|
|
483
|
+
description: 'Show staged diff (default: unstaged)',
|
|
484
|
+
},
|
|
485
|
+
],
|
|
486
|
+
responses: {
|
|
487
|
+
200: {
|
|
488
|
+
description: 'OK',
|
|
489
|
+
content: {
|
|
490
|
+
'application/json': {
|
|
491
|
+
schema: {
|
|
492
|
+
type: 'object',
|
|
493
|
+
properties: {
|
|
494
|
+
status: { type: 'string', enum: ['ok'] },
|
|
495
|
+
data: { $ref: '#/components/schemas/GitDiff' },
|
|
496
|
+
},
|
|
497
|
+
required: ['status', 'data'],
|
|
498
|
+
},
|
|
499
|
+
},
|
|
500
|
+
},
|
|
501
|
+
},
|
|
502
|
+
400: gitErrorResponse(),
|
|
503
|
+
500: gitErrorResponse(),
|
|
504
|
+
},
|
|
505
|
+
},
|
|
506
|
+
},
|
|
507
|
+
'/v1/git/branch': {
|
|
508
|
+
get: {
|
|
509
|
+
tags: ['git'],
|
|
510
|
+
operationId: 'getGitBranch',
|
|
511
|
+
summary: 'Get git branch information',
|
|
512
|
+
parameters: [projectQueryParam()],
|
|
513
|
+
responses: {
|
|
514
|
+
200: {
|
|
515
|
+
description: 'OK',
|
|
516
|
+
content: {
|
|
517
|
+
'application/json': {
|
|
518
|
+
schema: {
|
|
519
|
+
type: 'object',
|
|
520
|
+
properties: {
|
|
521
|
+
status: { type: 'string', enum: ['ok'] },
|
|
522
|
+
data: { $ref: '#/components/schemas/GitBranch' },
|
|
523
|
+
},
|
|
524
|
+
required: ['status', 'data'],
|
|
525
|
+
},
|
|
526
|
+
},
|
|
527
|
+
},
|
|
528
|
+
},
|
|
529
|
+
400: gitErrorResponse(),
|
|
530
|
+
500: gitErrorResponse(),
|
|
531
|
+
},
|
|
532
|
+
},
|
|
533
|
+
},
|
|
534
|
+
'/v1/git/stage': {
|
|
535
|
+
post: {
|
|
536
|
+
tags: ['git'],
|
|
537
|
+
operationId: 'stageFiles',
|
|
538
|
+
summary: 'Stage files',
|
|
539
|
+
requestBody: {
|
|
540
|
+
required: true,
|
|
541
|
+
content: {
|
|
542
|
+
'application/json': {
|
|
543
|
+
schema: {
|
|
544
|
+
type: 'object',
|
|
545
|
+
properties: {
|
|
546
|
+
project: { type: 'string' },
|
|
547
|
+
files: {
|
|
548
|
+
type: 'array',
|
|
549
|
+
items: { type: 'string' },
|
|
550
|
+
},
|
|
551
|
+
},
|
|
552
|
+
required: ['files'],
|
|
553
|
+
},
|
|
554
|
+
},
|
|
555
|
+
},
|
|
556
|
+
},
|
|
557
|
+
responses: {
|
|
558
|
+
200: {
|
|
559
|
+
description: 'OK',
|
|
560
|
+
content: {
|
|
561
|
+
'application/json': {
|
|
562
|
+
schema: {
|
|
563
|
+
type: 'object',
|
|
564
|
+
properties: {
|
|
565
|
+
status: { type: 'string', enum: ['ok'] },
|
|
566
|
+
data: {
|
|
567
|
+
type: 'object',
|
|
568
|
+
properties: {
|
|
569
|
+
staged: {
|
|
570
|
+
type: 'array',
|
|
571
|
+
items: { type: 'string' },
|
|
572
|
+
},
|
|
573
|
+
failed: {
|
|
574
|
+
type: 'array',
|
|
575
|
+
items: { type: 'string' },
|
|
576
|
+
},
|
|
577
|
+
},
|
|
578
|
+
required: ['staged', 'failed'],
|
|
579
|
+
},
|
|
580
|
+
},
|
|
581
|
+
required: ['status', 'data'],
|
|
582
|
+
},
|
|
583
|
+
},
|
|
584
|
+
},
|
|
585
|
+
},
|
|
586
|
+
500: gitErrorResponse(),
|
|
587
|
+
},
|
|
588
|
+
},
|
|
589
|
+
},
|
|
590
|
+
'/v1/git/unstage': {
|
|
591
|
+
post: {
|
|
592
|
+
tags: ['git'],
|
|
593
|
+
operationId: 'unstageFiles',
|
|
594
|
+
summary: 'Unstage files',
|
|
595
|
+
requestBody: {
|
|
596
|
+
required: true,
|
|
597
|
+
content: {
|
|
598
|
+
'application/json': {
|
|
599
|
+
schema: {
|
|
600
|
+
type: 'object',
|
|
601
|
+
properties: {
|
|
602
|
+
project: { type: 'string' },
|
|
603
|
+
files: {
|
|
604
|
+
type: 'array',
|
|
605
|
+
items: { type: 'string' },
|
|
606
|
+
},
|
|
607
|
+
},
|
|
608
|
+
required: ['files'],
|
|
609
|
+
},
|
|
610
|
+
},
|
|
611
|
+
},
|
|
612
|
+
},
|
|
613
|
+
responses: {
|
|
614
|
+
200: {
|
|
615
|
+
description: 'OK',
|
|
616
|
+
content: {
|
|
617
|
+
'application/json': {
|
|
618
|
+
schema: {
|
|
619
|
+
type: 'object',
|
|
620
|
+
properties: {
|
|
621
|
+
status: { type: 'string', enum: ['ok'] },
|
|
622
|
+
data: {
|
|
623
|
+
type: 'object',
|
|
624
|
+
properties: {
|
|
625
|
+
unstaged: {
|
|
626
|
+
type: 'array',
|
|
627
|
+
items: { type: 'string' },
|
|
628
|
+
},
|
|
629
|
+
failed: {
|
|
630
|
+
type: 'array',
|
|
631
|
+
items: { type: 'string' },
|
|
632
|
+
},
|
|
633
|
+
},
|
|
634
|
+
required: ['unstaged', 'failed'],
|
|
635
|
+
},
|
|
636
|
+
},
|
|
637
|
+
required: ['status', 'data'],
|
|
638
|
+
},
|
|
639
|
+
},
|
|
640
|
+
},
|
|
641
|
+
},
|
|
642
|
+
500: gitErrorResponse(),
|
|
643
|
+
},
|
|
644
|
+
},
|
|
645
|
+
},
|
|
646
|
+
'/v1/git/commit': {
|
|
647
|
+
post: {
|
|
648
|
+
tags: ['git'],
|
|
649
|
+
operationId: 'commitChanges',
|
|
650
|
+
summary: 'Commit staged changes',
|
|
651
|
+
requestBody: {
|
|
652
|
+
required: true,
|
|
653
|
+
content: {
|
|
654
|
+
'application/json': {
|
|
655
|
+
schema: {
|
|
656
|
+
type: 'object',
|
|
657
|
+
properties: {
|
|
658
|
+
project: { type: 'string' },
|
|
659
|
+
message: { type: 'string', minLength: 1 },
|
|
660
|
+
},
|
|
661
|
+
required: ['message'],
|
|
662
|
+
},
|
|
663
|
+
},
|
|
664
|
+
},
|
|
665
|
+
},
|
|
666
|
+
responses: {
|
|
667
|
+
200: {
|
|
668
|
+
description: 'OK',
|
|
669
|
+
content: {
|
|
670
|
+
'application/json': {
|
|
671
|
+
schema: {
|
|
672
|
+
type: 'object',
|
|
673
|
+
properties: {
|
|
674
|
+
status: { type: 'string', enum: ['ok'] },
|
|
675
|
+
data: { $ref: '#/components/schemas/GitCommit' },
|
|
676
|
+
},
|
|
677
|
+
required: ['status', 'data'],
|
|
678
|
+
},
|
|
679
|
+
},
|
|
680
|
+
},
|
|
681
|
+
},
|
|
682
|
+
400: gitErrorResponse(),
|
|
683
|
+
500: gitErrorResponse(),
|
|
684
|
+
},
|
|
685
|
+
},
|
|
686
|
+
},
|
|
687
|
+
'/v1/git/generate-commit-message': {
|
|
688
|
+
post: {
|
|
689
|
+
tags: ['git'],
|
|
690
|
+
operationId: 'generateCommitMessage',
|
|
691
|
+
summary: 'Generate AI-powered commit message',
|
|
692
|
+
description:
|
|
693
|
+
'Uses AI to generate a commit message based on staged changes',
|
|
694
|
+
requestBody: {
|
|
695
|
+
required: false,
|
|
696
|
+
content: {
|
|
697
|
+
'application/json': {
|
|
698
|
+
schema: {
|
|
699
|
+
type: 'object',
|
|
700
|
+
properties: {
|
|
701
|
+
project: { type: 'string' },
|
|
702
|
+
},
|
|
703
|
+
},
|
|
704
|
+
},
|
|
705
|
+
},
|
|
706
|
+
},
|
|
707
|
+
responses: {
|
|
708
|
+
200: {
|
|
709
|
+
description: 'OK',
|
|
710
|
+
content: {
|
|
711
|
+
'application/json': {
|
|
712
|
+
schema: {
|
|
713
|
+
type: 'object',
|
|
714
|
+
properties: {
|
|
715
|
+
status: { type: 'string', enum: ['ok'] },
|
|
716
|
+
data: {
|
|
717
|
+
type: 'object',
|
|
718
|
+
properties: {
|
|
719
|
+
message: { type: 'string' },
|
|
720
|
+
},
|
|
721
|
+
required: ['message'],
|
|
722
|
+
},
|
|
723
|
+
},
|
|
724
|
+
required: ['status', 'data'],
|
|
725
|
+
},
|
|
726
|
+
},
|
|
727
|
+
},
|
|
728
|
+
},
|
|
729
|
+
400: gitErrorResponse(),
|
|
730
|
+
500: gitErrorResponse(),
|
|
731
|
+
},
|
|
732
|
+
},
|
|
733
|
+
},
|
|
240
734
|
},
|
|
241
735
|
components: {
|
|
242
736
|
schemas: {
|
|
@@ -421,6 +915,134 @@ export function getOpenAPISpec() {
|
|
|
421
915
|
},
|
|
422
916
|
required: ['kind', 'path'],
|
|
423
917
|
},
|
|
918
|
+
Config: {
|
|
919
|
+
type: 'object',
|
|
920
|
+
properties: {
|
|
921
|
+
agents: {
|
|
922
|
+
type: 'array',
|
|
923
|
+
items: { type: 'string' },
|
|
924
|
+
},
|
|
925
|
+
providers: {
|
|
926
|
+
type: 'array',
|
|
927
|
+
items: { $ref: '#/components/schemas/Provider' },
|
|
928
|
+
},
|
|
929
|
+
defaults: {
|
|
930
|
+
type: 'object',
|
|
931
|
+
properties: {
|
|
932
|
+
agent: { type: 'string' },
|
|
933
|
+
provider: { $ref: '#/components/schemas/Provider' },
|
|
934
|
+
model: { type: 'string' },
|
|
935
|
+
},
|
|
936
|
+
required: ['agent', 'provider', 'model'],
|
|
937
|
+
},
|
|
938
|
+
},
|
|
939
|
+
required: ['agents', 'providers', 'defaults'],
|
|
940
|
+
},
|
|
941
|
+
Model: {
|
|
942
|
+
type: 'object',
|
|
943
|
+
properties: {
|
|
944
|
+
id: { type: 'string' },
|
|
945
|
+
label: { type: 'string' },
|
|
946
|
+
toolCall: { type: 'boolean' },
|
|
947
|
+
reasoning: { type: 'boolean' },
|
|
948
|
+
},
|
|
949
|
+
required: ['id', 'label'],
|
|
950
|
+
},
|
|
951
|
+
GitStatus: {
|
|
952
|
+
type: 'object',
|
|
953
|
+
properties: {
|
|
954
|
+
branch: { type: 'string' },
|
|
955
|
+
ahead: { type: 'integer' },
|
|
956
|
+
behind: { type: 'integer' },
|
|
957
|
+
staged: {
|
|
958
|
+
type: 'array',
|
|
959
|
+
items: { $ref: '#/components/schemas/GitFile' },
|
|
960
|
+
},
|
|
961
|
+
unstaged: {
|
|
962
|
+
type: 'array',
|
|
963
|
+
items: { $ref: '#/components/schemas/GitFile' },
|
|
964
|
+
},
|
|
965
|
+
untracked: {
|
|
966
|
+
type: 'array',
|
|
967
|
+
items: { $ref: '#/components/schemas/GitFile' },
|
|
968
|
+
},
|
|
969
|
+
hasChanges: { type: 'boolean' },
|
|
970
|
+
},
|
|
971
|
+
required: [
|
|
972
|
+
'branch',
|
|
973
|
+
'ahead',
|
|
974
|
+
'behind',
|
|
975
|
+
'staged',
|
|
976
|
+
'unstaged',
|
|
977
|
+
'untracked',
|
|
978
|
+
'hasChanges',
|
|
979
|
+
],
|
|
980
|
+
},
|
|
981
|
+
GitFile: {
|
|
982
|
+
type: 'object',
|
|
983
|
+
properties: {
|
|
984
|
+
path: { type: 'string' },
|
|
985
|
+
status: {
|
|
986
|
+
type: 'string',
|
|
987
|
+
enum: ['modified', 'added', 'deleted', 'renamed', 'untracked'],
|
|
988
|
+
},
|
|
989
|
+
staged: { type: 'boolean' },
|
|
990
|
+
insertions: { type: 'integer' },
|
|
991
|
+
deletions: { type: 'integer' },
|
|
992
|
+
oldPath: { type: 'string' },
|
|
993
|
+
},
|
|
994
|
+
required: ['path', 'status', 'staged'],
|
|
995
|
+
},
|
|
996
|
+
GitDiff: {
|
|
997
|
+
type: 'object',
|
|
998
|
+
properties: {
|
|
999
|
+
file: { type: 'string' },
|
|
1000
|
+
diff: { type: 'string' },
|
|
1001
|
+
insertions: { type: 'integer' },
|
|
1002
|
+
deletions: { type: 'integer' },
|
|
1003
|
+
language: { type: 'string' },
|
|
1004
|
+
binary: { type: 'boolean' },
|
|
1005
|
+
},
|
|
1006
|
+
required: [
|
|
1007
|
+
'file',
|
|
1008
|
+
'diff',
|
|
1009
|
+
'insertions',
|
|
1010
|
+
'deletions',
|
|
1011
|
+
'language',
|
|
1012
|
+
'binary',
|
|
1013
|
+
],
|
|
1014
|
+
},
|
|
1015
|
+
GitBranch: {
|
|
1016
|
+
type: 'object',
|
|
1017
|
+
properties: {
|
|
1018
|
+
current: { type: 'string' },
|
|
1019
|
+
upstream: { type: 'string' },
|
|
1020
|
+
ahead: { type: 'integer' },
|
|
1021
|
+
behind: { type: 'integer' },
|
|
1022
|
+
all: {
|
|
1023
|
+
type: 'array',
|
|
1024
|
+
items: { type: 'string' },
|
|
1025
|
+
},
|
|
1026
|
+
},
|
|
1027
|
+
required: ['current', 'upstream', 'ahead', 'behind', 'all'],
|
|
1028
|
+
},
|
|
1029
|
+
GitCommit: {
|
|
1030
|
+
type: 'object',
|
|
1031
|
+
properties: {
|
|
1032
|
+
hash: { type: 'string' },
|
|
1033
|
+
message: { type: 'string' },
|
|
1034
|
+
filesChanged: { type: 'integer' },
|
|
1035
|
+
insertions: { type: 'integer' },
|
|
1036
|
+
deletions: { type: 'integer' },
|
|
1037
|
+
},
|
|
1038
|
+
required: [
|
|
1039
|
+
'hash',
|
|
1040
|
+
'message',
|
|
1041
|
+
'filesChanged',
|
|
1042
|
+
'insertions',
|
|
1043
|
+
'deletions',
|
|
1044
|
+
],
|
|
1045
|
+
},
|
|
424
1046
|
},
|
|
425
1047
|
},
|
|
426
1048
|
} as const;
|
|
@@ -472,3 +1094,22 @@ function errorResponse() {
|
|
|
472
1094
|
},
|
|
473
1095
|
} as const;
|
|
474
1096
|
}
|
|
1097
|
+
|
|
1098
|
+
function gitErrorResponse() {
|
|
1099
|
+
return {
|
|
1100
|
+
description: 'Error',
|
|
1101
|
+
content: {
|
|
1102
|
+
'application/json': {
|
|
1103
|
+
schema: {
|
|
1104
|
+
type: 'object',
|
|
1105
|
+
properties: {
|
|
1106
|
+
status: { type: 'string', enum: ['error'] },
|
|
1107
|
+
error: { type: 'string' },
|
|
1108
|
+
code: { type: 'string' },
|
|
1109
|
+
},
|
|
1110
|
+
required: ['status', 'error'],
|
|
1111
|
+
},
|
|
1112
|
+
},
|
|
1113
|
+
},
|
|
1114
|
+
} as const;
|
|
1115
|
+
}
|
|
@@ -10,6 +10,17 @@ interface FileRead {
|
|
|
10
10
|
path: string;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
interface ToolPart {
|
|
14
|
+
type: string;
|
|
15
|
+
input?: {
|
|
16
|
+
path?: string;
|
|
17
|
+
filePattern?: string;
|
|
18
|
+
pattern?: string;
|
|
19
|
+
};
|
|
20
|
+
output?: unknown;
|
|
21
|
+
[key: string]: unknown;
|
|
22
|
+
}
|
|
23
|
+
|
|
13
24
|
/**
|
|
14
25
|
* Deduplicates file read results, keeping only the latest version of each file.
|
|
15
26
|
*
|
|
@@ -38,7 +49,8 @@ export function deduplicateFileReads(messages: ModelMessage[]): ModelMessage[] {
|
|
|
38
49
|
if (!['read', 'grep', 'glob'].includes(toolName)) return;
|
|
39
50
|
|
|
40
51
|
// Extract file path from input
|
|
41
|
-
const
|
|
52
|
+
const toolPart = part as ToolPart;
|
|
53
|
+
const input = toolPart.input;
|
|
42
54
|
if (!input) return;
|
|
43
55
|
|
|
44
56
|
const path = input.path || input.filePattern || input.pattern;
|
|
@@ -49,8 +61,8 @@ export function deduplicateFileReads(messages: ModelMessage[]): ModelMessage[] {
|
|
|
49
61
|
fileReads.set(path, []);
|
|
50
62
|
}
|
|
51
63
|
fileReads
|
|
52
|
-
.get(path)
|
|
53
|
-
|
|
64
|
+
.get(path)
|
|
65
|
+
?.push({ messageIndex: msgIdx, partIndex: partIdx, path });
|
|
54
66
|
});
|
|
55
67
|
});
|
|
56
68
|
|
|
@@ -112,7 +124,8 @@ export function pruneToolResults(
|
|
|
112
124
|
if (!toolType.startsWith('tool-')) return;
|
|
113
125
|
|
|
114
126
|
// Check if this has output
|
|
115
|
-
const
|
|
127
|
+
const toolPart = part as ToolPart;
|
|
128
|
+
const hasOutput = toolPart.output !== undefined;
|
|
116
129
|
if (!hasOutput) return;
|
|
117
130
|
|
|
118
131
|
toolResults.push({ messageIndex: msgIdx, partIndex: partIdx });
|
|
@@ -142,11 +155,12 @@ export function pruneToolResults(
|
|
|
142
155
|
if (!part || typeof part !== 'object') return part;
|
|
143
156
|
if (!('type' in part)) return part;
|
|
144
157
|
|
|
145
|
-
const
|
|
158
|
+
const toolPart = part as ToolPart;
|
|
159
|
+
const toolType = toolPart.type;
|
|
146
160
|
if (!toolType.startsWith('tool-')) return part;
|
|
147
161
|
|
|
148
162
|
const key = `${msgIdx}-${partIdx}`;
|
|
149
|
-
const hasOutput =
|
|
163
|
+
const hasOutput = toolPart.output !== undefined;
|
|
150
164
|
|
|
151
165
|
// If this tool result should be pruned, remove its output
|
|
152
166
|
if (hasOutput && !toKeep.has(key)) {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ModelMessage } from 'ai';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Truncates conversation history to keep only the most recent messages.
|
|
5
|
+
* This helps manage context window size and improves performance.
|
|
6
|
+
*
|
|
7
|
+
* Strategy:
|
|
8
|
+
* - Keep only the last N messages
|
|
9
|
+
* - Preserve message pairs (assistant + user responses) when possible
|
|
10
|
+
* - Always keep at least the system message if present
|
|
11
|
+
*/
|
|
12
|
+
export function truncateHistory(
|
|
13
|
+
messages: ModelMessage[],
|
|
14
|
+
maxMessages: number,
|
|
15
|
+
): ModelMessage[] {
|
|
16
|
+
if (messages.length <= maxMessages) {
|
|
17
|
+
return messages;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Calculate how many messages to keep
|
|
21
|
+
const keepCount = Math.min(maxMessages, messages.length);
|
|
22
|
+
const startIndex = messages.length - keepCount;
|
|
23
|
+
|
|
24
|
+
// Return the most recent messages
|
|
25
|
+
return messages.slice(startIndex);
|
|
26
|
+
}
|
package/src/runtime/runner.ts
CHANGED
|
@@ -27,7 +27,6 @@ import {
|
|
|
27
27
|
type RunnerToolContext,
|
|
28
28
|
} from './tool-context-setup.ts';
|
|
29
29
|
import {
|
|
30
|
-
updateSessionTokens,
|
|
31
30
|
updateSessionTokensIncremental,
|
|
32
31
|
updateMessageTokensIncremental,
|
|
33
32
|
completeAssistantMessage,
|
|
@@ -269,6 +268,7 @@ async function runAssistant(opts: RunOpts) {
|
|
|
269
268
|
);
|
|
270
269
|
|
|
271
270
|
try {
|
|
271
|
+
// @ts-expect-error this is fine 🔥
|
|
272
272
|
const result = streamText({
|
|
273
273
|
model,
|
|
274
274
|
tools: toolset,
|