kevlar-4u 1.0.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 +357 -0
- package/config/mcp-config.json +9 -0
- package/dist/__tests__/configureWizard.test.d.ts +2 -0
- package/dist/__tests__/configureWizard.test.d.ts.map +1 -0
- package/dist/__tests__/configureWizard.test.js +89 -0
- package/dist/__tests__/configureWizard.test.js.map +1 -0
- package/dist/__tests__/createPersonaTool.test.d.ts +2 -0
- package/dist/__tests__/createPersonaTool.test.d.ts.map +1 -0
- package/dist/__tests__/createPersonaTool.test.js +292 -0
- package/dist/__tests__/createPersonaTool.test.js.map +1 -0
- package/dist/__tests__/createPersonaWizard.test.d.ts +2 -0
- package/dist/__tests__/createPersonaWizard.test.d.ts.map +1 -0
- package/dist/__tests__/createPersonaWizard.test.js +138 -0
- package/dist/__tests__/createPersonaWizard.test.js.map +1 -0
- package/dist/__tests__/deletePersonaWizard.test.d.ts +2 -0
- package/dist/__tests__/deletePersonaWizard.test.d.ts.map +1 -0
- package/dist/__tests__/deletePersonaWizard.test.js +78 -0
- package/dist/__tests__/deletePersonaWizard.test.js.map +1 -0
- package/dist/__tests__/e2e.test.d.ts +2 -0
- package/dist/__tests__/e2e.test.d.ts.map +1 -0
- package/dist/__tests__/e2e.test.js +121 -0
- package/dist/__tests__/e2e.test.js.map +1 -0
- package/dist/__tests__/errors.test.d.ts +2 -0
- package/dist/__tests__/errors.test.d.ts.map +1 -0
- package/dist/__tests__/errors.test.js +86 -0
- package/dist/__tests__/errors.test.js.map +1 -0
- package/dist/__tests__/execution.test.d.ts +2 -0
- package/dist/__tests__/execution.test.d.ts.map +1 -0
- package/dist/__tests__/execution.test.js +792 -0
- package/dist/__tests__/execution.test.js.map +1 -0
- package/dist/__tests__/getModesTool.test.d.ts +2 -0
- package/dist/__tests__/getModesTool.test.d.ts.map +1 -0
- package/dist/__tests__/getModesTool.test.js +47 -0
- package/dist/__tests__/getModesTool.test.js.map +1 -0
- package/dist/__tests__/helpTool.test.d.ts +2 -0
- package/dist/__tests__/helpTool.test.d.ts.map +1 -0
- package/dist/__tests__/helpTool.test.js +18 -0
- package/dist/__tests__/helpTool.test.js.map +1 -0
- package/dist/__tests__/listPersonasTool.test.d.ts +2 -0
- package/dist/__tests__/listPersonasTool.test.d.ts.map +1 -0
- package/dist/__tests__/listPersonasTool.test.js +110 -0
- package/dist/__tests__/listPersonasTool.test.js.map +1 -0
- package/dist/__tests__/logger.test.d.ts +2 -0
- package/dist/__tests__/logger.test.d.ts.map +1 -0
- package/dist/__tests__/logger.test.js +56 -0
- package/dist/__tests__/logger.test.js.map +1 -0
- package/dist/__tests__/observability.test.d.ts +2 -0
- package/dist/__tests__/observability.test.d.ts.map +1 -0
- package/dist/__tests__/observability.test.js +60 -0
- package/dist/__tests__/observability.test.js.map +1 -0
- package/dist/__tests__/parser.test.d.ts +2 -0
- package/dist/__tests__/parser.test.d.ts.map +1 -0
- package/dist/__tests__/parser.test.js +259 -0
- package/dist/__tests__/parser.test.js.map +1 -0
- package/dist/__tests__/persona_creation_debug.test.d.ts +2 -0
- package/dist/__tests__/persona_creation_debug.test.d.ts.map +1 -0
- package/dist/__tests__/persona_creation_debug.test.js +56 -0
- package/dist/__tests__/persona_creation_debug.test.js.map +1 -0
- package/dist/__tests__/resetPersonasWizard.test.d.ts +2 -0
- package/dist/__tests__/resetPersonasWizard.test.d.ts.map +1 -0
- package/dist/__tests__/resetPersonasWizard.test.js +74 -0
- package/dist/__tests__/resetPersonasWizard.test.js.map +1 -0
- package/dist/__tests__/reviewContentWizard.test.d.ts +2 -0
- package/dist/__tests__/reviewContentWizard.test.d.ts.map +1 -0
- package/dist/__tests__/reviewContentWizard.test.js +148 -0
- package/dist/__tests__/reviewContentWizard.test.js.map +1 -0
- package/dist/__tests__/sanitize.test.d.ts +2 -0
- package/dist/__tests__/sanitize.test.d.ts.map +1 -0
- package/dist/__tests__/sanitize.test.js +138 -0
- package/dist/__tests__/sanitize.test.js.map +1 -0
- package/dist/__tests__/server.test.d.ts +2 -0
- package/dist/__tests__/server.test.d.ts.map +1 -0
- package/dist/__tests__/server.test.js +49 -0
- package/dist/__tests__/server.test.js.map +1 -0
- package/dist/execution/aggregator.d.ts +43 -0
- package/dist/execution/aggregator.d.ts.map +1 -0
- package/dist/execution/aggregator.js +132 -0
- package/dist/execution/aggregator.js.map +1 -0
- package/dist/execution/base.d.ts +62 -0
- package/dist/execution/base.d.ts.map +1 -0
- package/dist/execution/base.js +5 -0
- package/dist/execution/base.js.map +1 -0
- package/dist/execution/client.d.ts +9 -0
- package/dist/execution/client.d.ts.map +1 -0
- package/dist/execution/client.js +30 -0
- package/dist/execution/client.js.map +1 -0
- package/dist/execution/config.d.ts +30 -0
- package/dist/execution/config.d.ts.map +1 -0
- package/dist/execution/config.js +95 -0
- package/dist/execution/config.js.map +1 -0
- package/dist/execution/index.d.ts +19 -0
- package/dist/execution/index.d.ts.map +1 -0
- package/dist/execution/index.js +151 -0
- package/dist/execution/index.js.map +1 -0
- package/dist/execution/limiter.d.ts +32 -0
- package/dist/execution/limiter.d.ts.map +1 -0
- package/dist/execution/limiter.js +147 -0
- package/dist/execution/limiter.js.map +1 -0
- package/dist/execution/lock.d.ts +17 -0
- package/dist/execution/lock.d.ts.map +1 -0
- package/dist/execution/lock.js +37 -0
- package/dist/execution/lock.js.map +1 -0
- package/dist/execution/modes/direct_api.d.ts +11 -0
- package/dist/execution/modes/direct_api.d.ts.map +1 -0
- package/dist/execution/modes/direct_api.js +213 -0
- package/dist/execution/modes/direct_api.js.map +1 -0
- package/dist/execution/modes/index.d.ts +7 -0
- package/dist/execution/modes/index.d.ts.map +1 -0
- package/dist/execution/modes/index.js +7 -0
- package/dist/execution/modes/index.js.map +1 -0
- package/dist/execution/modes/orchestration.d.ts +11 -0
- package/dist/execution/modes/orchestration.d.ts.map +1 -0
- package/dist/execution/modes/orchestration.js +110 -0
- package/dist/execution/modes/orchestration.js.map +1 -0
- package/dist/execution/modes/sampling.d.ts +9 -0
- package/dist/execution/modes/sampling.d.ts.map +1 -0
- package/dist/execution/modes/sampling.js +66 -0
- package/dist/execution/modes/sampling.js.map +1 -0
- package/dist/execution/parallel.d.ts +16 -0
- package/dist/execution/parallel.d.ts.map +1 -0
- package/dist/execution/parallel.js +90 -0
- package/dist/execution/parallel.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts/reviewDispatcherPrompt.d.ts +2 -0
- package/dist/prompts/reviewDispatcherPrompt.d.ts.map +1 -0
- package/dist/prompts/reviewDispatcherPrompt.js +67 -0
- package/dist/prompts/reviewDispatcherPrompt.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +156 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/configureTool.d.ts +17 -0
- package/dist/tools/configureTool.d.ts.map +1 -0
- package/dist/tools/configureTool.js +104 -0
- package/dist/tools/configureTool.js.map +1 -0
- package/dist/tools/configureWizardTool.d.ts +11 -0
- package/dist/tools/configureWizardTool.d.ts.map +1 -0
- package/dist/tools/configureWizardTool.js +205 -0
- package/dist/tools/configureWizardTool.js.map +1 -0
- package/dist/tools/createPersonaTool.d.ts +37 -0
- package/dist/tools/createPersonaTool.d.ts.map +1 -0
- package/dist/tools/createPersonaTool.js +353 -0
- package/dist/tools/createPersonaTool.js.map +1 -0
- package/dist/tools/createPersonaWizardTool.d.ts +13 -0
- package/dist/tools/createPersonaWizardTool.d.ts.map +1 -0
- package/dist/tools/createPersonaWizardTool.js +713 -0
- package/dist/tools/createPersonaWizardTool.js.map +1 -0
- package/dist/tools/deletePersonaTool.d.ts +10 -0
- package/dist/tools/deletePersonaTool.d.ts.map +1 -0
- package/dist/tools/deletePersonaTool.js +75 -0
- package/dist/tools/deletePersonaTool.js.map +1 -0
- package/dist/tools/deletePersonaWizardTool.d.ts +11 -0
- package/dist/tools/deletePersonaWizardTool.d.ts.map +1 -0
- package/dist/tools/deletePersonaWizardTool.js +184 -0
- package/dist/tools/deletePersonaWizardTool.js.map +1 -0
- package/dist/tools/getModesTool.d.ts +12 -0
- package/dist/tools/getModesTool.d.ts.map +1 -0
- package/dist/tools/getModesTool.js +78 -0
- package/dist/tools/getModesTool.js.map +1 -0
- package/dist/tools/helpTool.d.ts +7 -0
- package/dist/tools/helpTool.d.ts.map +1 -0
- package/dist/tools/helpTool.js +65 -0
- package/dist/tools/helpTool.js.map +1 -0
- package/dist/tools/index.d.ts +9 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +30 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/listPersonasTool.d.ts +7 -0
- package/dist/tools/listPersonasTool.d.ts.map +1 -0
- package/dist/tools/listPersonasTool.js +118 -0
- package/dist/tools/listPersonasTool.js.map +1 -0
- package/dist/tools/resetPersonasTool.d.ts +7 -0
- package/dist/tools/resetPersonasTool.d.ts.map +1 -0
- package/dist/tools/resetPersonasTool.js +447 -0
- package/dist/tools/resetPersonasTool.js.map +1 -0
- package/dist/tools/resetPersonasWizardTool.d.ts +9 -0
- package/dist/tools/resetPersonasWizardTool.d.ts.map +1 -0
- package/dist/tools/resetPersonasWizardTool.js +125 -0
- package/dist/tools/resetPersonasWizardTool.js.map +1 -0
- package/dist/tools/reviewContentWizardTool.d.ts +13 -0
- package/dist/tools/reviewContentWizardTool.d.ts.map +1 -0
- package/dist/tools/reviewContentWizardTool.js +411 -0
- package/dist/tools/reviewContentWizardTool.js.map +1 -0
- package/dist/tools/reviewTool.d.ts +10 -0
- package/dist/tools/reviewTool.d.ts.map +1 -0
- package/dist/tools/reviewTool.js +133 -0
- package/dist/tools/reviewTool.js.map +1 -0
- package/dist/tools/types.d.ts +14 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/utils/errors.d.ts +30 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +47 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/logger.d.ts +18 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +52 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/observability.d.ts +61 -0
- package/dist/utils/observability.d.ts.map +1 -0
- package/dist/utils/observability.js +69 -0
- package/dist/utils/observability.js.map +1 -0
- package/dist/utils/parser.d.ts +27 -0
- package/dist/utils/parser.d.ts.map +1 -0
- package/dist/utils/parser.js +178 -0
- package/dist/utils/parser.js.map +1 -0
- package/dist/utils/personaIdMaps.d.ts +7 -0
- package/dist/utils/personaIdMaps.d.ts.map +1 -0
- package/dist/utils/personaIdMaps.js +51 -0
- package/dist/utils/personaIdMaps.js.map +1 -0
- package/dist/utils/sanitize.d.ts +4 -0
- package/dist/utils/sanitize.d.ts.map +1 -0
- package/dist/utils/sanitize.js +49 -0
- package/dist/utils/sanitize.js.map +1 -0
- package/dist/utils/types.d.ts +8 -0
- package/dist/utils/types.d.ts.map +1 -0
- package/dist/utils/types.js +2 -0
- package/dist/utils/types.js.map +1 -0
- package/package.json +42 -0
- package/skills/_template.md +66 -0
- package/skills/tmp/wizard-create-cwzrrpim_draft.json +26 -0
- package/skills/tmp/wizard-create-cwzrrpim_wizard.json +26 -0
- package/skills/tmp/wizard-create-d81intme_draft.json +26 -0
- package/skills/tmp/wizard-create-d81intme_wizard.json +26 -0
- package/skills/tmp/wizard-create-g50jqzmh_draft.json +8 -0
- package/skills/tmp/wizard-create-g50jqzmh_wizard.json +8 -0
- package/skills/tmp/wizard-create-onupu9wb_draft.json +8 -0
- package/skills/tmp/wizard-create-onupu9wb_wizard.json +8 -0
- package/skills/tmp/wizard-review-fwbxe3d2_review_wizard.json +9 -0
- package/skills/tmp/wizard-review-sypg5e9d_review_wizard.json +9 -0
- package/skills/wechat_official/wechat_official.md +26 -0
- package/skills/wechat_official/wechat_official_1.md +31 -0
- package/skills/xiaohongshu/xiaohongshu.md +26 -0
- package/skills/xiaohongshu/xiaohongshu_1.md +29 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kevlar Configuration Management
|
|
3
|
+
*
|
|
4
|
+
* Reads and writes the kevlar-config.json file for user preferences.
|
|
5
|
+
* API keys are NEVER stored here - only environment variables.
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync, writeFileSync } from "fs";
|
|
8
|
+
import * as path from "path";
|
|
9
|
+
import { logger, getErrorInfo } from "../utils/observability.js";
|
|
10
|
+
// ── Defaults ─────────────────────────────────────────────────────────────────
|
|
11
|
+
const DEFAULT_CONFIG = {
|
|
12
|
+
mode: "auto",
|
|
13
|
+
multiAgent: {
|
|
14
|
+
maxConcurrency: 3,
|
|
15
|
+
timeoutMs: 60000,
|
|
16
|
+
},
|
|
17
|
+
personaOrder: [],
|
|
18
|
+
createdAt: new Date().toISOString(),
|
|
19
|
+
updatedAt: new Date().toISOString(),
|
|
20
|
+
};
|
|
21
|
+
// ── Config File Path ─────────────────────────────────────────────────────────
|
|
22
|
+
let configPath = null;
|
|
23
|
+
export function setConfigPath(skillsDir) {
|
|
24
|
+
configPath = path.join(skillsDir, "kevlar-config.json");
|
|
25
|
+
}
|
|
26
|
+
// ── Read Config ──────────────────────────────────────────────────────────────
|
|
27
|
+
export function readConfig() {
|
|
28
|
+
if (!configPath) {
|
|
29
|
+
logger.warn("Config path not initialized, using defaults", { event: "config_not_initialized" });
|
|
30
|
+
return { ...DEFAULT_CONFIG };
|
|
31
|
+
}
|
|
32
|
+
let result;
|
|
33
|
+
try {
|
|
34
|
+
const raw = readFileSync(configPath, "utf-8");
|
|
35
|
+
const parsed = JSON.parse(raw);
|
|
36
|
+
result = { ...DEFAULT_CONFIG, ...parsed };
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
// Config doesn't exist or is invalid - use defaults
|
|
40
|
+
result = { ...DEFAULT_CONFIG };
|
|
41
|
+
}
|
|
42
|
+
const envMaxConcurrency = process.env.KEVLAR_MAX_CONCURRENT;
|
|
43
|
+
if (envMaxConcurrency) {
|
|
44
|
+
const parsed = parseInt(envMaxConcurrency, 10);
|
|
45
|
+
if (!isNaN(parsed) && isValidConcurrency(parsed)) {
|
|
46
|
+
result.multiAgent = { ...result.multiAgent, maxConcurrency: parsed };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
export async function readConfigAsync() {
|
|
52
|
+
// Kept for backward compatibility, using synchronous read for safety
|
|
53
|
+
return readConfig();
|
|
54
|
+
}
|
|
55
|
+
export async function updateConfig(options) {
|
|
56
|
+
if (!configPath) {
|
|
57
|
+
throw new Error("Config path not initialized");
|
|
58
|
+
}
|
|
59
|
+
// Use synchronous atomic read-merge-write to prevent async race conditions
|
|
60
|
+
const current = readConfig();
|
|
61
|
+
const updated = {
|
|
62
|
+
...current,
|
|
63
|
+
multiAgent: {
|
|
64
|
+
...current.multiAgent,
|
|
65
|
+
},
|
|
66
|
+
updatedAt: new Date().toISOString(),
|
|
67
|
+
};
|
|
68
|
+
if (options.mode !== undefined) {
|
|
69
|
+
updated.mode = options.mode;
|
|
70
|
+
}
|
|
71
|
+
if (options.maxConcurrency !== undefined) {
|
|
72
|
+
updated.multiAgent.maxConcurrency = options.maxConcurrency;
|
|
73
|
+
}
|
|
74
|
+
if (options.personaOrder !== undefined) {
|
|
75
|
+
updated.personaOrder = options.personaOrder;
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
writeFileSync(configPath, JSON.stringify(updated, null, 2), "utf-8");
|
|
79
|
+
logger.info("Config updated", { event: "config_update", path: configPath, options });
|
|
80
|
+
return updated;
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
const info = getErrorInfo(err);
|
|
84
|
+
logger.error("Failed to write config", { event: "config_write_error", error: info.code, message: info.message });
|
|
85
|
+
throw err;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// ── Config Validation ─────────────────────────────────────────────────────────
|
|
89
|
+
export function isValidMode(mode) {
|
|
90
|
+
return ["auto", "orchestration", "mcp_sampling", "direct_api"].includes(mode);
|
|
91
|
+
}
|
|
92
|
+
export function isValidConcurrency(concurrency) {
|
|
93
|
+
return Number.isInteger(concurrency) && concurrency >= 1 && concurrency <= 10;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/execution/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACjD,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAgBjE,gFAAgF;AAEhF,MAAM,cAAc,GAAiB;IACnC,IAAI,EAAE,MAAM;IACZ,UAAU,EAAE;QACV,cAAc,EAAE,CAAC;QACjB,SAAS,EAAE,KAAK;KACjB;IACD,YAAY,EAAE,EAAE;IAChB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;IACnC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;CACpC,CAAC;AAEF,gFAAgF;AAEhF,IAAI,UAAU,GAAkB,IAAI,CAAC;AAErC,MAAM,UAAU,aAAa,CAAC,SAAiB;IAC7C,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC;AAC1D,CAAC;AAED,gFAAgF;AAEhF,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,CAAC,IAAI,CAAC,6CAA6C,EAAE,EAAE,KAAK,EAAE,wBAAwB,EAAE,CAAC,CAAC;QAChG,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAC/B,CAAC;IAED,IAAI,MAAoB,CAAC;IACzB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA0B,CAAC;QACxD,MAAM,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,MAAM,EAAE,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,oDAAoD;QACpD,MAAM,GAAG,EAAE,GAAG,cAAc,EAAE,CAAC;IACjC,CAAC;IAED,MAAM,iBAAiB,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;IAC5D,IAAI,iBAAiB,EAAE,CAAC;QACtB,MAAM,MAAM,GAAG,QAAQ,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC;QAC/C,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC;YACjD,MAAM,CAAC,UAAU,GAAG,EAAE,GAAG,MAAM,CAAC,UAAU,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC;QACvE,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,qEAAqE;IACrE,OAAO,UAAU,EAAE,CAAC;AACtB,CAAC;AAUD,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAA4B;IAC7D,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjD,CAAC;IAED,2EAA2E;IAC3E,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,OAAO,GAAiB;QAC5B,GAAG,OAAO;QACV,UAAU,EAAE;YACV,GAAG,OAAO,CAAC,UAAU;SACtB;QACD,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;IAEF,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAC9B,CAAC;IACD,IAAI,OAAO,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;QACzC,OAAO,CAAC,UAAU,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;IAC7D,CAAC;IACD,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;QACvC,OAAO,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IAC9C,CAAC;IAED,IAAI,CAAC;QACH,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACrE,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC;QACrF,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QAC/B,MAAM,CAAC,KAAK,CAAC,wBAAwB,EAAE,EAAE,KAAK,EAAE,oBAAoB,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QACjH,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED,iFAAiF;AAEjF,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,CAAC,MAAM,EAAE,eAAe,EAAE,cAAc,EAAE,YAAY,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAChF,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,WAAmB;IACpD,OAAO,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,WAAW,IAAI,CAAC,IAAI,WAAW,IAAI,EAAE,CAAC;AAChF,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kevlar Execution Engine
|
|
3
|
+
*
|
|
4
|
+
* Unified entry point for all execution modes with automatic mode resolution.
|
|
5
|
+
*/
|
|
6
|
+
import { Persona } from "../utils/parser.js";
|
|
7
|
+
import { isSamplingSupported } from "./client.js";
|
|
8
|
+
import type { ExecutionContext, ExecutionResult, ModesInfo, ResolveableMode } from "./base.js";
|
|
9
|
+
export declare const MAX_PERSONAS = 50;
|
|
10
|
+
export declare function executeReview(mode: ResolveableMode, ctx: ExecutionContext): Promise<ExecutionResult>;
|
|
11
|
+
export declare function getModesInfo(): ModesInfo;
|
|
12
|
+
export interface PersonaLoadingResult {
|
|
13
|
+
personas: Persona[];
|
|
14
|
+
missingIds?: string[];
|
|
15
|
+
}
|
|
16
|
+
export declare function validatePersonaFields(persona: Persona): void;
|
|
17
|
+
export declare function loadPersonasForReview(skillsDir: string, personaIds?: string[]): Promise<PersonaLoadingResult>;
|
|
18
|
+
export { isSamplingSupported };
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/execution/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAsC,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAGjF,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAIlD,OAAO,KAAK,EACV,gBAAgB,EAGhB,eAAe,EACf,SAAS,EAET,eAAe,EAChB,MAAM,WAAW,CAAC;AAYnB,eAAO,MAAM,YAAY,KAAK,CAAC;AAI/B,wBAAsB,aAAa,CACjC,IAAI,EAAE,eAAe,EACrB,GAAG,EAAE,gBAAgB,GACpB,OAAO,CAAC,eAAe,CAAC,CAyD1B;AAkCD,wBAAgB,YAAY,IAAI,SAAS,CA4BxC;AAID,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAY5D;AAED,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,MAAM,EAAE,GACpB,OAAO,CAAC,oBAAoB,CAAC,CAe/B;AAID,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kevlar Execution Engine
|
|
3
|
+
*
|
|
4
|
+
* Unified entry point for all execution modes with automatic mode resolution.
|
|
5
|
+
*/
|
|
6
|
+
import { loadAllPersonas, loadPersonasByIds } from "../utils/parser.js";
|
|
7
|
+
import { logger } from "../utils/logger.js";
|
|
8
|
+
import { readConfig, isValidMode } from "./config.js";
|
|
9
|
+
import { isSamplingSupported } from "./client.js";
|
|
10
|
+
import { orchestrationHandler } from "./modes/orchestration.js";
|
|
11
|
+
import { samplingHandler } from "./modes/sampling.js";
|
|
12
|
+
import { directApiHandler } from "./modes/direct_api.js";
|
|
13
|
+
// ── Handler Registry ──────────────────────────────────────────────────────────
|
|
14
|
+
const handlers = [
|
|
15
|
+
orchestrationHandler, // priority: 30 (fallback)
|
|
16
|
+
samplingHandler, // priority: 10 (preferred)
|
|
17
|
+
directApiHandler, // priority: 20 (medium)
|
|
18
|
+
];
|
|
19
|
+
// ── Limits ────────────────────────────────────────────────────────────────────
|
|
20
|
+
export const MAX_PERSONAS = 50;
|
|
21
|
+
// ── Core Execution Function ───────────────────────────────────────────────────
|
|
22
|
+
export async function executeReview(mode, ctx) {
|
|
23
|
+
const resolved = mode === "auto" ? await resolveMode() : mode;
|
|
24
|
+
const personaCount = ctx.personas.length;
|
|
25
|
+
if (personaCount > MAX_PERSONAS) {
|
|
26
|
+
throw new Error(`评论员数量超出限制(最多${MAX_PERSONAS}个,当前${personaCount}个)。`);
|
|
27
|
+
}
|
|
28
|
+
const handler = handlers.find((h) => h.mode === resolved);
|
|
29
|
+
if (!handler) {
|
|
30
|
+
throw new Error(`未知执行模式: ${resolved}`);
|
|
31
|
+
}
|
|
32
|
+
if (!handler.canExecute()) {
|
|
33
|
+
throw new Error(`${resolved} 模式当前不可用`);
|
|
34
|
+
}
|
|
35
|
+
logger.info("Executing review", {
|
|
36
|
+
event: "review_execute",
|
|
37
|
+
mode: resolved,
|
|
38
|
+
personas: ctx.personas.length,
|
|
39
|
+
contentLength: ctx.content.length,
|
|
40
|
+
});
|
|
41
|
+
const startTime = Date.now();
|
|
42
|
+
let result;
|
|
43
|
+
if (resolved !== "orchestration") {
|
|
44
|
+
const { acquireReviewLock, releaseReviewLock, getReviewLock } = await import("./lock.js");
|
|
45
|
+
if (!acquireReviewLock(resolved)) {
|
|
46
|
+
const lock = getReviewLock();
|
|
47
|
+
throw new Error(`已有评测任务正在执行(${lock?.mode || "unknown"}),请等待完成后再试。`);
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
result = await handler.execute(ctx);
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
releaseReviewLock();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
result = await handler.execute(ctx);
|
|
58
|
+
}
|
|
59
|
+
const durationMs = Date.now() - startTime;
|
|
60
|
+
const failedCount = result.partialFailures?.length ?? 0;
|
|
61
|
+
logger.info("Review summary", {
|
|
62
|
+
event: "review_summary",
|
|
63
|
+
mode: resolved,
|
|
64
|
+
personas: ctx.personas.length,
|
|
65
|
+
success: ctx.personas.length - failedCount,
|
|
66
|
+
failure: failedCount,
|
|
67
|
+
durationMs,
|
|
68
|
+
});
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
// ── Mode Resolution ──────────────────────────────────────────────────────────
|
|
72
|
+
async function resolveMode() {
|
|
73
|
+
// 1. Check persisted config (user preference, highest priority)
|
|
74
|
+
const config = readConfig();
|
|
75
|
+
if (config.mode && config.mode !== "auto") {
|
|
76
|
+
logger.debug("Using persisted mode", { event: "mode_persist", mode: config.mode });
|
|
77
|
+
return config.mode;
|
|
78
|
+
}
|
|
79
|
+
// 2. Check KEVLAR_MODE env var (global default, overridden by config)
|
|
80
|
+
const envMode = process.env.KEVLAR_MODE;
|
|
81
|
+
if (envMode && envMode !== "auto" && isValidMode(envMode)) {
|
|
82
|
+
logger.debug("Using env var mode", { event: "mode_env", mode: envMode });
|
|
83
|
+
return envMode;
|
|
84
|
+
}
|
|
85
|
+
// 3. Select first available by priority
|
|
86
|
+
const sorted = [...handlers].sort((a, b) => a.priority - b.priority);
|
|
87
|
+
for (const h of sorted) {
|
|
88
|
+
if (h.canExecute()) {
|
|
89
|
+
logger.debug("Auto-resolved mode", { event: "mode_auto", mode: h.mode });
|
|
90
|
+
return h.mode;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// 4. Fallback to orchestration (always available)
|
|
94
|
+
return "orchestration";
|
|
95
|
+
}
|
|
96
|
+
// ── Mode Information ──────────────────────────────────────────────────────────
|
|
97
|
+
export function getModesInfo() {
|
|
98
|
+
const config = readConfig();
|
|
99
|
+
const currentMode = (config.mode || "auto");
|
|
100
|
+
const modes = handlers.map((h) => ({
|
|
101
|
+
mode: h.mode,
|
|
102
|
+
available: h.canExecute(),
|
|
103
|
+
reason: h.canExecute() ? undefined : "当前环境不支持",
|
|
104
|
+
}));
|
|
105
|
+
// Determine recommended mode
|
|
106
|
+
const sorted = [...handlers].sort((a, b) => a.priority - b.priority);
|
|
107
|
+
let recommended = "orchestration";
|
|
108
|
+
for (const h of sorted) {
|
|
109
|
+
if (h.canExecute()) {
|
|
110
|
+
recommended = h.mode;
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const resolved = currentMode === "auto" ? recommended : currentMode;
|
|
115
|
+
return {
|
|
116
|
+
modes,
|
|
117
|
+
recommendedMode: recommended,
|
|
118
|
+
currentMode,
|
|
119
|
+
resolvedMode: resolved,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
export function validatePersonaFields(persona) {
|
|
123
|
+
const prompt = persona.systemPrompt || "";
|
|
124
|
+
const tags = persona.meta.tags ?? [];
|
|
125
|
+
// Use structured metadata first, fall back to keyword matching in system prompt
|
|
126
|
+
const hasPlatform = tags.length > 0 || prompt.includes("常用平台") || (persona.meta.description?.includes("平台") ?? false);
|
|
127
|
+
const hasTraits = (persona.meta.description?.length ?? 0) >= 4 || prompt.includes("性格特质") || prompt.includes("性格");
|
|
128
|
+
const hasBlindSpot = !!persona.meta.blindSpot || prompt.includes("盲区");
|
|
129
|
+
if (!hasPlatform || !hasTraits || !hasBlindSpot) {
|
|
130
|
+
throw new Error(`[${persona.meta.name}] 角色 ${!hasPlatform ? "缺少平台标签/描述, " : ""}${!hasTraits ? "缺少性格描述, " : ""}${!hasBlindSpot ? "缺少盲区" : ""}`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
export async function loadPersonasForReview(skillsDir, personaIds) {
|
|
134
|
+
if (personaIds && personaIds.length > 0) {
|
|
135
|
+
const personas = await loadPersonasByIds(skillsDir, personaIds);
|
|
136
|
+
for (const p of personas) {
|
|
137
|
+
validatePersonaFields(p);
|
|
138
|
+
}
|
|
139
|
+
const foundIds = new Set(personas.map((p) => p.meta.id));
|
|
140
|
+
const missing = personaIds.filter((id) => !foundIds.has(id));
|
|
141
|
+
return { personas, missingIds: missing.length > 0 ? missing : undefined };
|
|
142
|
+
}
|
|
143
|
+
const personas = await loadAllPersonas(skillsDir);
|
|
144
|
+
for (const p of personas) {
|
|
145
|
+
validatePersonaFields(p);
|
|
146
|
+
}
|
|
147
|
+
return { personas };
|
|
148
|
+
}
|
|
149
|
+
// ── Sampling Support Check ────────────────────────────────────────────────────
|
|
150
|
+
export { isSamplingSupported };
|
|
151
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/execution/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate Limiter with Semaphore and Exponential Backoff
|
|
3
|
+
*
|
|
4
|
+
* Shared between mcp_sampling and direct_api modes.
|
|
5
|
+
*/
|
|
6
|
+
interface RateLimitConfig {
|
|
7
|
+
maxConcurrent: number;
|
|
8
|
+
minDelayMs: number;
|
|
9
|
+
}
|
|
10
|
+
export declare class RateLimiter {
|
|
11
|
+
private semaphore;
|
|
12
|
+
private minDelayMs;
|
|
13
|
+
private lastExecution;
|
|
14
|
+
private maxConcurrent;
|
|
15
|
+
constructor(config?: RateLimitConfig);
|
|
16
|
+
acquire(): Promise<void>;
|
|
17
|
+
release(): void;
|
|
18
|
+
waitForDelay(): Promise<void>;
|
|
19
|
+
getConfig(): RateLimitConfig;
|
|
20
|
+
}
|
|
21
|
+
export type RetryableErrorType = "rate_limit_exceeded" | "service_unavailable" | "timeout" | "network_error";
|
|
22
|
+
export declare function isRetryableError(errorType: string): errorType is RetryableErrorType;
|
|
23
|
+
interface RetryOptions {
|
|
24
|
+
maxRetries?: number;
|
|
25
|
+
backoffMs?: number;
|
|
26
|
+
backoffMultiplier?: number;
|
|
27
|
+
onRetry?: (attempt: number, error: Error, delayMs: number) => void;
|
|
28
|
+
}
|
|
29
|
+
export declare function withRetry<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T>;
|
|
30
|
+
export declare function getRateLimiter(config?: RateLimitConfig): RateLimiter;
|
|
31
|
+
export {};
|
|
32
|
+
//# sourceMappingURL=limiter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"limiter.d.ts","sourceRoot":"","sources":["../../src/execution/limiter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,UAAU,eAAe;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB;AAwCD,qBAAa,WAAW;IACtB,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,aAAa,CAAS;gBAElB,MAAM,GAAE,eAAgC;IAM9C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAI9B,OAAO,IAAI,IAAI;IAKT,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAUnC,SAAS,IAAI,eAAe;CAM7B;AAgBD,MAAM,MAAM,kBAAkB,GAC1B,qBAAqB,GACrB,qBAAqB,GACrB,SAAS,GACT,eAAe,CAAC;AASpB,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,IAAI,kBAAkB,CAEnF;AAID,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACpE;AAED,wBAAsB,SAAS,CAAC,CAAC,EAC/B,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,CAAC,CAAC,CAqCZ;AAwBD,wBAAgB,cAAc,CAAC,MAAM,CAAC,EAAE,eAAe,GAAG,WAAW,CAEpE"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate Limiter with Semaphore and Exponential Backoff
|
|
3
|
+
*
|
|
4
|
+
* Shared between mcp_sampling and direct_api modes.
|
|
5
|
+
*/
|
|
6
|
+
import { logger, getErrorInfo } from "../utils/observability.js";
|
|
7
|
+
const DEFAULT_CONFIG = {
|
|
8
|
+
maxConcurrent: Number(process.env.KEVLAR_MAX_CONCURRENT) || 3,
|
|
9
|
+
minDelayMs: Number(process.env.KEVLAR_MIN_DELAY_MS) || 1000,
|
|
10
|
+
};
|
|
11
|
+
// ── Semaphore ─────────────────────────────────────────────────────────────────
|
|
12
|
+
class Semaphore {
|
|
13
|
+
permits;
|
|
14
|
+
queue = [];
|
|
15
|
+
constructor(permits) {
|
|
16
|
+
this.permits = permits;
|
|
17
|
+
}
|
|
18
|
+
async acquire() {
|
|
19
|
+
if (this.permits > 0) {
|
|
20
|
+
this.permits--;
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
return new Promise((resolve) => {
|
|
24
|
+
this.queue.push(resolve);
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
release() {
|
|
28
|
+
if (this.queue.length > 0) {
|
|
29
|
+
const next = this.queue.shift();
|
|
30
|
+
if (next)
|
|
31
|
+
next();
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
this.permits++;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// ── Rate Limiter ──────────────────────────────────────────────────────────────
|
|
39
|
+
export class RateLimiter {
|
|
40
|
+
semaphore;
|
|
41
|
+
minDelayMs;
|
|
42
|
+
lastExecution = 0;
|
|
43
|
+
maxConcurrent;
|
|
44
|
+
constructor(config = DEFAULT_CONFIG) {
|
|
45
|
+
this.semaphore = new Semaphore(config.maxConcurrent);
|
|
46
|
+
this.minDelayMs = config.minDelayMs;
|
|
47
|
+
this.maxConcurrent = config.maxConcurrent;
|
|
48
|
+
}
|
|
49
|
+
async acquire() {
|
|
50
|
+
await this.semaphore.acquire();
|
|
51
|
+
}
|
|
52
|
+
release() {
|
|
53
|
+
this.semaphore.release();
|
|
54
|
+
this.lastExecution = Date.now();
|
|
55
|
+
}
|
|
56
|
+
async waitForDelay() {
|
|
57
|
+
const now = Date.now();
|
|
58
|
+
const elapsed = now - this.lastExecution;
|
|
59
|
+
if (elapsed < this.minDelayMs) {
|
|
60
|
+
await new Promise((resolve) => setTimeout(resolve, this.minDelayMs - elapsed));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
getConfig() {
|
|
64
|
+
return {
|
|
65
|
+
maxConcurrent: this.maxConcurrent,
|
|
66
|
+
minDelayMs: this.minDelayMs,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const DEFAULT_RETRY = {
|
|
71
|
+
maxRetries: 3,
|
|
72
|
+
backoffMs: 1000,
|
|
73
|
+
backoffMultiplier: 2,
|
|
74
|
+
};
|
|
75
|
+
const RETRYABLE_ERRORS = [
|
|
76
|
+
"rate_limit_exceeded",
|
|
77
|
+
"service_unavailable",
|
|
78
|
+
"timeout",
|
|
79
|
+
"network_error",
|
|
80
|
+
];
|
|
81
|
+
export function isRetryableError(errorType) {
|
|
82
|
+
return RETRYABLE_ERRORS.includes(errorType);
|
|
83
|
+
}
|
|
84
|
+
export async function withRetry(fn, options = {}) {
|
|
85
|
+
const config = {
|
|
86
|
+
maxRetries: options.maxRetries ?? DEFAULT_RETRY.maxRetries,
|
|
87
|
+
backoffMs: options.backoffMs ?? DEFAULT_RETRY.backoffMs,
|
|
88
|
+
backoffMultiplier: options.backoffMultiplier ?? DEFAULT_RETRY.backoffMultiplier,
|
|
89
|
+
};
|
|
90
|
+
let lastError;
|
|
91
|
+
let delay = config.backoffMs;
|
|
92
|
+
for (let attempt = 0; attempt <= config.maxRetries; attempt++) {
|
|
93
|
+
try {
|
|
94
|
+
return await fn();
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
lastError = err instanceof Error ? err : new Error(getErrorInfo(err).message);
|
|
98
|
+
// Check if error is retryable
|
|
99
|
+
const errorType = getErrorType(lastError);
|
|
100
|
+
if (attempt < config.maxRetries && isRetryableError(errorType)) {
|
|
101
|
+
logger.debug("Retrying after error", {
|
|
102
|
+
event: "retry",
|
|
103
|
+
attempt: attempt + 1,
|
|
104
|
+
errorType,
|
|
105
|
+
delayMs: delay,
|
|
106
|
+
});
|
|
107
|
+
options.onRetry?.(attempt + 1, lastError, delay);
|
|
108
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
109
|
+
delay *= config.backoffMultiplier;
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
throw lastError;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
throw lastError;
|
|
117
|
+
}
|
|
118
|
+
function getErrorType(err) {
|
|
119
|
+
const message = err.message.toLowerCase();
|
|
120
|
+
// Check by status code first (structured API error responses)
|
|
121
|
+
const statusMatch = message.match(/\b(\d{3})\b/);
|
|
122
|
+
if (statusMatch) {
|
|
123
|
+
const code = statusMatch[1];
|
|
124
|
+
if (code === "429")
|
|
125
|
+
return "rate_limit_exceeded";
|
|
126
|
+
if (code === "503")
|
|
127
|
+
return "service_unavailable";
|
|
128
|
+
if (code === "504" || code === "408")
|
|
129
|
+
return "timeout";
|
|
130
|
+
if (code === "502")
|
|
131
|
+
return "service_unavailable";
|
|
132
|
+
}
|
|
133
|
+
if (message.includes("rate limit"))
|
|
134
|
+
return "rate_limit_exceeded";
|
|
135
|
+
if (message.includes("unavailable"))
|
|
136
|
+
return "service_unavailable";
|
|
137
|
+
if (message.includes("timeout") || message.includes("ETIMEDOUT"))
|
|
138
|
+
return "timeout";
|
|
139
|
+
if (message.includes("network") || message.includes("ECONNREFUSED") || message.includes("ENOTFOUND"))
|
|
140
|
+
return "network_error";
|
|
141
|
+
return "unknown";
|
|
142
|
+
}
|
|
143
|
+
// ── Factory ─────────────────────────────────────────────────────────────────────
|
|
144
|
+
export function getRateLimiter(config) {
|
|
145
|
+
return new RateLimiter(config);
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=limiter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"limiter.js","sourceRoot":"","sources":["../../src/execution/limiter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Review Execution Lock
|
|
3
|
+
*
|
|
4
|
+
* Prevents concurrent execution of sampling/direct_api modes.
|
|
5
|
+
* Orchestration mode is exempt (no external calls).
|
|
6
|
+
* Includes TTL to prevent deadlocks on crash.
|
|
7
|
+
*/
|
|
8
|
+
interface LockEntry {
|
|
9
|
+
mode: string;
|
|
10
|
+
acquiredAt: number;
|
|
11
|
+
}
|
|
12
|
+
export declare function acquireReviewLock(mode: string): boolean;
|
|
13
|
+
export declare function releaseReviewLock(): void;
|
|
14
|
+
export declare function getReviewLock(): LockEntry | null;
|
|
15
|
+
export declare function isLocked(): boolean;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=lock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lock.d.ts","sourceRoot":"","sources":["../../src/execution/lock.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAID,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAUvD;AAED,wBAAgB,iBAAiB,IAAI,IAAI,CAExC;AAED,wBAAgB,aAAa,IAAI,SAAS,GAAG,IAAI,CAKhD;AAED,wBAAgB,QAAQ,IAAI,OAAO,CAMlC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Review Execution Lock
|
|
3
|
+
*
|
|
4
|
+
* Prevents concurrent execution of sampling/direct_api modes.
|
|
5
|
+
* Orchestration mode is exempt (no external calls).
|
|
6
|
+
* Includes TTL to prevent deadlocks on crash.
|
|
7
|
+
*/
|
|
8
|
+
const LOCK_TTL_MS = 300_000; // 5 minutes
|
|
9
|
+
let reviewLock = null;
|
|
10
|
+
export function acquireReviewLock(mode) {
|
|
11
|
+
if (reviewLock) {
|
|
12
|
+
if (Date.now() - reviewLock.acquiredAt > LOCK_TTL_MS) {
|
|
13
|
+
reviewLock = { mode, acquiredAt: Date.now() };
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
reviewLock = { mode, acquiredAt: Date.now() };
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
export function releaseReviewLock() {
|
|
22
|
+
reviewLock = null;
|
|
23
|
+
}
|
|
24
|
+
export function getReviewLock() {
|
|
25
|
+
if (reviewLock && Date.now() - reviewLock.acquiredAt > LOCK_TTL_MS) {
|
|
26
|
+
reviewLock = null;
|
|
27
|
+
}
|
|
28
|
+
return reviewLock;
|
|
29
|
+
}
|
|
30
|
+
export function isLocked() {
|
|
31
|
+
if (reviewLock && Date.now() - reviewLock.acquiredAt > LOCK_TTL_MS) {
|
|
32
|
+
reviewLock = null;
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
return reviewLock !== null;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=lock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lock.js","sourceRoot":"","sources":["../../src/execution/lock.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,GAAG,OAAO,CAAC,CAAC,YAAY;AAOzC,IAAI,UAAU,GAAqB,IAAI,CAAC;AAExC,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,IAAI,UAAU,EAAE,CAAC;QACf,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,UAAU,GAAG,WAAW,EAAE,CAAC;YACrD,UAAU,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YAC9C,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,UAAU,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IAC9C,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,UAAU,GAAG,IAAI,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,IAAI,UAAU,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,UAAU,GAAG,WAAW,EAAE,CAAC;QACnE,UAAU,GAAG,IAAI,CAAC;IACpB,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,QAAQ;IACtB,IAAI,UAAU,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,UAAU,GAAG,WAAW,EAAE,CAAC;QACnE,UAAU,GAAG,IAAI,CAAC;QAClB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,UAAU,KAAK,IAAI,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Direct API Execution Mode
|
|
3
|
+
*
|
|
4
|
+
* Directly calls third-party LLM APIs (OpenAI / Anthropic / Ollama).
|
|
5
|
+
* API keys are read ONLY from environment variables.
|
|
6
|
+
*/
|
|
7
|
+
import type { ExecutionHandler } from "../base.js";
|
|
8
|
+
export declare function hasApiKey(): boolean;
|
|
9
|
+
export declare function maskApiKey(key: string, visible?: number): string;
|
|
10
|
+
export declare const directApiHandler: ExecutionHandler;
|
|
11
|
+
//# sourceMappingURL=direct_api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"direct_api.d.ts","sourceRoot":"","sources":["../../../src/execution/modes/direct_api.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAoB,gBAAgB,EAAkC,MAAM,YAAY,CAAC;AAgDrG,wBAAgB,SAAS,IAAI,OAAO,CAEnC;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,SAAI,GAAG,MAAM,CAG3D;AAsKD,eAAO,MAAM,gBAAgB,EAAE,gBAwC9B,CAAC"}
|