ghagga-core 2.5.0 → 2.6.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/README.md +1 -1
- package/dist/agents/consensus.d.ts +16 -0
- package/dist/agents/consensus.d.ts.map +1 -1
- package/dist/agents/consensus.js +57 -33
- package/dist/agents/consensus.js.map +1 -1
- package/dist/agents/diagnostic.d.ts +55 -0
- package/dist/agents/diagnostic.d.ts.map +1 -0
- package/dist/agents/diagnostic.js +143 -0
- package/dist/agents/diagnostic.js.map +1 -0
- package/dist/agents/prompts.d.ts +6 -4
- package/dist/agents/prompts.d.ts.map +1 -1
- package/dist/agents/prompts.js +110 -24
- package/dist/agents/prompts.js.map +1 -1
- package/dist/agents/simple.d.ts +7 -0
- package/dist/agents/simple.d.ts.map +1 -1
- package/dist/agents/simple.js +32 -18
- package/dist/agents/simple.js.map +1 -1
- package/dist/agents/workflow.d.ts +28 -1
- package/dist/agents/workflow.d.ts.map +1 -1
- package/dist/agents/workflow.js +112 -45
- package/dist/agents/workflow.js.map +1 -1
- package/dist/enhance/enhance.d.ts.map +1 -1
- package/dist/enhance/enhance.js +16 -4
- package/dist/enhance/enhance.js.map +1 -1
- package/dist/format.d.ts +47 -1
- package/dist/format.d.ts.map +1 -1
- package/dist/format.js +175 -3
- package/dist/format.js.map +1 -1
- package/dist/graph/blast-radius.d.ts +57 -0
- package/dist/graph/blast-radius.d.ts.map +1 -0
- package/dist/graph/blast-radius.js +145 -0
- package/dist/graph/blast-radius.js.map +1 -0
- package/dist/graph/builder.d.ts +50 -0
- package/dist/graph/builder.d.ts.map +1 -0
- package/dist/graph/builder.js +210 -0
- package/dist/graph/builder.js.map +1 -0
- package/dist/graph/extractors/go.d.ts +9 -0
- package/dist/graph/extractors/go.d.ts.map +1 -0
- package/dist/graph/extractors/go.js +78 -0
- package/dist/graph/extractors/go.js.map +1 -0
- package/dist/graph/extractors/index.d.ts +22 -0
- package/dist/graph/extractors/index.d.ts.map +1 -0
- package/dist/graph/extractors/index.js +37 -0
- package/dist/graph/extractors/index.js.map +1 -0
- package/dist/graph/extractors/java.d.ts +9 -0
- package/dist/graph/extractors/java.d.ts.map +1 -0
- package/dist/graph/extractors/java.js +80 -0
- package/dist/graph/extractors/java.js.map +1 -0
- package/dist/graph/extractors/javascript.d.ts +9 -0
- package/dist/graph/extractors/javascript.d.ts.map +1 -0
- package/dist/graph/extractors/javascript.js +204 -0
- package/dist/graph/extractors/javascript.js.map +1 -0
- package/dist/graph/extractors/python.d.ts +9 -0
- package/dist/graph/extractors/python.d.ts.map +1 -0
- package/dist/graph/extractors/python.js +103 -0
- package/dist/graph/extractors/python.js.map +1 -0
- package/dist/graph/extractors/rust.d.ts +9 -0
- package/dist/graph/extractors/rust.d.ts.map +1 -0
- package/dist/graph/extractors/rust.js +115 -0
- package/dist/graph/extractors/rust.js.map +1 -0
- package/dist/graph/extractors/types.d.ts +31 -0
- package/dist/graph/extractors/types.d.ts.map +1 -0
- package/dist/graph/extractors/types.js +9 -0
- package/dist/graph/extractors/types.js.map +1 -0
- package/dist/graph/extractors/typescript.d.ts +9 -0
- package/dist/graph/extractors/typescript.d.ts.map +1 -0
- package/dist/graph/extractors/typescript.js +151 -0
- package/dist/graph/extractors/typescript.js.map +1 -0
- package/dist/graph/index.d.ts +15 -0
- package/dist/graph/index.d.ts.map +1 -0
- package/dist/graph/index.js +14 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/graph/loader.d.ts +43 -0
- package/dist/graph/loader.d.ts.map +1 -0
- package/dist/graph/loader.js +104 -0
- package/dist/graph/loader.js.map +1 -0
- package/dist/graph/schema.d.ts +113 -0
- package/dist/graph/schema.d.ts.map +1 -0
- package/dist/graph/schema.js +144 -0
- package/dist/graph/schema.js.map +1 -0
- package/dist/health/trends.js +1 -1
- package/dist/health/trends.js.map +1 -1
- package/dist/index.d.ts +20 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -4
- package/dist/index.js.map +1 -1
- package/dist/memory/sqlite.js +4 -4
- package/dist/memory/sqlite.js.map +1 -1
- package/dist/pipeline.d.ts.map +1 -1
- package/dist/pipeline.js +291 -42
- package/dist/pipeline.js.map +1 -1
- package/dist/providers/cli-bridge.d.ts +136 -0
- package/dist/providers/cli-bridge.d.ts.map +1 -0
- package/dist/providers/cli-bridge.js +457 -0
- package/dist/providers/cli-bridge.js.map +1 -0
- package/dist/providers/fallback.d.ts +8 -0
- package/dist/providers/fallback.d.ts.map +1 -1
- package/dist/providers/fallback.js +24 -8
- package/dist/providers/fallback.js.map +1 -1
- package/dist/providers/gateway.d.ts +40 -0
- package/dist/providers/gateway.d.ts.map +1 -0
- package/dist/providers/gateway.js +52 -0
- package/dist/providers/gateway.js.map +1 -0
- package/dist/providers/generate-fn.d.ts +62 -0
- package/dist/providers/generate-fn.d.ts.map +1 -0
- package/dist/providers/generate-fn.js +84 -0
- package/dist/providers/generate-fn.js.map +1 -0
- package/dist/providers/index.d.ts +5 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +53 -0
- package/dist/providers/index.js.map +1 -1
- package/dist/tools/plugins/index.d.ts +2 -0
- package/dist/tools/plugins/index.d.ts.map +1 -1
- package/dist/tools/plugins/index.js +7 -0
- package/dist/tools/plugins/index.js.map +1 -1
- package/dist/tools/plugins/zizmor.d.ts +22 -0
- package/dist/tools/plugins/zizmor.d.ts.map +1 -0
- package/dist/tools/plugins/zizmor.js +112 -0
- package/dist/tools/plugins/zizmor.js.map +1 -0
- package/dist/tools/resolve.js +1 -1
- package/dist/tools/resolve.js.map +1 -1
- package/dist/tools/types.d.ts +1 -1
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/types.d.ts +54 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +21 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/concurrency.d.ts +29 -0
- package/dist/utils/concurrency.d.ts.map +1 -0
- package/dist/utils/concurrency.js +40 -0
- package/dist/utils/concurrency.js.map +1 -0
- package/dist/utils/context-levels.d.ts +113 -0
- package/dist/utils/context-levels.d.ts.map +1 -0
- package/dist/utils/context-levels.js +255 -0
- package/dist/utils/context-levels.js.map +1 -0
- package/dist/utils/diff.d.ts +25 -0
- package/dist/utils/diff.d.ts.map +1 -1
- package/dist/utils/diff.js +28 -0
- package/dist/utils/diff.js.map +1 -1
- package/dist/utils/llm-timeout.d.ts +38 -0
- package/dist/utils/llm-timeout.d.ts.map +1 -0
- package/dist/utils/llm-timeout.js +76 -0
- package/dist/utils/llm-timeout.js.map +1 -0
- package/dist/utils/path-protection.d.ts +59 -0
- package/dist/utils/path-protection.d.ts.map +1 -0
- package/dist/utils/path-protection.js +136 -0
- package/dist/utils/path-protection.js.map +1 -0
- package/dist/utils/token-budget.d.ts +34 -1
- package/dist/utils/token-budget.d.ts.map +1 -1
- package/dist/utils/token-budget.js +108 -3
- package/dist/utils/token-budget.js.map +1 -1
- package/package.json +21 -19
- package/LICENSE +0 -21
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Three-tier path protection for sensitive files.
|
|
3
|
+
*
|
|
4
|
+
* Provides a non-overridable security layer that filters sensitive files
|
|
5
|
+
* BEFORE user-configurable ignorePatterns are applied. This ensures that
|
|
6
|
+
* secrets, credentials, and private keys are never sent to the LLM for review.
|
|
7
|
+
*
|
|
8
|
+
* Tiers:
|
|
9
|
+
* 1. ZERO_ACCESS — hardcoded, content never sent to LLM, non-overridable
|
|
10
|
+
* 2. REDACT — content replaced with redaction notice, path still visible
|
|
11
|
+
* 3. User ignore — existing configurable ignorePatterns (handled in diff.ts)
|
|
12
|
+
*/
|
|
13
|
+
import { minimatch } from 'minimatch';
|
|
14
|
+
// ─── Constants ──────────────────────────────────────────────────
|
|
15
|
+
/** Redaction notice used to replace content of REDACT-tier files. */
|
|
16
|
+
export const REDACTED_CONTENT = '[REDACTED — sensitive file detected by GHAGGA path protection]';
|
|
17
|
+
/**
|
|
18
|
+
* Tier 1 — ZERO_ACCESS patterns.
|
|
19
|
+
*
|
|
20
|
+
* Files matching these patterns are completely blocked from the review
|
|
21
|
+
* pipeline. Their content is never sent to the LLM. These patterns are
|
|
22
|
+
* hardcoded and cannot be overridden by user configuration.
|
|
23
|
+
*/
|
|
24
|
+
export const ZERO_ACCESS_PATTERNS = [
|
|
25
|
+
// Environment files
|
|
26
|
+
'.env',
|
|
27
|
+
'.env.*',
|
|
28
|
+
// Private keys and certificates
|
|
29
|
+
'*.pem',
|
|
30
|
+
'*.key',
|
|
31
|
+
'*.p12',
|
|
32
|
+
'*.pfx',
|
|
33
|
+
'*.jks',
|
|
34
|
+
'*.keystore',
|
|
35
|
+
// SSH keys
|
|
36
|
+
'id_rsa',
|
|
37
|
+
'id_ed25519',
|
|
38
|
+
'id_ecdsa',
|
|
39
|
+
'*.pub',
|
|
40
|
+
// Cloud credentials
|
|
41
|
+
'credentials.json',
|
|
42
|
+
'service-account*.json',
|
|
43
|
+
'gcloud*.json',
|
|
44
|
+
// Package manager credentials
|
|
45
|
+
'.npmrc',
|
|
46
|
+
'.pypirc',
|
|
47
|
+
'.gem/credentials',
|
|
48
|
+
// Container and cluster configs
|
|
49
|
+
'.docker/config.json',
|
|
50
|
+
'kubeconfig',
|
|
51
|
+
'kube/config',
|
|
52
|
+
// Directory-level patterns
|
|
53
|
+
'**/.aws/*',
|
|
54
|
+
'**/.ssh/*',
|
|
55
|
+
'**/.gnupg/*',
|
|
56
|
+
// Generic secrets
|
|
57
|
+
'*.secret',
|
|
58
|
+
'*.secrets',
|
|
59
|
+
'secrets.yml',
|
|
60
|
+
'secrets.yaml',
|
|
61
|
+
'vault.yml',
|
|
62
|
+
];
|
|
63
|
+
/**
|
|
64
|
+
* Tier 2 — REDACT patterns.
|
|
65
|
+
*
|
|
66
|
+
* Files matching these patterns have their content replaced with a
|
|
67
|
+
* redaction notice. The file path is still visible in the review so
|
|
68
|
+
* reviewers know the file was changed, but the actual content is not
|
|
69
|
+
* sent to the LLM.
|
|
70
|
+
*/
|
|
71
|
+
export const REDACT_PATTERNS = [
|
|
72
|
+
// Environment templates (may leak structure)
|
|
73
|
+
'.env.example',
|
|
74
|
+
'.env.sample',
|
|
75
|
+
'.env.template',
|
|
76
|
+
// Docker Compose (may contain credentials in environment blocks)
|
|
77
|
+
'docker-compose*.yml',
|
|
78
|
+
// Terraform state and variables (may contain secrets)
|
|
79
|
+
'**/terraform.tfvars',
|
|
80
|
+
'**/terraform.tfstate*',
|
|
81
|
+
];
|
|
82
|
+
// ─── Matching Options ───────────────────────────────────────────
|
|
83
|
+
/** Minimatch options used for all path protection matching. */
|
|
84
|
+
const MATCH_OPTIONS = { dot: true, matchBase: true };
|
|
85
|
+
/**
|
|
86
|
+
* Apply three-tier path protection to a set of diff files.
|
|
87
|
+
*
|
|
88
|
+
* This function is pure and deterministic. It processes files in the
|
|
89
|
+
* following order:
|
|
90
|
+
* 1. Check against REDACT patterns first — these are specific exceptions
|
|
91
|
+
* (e.g., `.env.example`) that would otherwise be caught by broader
|
|
92
|
+
* ZERO_ACCESS globs (e.g., `.env.*`). Content is replaced.
|
|
93
|
+
* 2. Check against ZERO_ACCESS patterns — block entirely
|
|
94
|
+
* 3. Everything else passes through untouched
|
|
95
|
+
*
|
|
96
|
+
* @param files - Array of DiffFile objects from the parsed diff
|
|
97
|
+
* @returns Object with allowed, redacted, and blocked files
|
|
98
|
+
*/
|
|
99
|
+
export function applyPathProtection(files) {
|
|
100
|
+
const allowed = [];
|
|
101
|
+
const redacted = [];
|
|
102
|
+
const blocked = [];
|
|
103
|
+
for (const file of files) {
|
|
104
|
+
if (matchesAnyPattern(file.path, REDACT_PATTERNS)) {
|
|
105
|
+
// Tier 2: REDACT — checked first because REDACT patterns are more
|
|
106
|
+
// specific exceptions (e.g. .env.example) that would otherwise be
|
|
107
|
+
// caught by broader ZERO_ACCESS globs (e.g. .env.*)
|
|
108
|
+
redacted.push({
|
|
109
|
+
path: file.path,
|
|
110
|
+
additions: file.additions,
|
|
111
|
+
deletions: file.deletions,
|
|
112
|
+
content: REDACTED_CONTENT,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
else if (matchesAnyPattern(file.path, ZERO_ACCESS_PATTERNS)) {
|
|
116
|
+
// Tier 1: ZERO_ACCESS — broad security patterns
|
|
117
|
+
blocked.push(file.path);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
allowed.push(file);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return { allowed, redacted, blocked };
|
|
124
|
+
}
|
|
125
|
+
// ─── Internal Helpers ───────────────────────────────────────────
|
|
126
|
+
/**
|
|
127
|
+
* Check if a file path matches any of the given glob patterns.
|
|
128
|
+
*
|
|
129
|
+
* Uses minimatch with `{ dot: true, matchBase: true }` to ensure:
|
|
130
|
+
* - Dotfiles are matched (e.g., `.env`)
|
|
131
|
+
* - Basename matching works (e.g., `.env` matches `src/.env`)
|
|
132
|
+
*/
|
|
133
|
+
function matchesAnyPattern(filePath, patterns) {
|
|
134
|
+
return patterns.some((pattern) => minimatch(filePath, pattern, MATCH_OPTIONS));
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=path-protection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-protection.js","sourceRoot":"","sources":["../../src/utils/path-protection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGtC,mEAAmE;AAEnE,qEAAqE;AACrE,MAAM,CAAC,MAAM,gBAAgB,GAAG,gEAAgE,CAAC;AAEjG;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAsB;IACrD,oBAAoB;IACpB,MAAM;IACN,QAAQ;IAER,gCAAgC;IAChC,OAAO;IACP,OAAO;IACP,OAAO;IACP,OAAO;IACP,OAAO;IACP,YAAY;IAEZ,WAAW;IACX,QAAQ;IACR,YAAY;IACZ,UAAU;IACV,OAAO;IAEP,oBAAoB;IACpB,kBAAkB;IAClB,uBAAuB;IACvB,cAAc;IAEd,8BAA8B;IAC9B,QAAQ;IACR,SAAS;IACT,kBAAkB;IAElB,gCAAgC;IAChC,qBAAqB;IACrB,YAAY;IACZ,aAAa;IAEb,2BAA2B;IAC3B,WAAW;IACX,WAAW;IACX,aAAa;IAEb,kBAAkB;IAClB,UAAU;IACV,WAAW;IACX,aAAa;IACb,cAAc;IACd,WAAW;CACH,CAAC;AAEX;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAsB;IAChD,6CAA6C;IAC7C,cAAc;IACd,aAAa;IACb,eAAe;IAEf,iEAAiE;IACjE,qBAAqB;IAErB,sDAAsD;IACtD,qBAAqB;IACrB,uBAAuB;CACf,CAAC;AAEX,mEAAmE;AAEnE,+DAA+D;AAC/D,MAAM,aAAa,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAW,CAAC;AAkB9D;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAiB;IACnD,MAAM,OAAO,GAAe,EAAE,CAAC;IAC/B,MAAM,QAAQ,GAAe,EAAE,CAAC;IAChC,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,iBAAiB,CAAC,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,EAAE,CAAC;YAClD,kEAAkE;YAClE,kEAAkE;YAClE,oDAAoD;YACpD,QAAQ,CAAC,IAAI,CAAC;gBACZ,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,OAAO,EAAE,gBAAgB;aAC1B,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,iBAAiB,CAAC,IAAI,CAAC,IAAI,EAAE,oBAAoB,CAAC,EAAE,CAAC;YAC9D,gDAAgD;YAChD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AACxC,CAAC;AAED,mEAAmE;AAEnE;;;;;;GAMG;AACH,SAAS,iBAAiB,CAAC,QAAgB,EAAE,QAA2B;IACtE,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC;AACjF,CAAC"}
|
|
@@ -5,11 +5,20 @@
|
|
|
5
5
|
* provides utilities to calculate how much of the token budget should
|
|
6
6
|
* be allocated to the diff vs. surrounding context (system prompt,
|
|
7
7
|
* static analysis, memory, stack hints).
|
|
8
|
+
*
|
|
9
|
+
* For providers with low TPM (Tokens Per Minute) limits on free tiers
|
|
10
|
+
* (e.g., Groq, Cerebras), the effective context window is capped to
|
|
11
|
+
* ensure individual requests don't exceed the TPM limit.
|
|
8
12
|
*/
|
|
9
13
|
/**
|
|
10
14
|
* Get the context window size for a given model.
|
|
11
15
|
*
|
|
12
|
-
*
|
|
16
|
+
* Handles model name normalization:
|
|
17
|
+
* - Strips common prefixes (e.g., "openai/gpt-oss-120b" → lookup "openai/gpt-oss-120b" first,
|
|
18
|
+
* then try "gpt-oss-120b")
|
|
19
|
+
* - Falls back to DEFAULT_CONTEXT_WINDOW for truly unknown models
|
|
20
|
+
*
|
|
21
|
+
* @param model - Model identifier (e.g., "claude-sonnet-4-20250514", "openai/gpt-oss-120b")
|
|
13
22
|
* @returns Context window size in tokens
|
|
14
23
|
*/
|
|
15
24
|
export declare function getContextWindow(model: string): number;
|
|
@@ -21,6 +30,10 @@ export declare function getContextWindow(model: string): number;
|
|
|
21
30
|
* This ensures the diff always has enough room while leaving space
|
|
22
31
|
* for enrichment.
|
|
23
32
|
*
|
|
33
|
+
* For very constrained models (e.g., Groq free tier with 6K effective window),
|
|
34
|
+
* the budgets are still split 70/30 but the absolute numbers are much smaller,
|
|
35
|
+
* ensuring the diff is aggressively truncated to fit.
|
|
36
|
+
*
|
|
24
37
|
* @param model - Model identifier
|
|
25
38
|
* @returns Object with diffBudget and contextBudget in tokens
|
|
26
39
|
*/
|
|
@@ -28,4 +41,24 @@ export declare function calculateTokenBudget(model: string): {
|
|
|
28
41
|
diffBudget: number;
|
|
29
42
|
contextBudget: number;
|
|
30
43
|
};
|
|
44
|
+
/**
|
|
45
|
+
* Calculate concurrency and delay for workflow/consensus specialists
|
|
46
|
+
* based on the model's effective token budget (TPM for free tiers).
|
|
47
|
+
*
|
|
48
|
+
* For free-tier models with low TPM:
|
|
49
|
+
* - concurrency=1, delay=60s → one specialist per minute
|
|
50
|
+
*
|
|
51
|
+
* For mid-range models:
|
|
52
|
+
* - concurrency=2, delay=30s → two at a time with gaps
|
|
53
|
+
*
|
|
54
|
+
* For high-capacity models:
|
|
55
|
+
* - concurrency=5, delay=0 → full parallel, no delays
|
|
56
|
+
*
|
|
57
|
+
* @param model - Model identifier
|
|
58
|
+
* @returns { concurrency, delayMs } for runWithConcurrency
|
|
59
|
+
*/
|
|
60
|
+
export declare function calculateRateSchedule(model: string): {
|
|
61
|
+
concurrency: number;
|
|
62
|
+
delayMs: number;
|
|
63
|
+
};
|
|
31
64
|
//# sourceMappingURL=token-budget.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-budget.d.ts","sourceRoot":"","sources":["../../src/utils/token-budget.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"token-budget.d.ts","sourceRoot":"","sources":["../../src/utils/token-budget.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAoFH;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAgBtD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG;IACnD,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;CACvB,CAOA;AAiBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB,CAiBA"}
|
|
@@ -5,6 +5,10 @@
|
|
|
5
5
|
* provides utilities to calculate how much of the token budget should
|
|
6
6
|
* be allocated to the diff vs. surrounding context (system prompt,
|
|
7
7
|
* static analysis, memory, stack hints).
|
|
8
|
+
*
|
|
9
|
+
* For providers with low TPM (Tokens Per Minute) limits on free tiers
|
|
10
|
+
* (e.g., Groq, Cerebras), the effective context window is capped to
|
|
11
|
+
* ensure individual requests don't exceed the TPM limit.
|
|
8
12
|
*/
|
|
9
13
|
// ─── Context Window Sizes ───────────────────────────────────────
|
|
10
14
|
/**
|
|
@@ -14,12 +18,15 @@
|
|
|
14
18
|
const MODEL_CONTEXT_WINDOWS = {
|
|
15
19
|
// Anthropic
|
|
16
20
|
'claude-sonnet-4-20250514': 200_000,
|
|
21
|
+
'claude-opus-4-20250514': 200_000,
|
|
22
|
+
'claude-haiku-4-20250414': 200_000,
|
|
17
23
|
'claude-3-5-sonnet-20241022': 200_000,
|
|
18
24
|
'claude-3-5-haiku-20241022': 200_000,
|
|
19
25
|
// OpenAI
|
|
20
26
|
'gpt-4o': 128_000,
|
|
21
27
|
'gpt-4o-mini': 128_000,
|
|
22
28
|
'gpt-4-turbo': 128_000,
|
|
29
|
+
'o3-mini': 128_000,
|
|
23
30
|
// Google
|
|
24
31
|
'gemini-2.5-flash': 1_048_576,
|
|
25
32
|
'gemini-2.5-flash-lite': 1_048_576,
|
|
@@ -29,9 +36,43 @@ const MODEL_CONTEXT_WINDOWS = {
|
|
|
29
36
|
'gemini-2.0-flash-lite': 1_048_576,
|
|
30
37
|
'gemini-1.5-pro': 2_097_152,
|
|
31
38
|
'gemini-1.5-flash': 1_048_576,
|
|
39
|
+
// Groq — context windows are large but FREE-TIER TPM limits are very low.
|
|
40
|
+
// We cap to TPM limit since Groq rejects any single request exceeding TPM.
|
|
41
|
+
// Free tier TPM: gpt-oss-120b=8K, llama-3.3-70b=12K, llama-3.1-8b=6K
|
|
42
|
+
'openai/gpt-oss-120b': 6_000,
|
|
43
|
+
'llama-3.3-70b-versatile': 8_000,
|
|
44
|
+
'llama-3.1-70b-versatile': 8_000,
|
|
45
|
+
'llama-3.1-8b-instant': 4_000,
|
|
46
|
+
'gemma2-9b-it': 6_000,
|
|
47
|
+
'mixtral-8x7b-32768': 12_000,
|
|
48
|
+
'qwen-qwq-32b': 8_000,
|
|
49
|
+
// Cerebras — very fast inference, generous limits
|
|
50
|
+
'llama3.1-8b': 128_000,
|
|
51
|
+
'qwen-3-235b-a22b-instruct-2507': 128_000,
|
|
52
|
+
'zai-glm-4.7': 128_000,
|
|
53
|
+
// DeepSeek
|
|
54
|
+
'deepseek-chat': 64_000,
|
|
55
|
+
'deepseek-reasoner': 64_000,
|
|
56
|
+
// GitHub Models
|
|
57
|
+
'Phi-4': 16_000,
|
|
58
|
+
'Mistral-Large-2411': 128_000,
|
|
59
|
+
'DeepSeek-R1': 64_000,
|
|
60
|
+
// Qwen
|
|
61
|
+
'qwen-coder-plus': 128_000,
|
|
62
|
+
'qwen-plus': 128_000,
|
|
63
|
+
'qwen-max': 32_000,
|
|
64
|
+
'qwen-turbo': 128_000,
|
|
65
|
+
'qwen-coder-turbo': 128_000,
|
|
66
|
+
'qwen-long': 1_000_000,
|
|
32
67
|
};
|
|
33
68
|
/** Default context window when the model is not in our lookup table. */
|
|
34
69
|
const DEFAULT_CONTEXT_WINDOW = 128_000;
|
|
70
|
+
/**
|
|
71
|
+
* Minimum effective context window.
|
|
72
|
+
* Even for the most constrained models, we need at least this much
|
|
73
|
+
* to produce a meaningful review (system prompt + small diff).
|
|
74
|
+
*/
|
|
75
|
+
const MINIMUM_CONTEXT_WINDOW = 2_000;
|
|
35
76
|
/** Fraction of total budget allocated to the diff content. */
|
|
36
77
|
const DIFF_BUDGET_RATIO = 0.7;
|
|
37
78
|
/** Fraction of total budget allocated to context (system, memory, static analysis). */
|
|
@@ -40,11 +81,28 @@ const CONTEXT_BUDGET_RATIO = 0.3;
|
|
|
40
81
|
/**
|
|
41
82
|
* Get the context window size for a given model.
|
|
42
83
|
*
|
|
43
|
-
*
|
|
84
|
+
* Handles model name normalization:
|
|
85
|
+
* - Strips common prefixes (e.g., "openai/gpt-oss-120b" → lookup "openai/gpt-oss-120b" first,
|
|
86
|
+
* then try "gpt-oss-120b")
|
|
87
|
+
* - Falls back to DEFAULT_CONTEXT_WINDOW for truly unknown models
|
|
88
|
+
*
|
|
89
|
+
* @param model - Model identifier (e.g., "claude-sonnet-4-20250514", "openai/gpt-oss-120b")
|
|
44
90
|
* @returns Context window size in tokens
|
|
45
91
|
*/
|
|
46
92
|
export function getContextWindow(model) {
|
|
47
|
-
|
|
93
|
+
// Direct lookup first
|
|
94
|
+
if (model in MODEL_CONTEXT_WINDOWS) {
|
|
95
|
+
return MODEL_CONTEXT_WINDOWS[model] ?? DEFAULT_CONTEXT_WINDOW;
|
|
96
|
+
}
|
|
97
|
+
// Try without provider prefix (e.g., "deepseek/deepseek-chat" → "deepseek-chat")
|
|
98
|
+
const slashIndex = model.indexOf('/');
|
|
99
|
+
if (slashIndex !== -1) {
|
|
100
|
+
const modelWithoutPrefix = model.slice(slashIndex + 1);
|
|
101
|
+
if (modelWithoutPrefix in MODEL_CONTEXT_WINDOWS) {
|
|
102
|
+
return MODEL_CONTEXT_WINDOWS[modelWithoutPrefix] ?? DEFAULT_CONTEXT_WINDOW;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return DEFAULT_CONTEXT_WINDOW;
|
|
48
106
|
}
|
|
49
107
|
/**
|
|
50
108
|
* Calculate token budgets for diff and context.
|
|
@@ -54,14 +112,61 @@ export function getContextWindow(model) {
|
|
|
54
112
|
* This ensures the diff always has enough room while leaving space
|
|
55
113
|
* for enrichment.
|
|
56
114
|
*
|
|
115
|
+
* For very constrained models (e.g., Groq free tier with 6K effective window),
|
|
116
|
+
* the budgets are still split 70/30 but the absolute numbers are much smaller,
|
|
117
|
+
* ensuring the diff is aggressively truncated to fit.
|
|
118
|
+
*
|
|
57
119
|
* @param model - Model identifier
|
|
58
120
|
* @returns Object with diffBudget and contextBudget in tokens
|
|
59
121
|
*/
|
|
60
122
|
export function calculateTokenBudget(model) {
|
|
61
|
-
const total = getContextWindow(model);
|
|
123
|
+
const total = Math.max(getContextWindow(model), MINIMUM_CONTEXT_WINDOW);
|
|
62
124
|
return {
|
|
63
125
|
diffBudget: Math.floor(total * DIFF_BUDGET_RATIO),
|
|
64
126
|
contextBudget: Math.floor(total * CONTEXT_BUDGET_RATIO),
|
|
65
127
|
};
|
|
66
128
|
}
|
|
129
|
+
// ─── Rate-Aware Scheduling ─────────────────────────────────────
|
|
130
|
+
/**
|
|
131
|
+
* Threshold below which a model is considered "TPM-constrained".
|
|
132
|
+
* Models with context windows below this are free-tier providers
|
|
133
|
+
* where we need to serialize requests to avoid rate limiting.
|
|
134
|
+
*/
|
|
135
|
+
const TPM_CONSTRAINED_THRESHOLD = 16_000;
|
|
136
|
+
/**
|
|
137
|
+
* Estimate tokens per specialist call (system prompt + diff + response).
|
|
138
|
+
* Used to calculate how many specialists can run per TPM window.
|
|
139
|
+
*/
|
|
140
|
+
const ESTIMATED_TOKENS_PER_SPECIALIST = 7_000;
|
|
141
|
+
/**
|
|
142
|
+
* Calculate concurrency and delay for workflow/consensus specialists
|
|
143
|
+
* based on the model's effective token budget (TPM for free tiers).
|
|
144
|
+
*
|
|
145
|
+
* For free-tier models with low TPM:
|
|
146
|
+
* - concurrency=1, delay=60s → one specialist per minute
|
|
147
|
+
*
|
|
148
|
+
* For mid-range models:
|
|
149
|
+
* - concurrency=2, delay=30s → two at a time with gaps
|
|
150
|
+
*
|
|
151
|
+
* For high-capacity models:
|
|
152
|
+
* - concurrency=5, delay=0 → full parallel, no delays
|
|
153
|
+
*
|
|
154
|
+
* @param model - Model identifier
|
|
155
|
+
* @returns { concurrency, delayMs } for runWithConcurrency
|
|
156
|
+
*/
|
|
157
|
+
export function calculateRateSchedule(model) {
|
|
158
|
+
const contextWindow = getContextWindow(model);
|
|
159
|
+
// High-capacity models (paid tiers, large context) → full parallel
|
|
160
|
+
if (contextWindow >= TPM_CONSTRAINED_THRESHOLD * 4) {
|
|
161
|
+
return { concurrency: 5, delayMs: 0 };
|
|
162
|
+
}
|
|
163
|
+
// Mid-range models (e.g., Cerebras 60K TPM) → some parallelism
|
|
164
|
+
if (contextWindow >= TPM_CONSTRAINED_THRESHOLD) {
|
|
165
|
+
const parallelCalls = Math.max(1, Math.floor(contextWindow / ESTIMATED_TOKENS_PER_SPECIALIST));
|
|
166
|
+
return { concurrency: Math.min(parallelCalls, 5), delayMs: 5_000 };
|
|
167
|
+
}
|
|
168
|
+
// TPM-constrained models (Groq free tier, 4K-12K) → serialize with 60s delay
|
|
169
|
+
// Groq resets TPM every 60 seconds, so we wait between each call
|
|
170
|
+
return { concurrency: 1, delayMs: 60_000 };
|
|
171
|
+
}
|
|
67
172
|
//# sourceMappingURL=token-budget.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-budget.js","sourceRoot":"","sources":["../../src/utils/token-budget.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"token-budget.js","sourceRoot":"","sources":["../../src/utils/token-budget.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,mEAAmE;AAEnE;;;GAGG;AACH,MAAM,qBAAqB,GAA2B;IACpD,YAAY;IACZ,0BAA0B,EAAE,OAAO;IACnC,wBAAwB,EAAE,OAAO;IACjC,yBAAyB,EAAE,OAAO;IAClC,4BAA4B,EAAE,OAAO;IACrC,2BAA2B,EAAE,OAAO;IAEpC,SAAS;IACT,QAAQ,EAAE,OAAO;IACjB,aAAa,EAAE,OAAO;IACtB,aAAa,EAAE,OAAO;IACtB,SAAS,EAAE,OAAO;IAElB,SAAS;IACT,kBAAkB,EAAE,SAAS;IAC7B,uBAAuB,EAAE,SAAS;IAClC,gBAAgB,EAAE,SAAS;IAC3B,gBAAgB,EAAE,SAAS;IAC3B,kBAAkB,EAAE,SAAS;IAC7B,uBAAuB,EAAE,SAAS;IAClC,gBAAgB,EAAE,SAAS;IAC3B,kBAAkB,EAAE,SAAS;IAE7B,0EAA0E;IAC1E,2EAA2E;IAC3E,qEAAqE;IACrE,qBAAqB,EAAE,KAAK;IAC5B,yBAAyB,EAAE,KAAK;IAChC,yBAAyB,EAAE,KAAK;IAChC,sBAAsB,EAAE,KAAK;IAC7B,cAAc,EAAE,KAAK;IACrB,oBAAoB,EAAE,MAAM;IAC5B,cAAc,EAAE,KAAK;IAErB,kDAAkD;IAClD,aAAa,EAAE,OAAO;IACtB,gCAAgC,EAAE,OAAO;IACzC,aAAa,EAAE,OAAO;IAEtB,WAAW;IACX,eAAe,EAAE,MAAM;IACvB,mBAAmB,EAAE,MAAM;IAE3B,gBAAgB;IAChB,OAAO,EAAE,MAAM;IACf,oBAAoB,EAAE,OAAO;IAC7B,aAAa,EAAE,MAAM;IAErB,OAAO;IACP,iBAAiB,EAAE,OAAO;IAC1B,WAAW,EAAE,OAAO;IACpB,UAAU,EAAE,MAAM;IAClB,YAAY,EAAE,OAAO;IACrB,kBAAkB,EAAE,OAAO;IAC3B,WAAW,EAAE,SAAS;CACvB,CAAC;AAEF,wEAAwE;AACxE,MAAM,sBAAsB,GAAG,OAAO,CAAC;AAEvC;;;;GAIG;AACH,MAAM,sBAAsB,GAAG,KAAK,CAAC;AAErC,8DAA8D;AAC9D,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAE9B,uFAAuF;AACvF,MAAM,oBAAoB,GAAG,GAAG,CAAC;AAEjC,mEAAmE;AAEnE;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,sBAAsB;IACtB,IAAI,KAAK,IAAI,qBAAqB,EAAE,CAAC;QACnC,OAAO,qBAAqB,CAAC,KAAK,CAAC,IAAI,sBAAsB,CAAC;IAChE,CAAC;IAED,iFAAiF;IACjF,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;QACtB,MAAM,kBAAkB,GAAG,KAAK,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;QACvD,IAAI,kBAAkB,IAAI,qBAAqB,EAAE,CAAC;YAChD,OAAO,qBAAqB,CAAC,kBAAkB,CAAC,IAAI,sBAAsB,CAAC;QAC7E,CAAC;IACH,CAAC;IAED,OAAO,sBAAsB,CAAC;AAChC,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAIhD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,sBAAsB,CAAC,CAAC;IAExE,OAAO;QACL,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,iBAAiB,CAAC;QACjD,aAAa,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,oBAAoB,CAAC;KACxD,CAAC;AACJ,CAAC;AAED,kEAAkE;AAElE;;;;GAIG;AACH,MAAM,yBAAyB,GAAG,MAAM,CAAC;AAEzC;;;GAGG;AACH,MAAM,+BAA+B,GAAG,KAAK,CAAC;AAE9C;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAa;IAIjD,MAAM,aAAa,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAE9C,mEAAmE;IACnE,IAAI,aAAa,IAAI,yBAAyB,GAAG,CAAC,EAAE,CAAC;QACnD,OAAO,EAAE,WAAW,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;IACxC,CAAC;IAED,+DAA+D;IAC/D,IAAI,aAAa,IAAI,yBAAyB,EAAE,CAAC;QAC/C,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,+BAA+B,CAAC,CAAC,CAAC;QAC/F,OAAO,EAAE,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACrE,CAAC;IAED,6EAA6E;IAC7E,iEAAiE;IACjE,OAAO,EAAE,WAAW,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AAC7C,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ghagga-core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Core review engine for GHAGGA — AI-powered multi-agent code reviewer",
|
|
@@ -39,22 +39,6 @@
|
|
|
39
39
|
"dist",
|
|
40
40
|
"README.md"
|
|
41
41
|
],
|
|
42
|
-
"dependencies": {
|
|
43
|
-
"@ai-sdk/anthropic": "^2.0.0",
|
|
44
|
-
"@ai-sdk/google": "^2.0.0",
|
|
45
|
-
"@ai-sdk/openai": "^2.0.0",
|
|
46
|
-
"ai": "^5.0.0",
|
|
47
|
-
"minimatch": "^10.0.1",
|
|
48
|
-
"fts5-sql-bundle": "^1.0.2",
|
|
49
|
-
"zod": "^4.1.8"
|
|
50
|
-
},
|
|
51
|
-
"devDependencies": {
|
|
52
|
-
"@stryker-mutator/core": "^9.6.0",
|
|
53
|
-
"@stryker-mutator/vitest-runner": "^9.6.0",
|
|
54
|
-
"@types/node": "^25.3.5",
|
|
55
|
-
"typescript": "^5.7.0",
|
|
56
|
-
"vitest": "^3.0.0"
|
|
57
|
-
},
|
|
58
42
|
"scripts": {
|
|
59
43
|
"build": "tsc",
|
|
60
44
|
"dev": "tsc --watch",
|
|
@@ -63,6 +47,24 @@
|
|
|
63
47
|
"test:coverage": "vitest run --coverage",
|
|
64
48
|
"test:watch": "vitest",
|
|
65
49
|
"test:mutate": "stryker run",
|
|
66
|
-
"clean": "rm -rf dist"
|
|
50
|
+
"clean": "rm -rf dist",
|
|
51
|
+
"prepublishOnly": "npm run build"
|
|
52
|
+
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"@ai-sdk/anthropic": "^3.0.0",
|
|
55
|
+
"@ai-sdk/google": "^3.0.0",
|
|
56
|
+
"@ai-sdk/openai": "^3.0.0",
|
|
57
|
+
"@ai-sdk/openai-compatible": "^2.0.35",
|
|
58
|
+
"ai": "^6.0.0",
|
|
59
|
+
"fts5-sql-bundle": "^1.0.2",
|
|
60
|
+
"minimatch": "^10.2.0",
|
|
61
|
+
"zod": "^4.3.0"
|
|
62
|
+
},
|
|
63
|
+
"devDependencies": {
|
|
64
|
+
"@stryker-mutator/core": "^9.6.0",
|
|
65
|
+
"@stryker-mutator/vitest-runner": "^9.6.0",
|
|
66
|
+
"@types/node": "^25.3.5",
|
|
67
|
+
"typescript": "^5.9.0",
|
|
68
|
+
"vitest": "^4.0.0"
|
|
67
69
|
}
|
|
68
|
-
}
|
|
70
|
+
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 JNZader & Gentleman Programming Community
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|