git-coco 0.25.0 → 0.27.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.ts CHANGED
@@ -86,6 +86,14 @@ type OllamaFields = Partial<OllamaInput> & BaseLLMParams;
86
86
  type OpenAILLMService = BaseLLMService & {
87
87
  provider: 'openai';
88
88
  model: OpenAIModel;
89
+ /**
90
+ * Custom base URL for OpenAI-compatible APIs (e.g., OpenRouter, Azure OpenAI).
91
+ * If not specified, uses the default OpenAI API endpoint.
92
+ *
93
+ * @example "https://openrouter.ai/api/v1"
94
+ * @example "https://your-resource.openai.azure.com"
95
+ */
96
+ baseURL?: string;
89
97
  fields?: OpenAIFields;
90
98
  };
91
99
  type OllamaLLMService = BaseLLMService & {
@@ -46,7 +46,7 @@ import { pathToFileURL } from 'url';
46
46
  /**
47
47
  * Current build version from package.json
48
48
  */
49
- const BUILD_VERSION = "0.25.0";
49
+ const BUILD_VERSION = "0.27.0";
50
50
 
51
51
  const isInteractive = (config) => {
52
52
  return config?.mode === 'interactive' || !!config?.interactive;
@@ -357,8 +357,11 @@ function getDefaultServiceApiKey(config) {
357
357
  const DEFAULT_OPENAI_LLM_SERVICE = {
358
358
  provider: 'openai',
359
359
  model: 'gpt-4o-mini',
360
- tokenLimit: 2024,
360
+ tokenLimit: 4096,
361
361
  temperature: 0.32,
362
+ maxConcurrent: 12,
363
+ minTokensForSummary: 800,
364
+ maxFileTokens: 2000,
362
365
  authentication: {
363
366
  type: 'APIKey',
364
367
  credentials: {
@@ -370,6 +373,10 @@ const DEFAULT_ANTHROPIC_LLM_SERVICE = {
370
373
  provider: 'anthropic',
371
374
  model: 'claude-3-5-sonnet-20240620',
372
375
  temperature: 0.32,
376
+ tokenLimit: 4096,
377
+ maxConcurrent: 12,
378
+ minTokensForSummary: 800,
379
+ maxFileTokens: 2000,
373
380
  authentication: {
374
381
  type: 'APIKey',
375
382
  credentials: {
@@ -382,9 +389,11 @@ const DEFAULT_OLLAMA_LLM_SERVICE = {
382
389
  model: 'llama3',
383
390
  endpoint: 'http://localhost:11434',
384
391
  maxConcurrent: 1,
385
- tokenLimit: 2024,
392
+ tokenLimit: 4096,
386
393
  temperature: 0.4,
387
394
  maxParsingAttempts: 3,
395
+ minTokensForSummary: 800,
396
+ maxFileTokens: 2000,
388
397
  authentication: {
389
398
  type: 'None',
390
399
  credentials: undefined,
@@ -470,6 +479,7 @@ function loadEnvConfig(config) {
470
479
  'COCO_SERVICE_PROVIDER',
471
480
  'COCO_SERVICE_MODEL',
472
481
  'OPEN_AI_KEY',
482
+ 'COCO_SERVICE_BASE_URL',
473
483
  'COCO_SERVICE_ENDPOINT',
474
484
  'COCO_SERVICE_REQUEST_OPTIONS_TIMEOUT',
475
485
  'COCO_SERVICE_REQUEST_OPTIONS_MAX_RETRIES',
@@ -484,6 +494,7 @@ function loadEnvConfig(config) {
484
494
  if (key === 'COCO_SERVICE_PROVIDER' ||
485
495
  key === 'COCO_SERVICE_MODEL' ||
486
496
  key === 'OPEN_AI_KEY' ||
497
+ key === 'COCO_SERVICE_BASE_URL' ||
487
498
  key === 'COCO_SERVICE_ENDPOINT' ||
488
499
  key === 'COCO_SERVICE_REQUEST_OPTIONS_TIMEOUT' ||
489
500
  key === 'COCO_SERVICE_REQUEST_OPTIONS_MAX_RETRIES' ||
@@ -522,6 +533,12 @@ function handleServiceEnvVar(service, key, value) {
522
533
  };
523
534
  }
524
535
  break;
536
+ case 'COCO_SERVICE_BASE_URL':
537
+ if (service.provider === 'openai') {
538
+ // Cast to OpenAILLMService to access baseURL property
539
+ service.baseURL = value;
540
+ }
541
+ break;
525
542
  case 'COCO_SERVICE_ENDPOINT':
526
543
  if (service.provider === 'ollama') {
527
544
  service.endpoint = value;
@@ -632,6 +649,25 @@ function loadGitConfig(config) {
632
649
  service = {
633
650
  provider: gitConfigParsed.coco?.serviceProvider,
634
651
  model: gitConfigParsed.coco?.serviceModel,
652
+ tokenLimit: gitConfigParsed.coco?.serviceTokenLimit
653
+ ? Number(gitConfigParsed.coco.serviceTokenLimit)
654
+ : undefined,
655
+ temperature: gitConfigParsed.coco?.serviceTemperature
656
+ ? Number(gitConfigParsed.coco.serviceTemperature)
657
+ : undefined,
658
+ maxConcurrent: gitConfigParsed.coco?.serviceMaxConcurrent
659
+ ? Number(gitConfigParsed.coco.serviceMaxConcurrent)
660
+ : undefined,
661
+ minTokensForSummary: gitConfigParsed.coco?.serviceMinTokensForSummary
662
+ ? Number(gitConfigParsed.coco.serviceMinTokensForSummary)
663
+ : undefined,
664
+ maxFileTokens: gitConfigParsed.coco?.serviceMaxFileTokens
665
+ ? Number(gitConfigParsed.coco.serviceMaxFileTokens)
666
+ : undefined,
667
+ maxParsingAttempts: gitConfigParsed.coco?.serviceMaxParsingAttempts
668
+ ? Number(gitConfigParsed.coco.serviceMaxParsingAttempts)
669
+ : undefined,
670
+ baseURL: gitConfigParsed.coco?.serviceBaseURL,
635
671
  authentication: {
636
672
  type: 'APIKey',
637
673
  credentials: {
@@ -687,12 +723,35 @@ const appendToGitConfig = async (filePath, config) => {
687
723
  if (service.authentication.type === 'APIKey') {
688
724
  contentLines.push(` serviceApiKey = ${service.authentication.credentials.apiKey}`);
689
725
  }
726
+ if (service.tokenLimit !== undefined) {
727
+ contentLines.push(` serviceTokenLimit = ${service.tokenLimit}`);
728
+ }
729
+ if (service.temperature !== undefined) {
730
+ contentLines.push(` serviceTemperature = ${service.temperature}`);
731
+ }
732
+ if (service.maxConcurrent !== undefined) {
733
+ contentLines.push(` serviceMaxConcurrent = ${service.maxConcurrent}`);
734
+ }
735
+ if (service.minTokensForSummary !== undefined) {
736
+ contentLines.push(` serviceMinTokensForSummary = ${service.minTokensForSummary}`);
737
+ }
738
+ if (service.maxFileTokens !== undefined) {
739
+ contentLines.push(` serviceMaxFileTokens = ${service.maxFileTokens}`);
740
+ }
741
+ if (service.maxParsingAttempts !== undefined) {
742
+ contentLines.push(` serviceMaxParsingAttempts = ${service.maxParsingAttempts}`);
743
+ }
690
744
  if (service.requestOptions?.timeout) {
691
745
  contentLines.push(` serviceRequestOptionsTimeout = ${service.requestOptions.timeout}`);
692
746
  }
693
747
  if (service.requestOptions?.maxRetries) {
694
748
  contentLines.push(` serviceRequestOptionsMaxRetries = ${service.requestOptions.maxRetries}`);
695
749
  }
750
+ // Handle baseURL for OpenAI
751
+ if (service.provider === 'openai' && 'baseURL' in service && service.baseURL) {
752
+ contentLines.push(` serviceBaseURL = ${service.baseURL}`);
753
+ }
754
+ // Handle endpoint for Ollama
696
755
  if (service.provider === 'ollama') {
697
756
  const ollamaService = service;
698
757
  if (ollamaService.endpoint) {
@@ -883,6 +942,14 @@ const schema$1 = {
883
942
  "model": {
884
943
  "$ref": "#/definitions/LLMModel"
885
944
  },
945
+ "baseURL": {
946
+ "type": "string",
947
+ "description": "Custom base URL for OpenAI-compatible APIs (e.g., OpenRouter, Azure OpenAI). If not specified, uses the default OpenAI API endpoint.",
948
+ "examples": [
949
+ "https://openrouter.ai/api/v1",
950
+ "https://your-resource.openai.azure.com"
951
+ ]
952
+ },
886
953
  "fields": {
887
954
  "type": "object",
888
955
  "additionalProperties": false,
@@ -2157,12 +2224,14 @@ function parseServiceConfig(service) {
2157
2224
  return {
2158
2225
  provider: 'openai',
2159
2226
  model: service.model,
2227
+ baseURL: service.baseURL,
2160
2228
  authentication: {
2161
2229
  type: 'APIKey',
2162
2230
  credentials: {
2163
2231
  apiKey: service.apiKey
2164
2232
  }
2165
- }
2233
+ },
2234
+ fields: service.fields
2166
2235
  };
2167
2236
  case 'anthropic':
2168
2237
  return {
@@ -6257,11 +6326,22 @@ function getLlm(provider, model, config) {
6257
6326
  model,
6258
6327
  });
6259
6328
  case 'openai':
6260
- return new ChatOpenAI({
6329
+ const openaiConfig = {
6261
6330
  apiKey: apiKey,
6262
6331
  model,
6263
6332
  temperature: config.service.temperature || 0.2,
6264
- });
6333
+ };
6334
+ // Add custom base URL if specified (for OpenRouter, Azure OpenAI, etc.)
6335
+ if ('baseURL' in config.service && config.service.baseURL) {
6336
+ openaiConfig.configuration = {
6337
+ baseURL: config.service.baseURL,
6338
+ };
6339
+ }
6340
+ // Merge any additional fields from config
6341
+ if ('fields' in config.service && config.service.fields) {
6342
+ Object.assign(openaiConfig, config.service.fields);
6343
+ }
6344
+ return new ChatOpenAI(openaiConfig);
6265
6345
  default:
6266
6346
  throw new LangChainConfigurationError(`getLlm: Unsupported provider '${provider}'`, { provider, model, supportedProviders: ['openai', 'anthropic', 'ollama'] });
6267
6347
  }
package/dist/index.js CHANGED
@@ -68,7 +68,7 @@ var readline__namespace = /*#__PURE__*/_interopNamespaceDefault(readline);
68
68
  /**
69
69
  * Current build version from package.json
70
70
  */
71
- const BUILD_VERSION = "0.25.0";
71
+ const BUILD_VERSION = "0.27.0";
72
72
 
73
73
  const isInteractive = (config) => {
74
74
  return config?.mode === 'interactive' || !!config?.interactive;
@@ -379,8 +379,11 @@ function getDefaultServiceApiKey(config) {
379
379
  const DEFAULT_OPENAI_LLM_SERVICE = {
380
380
  provider: 'openai',
381
381
  model: 'gpt-4o-mini',
382
- tokenLimit: 2024,
382
+ tokenLimit: 4096,
383
383
  temperature: 0.32,
384
+ maxConcurrent: 12,
385
+ minTokensForSummary: 800,
386
+ maxFileTokens: 2000,
384
387
  authentication: {
385
388
  type: 'APIKey',
386
389
  credentials: {
@@ -392,6 +395,10 @@ const DEFAULT_ANTHROPIC_LLM_SERVICE = {
392
395
  provider: 'anthropic',
393
396
  model: 'claude-3-5-sonnet-20240620',
394
397
  temperature: 0.32,
398
+ tokenLimit: 4096,
399
+ maxConcurrent: 12,
400
+ minTokensForSummary: 800,
401
+ maxFileTokens: 2000,
395
402
  authentication: {
396
403
  type: 'APIKey',
397
404
  credentials: {
@@ -404,9 +411,11 @@ const DEFAULT_OLLAMA_LLM_SERVICE = {
404
411
  model: 'llama3',
405
412
  endpoint: 'http://localhost:11434',
406
413
  maxConcurrent: 1,
407
- tokenLimit: 2024,
414
+ tokenLimit: 4096,
408
415
  temperature: 0.4,
409
416
  maxParsingAttempts: 3,
417
+ minTokensForSummary: 800,
418
+ maxFileTokens: 2000,
410
419
  authentication: {
411
420
  type: 'None',
412
421
  credentials: undefined,
@@ -492,6 +501,7 @@ function loadEnvConfig(config) {
492
501
  'COCO_SERVICE_PROVIDER',
493
502
  'COCO_SERVICE_MODEL',
494
503
  'OPEN_AI_KEY',
504
+ 'COCO_SERVICE_BASE_URL',
495
505
  'COCO_SERVICE_ENDPOINT',
496
506
  'COCO_SERVICE_REQUEST_OPTIONS_TIMEOUT',
497
507
  'COCO_SERVICE_REQUEST_OPTIONS_MAX_RETRIES',
@@ -506,6 +516,7 @@ function loadEnvConfig(config) {
506
516
  if (key === 'COCO_SERVICE_PROVIDER' ||
507
517
  key === 'COCO_SERVICE_MODEL' ||
508
518
  key === 'OPEN_AI_KEY' ||
519
+ key === 'COCO_SERVICE_BASE_URL' ||
509
520
  key === 'COCO_SERVICE_ENDPOINT' ||
510
521
  key === 'COCO_SERVICE_REQUEST_OPTIONS_TIMEOUT' ||
511
522
  key === 'COCO_SERVICE_REQUEST_OPTIONS_MAX_RETRIES' ||
@@ -544,6 +555,12 @@ function handleServiceEnvVar(service, key, value) {
544
555
  };
545
556
  }
546
557
  break;
558
+ case 'COCO_SERVICE_BASE_URL':
559
+ if (service.provider === 'openai') {
560
+ // Cast to OpenAILLMService to access baseURL property
561
+ service.baseURL = value;
562
+ }
563
+ break;
547
564
  case 'COCO_SERVICE_ENDPOINT':
548
565
  if (service.provider === 'ollama') {
549
566
  service.endpoint = value;
@@ -654,6 +671,25 @@ function loadGitConfig(config) {
654
671
  service = {
655
672
  provider: gitConfigParsed.coco?.serviceProvider,
656
673
  model: gitConfigParsed.coco?.serviceModel,
674
+ tokenLimit: gitConfigParsed.coco?.serviceTokenLimit
675
+ ? Number(gitConfigParsed.coco.serviceTokenLimit)
676
+ : undefined,
677
+ temperature: gitConfigParsed.coco?.serviceTemperature
678
+ ? Number(gitConfigParsed.coco.serviceTemperature)
679
+ : undefined,
680
+ maxConcurrent: gitConfigParsed.coco?.serviceMaxConcurrent
681
+ ? Number(gitConfigParsed.coco.serviceMaxConcurrent)
682
+ : undefined,
683
+ minTokensForSummary: gitConfigParsed.coco?.serviceMinTokensForSummary
684
+ ? Number(gitConfigParsed.coco.serviceMinTokensForSummary)
685
+ : undefined,
686
+ maxFileTokens: gitConfigParsed.coco?.serviceMaxFileTokens
687
+ ? Number(gitConfigParsed.coco.serviceMaxFileTokens)
688
+ : undefined,
689
+ maxParsingAttempts: gitConfigParsed.coco?.serviceMaxParsingAttempts
690
+ ? Number(gitConfigParsed.coco.serviceMaxParsingAttempts)
691
+ : undefined,
692
+ baseURL: gitConfigParsed.coco?.serviceBaseURL,
657
693
  authentication: {
658
694
  type: 'APIKey',
659
695
  credentials: {
@@ -709,12 +745,35 @@ const appendToGitConfig = async (filePath, config) => {
709
745
  if (service.authentication.type === 'APIKey') {
710
746
  contentLines.push(` serviceApiKey = ${service.authentication.credentials.apiKey}`);
711
747
  }
748
+ if (service.tokenLimit !== undefined) {
749
+ contentLines.push(` serviceTokenLimit = ${service.tokenLimit}`);
750
+ }
751
+ if (service.temperature !== undefined) {
752
+ contentLines.push(` serviceTemperature = ${service.temperature}`);
753
+ }
754
+ if (service.maxConcurrent !== undefined) {
755
+ contentLines.push(` serviceMaxConcurrent = ${service.maxConcurrent}`);
756
+ }
757
+ if (service.minTokensForSummary !== undefined) {
758
+ contentLines.push(` serviceMinTokensForSummary = ${service.minTokensForSummary}`);
759
+ }
760
+ if (service.maxFileTokens !== undefined) {
761
+ contentLines.push(` serviceMaxFileTokens = ${service.maxFileTokens}`);
762
+ }
763
+ if (service.maxParsingAttempts !== undefined) {
764
+ contentLines.push(` serviceMaxParsingAttempts = ${service.maxParsingAttempts}`);
765
+ }
712
766
  if (service.requestOptions?.timeout) {
713
767
  contentLines.push(` serviceRequestOptionsTimeout = ${service.requestOptions.timeout}`);
714
768
  }
715
769
  if (service.requestOptions?.maxRetries) {
716
770
  contentLines.push(` serviceRequestOptionsMaxRetries = ${service.requestOptions.maxRetries}`);
717
771
  }
772
+ // Handle baseURL for OpenAI
773
+ if (service.provider === 'openai' && 'baseURL' in service && service.baseURL) {
774
+ contentLines.push(` serviceBaseURL = ${service.baseURL}`);
775
+ }
776
+ // Handle endpoint for Ollama
718
777
  if (service.provider === 'ollama') {
719
778
  const ollamaService = service;
720
779
  if (ollamaService.endpoint) {
@@ -905,6 +964,14 @@ const schema$1 = {
905
964
  "model": {
906
965
  "$ref": "#/definitions/LLMModel"
907
966
  },
967
+ "baseURL": {
968
+ "type": "string",
969
+ "description": "Custom base URL for OpenAI-compatible APIs (e.g., OpenRouter, Azure OpenAI). If not specified, uses the default OpenAI API endpoint.",
970
+ "examples": [
971
+ "https://openrouter.ai/api/v1",
972
+ "https://your-resource.openai.azure.com"
973
+ ]
974
+ },
908
975
  "fields": {
909
976
  "type": "object",
910
977
  "additionalProperties": false,
@@ -2179,12 +2246,14 @@ function parseServiceConfig(service) {
2179
2246
  return {
2180
2247
  provider: 'openai',
2181
2248
  model: service.model,
2249
+ baseURL: service.baseURL,
2182
2250
  authentication: {
2183
2251
  type: 'APIKey',
2184
2252
  credentials: {
2185
2253
  apiKey: service.apiKey
2186
2254
  }
2187
- }
2255
+ },
2256
+ fields: service.fields
2188
2257
  };
2189
2258
  case 'anthropic':
2190
2259
  return {
@@ -6279,11 +6348,22 @@ function getLlm(provider, model, config) {
6279
6348
  model,
6280
6349
  });
6281
6350
  case 'openai':
6282
- return new openai.ChatOpenAI({
6351
+ const openaiConfig = {
6283
6352
  apiKey: apiKey,
6284
6353
  model,
6285
6354
  temperature: config.service.temperature || 0.2,
6286
- });
6355
+ };
6356
+ // Add custom base URL if specified (for OpenRouter, Azure OpenAI, etc.)
6357
+ if ('baseURL' in config.service && config.service.baseURL) {
6358
+ openaiConfig.configuration = {
6359
+ baseURL: config.service.baseURL,
6360
+ };
6361
+ }
6362
+ // Merge any additional fields from config
6363
+ if ('fields' in config.service && config.service.fields) {
6364
+ Object.assign(openaiConfig, config.service.fields);
6365
+ }
6366
+ return new openai.ChatOpenAI(openaiConfig);
6287
6367
  default:
6288
6368
  throw new LangChainConfigurationError(`getLlm: Unsupported provider '${provider}'`, { provider, model, supportedProviders: ['openai', 'anthropic', 'ollama'] });
6289
6369
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "git-coco",
3
- "version": "0.25.0",
3
+ "version": "0.27.0",
4
4
  "description": "zero-effort git commits with coco.",
5
5
  "author": "gfargo <ghfargo@gmail.com>",
6
6
  "license": "MIT",
@@ -53,7 +53,7 @@
53
53
  "@types/diff": "^8.0.0",
54
54
  "@types/ini": "^4.1.1",
55
55
  "@types/jest": "^30.0.0",
56
- "@types/node": "^24.0.8",
56
+ "@types/node": "^25.0.10",
57
57
  "@types/yargs": "^17.0.33",
58
58
  "@typescript-eslint/eslint-plugin": "^7.13.1",
59
59
  "@typescript-eslint/parser": "^7.13.1",