@defai.digital/automatosx 12.6.2 → 12.7.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/index.js +3135 -1139
- package/dist/mcp/index.js +2540 -210
- package/examples/abilities/api-design.md +9 -0
- package/examples/abilities/code-review.md +9 -0
- package/examples/abilities/db-modeling.md +9 -0
- package/examples/abilities/debugging.md +9 -0
- package/examples/abilities/performance.md +9 -0
- package/examples/abilities/secure-coding-review.md +9 -0
- package/examples/abilities/testing.md +9 -0
- package/examples/abilities/threat-modeling.md +9 -0
- package/examples/agents/backend.yaml +42 -73
- package/examples/agents/quality.yaml +44 -20
- package/package.json +1 -1
package/dist/mcp/index.js
CHANGED
|
@@ -22,7 +22,6 @@ import { EventEmitter } from 'events';
|
|
|
22
22
|
import { findUp } from 'find-up';
|
|
23
23
|
import * as sqliteVec from 'sqlite-vec';
|
|
24
24
|
import { randomUUID, randomBytes, createHash } from 'crypto';
|
|
25
|
-
import yaml from 'yaml';
|
|
26
25
|
import { gzipSync, gunzipSync } from 'zlib';
|
|
27
26
|
|
|
28
27
|
var __defProp = Object.defineProperty;
|
|
@@ -2492,6 +2491,7 @@ function getRetryableErrors(provider) {
|
|
|
2492
2491
|
return [...baseErrors, ...CODEX_RETRYABLE_ERRORS];
|
|
2493
2492
|
case "glm":
|
|
2494
2493
|
case "grok":
|
|
2494
|
+
case "qwen":
|
|
2495
2495
|
return [...baseErrors, ...OPENAI_RETRYABLE_ERRORS];
|
|
2496
2496
|
case "base":
|
|
2497
2497
|
default:
|
|
@@ -2594,6 +2594,10 @@ var init_base_provider = __esm({
|
|
|
2594
2594
|
// v12.0.0: Native Grok provider (xAI)
|
|
2595
2595
|
"ax-grok",
|
|
2596
2596
|
// v12.0.0: Alias for grok
|
|
2597
|
+
"qwen",
|
|
2598
|
+
// v12.7.0: Qwen Code provider (Alibaba Cloud)
|
|
2599
|
+
"qwen-code",
|
|
2600
|
+
// v12.7.0: Alias for qwen
|
|
2597
2601
|
"test-provider"
|
|
2598
2602
|
// For unit tests
|
|
2599
2603
|
];
|
|
@@ -2956,7 +2960,7 @@ var init_base_provider = __esm({
|
|
|
2956
2960
|
if (readlineInterface) {
|
|
2957
2961
|
try {
|
|
2958
2962
|
readlineInterface.close();
|
|
2959
|
-
} catch
|
|
2963
|
+
} catch {
|
|
2960
2964
|
} finally {
|
|
2961
2965
|
readlineInterface = null;
|
|
2962
2966
|
}
|
|
@@ -2964,7 +2968,7 @@ var init_base_provider = __esm({
|
|
|
2964
2968
|
if (stderrInterface) {
|
|
2965
2969
|
try {
|
|
2966
2970
|
stderrInterface.close();
|
|
2967
|
-
} catch
|
|
2971
|
+
} catch {
|
|
2968
2972
|
} finally {
|
|
2969
2973
|
stderrInterface = null;
|
|
2970
2974
|
}
|
|
@@ -3158,7 +3162,7 @@ ${fullPrompt}
|
|
|
3158
3162
|
this.health.consecutiveSuccesses = 0;
|
|
3159
3163
|
}
|
|
3160
3164
|
return available;
|
|
3161
|
-
} catch
|
|
3165
|
+
} catch {
|
|
3162
3166
|
this.health.available = false;
|
|
3163
3167
|
this.health.errorRate = 1;
|
|
3164
3168
|
this.health.lastCheck = Date.now();
|
|
@@ -3334,6 +3338,8 @@ ${fullPrompt}
|
|
|
3334
3338
|
retryableProvider = "glm";
|
|
3335
3339
|
} else if (providerName === "grok" || providerName === "ax-grok") {
|
|
3336
3340
|
retryableProvider = "grok";
|
|
3341
|
+
} else if (providerName === "qwen" || providerName === "qwen-code") {
|
|
3342
|
+
retryableProvider = "qwen";
|
|
3337
3343
|
}
|
|
3338
3344
|
return shouldRetryError(error, retryableProvider);
|
|
3339
3345
|
}
|
|
@@ -5788,13 +5794,21 @@ var init_types2 = __esm({
|
|
|
5788
5794
|
"src/integrations/ax-glm/types.ts"() {
|
|
5789
5795
|
init_esm_shims();
|
|
5790
5796
|
GLM_MODEL_MAPPING = {
|
|
5797
|
+
// Convenience aliases (ax-cli v4.3.15)
|
|
5798
|
+
"glm-latest": "glm-4.6",
|
|
5799
|
+
"glm-vision": "glm-4.6v",
|
|
5800
|
+
"glm-fast": "glm-4-flash",
|
|
5801
|
+
"glm-image": "cogview-4",
|
|
5802
|
+
// Legacy aliases (deprecated)
|
|
5791
5803
|
"glm-4-plus": "glm-4.6",
|
|
5792
|
-
"glm-
|
|
5804
|
+
"glm-4.5v": "glm-4.6v",
|
|
5805
|
+
"glm-4v": "glm-4.6v",
|
|
5806
|
+
"glm-4": "glm-4.6",
|
|
5793
5807
|
"glm-4-air": "glm-4-flash",
|
|
5794
5808
|
"glm-4-airx": "glm-4-flash"
|
|
5795
5809
|
};
|
|
5796
5810
|
GLM_DEFAULT_BASE_URL = "https://open.bigmodel.cn/api/paas/v4";
|
|
5797
|
-
GLM_DEFAULT_MODEL = "glm-4";
|
|
5811
|
+
GLM_DEFAULT_MODEL = "glm-4.6";
|
|
5798
5812
|
GLM_DEFAULT_COMMAND = "ax-glm";
|
|
5799
5813
|
}
|
|
5800
5814
|
});
|
|
@@ -6743,10 +6757,18 @@ var init_types3 = __esm({
|
|
|
6743
6757
|
"src/integrations/ax-grok/types.ts"() {
|
|
6744
6758
|
init_esm_shims();
|
|
6745
6759
|
GROK_MODEL_MAPPING = {
|
|
6746
|
-
|
|
6760
|
+
// Convenience aliases (ax-cli v4.3.15)
|
|
6761
|
+
"grok-latest": "grok-4-0709",
|
|
6762
|
+
"grok-fast": "grok-4.1-fast",
|
|
6763
|
+
"grok-mini": "grok-3-mini",
|
|
6764
|
+
"grok-vision": "grok-2-vision-1212",
|
|
6765
|
+
"grok-image": "grok-2-image-1212",
|
|
6766
|
+
// Legacy aliases (deprecated)
|
|
6767
|
+
"grok-beta": "grok-3",
|
|
6768
|
+
"grok-2-vision": "grok-2-vision-1212"
|
|
6747
6769
|
};
|
|
6748
6770
|
GROK_DEFAULT_BASE_URL = "https://api.x.ai/v1";
|
|
6749
|
-
GROK_DEFAULT_MODEL = "grok-
|
|
6771
|
+
GROK_DEFAULT_MODEL = "grok-4-0709";
|
|
6750
6772
|
GROK_DEFAULT_COMMAND = "ax-grok";
|
|
6751
6773
|
}
|
|
6752
6774
|
});
|
|
@@ -7678,6 +7700,902 @@ Mode: ${this.grokConfig.mode || "auto"}`;
|
|
|
7678
7700
|
}
|
|
7679
7701
|
});
|
|
7680
7702
|
|
|
7703
|
+
// src/integrations/qwen-code/types.ts
|
|
7704
|
+
function normalizeQwenModel(model) {
|
|
7705
|
+
return QWEN_MODEL_MAPPING[model] || model;
|
|
7706
|
+
}
|
|
7707
|
+
function isVisionModel(model) {
|
|
7708
|
+
return model.includes("qwen3-coder") || model.includes("qwen-max");
|
|
7709
|
+
}
|
|
7710
|
+
function getModelContextWindow(model) {
|
|
7711
|
+
const normalizedModel = normalizeQwenModel(model);
|
|
7712
|
+
if (normalizedModel.includes("480b")) return 128e3;
|
|
7713
|
+
if (normalizedModel.includes("30b")) return 64e3;
|
|
7714
|
+
if (normalizedModel.includes("qwen-max")) return 128e3;
|
|
7715
|
+
if (normalizedModel.includes("qwen-plus")) return 128e3;
|
|
7716
|
+
if (normalizedModel.includes("qwen-turbo")) return 128e3;
|
|
7717
|
+
return 64e3;
|
|
7718
|
+
}
|
|
7719
|
+
var QWEN_DEFAULT_BASE_URL, QWEN_DEFAULT_MODEL, QWEN_DEFAULT_COMMAND, QWEN_MODEL_MAPPING;
|
|
7720
|
+
var init_types4 = __esm({
|
|
7721
|
+
"src/integrations/qwen-code/types.ts"() {
|
|
7722
|
+
init_esm_shims();
|
|
7723
|
+
QWEN_DEFAULT_BASE_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1";
|
|
7724
|
+
QWEN_DEFAULT_MODEL = "qwen-turbo";
|
|
7725
|
+
QWEN_DEFAULT_COMMAND = "qwen";
|
|
7726
|
+
QWEN_MODEL_MAPPING = {
|
|
7727
|
+
// Normalize common aliases
|
|
7728
|
+
"qwen-coder": "qwen3-coder-480b-a35b-instruct",
|
|
7729
|
+
"qwen-coder-480b": "qwen3-coder-480b-a35b-instruct",
|
|
7730
|
+
"qwen-coder-30b": "qwen3-coder-30b-a3b-instruct",
|
|
7731
|
+
"qwen2.5-coder": "qwen2.5-coder-32b-instruct"
|
|
7732
|
+
};
|
|
7733
|
+
}
|
|
7734
|
+
});
|
|
7735
|
+
|
|
7736
|
+
// src/integrations/qwen-code/sdk-adapter.ts
|
|
7737
|
+
var QwenSdkAdapter;
|
|
7738
|
+
var init_sdk_adapter4 = __esm({
|
|
7739
|
+
"src/integrations/qwen-code/sdk-adapter.ts"() {
|
|
7740
|
+
init_esm_shims();
|
|
7741
|
+
init_logger();
|
|
7742
|
+
init_validation_limits();
|
|
7743
|
+
init_types4();
|
|
7744
|
+
QwenSdkAdapter = class {
|
|
7745
|
+
client = null;
|
|
7746
|
+
config;
|
|
7747
|
+
initialized = false;
|
|
7748
|
+
constructor(config = {}) {
|
|
7749
|
+
const apiKey = config.apiKey || process.env.DASHSCOPE_API_KEY || process.env.QWEN_API_KEY || "";
|
|
7750
|
+
this.config = {
|
|
7751
|
+
apiKey,
|
|
7752
|
+
baseUrl: config.baseUrl || QWEN_DEFAULT_BASE_URL,
|
|
7753
|
+
model: config.model || QWEN_DEFAULT_MODEL,
|
|
7754
|
+
timeout: config.timeout || TIMEOUTS.PROVIDER_DEFAULT
|
|
7755
|
+
};
|
|
7756
|
+
logger.debug("[Qwen SDK] Adapter created", {
|
|
7757
|
+
model: this.config.model,
|
|
7758
|
+
baseUrl: this.config.baseUrl,
|
|
7759
|
+
hasApiKey: !!this.config.apiKey
|
|
7760
|
+
});
|
|
7761
|
+
}
|
|
7762
|
+
/**
|
|
7763
|
+
* Check if SDK is available (OpenAI package installed and API key configured)
|
|
7764
|
+
*/
|
|
7765
|
+
async isAvailable() {
|
|
7766
|
+
try {
|
|
7767
|
+
if (!this.config.apiKey) {
|
|
7768
|
+
logger.debug("[Qwen SDK] No API key configured (set DASHSCOPE_API_KEY or QWEN_API_KEY)");
|
|
7769
|
+
return false;
|
|
7770
|
+
}
|
|
7771
|
+
await import('openai');
|
|
7772
|
+
return true;
|
|
7773
|
+
} catch (error) {
|
|
7774
|
+
logger.debug("[Qwen SDK] OpenAI SDK not available", {
|
|
7775
|
+
error: error instanceof Error ? error.message : String(error)
|
|
7776
|
+
});
|
|
7777
|
+
return false;
|
|
7778
|
+
}
|
|
7779
|
+
}
|
|
7780
|
+
/**
|
|
7781
|
+
* Initialize the SDK client
|
|
7782
|
+
*/
|
|
7783
|
+
async initialize() {
|
|
7784
|
+
if (this.initialized) {
|
|
7785
|
+
return;
|
|
7786
|
+
}
|
|
7787
|
+
try {
|
|
7788
|
+
const OpenAI = (await import('openai')).default;
|
|
7789
|
+
this.client = new OpenAI({
|
|
7790
|
+
apiKey: this.config.apiKey,
|
|
7791
|
+
baseURL: this.config.baseUrl,
|
|
7792
|
+
timeout: this.config.timeout
|
|
7793
|
+
});
|
|
7794
|
+
this.initialized = true;
|
|
7795
|
+
logger.debug("[Qwen SDK] Client initialized", {
|
|
7796
|
+
model: this.config.model
|
|
7797
|
+
});
|
|
7798
|
+
} catch (error) {
|
|
7799
|
+
throw new Error(
|
|
7800
|
+
`Failed to initialize Qwen SDK: ${error instanceof Error ? error.message : String(error)}`
|
|
7801
|
+
);
|
|
7802
|
+
}
|
|
7803
|
+
}
|
|
7804
|
+
/**
|
|
7805
|
+
* Execute a request using the Qwen SDK
|
|
7806
|
+
*/
|
|
7807
|
+
async execute(request) {
|
|
7808
|
+
if (!this.initialized) {
|
|
7809
|
+
await this.initialize();
|
|
7810
|
+
}
|
|
7811
|
+
const startTime = Date.now();
|
|
7812
|
+
try {
|
|
7813
|
+
const messages = [];
|
|
7814
|
+
if (request.systemPrompt) {
|
|
7815
|
+
messages.push({
|
|
7816
|
+
role: "system",
|
|
7817
|
+
content: request.systemPrompt
|
|
7818
|
+
});
|
|
7819
|
+
}
|
|
7820
|
+
messages.push({
|
|
7821
|
+
role: "user",
|
|
7822
|
+
content: request.prompt
|
|
7823
|
+
});
|
|
7824
|
+
const model = normalizeQwenModel(request.model || this.config.model);
|
|
7825
|
+
logger.debug("[Qwen SDK] Executing request", {
|
|
7826
|
+
model,
|
|
7827
|
+
messageCount: messages.length,
|
|
7828
|
+
promptLength: request.prompt.length
|
|
7829
|
+
});
|
|
7830
|
+
const openaiClient = this.client;
|
|
7831
|
+
const response = await openaiClient.chat.completions.create({
|
|
7832
|
+
model,
|
|
7833
|
+
messages,
|
|
7834
|
+
max_tokens: request.maxTokens,
|
|
7835
|
+
temperature: request.temperature,
|
|
7836
|
+
stream: false
|
|
7837
|
+
});
|
|
7838
|
+
const latencyMs = Date.now() - startTime;
|
|
7839
|
+
if (!response.choices || response.choices.length === 0) {
|
|
7840
|
+
throw new Error("Qwen API returned empty choices array");
|
|
7841
|
+
}
|
|
7842
|
+
const choice = response.choices[0];
|
|
7843
|
+
const content = choice?.message?.content || "";
|
|
7844
|
+
const finishReason = choice?.finish_reason || "unknown";
|
|
7845
|
+
logger.debug("[Qwen SDK] Request completed", {
|
|
7846
|
+
model: response.model,
|
|
7847
|
+
latencyMs,
|
|
7848
|
+
tokensUsed: response.usage?.total_tokens
|
|
7849
|
+
});
|
|
7850
|
+
return {
|
|
7851
|
+
content,
|
|
7852
|
+
model: response.model,
|
|
7853
|
+
tokensUsed: response.usage ? {
|
|
7854
|
+
prompt: response.usage.prompt_tokens,
|
|
7855
|
+
completion: response.usage.completion_tokens,
|
|
7856
|
+
total: response.usage.total_tokens
|
|
7857
|
+
} : { prompt: 0, completion: 0, total: 0 },
|
|
7858
|
+
latencyMs,
|
|
7859
|
+
finishReason,
|
|
7860
|
+
cached: false
|
|
7861
|
+
};
|
|
7862
|
+
} catch (error) {
|
|
7863
|
+
const latencyMs = Date.now() - startTime;
|
|
7864
|
+
logger.error("[Qwen SDK] Request failed", {
|
|
7865
|
+
error: error instanceof Error ? error.message : String(error),
|
|
7866
|
+
latencyMs
|
|
7867
|
+
});
|
|
7868
|
+
throw error;
|
|
7869
|
+
}
|
|
7870
|
+
}
|
|
7871
|
+
/**
|
|
7872
|
+
* Get the configured model
|
|
7873
|
+
*/
|
|
7874
|
+
getModel() {
|
|
7875
|
+
return this.config.model;
|
|
7876
|
+
}
|
|
7877
|
+
/**
|
|
7878
|
+
* Clean up resources
|
|
7879
|
+
*/
|
|
7880
|
+
async destroy() {
|
|
7881
|
+
this.client = null;
|
|
7882
|
+
this.initialized = false;
|
|
7883
|
+
logger.debug("[Qwen SDK] Adapter destroyed");
|
|
7884
|
+
}
|
|
7885
|
+
};
|
|
7886
|
+
}
|
|
7887
|
+
});
|
|
7888
|
+
var NON_INTERACTIVE_ENV, SIGKILL_ESCALATION_MS, QwenCliWrapper;
|
|
7889
|
+
var init_cli_wrapper4 = __esm({
|
|
7890
|
+
"src/integrations/qwen-code/cli-wrapper.ts"() {
|
|
7891
|
+
init_esm_shims();
|
|
7892
|
+
init_logger();
|
|
7893
|
+
init_validation_limits();
|
|
7894
|
+
init_cli_provider_detector();
|
|
7895
|
+
init_types4();
|
|
7896
|
+
NON_INTERACTIVE_ENV = {
|
|
7897
|
+
TERM: "dumb",
|
|
7898
|
+
NO_COLOR: "1",
|
|
7899
|
+
FORCE_COLOR: "0",
|
|
7900
|
+
CI: "true",
|
|
7901
|
+
NO_UPDATE_NOTIFIER: "1",
|
|
7902
|
+
DEBIAN_FRONTEND: "noninteractive"
|
|
7903
|
+
};
|
|
7904
|
+
SIGKILL_ESCALATION_MS = 5e3;
|
|
7905
|
+
QwenCliWrapper = class {
|
|
7906
|
+
config;
|
|
7907
|
+
constructor(config = {}) {
|
|
7908
|
+
this.config = {
|
|
7909
|
+
command: config.command || QWEN_DEFAULT_COMMAND,
|
|
7910
|
+
vlmSwitchMode: config.vlmSwitchMode || "once",
|
|
7911
|
+
yolo: config.yolo || false,
|
|
7912
|
+
timeout: config.timeout || TIMEOUTS.PROVIDER_DEFAULT
|
|
7913
|
+
};
|
|
7914
|
+
logger.debug("[Qwen CLI] Wrapper created", {
|
|
7915
|
+
command: this.config.command,
|
|
7916
|
+
timeout: this.config.timeout
|
|
7917
|
+
});
|
|
7918
|
+
}
|
|
7919
|
+
/**
|
|
7920
|
+
* Check if Qwen CLI is available on PATH
|
|
7921
|
+
*/
|
|
7922
|
+
async isAvailable() {
|
|
7923
|
+
if (process.env.AX_MOCK_PROVIDERS === "true") {
|
|
7924
|
+
return true;
|
|
7925
|
+
}
|
|
7926
|
+
try {
|
|
7927
|
+
const result = findOnPath(this.config.command);
|
|
7928
|
+
logger.debug("[Qwen CLI] Availability check", {
|
|
7929
|
+
available: result.found,
|
|
7930
|
+
path: result.path
|
|
7931
|
+
});
|
|
7932
|
+
return result.found;
|
|
7933
|
+
} catch (error) {
|
|
7934
|
+
logger.debug("[Qwen CLI] Availability check failed", {
|
|
7935
|
+
error: error instanceof Error ? error.message : String(error)
|
|
7936
|
+
});
|
|
7937
|
+
return false;
|
|
7938
|
+
}
|
|
7939
|
+
}
|
|
7940
|
+
/**
|
|
7941
|
+
* Execute a prompt using the Qwen CLI
|
|
7942
|
+
*
|
|
7943
|
+
* Since Qwen CLI is interactive, we:
|
|
7944
|
+
* 1. Spawn the process
|
|
7945
|
+
* 2. Send the prompt via stdin
|
|
7946
|
+
* 3. Capture output until we detect completion
|
|
7947
|
+
* 4. Return the response
|
|
7948
|
+
*/
|
|
7949
|
+
async execute(request) {
|
|
7950
|
+
if (process.env.AX_MOCK_PROVIDERS === "true") {
|
|
7951
|
+
return this.createMockResponse(request.prompt);
|
|
7952
|
+
}
|
|
7953
|
+
const startTime = Date.now();
|
|
7954
|
+
return new Promise((resolve5, reject) => {
|
|
7955
|
+
const args2 = [];
|
|
7956
|
+
if (this.config.vlmSwitchMode !== "once") {
|
|
7957
|
+
args2.push("--vlm-switch-mode", this.config.vlmSwitchMode);
|
|
7958
|
+
}
|
|
7959
|
+
if (this.config.yolo) {
|
|
7960
|
+
args2.push("--yolo");
|
|
7961
|
+
}
|
|
7962
|
+
logger.debug("[Qwen CLI] Spawning process", {
|
|
7963
|
+
command: this.config.command,
|
|
7964
|
+
args: args2,
|
|
7965
|
+
promptLength: request.prompt.length
|
|
7966
|
+
});
|
|
7967
|
+
const child = spawn(this.config.command, args2, {
|
|
7968
|
+
env: { ...process.env, ...NON_INTERACTIVE_ENV }
|
|
7969
|
+
});
|
|
7970
|
+
let stdout = "";
|
|
7971
|
+
let stderr = "";
|
|
7972
|
+
let timeoutId = null;
|
|
7973
|
+
let forceKillTimer = null;
|
|
7974
|
+
let readlineInterface = null;
|
|
7975
|
+
let responseStarted = false;
|
|
7976
|
+
const cleanup = () => {
|
|
7977
|
+
if (timeoutId) {
|
|
7978
|
+
clearTimeout(timeoutId);
|
|
7979
|
+
timeoutId = null;
|
|
7980
|
+
}
|
|
7981
|
+
if (forceKillTimer) {
|
|
7982
|
+
clearTimeout(forceKillTimer);
|
|
7983
|
+
forceKillTimer = null;
|
|
7984
|
+
}
|
|
7985
|
+
if (readlineInterface) {
|
|
7986
|
+
try {
|
|
7987
|
+
readlineInterface.close();
|
|
7988
|
+
} catch {
|
|
7989
|
+
}
|
|
7990
|
+
readlineInterface = null;
|
|
7991
|
+
}
|
|
7992
|
+
};
|
|
7993
|
+
if (child.stdout) {
|
|
7994
|
+
readlineInterface = readline.createInterface({
|
|
7995
|
+
input: child.stdout,
|
|
7996
|
+
crlfDelay: Infinity
|
|
7997
|
+
});
|
|
7998
|
+
readlineInterface.on("line", (line) => {
|
|
7999
|
+
if (line.startsWith(">") && !responseStarted) {
|
|
8000
|
+
responseStarted = true;
|
|
8001
|
+
return;
|
|
8002
|
+
}
|
|
8003
|
+
if (responseStarted) {
|
|
8004
|
+
stdout += line + "\n";
|
|
8005
|
+
}
|
|
8006
|
+
});
|
|
8007
|
+
readlineInterface.on("error", (error) => {
|
|
8008
|
+
logger.debug("[Qwen CLI] Readline error", {
|
|
8009
|
+
error: error.message
|
|
8010
|
+
});
|
|
8011
|
+
});
|
|
8012
|
+
}
|
|
8013
|
+
if (child.stderr) {
|
|
8014
|
+
child.stderr.on("data", (data) => {
|
|
8015
|
+
stderr += data.toString();
|
|
8016
|
+
});
|
|
8017
|
+
}
|
|
8018
|
+
if (child.stdin) {
|
|
8019
|
+
try {
|
|
8020
|
+
let fullPrompt = request.prompt;
|
|
8021
|
+
if (request.systemPrompt) {
|
|
8022
|
+
fullPrompt = `${request.systemPrompt}
|
|
8023
|
+
|
|
8024
|
+
${request.prompt}`;
|
|
8025
|
+
}
|
|
8026
|
+
child.stdin.write(fullPrompt);
|
|
8027
|
+
child.stdin.write("\n");
|
|
8028
|
+
child.stdin.end();
|
|
8029
|
+
} catch (error) {
|
|
8030
|
+
cleanup();
|
|
8031
|
+
child.kill("SIGTERM");
|
|
8032
|
+
reject(new Error(`Failed to write to Qwen stdin: ${error instanceof Error ? error.message : String(error)}`));
|
|
8033
|
+
return;
|
|
8034
|
+
}
|
|
8035
|
+
} else {
|
|
8036
|
+
cleanup();
|
|
8037
|
+
reject(new Error("Qwen CLI stdin not available"));
|
|
8038
|
+
return;
|
|
8039
|
+
}
|
|
8040
|
+
child.on("close", (code, signal) => {
|
|
8041
|
+
cleanup();
|
|
8042
|
+
const latencyMs = Date.now() - startTime;
|
|
8043
|
+
if (stderr) {
|
|
8044
|
+
logger.debug("[Qwen CLI] stderr output", { stderr: stderr.trim() });
|
|
8045
|
+
}
|
|
8046
|
+
if ((code === 0 || code === null) && !signal) {
|
|
8047
|
+
const content = this.parseResponse(stdout);
|
|
8048
|
+
resolve5({
|
|
8049
|
+
content: content.trim(),
|
|
8050
|
+
model: "qwen-code-cli",
|
|
8051
|
+
tokensUsed: {
|
|
8052
|
+
prompt: this.estimateTokens(request.prompt),
|
|
8053
|
+
completion: this.estimateTokens(content),
|
|
8054
|
+
total: this.estimateTokens(request.prompt) + this.estimateTokens(content)
|
|
8055
|
+
},
|
|
8056
|
+
latencyMs,
|
|
8057
|
+
finishReason: "stop",
|
|
8058
|
+
cached: false
|
|
8059
|
+
});
|
|
8060
|
+
} else if (signal) {
|
|
8061
|
+
reject(new Error(`Qwen CLI killed by signal ${signal}. stderr: ${stderr || "none"}`));
|
|
8062
|
+
} else {
|
|
8063
|
+
reject(new Error(`Qwen CLI exited with code ${code}. stderr: ${stderr || "none"}`));
|
|
8064
|
+
}
|
|
8065
|
+
});
|
|
8066
|
+
child.on("error", (error) => {
|
|
8067
|
+
cleanup();
|
|
8068
|
+
logger.error("[Qwen CLI] Process error", {
|
|
8069
|
+
error: error.message
|
|
8070
|
+
});
|
|
8071
|
+
reject(new Error(`Failed to spawn Qwen CLI: ${error.message}`));
|
|
8072
|
+
});
|
|
8073
|
+
timeoutId = setTimeout(() => {
|
|
8074
|
+
if (child.pid && !child.killed) {
|
|
8075
|
+
logger.warn("[Qwen CLI] Killing process due to timeout", {
|
|
8076
|
+
pid: child.pid,
|
|
8077
|
+
timeout: this.config.timeout
|
|
8078
|
+
});
|
|
8079
|
+
child.kill("SIGTERM");
|
|
8080
|
+
forceKillTimer = setTimeout(() => {
|
|
8081
|
+
if (child.pid) {
|
|
8082
|
+
try {
|
|
8083
|
+
process.kill(child.pid, 0);
|
|
8084
|
+
logger.warn("[Qwen CLI] Force killing process", { pid: child.pid });
|
|
8085
|
+
child.kill("SIGKILL");
|
|
8086
|
+
} catch {
|
|
8087
|
+
}
|
|
8088
|
+
}
|
|
8089
|
+
}, SIGKILL_ESCALATION_MS);
|
|
8090
|
+
}
|
|
8091
|
+
}, this.config.timeout);
|
|
8092
|
+
});
|
|
8093
|
+
}
|
|
8094
|
+
/**
|
|
8095
|
+
* Parse response from CLI output
|
|
8096
|
+
*
|
|
8097
|
+
* Qwen CLI outputs include prompts and formatting that we need to strip.
|
|
8098
|
+
*/
|
|
8099
|
+
parseResponse(output) {
|
|
8100
|
+
let content = output.trim();
|
|
8101
|
+
content = content.replace(/\x1B\[[0-9;]*[mGKH]/g, "");
|
|
8102
|
+
content = content.replace(/^>\s*/gm, "").replace(/\n{3,}/g, "\n\n").trim();
|
|
8103
|
+
return content;
|
|
8104
|
+
}
|
|
8105
|
+
/**
|
|
8106
|
+
* Estimate token count
|
|
8107
|
+
*/
|
|
8108
|
+
estimateTokens(text) {
|
|
8109
|
+
return Math.ceil(text.length / 4);
|
|
8110
|
+
}
|
|
8111
|
+
/**
|
|
8112
|
+
* Create mock response for testing
|
|
8113
|
+
*/
|
|
8114
|
+
createMockResponse(prompt) {
|
|
8115
|
+
return {
|
|
8116
|
+
content: `[Mock Qwen Response]
|
|
8117
|
+
|
|
8118
|
+
This is a mock response from Qwen Code CLI.
|
|
8119
|
+
Prompt length: ${prompt.length} characters.`,
|
|
8120
|
+
model: "qwen-code-cli-mock",
|
|
8121
|
+
tokensUsed: {
|
|
8122
|
+
prompt: this.estimateTokens(prompt),
|
|
8123
|
+
completion: 50,
|
|
8124
|
+
total: this.estimateTokens(prompt) + 50
|
|
8125
|
+
},
|
|
8126
|
+
latencyMs: 10,
|
|
8127
|
+
finishReason: "stop",
|
|
8128
|
+
cached: false
|
|
8129
|
+
};
|
|
8130
|
+
}
|
|
8131
|
+
/**
|
|
8132
|
+
* Get CLI command
|
|
8133
|
+
*/
|
|
8134
|
+
getCommand() {
|
|
8135
|
+
return this.config.command;
|
|
8136
|
+
}
|
|
8137
|
+
};
|
|
8138
|
+
}
|
|
8139
|
+
});
|
|
8140
|
+
|
|
8141
|
+
// src/integrations/qwen-code/hybrid-adapter.ts
|
|
8142
|
+
var QwenHybridAdapter;
|
|
8143
|
+
var init_hybrid_adapter4 = __esm({
|
|
8144
|
+
"src/integrations/qwen-code/hybrid-adapter.ts"() {
|
|
8145
|
+
init_esm_shims();
|
|
8146
|
+
init_logger();
|
|
8147
|
+
init_sdk_adapter4();
|
|
8148
|
+
init_cli_wrapper4();
|
|
8149
|
+
QwenHybridAdapter = class {
|
|
8150
|
+
sdkAdapter = null;
|
|
8151
|
+
cliWrapper = null;
|
|
8152
|
+
options;
|
|
8153
|
+
activeMode = null;
|
|
8154
|
+
// Circuit breakers for each mode
|
|
8155
|
+
sdkCircuitBreaker = {
|
|
8156
|
+
failures: 0,
|
|
8157
|
+
lastFailure: 0,
|
|
8158
|
+
isOpen: false
|
|
8159
|
+
};
|
|
8160
|
+
cliCircuitBreaker = {
|
|
8161
|
+
failures: 0,
|
|
8162
|
+
lastFailure: 0,
|
|
8163
|
+
isOpen: false
|
|
8164
|
+
};
|
|
8165
|
+
// Circuit breaker configuration
|
|
8166
|
+
FAILURE_THRESHOLD = 3;
|
|
8167
|
+
RECOVERY_TIMEOUT_MS = 6e4;
|
|
8168
|
+
// 1 minute
|
|
8169
|
+
constructor(options = {}) {
|
|
8170
|
+
this.options = {
|
|
8171
|
+
mode: options.mode || "auto",
|
|
8172
|
+
model: options.model || "qwen-turbo",
|
|
8173
|
+
apiKey: options.apiKey,
|
|
8174
|
+
baseUrl: options.baseUrl,
|
|
8175
|
+
command: options.command || "qwen",
|
|
8176
|
+
timeout: options.timeout
|
|
8177
|
+
};
|
|
8178
|
+
logger.debug("[Qwen Hybrid] Adapter created", {
|
|
8179
|
+
mode: this.options.mode,
|
|
8180
|
+
model: this.options.model
|
|
8181
|
+
});
|
|
8182
|
+
}
|
|
8183
|
+
/**
|
|
8184
|
+
* Get or create SDK adapter
|
|
8185
|
+
*/
|
|
8186
|
+
getSdkAdapter() {
|
|
8187
|
+
if (!this.sdkAdapter) {
|
|
8188
|
+
const config = {
|
|
8189
|
+
apiKey: this.options.apiKey,
|
|
8190
|
+
baseUrl: this.options.baseUrl,
|
|
8191
|
+
model: this.options.model,
|
|
8192
|
+
timeout: this.options.timeout
|
|
8193
|
+
};
|
|
8194
|
+
this.sdkAdapter = new QwenSdkAdapter(config);
|
|
8195
|
+
}
|
|
8196
|
+
return this.sdkAdapter;
|
|
8197
|
+
}
|
|
8198
|
+
/**
|
|
8199
|
+
* Get or create CLI wrapper
|
|
8200
|
+
*/
|
|
8201
|
+
getCliWrapper() {
|
|
8202
|
+
if (!this.cliWrapper) {
|
|
8203
|
+
const config = {
|
|
8204
|
+
command: this.options.command,
|
|
8205
|
+
timeout: this.options.timeout
|
|
8206
|
+
};
|
|
8207
|
+
this.cliWrapper = new QwenCliWrapper(config);
|
|
8208
|
+
}
|
|
8209
|
+
return this.cliWrapper;
|
|
8210
|
+
}
|
|
8211
|
+
/**
|
|
8212
|
+
* Check if a circuit breaker should allow requests
|
|
8213
|
+
*/
|
|
8214
|
+
isCircuitClosed(breaker) {
|
|
8215
|
+
if (!breaker.isOpen) {
|
|
8216
|
+
return true;
|
|
8217
|
+
}
|
|
8218
|
+
if (Date.now() - breaker.lastFailure > this.RECOVERY_TIMEOUT_MS) {
|
|
8219
|
+
breaker.isOpen = false;
|
|
8220
|
+
breaker.failures = 0;
|
|
8221
|
+
return true;
|
|
8222
|
+
}
|
|
8223
|
+
return false;
|
|
8224
|
+
}
|
|
8225
|
+
/**
|
|
8226
|
+
* Record a failure on a circuit breaker
|
|
8227
|
+
*/
|
|
8228
|
+
recordFailure(breaker) {
|
|
8229
|
+
breaker.failures++;
|
|
8230
|
+
breaker.lastFailure = Date.now();
|
|
8231
|
+
if (breaker.failures >= this.FAILURE_THRESHOLD) {
|
|
8232
|
+
breaker.isOpen = true;
|
|
8233
|
+
logger.warn("[Qwen Hybrid] Circuit breaker opened", {
|
|
8234
|
+
failures: breaker.failures
|
|
8235
|
+
});
|
|
8236
|
+
}
|
|
8237
|
+
}
|
|
8238
|
+
/**
|
|
8239
|
+
* Record a success on a circuit breaker
|
|
8240
|
+
*/
|
|
8241
|
+
recordSuccess(breaker) {
|
|
8242
|
+
breaker.failures = 0;
|
|
8243
|
+
breaker.isOpen = false;
|
|
8244
|
+
}
|
|
8245
|
+
/**
|
|
8246
|
+
* Execute a request using the appropriate mode
|
|
8247
|
+
*/
|
|
8248
|
+
async execute(request) {
|
|
8249
|
+
const mode = this.options.mode;
|
|
8250
|
+
if (mode === "sdk") {
|
|
8251
|
+
return this.executeWithSdk(request);
|
|
8252
|
+
}
|
|
8253
|
+
if (mode === "cli") {
|
|
8254
|
+
return this.executeWithCli(request);
|
|
8255
|
+
}
|
|
8256
|
+
return this.executeWithAuto(request);
|
|
8257
|
+
}
|
|
8258
|
+
/**
|
|
8259
|
+
* Execute with SDK only
|
|
8260
|
+
*/
|
|
8261
|
+
async executeWithSdk(request) {
|
|
8262
|
+
const adapter = this.getSdkAdapter();
|
|
8263
|
+
if (!await adapter.isAvailable()) {
|
|
8264
|
+
throw new Error("Qwen SDK is not available. Check DASHSCOPE_API_KEY or QWEN_API_KEY.");
|
|
8265
|
+
}
|
|
8266
|
+
this.activeMode = "sdk";
|
|
8267
|
+
return adapter.execute(request);
|
|
8268
|
+
}
|
|
8269
|
+
/**
|
|
8270
|
+
* Execute with CLI only
|
|
8271
|
+
*/
|
|
8272
|
+
async executeWithCli(request) {
|
|
8273
|
+
const wrapper = this.getCliWrapper();
|
|
8274
|
+
if (!await wrapper.isAvailable()) {
|
|
8275
|
+
throw new Error("Qwen CLI is not available. Run: npm install -g @qwen-code/qwen-code@latest");
|
|
8276
|
+
}
|
|
8277
|
+
this.activeMode = "cli";
|
|
8278
|
+
return wrapper.execute(request);
|
|
8279
|
+
}
|
|
8280
|
+
/**
|
|
8281
|
+
* Execute with automatic mode selection
|
|
8282
|
+
*/
|
|
8283
|
+
async executeWithAuto(request) {
|
|
8284
|
+
if (this.isCircuitClosed(this.sdkCircuitBreaker)) {
|
|
8285
|
+
const adapter = this.getSdkAdapter();
|
|
8286
|
+
try {
|
|
8287
|
+
if (await adapter.isAvailable()) {
|
|
8288
|
+
logger.debug("[Qwen Hybrid] Using SDK mode");
|
|
8289
|
+
this.activeMode = "sdk";
|
|
8290
|
+
const response = await adapter.execute(request);
|
|
8291
|
+
this.recordSuccess(this.sdkCircuitBreaker);
|
|
8292
|
+
return response;
|
|
8293
|
+
}
|
|
8294
|
+
} catch (error) {
|
|
8295
|
+
logger.warn("[Qwen Hybrid] SDK execution failed, trying CLI", {
|
|
8296
|
+
error: error instanceof Error ? error.message : String(error)
|
|
8297
|
+
});
|
|
8298
|
+
this.recordFailure(this.sdkCircuitBreaker);
|
|
8299
|
+
}
|
|
8300
|
+
}
|
|
8301
|
+
if (this.isCircuitClosed(this.cliCircuitBreaker)) {
|
|
8302
|
+
const wrapper = this.getCliWrapper();
|
|
8303
|
+
try {
|
|
8304
|
+
if (await wrapper.isAvailable()) {
|
|
8305
|
+
logger.debug("[Qwen Hybrid] Using CLI mode (fallback)");
|
|
8306
|
+
this.activeMode = "cli";
|
|
8307
|
+
const response = await wrapper.execute(request);
|
|
8308
|
+
this.recordSuccess(this.cliCircuitBreaker);
|
|
8309
|
+
return response;
|
|
8310
|
+
}
|
|
8311
|
+
} catch (error) {
|
|
8312
|
+
logger.error("[Qwen Hybrid] CLI execution also failed", {
|
|
8313
|
+
error: error instanceof Error ? error.message : String(error)
|
|
8314
|
+
});
|
|
8315
|
+
this.recordFailure(this.cliCircuitBreaker);
|
|
8316
|
+
throw error;
|
|
8317
|
+
}
|
|
8318
|
+
}
|
|
8319
|
+
throw new Error(
|
|
8320
|
+
"Qwen execution failed: Both SDK and CLI modes are unavailable or have failed too many times. Ensure DASHSCOPE_API_KEY is set or Qwen CLI is installed."
|
|
8321
|
+
);
|
|
8322
|
+
}
|
|
8323
|
+
/**
|
|
8324
|
+
* Get the currently active execution mode
|
|
8325
|
+
*/
|
|
8326
|
+
getActiveMode() {
|
|
8327
|
+
return this.activeMode;
|
|
8328
|
+
}
|
|
8329
|
+
/**
|
|
8330
|
+
* Reset circuit breakers
|
|
8331
|
+
*/
|
|
8332
|
+
resetCircuitBreakers() {
|
|
8333
|
+
this.sdkCircuitBreaker = { failures: 0, lastFailure: 0, isOpen: false };
|
|
8334
|
+
this.cliCircuitBreaker = { failures: 0, lastFailure: 0, isOpen: false };
|
|
8335
|
+
logger.debug("[Qwen Hybrid] Circuit breakers reset");
|
|
8336
|
+
}
|
|
8337
|
+
/**
|
|
8338
|
+
* Clean up resources
|
|
8339
|
+
*/
|
|
8340
|
+
async destroy() {
|
|
8341
|
+
if (this.sdkAdapter) {
|
|
8342
|
+
await this.sdkAdapter.destroy();
|
|
8343
|
+
this.sdkAdapter = null;
|
|
8344
|
+
}
|
|
8345
|
+
this.cliWrapper = null;
|
|
8346
|
+
this.activeMode = null;
|
|
8347
|
+
logger.debug("[Qwen Hybrid] Adapter destroyed");
|
|
8348
|
+
}
|
|
8349
|
+
};
|
|
8350
|
+
}
|
|
8351
|
+
});
|
|
8352
|
+
|
|
8353
|
+
// src/integrations/qwen-code/index.ts
|
|
8354
|
+
var init_qwen_code = __esm({
|
|
8355
|
+
"src/integrations/qwen-code/index.ts"() {
|
|
8356
|
+
init_esm_shims();
|
|
8357
|
+
init_hybrid_adapter4();
|
|
8358
|
+
init_sdk_adapter4();
|
|
8359
|
+
init_cli_wrapper4();
|
|
8360
|
+
init_types4();
|
|
8361
|
+
}
|
|
8362
|
+
});
|
|
8363
|
+
|
|
8364
|
+
// src/providers/qwen-provider.ts
|
|
8365
|
+
var qwen_provider_exports = {};
|
|
8366
|
+
__export(qwen_provider_exports, {
|
|
8367
|
+
QwenProvider: () => QwenProvider,
|
|
8368
|
+
default: () => QwenProvider
|
|
8369
|
+
});
|
|
8370
|
+
var SUPPORTED_MODELS, QwenProvider;
|
|
8371
|
+
var init_qwen_provider = __esm({
|
|
8372
|
+
"src/providers/qwen-provider.ts"() {
|
|
8373
|
+
init_esm_shims();
|
|
8374
|
+
init_base_provider();
|
|
8375
|
+
init_logger();
|
|
8376
|
+
init_qwen_code();
|
|
8377
|
+
SUPPORTED_MODELS = [
|
|
8378
|
+
"qwen3-coder-480b-a35b-instruct",
|
|
8379
|
+
"qwen3-coder-30b-a3b-instruct",
|
|
8380
|
+
"qwen2.5-coder-32b-instruct",
|
|
8381
|
+
"qwen-max",
|
|
8382
|
+
"qwen-plus",
|
|
8383
|
+
"qwen-turbo"
|
|
8384
|
+
];
|
|
8385
|
+
QwenProvider = class extends BaseProvider {
|
|
8386
|
+
/** Selected model */
|
|
8387
|
+
model;
|
|
8388
|
+
/** SDK adapter for direct execution */
|
|
8389
|
+
sdkAdapter = null;
|
|
8390
|
+
/** Hybrid adapter for 'auto' mode */
|
|
8391
|
+
hybridAdapter = null;
|
|
8392
|
+
/** Provider configuration */
|
|
8393
|
+
qwenConfig;
|
|
8394
|
+
/** Supported models */
|
|
8395
|
+
static SUPPORTED_MODELS = SUPPORTED_MODELS;
|
|
8396
|
+
constructor(config) {
|
|
8397
|
+
super({
|
|
8398
|
+
...config,
|
|
8399
|
+
command: "qwen"
|
|
8400
|
+
});
|
|
8401
|
+
this.qwenConfig = config;
|
|
8402
|
+
const requestedModel = config.model || QWEN_DEFAULT_MODEL;
|
|
8403
|
+
if (!SUPPORTED_MODELS.includes(requestedModel)) {
|
|
8404
|
+
logger.warn(`[Qwen] Unknown model: ${requestedModel}. Using ${QWEN_DEFAULT_MODEL}.`);
|
|
8405
|
+
this.model = QWEN_DEFAULT_MODEL;
|
|
8406
|
+
} else {
|
|
8407
|
+
this.model = requestedModel;
|
|
8408
|
+
}
|
|
8409
|
+
logger.debug("[Qwen Provider] Initialized", {
|
|
8410
|
+
model: this.model,
|
|
8411
|
+
mode: config.mode || "sdk"
|
|
8412
|
+
});
|
|
8413
|
+
}
|
|
8414
|
+
/**
|
|
8415
|
+
* Get the normalized model name
|
|
8416
|
+
*/
|
|
8417
|
+
getNormalizedModel() {
|
|
8418
|
+
return normalizeQwenModel(this.model);
|
|
8419
|
+
}
|
|
8420
|
+
/**
|
|
8421
|
+
* Get or create SDK adapter
|
|
8422
|
+
*/
|
|
8423
|
+
getSdkAdapter() {
|
|
8424
|
+
if (!this.sdkAdapter) {
|
|
8425
|
+
this.sdkAdapter = new QwenSdkAdapter({
|
|
8426
|
+
model: this.model,
|
|
8427
|
+
apiKey: this.qwenConfig.apiKey,
|
|
8428
|
+
baseUrl: this.qwenConfig.baseUrl,
|
|
8429
|
+
timeout: this.qwenConfig.timeout
|
|
8430
|
+
});
|
|
8431
|
+
}
|
|
8432
|
+
return this.sdkAdapter;
|
|
8433
|
+
}
|
|
8434
|
+
/**
|
|
8435
|
+
* Get or create hybrid adapter
|
|
8436
|
+
*/
|
|
8437
|
+
getHybridAdapter() {
|
|
8438
|
+
if (!this.hybridAdapter) {
|
|
8439
|
+
const options = {
|
|
8440
|
+
mode: this.qwenConfig.mode || "auto",
|
|
8441
|
+
model: this.model,
|
|
8442
|
+
apiKey: this.qwenConfig.apiKey,
|
|
8443
|
+
baseUrl: this.qwenConfig.baseUrl,
|
|
8444
|
+
command: "qwen",
|
|
8445
|
+
timeout: this.qwenConfig.timeout
|
|
8446
|
+
};
|
|
8447
|
+
this.hybridAdapter = new QwenHybridAdapter(options);
|
|
8448
|
+
}
|
|
8449
|
+
return this.hybridAdapter;
|
|
8450
|
+
}
|
|
8451
|
+
/**
|
|
8452
|
+
* Execute a task using Qwen
|
|
8453
|
+
*
|
|
8454
|
+
* Execution flow:
|
|
8455
|
+
* 1. Mock mode → return mock response
|
|
8456
|
+
* 2. mode='sdk' (default) → use SDK adapter
|
|
8457
|
+
* 3. mode='auto' → use hybrid adapter (SDK with CLI fallback)
|
|
8458
|
+
* 4. mode='cli' → use CLI via BaseProvider
|
|
8459
|
+
*/
|
|
8460
|
+
async execute(request) {
|
|
8461
|
+
if (process.env.AX_MOCK_PROVIDERS === "true") {
|
|
8462
|
+
return this.createMockResponse(request.prompt);
|
|
8463
|
+
}
|
|
8464
|
+
const effectiveMode = this.qwenConfig.mode || "sdk";
|
|
8465
|
+
if (effectiveMode === "cli") {
|
|
8466
|
+
logger.debug("[Qwen Provider] Executing via CLI", {
|
|
8467
|
+
model: this.model
|
|
8468
|
+
});
|
|
8469
|
+
return super.execute(request);
|
|
8470
|
+
}
|
|
8471
|
+
if (effectiveMode === "auto") {
|
|
8472
|
+
logger.debug("[Qwen Provider] Executing via hybrid adapter", {
|
|
8473
|
+
promptLength: request.prompt.length,
|
|
8474
|
+
model: this.model
|
|
8475
|
+
});
|
|
8476
|
+
const adapter2 = this.getHybridAdapter();
|
|
8477
|
+
return adapter2.execute(request);
|
|
8478
|
+
}
|
|
8479
|
+
logger.debug("[Qwen Provider] Executing via SDK adapter", {
|
|
8480
|
+
promptLength: request.prompt.length,
|
|
8481
|
+
model: this.model
|
|
8482
|
+
});
|
|
8483
|
+
const adapter = this.getSdkAdapter();
|
|
8484
|
+
if (!await adapter.isAvailable()) {
|
|
8485
|
+
throw new Error(
|
|
8486
|
+
'Qwen SDK is not available. Set DASHSCOPE_API_KEY or QWEN_API_KEY environment variable, or use mode: "cli" to use Qwen Code CLI.'
|
|
8487
|
+
);
|
|
8488
|
+
}
|
|
8489
|
+
return adapter.execute(request);
|
|
8490
|
+
}
|
|
8491
|
+
/**
|
|
8492
|
+
* Get CLI command
|
|
8493
|
+
*/
|
|
8494
|
+
getCLICommand() {
|
|
8495
|
+
const activeMode = this.hybridAdapter?.getActiveMode();
|
|
8496
|
+
if (activeMode === "sdk") {
|
|
8497
|
+
return "qwen-sdk";
|
|
8498
|
+
}
|
|
8499
|
+
return "qwen";
|
|
8500
|
+
}
|
|
8501
|
+
/**
|
|
8502
|
+
* Get CLI arguments for Qwen Code CLI
|
|
8503
|
+
*
|
|
8504
|
+
* Note: Qwen Code CLI is interactive by default.
|
|
8505
|
+
* We pass the prompt via stdin instead of command-line args.
|
|
8506
|
+
*/
|
|
8507
|
+
getCLIArgs() {
|
|
8508
|
+
return [];
|
|
8509
|
+
}
|
|
8510
|
+
/**
|
|
8511
|
+
* Create mock response for testing
|
|
8512
|
+
*/
|
|
8513
|
+
createMockResponse(prompt) {
|
|
8514
|
+
return {
|
|
8515
|
+
content: this.getMockResponse(),
|
|
8516
|
+
model: this.getNormalizedModel(),
|
|
8517
|
+
tokensUsed: {
|
|
8518
|
+
prompt: this.estimateTokens(prompt),
|
|
8519
|
+
completion: 50,
|
|
8520
|
+
total: this.estimateTokens(prompt) + 50
|
|
8521
|
+
},
|
|
8522
|
+
latencyMs: 10,
|
|
8523
|
+
finishReason: "stop",
|
|
8524
|
+
cached: false
|
|
8525
|
+
};
|
|
8526
|
+
}
|
|
8527
|
+
/**
|
|
8528
|
+
* Estimate token count
|
|
8529
|
+
*/
|
|
8530
|
+
estimateTokens(text) {
|
|
8531
|
+
return Math.ceil(text.length / 4);
|
|
8532
|
+
}
|
|
8533
|
+
/**
|
|
8534
|
+
* Get mock response for testing
|
|
8535
|
+
*/
|
|
8536
|
+
getMockResponse() {
|
|
8537
|
+
return `[Mock Qwen Response]
|
|
8538
|
+
|
|
8539
|
+
This is a mock response from the Qwen provider (${this.getNormalizedModel()}).
|
|
8540
|
+
In production, this would be a response from ${this.qwenConfig.mode === "sdk" ? "Qwen SDK" : "Qwen Code CLI"}.
|
|
8541
|
+
|
|
8542
|
+
Model: ${this.getNormalizedModel()}
|
|
8543
|
+
Provider: Qwen (Alibaba Cloud)
|
|
8544
|
+
Mode: ${this.qwenConfig.mode || "sdk"}`;
|
|
8545
|
+
}
|
|
8546
|
+
/**
|
|
8547
|
+
* Get provider capabilities
|
|
8548
|
+
*/
|
|
8549
|
+
get capabilities() {
|
|
8550
|
+
const model = this.getNormalizedModel();
|
|
8551
|
+
const hasVision = isVisionModel(model);
|
|
8552
|
+
const maxContextTokens = getModelContextWindow(model);
|
|
8553
|
+
const activeMode = this.hybridAdapter?.getActiveMode();
|
|
8554
|
+
const integrationMode = activeMode === "sdk" ? "sdk" : "cli";
|
|
8555
|
+
return {
|
|
8556
|
+
...super.capabilities,
|
|
8557
|
+
supportsStreaming: true,
|
|
8558
|
+
supportsVision: hasVision,
|
|
8559
|
+
maxContextTokens,
|
|
8560
|
+
supportedModels: SUPPORTED_MODELS,
|
|
8561
|
+
integrationMode
|
|
8562
|
+
};
|
|
8563
|
+
}
|
|
8564
|
+
/**
|
|
8565
|
+
* Get the active execution mode
|
|
8566
|
+
*/
|
|
8567
|
+
getActiveMode() {
|
|
8568
|
+
return this.hybridAdapter?.getActiveMode() || null;
|
|
8569
|
+
}
|
|
8570
|
+
/**
|
|
8571
|
+
* Reset circuit breakers
|
|
8572
|
+
*/
|
|
8573
|
+
resetCircuitBreakers() {
|
|
8574
|
+
this.hybridAdapter?.resetCircuitBreakers();
|
|
8575
|
+
}
|
|
8576
|
+
/**
|
|
8577
|
+
* Clean up resources
|
|
8578
|
+
*/
|
|
8579
|
+
async destroy() {
|
|
8580
|
+
if (this.sdkAdapter) {
|
|
8581
|
+
await this.sdkAdapter.destroy();
|
|
8582
|
+
this.sdkAdapter = null;
|
|
8583
|
+
}
|
|
8584
|
+
if (this.hybridAdapter) {
|
|
8585
|
+
await this.hybridAdapter.destroy();
|
|
8586
|
+
this.hybridAdapter = null;
|
|
8587
|
+
}
|
|
8588
|
+
}
|
|
8589
|
+
/**
|
|
8590
|
+
* Get the list of supported models
|
|
8591
|
+
*/
|
|
8592
|
+
static getSupportedModels() {
|
|
8593
|
+
return [...SUPPORTED_MODELS];
|
|
8594
|
+
}
|
|
8595
|
+
};
|
|
8596
|
+
}
|
|
8597
|
+
});
|
|
8598
|
+
|
|
7681
8599
|
// src/mcp/index.ts
|
|
7682
8600
|
init_esm_shims();
|
|
7683
8601
|
|
|
@@ -8130,12 +9048,16 @@ init_logger();
|
|
|
8130
9048
|
|
|
8131
9049
|
// src/shared/helpers/deep-merge.ts
|
|
8132
9050
|
init_esm_shims();
|
|
9051
|
+
function isPlainObject(value) {
|
|
9052
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && Object.prototype.toString.call(value) === "[object Object]";
|
|
9053
|
+
}
|
|
8133
9054
|
function deepMerge(defaults, user) {
|
|
8134
9055
|
if (user === null || user === void 0) {
|
|
8135
|
-
return defaults;
|
|
9056
|
+
return { ...defaults };
|
|
8136
9057
|
}
|
|
8137
|
-
const result = {
|
|
8138
|
-
|
|
9058
|
+
const result = Object.assign({}, defaults);
|
|
9059
|
+
const userKeys = Object.keys(user);
|
|
9060
|
+
for (const key of userKeys) {
|
|
8139
9061
|
const userValue = user[key];
|
|
8140
9062
|
if (userValue === null) {
|
|
8141
9063
|
result[key] = void 0;
|
|
@@ -8145,8 +9067,11 @@ function deepMerge(defaults, user) {
|
|
|
8145
9067
|
continue;
|
|
8146
9068
|
}
|
|
8147
9069
|
const defaultValue = defaults[key];
|
|
8148
|
-
if (
|
|
8149
|
-
result[key] = deepMerge(
|
|
9070
|
+
if (isPlainObject(userValue) && isPlainObject(defaultValue)) {
|
|
9071
|
+
result[key] = deepMerge(
|
|
9072
|
+
defaultValue,
|
|
9073
|
+
userValue
|
|
9074
|
+
);
|
|
8150
9075
|
} else {
|
|
8151
9076
|
result[key] = userValue;
|
|
8152
9077
|
}
|
|
@@ -8788,7 +9713,7 @@ var PRECOMPILED_CONFIG = {
|
|
|
8788
9713
|
"enableFreeTierPrioritization": true,
|
|
8789
9714
|
"enableWorkloadAwareRouting": true
|
|
8790
9715
|
},
|
|
8791
|
-
"version": "12.
|
|
9716
|
+
"version": "12.7.0"
|
|
8792
9717
|
};
|
|
8793
9718
|
|
|
8794
9719
|
// src/core/config/schemas.ts
|
|
@@ -9221,10 +10146,11 @@ async function loadConfigFile(path9) {
|
|
|
9221
10146
|
if (error instanceof ConfigError) {
|
|
9222
10147
|
throw error;
|
|
9223
10148
|
}
|
|
9224
|
-
|
|
10149
|
+
const nodeError = error;
|
|
10150
|
+
if (nodeError.code === "ENOENT") {
|
|
9225
10151
|
throw ConfigError.notFound(path9);
|
|
9226
10152
|
}
|
|
9227
|
-
if (
|
|
10153
|
+
if (nodeError.code === "EACCES") {
|
|
9228
10154
|
throw new ConfigError(
|
|
9229
10155
|
`Permission denied reading config: ${path9}`,
|
|
9230
10156
|
"E1002" /* CONFIG_PARSE_ERROR */,
|
|
@@ -13211,7 +14137,7 @@ var MemoryManager = class _MemoryManager {
|
|
|
13211
14137
|
if (this.db) {
|
|
13212
14138
|
try {
|
|
13213
14139
|
this.db.close();
|
|
13214
|
-
} catch
|
|
14140
|
+
} catch {
|
|
13215
14141
|
}
|
|
13216
14142
|
this.initialized = false;
|
|
13217
14143
|
this.entryCount = 0;
|
|
@@ -14052,9 +14978,9 @@ var MemoryManager = class _MemoryManager {
|
|
|
14052
14978
|
}
|
|
14053
14979
|
}
|
|
14054
14980
|
const {
|
|
14055
|
-
includeEmbeddings = false,
|
|
14981
|
+
includeEmbeddings: _includeEmbeddings = false,
|
|
14056
14982
|
filters = {},
|
|
14057
|
-
batchSize = 1e3,
|
|
14983
|
+
batchSize: _batchSize = 1e3,
|
|
14058
14984
|
pretty = false
|
|
14059
14985
|
} = options || {};
|
|
14060
14986
|
try {
|
|
@@ -15211,7 +16137,7 @@ var SessionManager = class _SessionManager {
|
|
|
15211
16137
|
if (this.pendingSave) {
|
|
15212
16138
|
try {
|
|
15213
16139
|
await this.pendingSave;
|
|
15214
|
-
} catch
|
|
16140
|
+
} catch {
|
|
15215
16141
|
}
|
|
15216
16142
|
}
|
|
15217
16143
|
this.pendingSave = this.doSave().finally(() => {
|
|
@@ -15279,7 +16205,7 @@ var SessionManager = class _SessionManager {
|
|
|
15279
16205
|
}
|
|
15280
16206
|
try {
|
|
15281
16207
|
await unlink(tempPath);
|
|
15282
|
-
} catch
|
|
16208
|
+
} catch {
|
|
15283
16209
|
}
|
|
15284
16210
|
throw renameError;
|
|
15285
16211
|
}
|
|
@@ -15287,7 +16213,7 @@ var SessionManager = class _SessionManager {
|
|
|
15287
16213
|
const tempPath = `${this.persistencePath}.tmp`;
|
|
15288
16214
|
try {
|
|
15289
16215
|
await unlink(tempPath);
|
|
15290
|
-
} catch
|
|
16216
|
+
} catch {
|
|
15291
16217
|
}
|
|
15292
16218
|
logger.error("Failed to save sessions to persistence", {
|
|
15293
16219
|
path: normalizePath(this.persistencePath),
|
|
@@ -15825,6 +16751,7 @@ init_esm_shims();
|
|
|
15825
16751
|
init_logger();
|
|
15826
16752
|
var MAX_CONTEXT_SIZE = 100 * 1024;
|
|
15827
16753
|
var DEFAULT_CACHE_TTL = 3e5;
|
|
16754
|
+
var STALE_THRESHOLD_MS = 24 * 60 * 60 * 1e3;
|
|
15828
16755
|
var ProjectContextLoader = class {
|
|
15829
16756
|
constructor(projectRoot, options) {
|
|
15830
16757
|
this.projectRoot = projectRoot;
|
|
@@ -15848,76 +16775,79 @@ var ProjectContextLoader = class {
|
|
|
15848
16775
|
});
|
|
15849
16776
|
const context = {};
|
|
15850
16777
|
try {
|
|
15851
|
-
const
|
|
15852
|
-
const resolvedPath = await realpath(
|
|
16778
|
+
const indexPath = path4__default.join(this.projectRoot, "ax.index.json");
|
|
16779
|
+
const resolvedPath = await realpath(indexPath).catch(() => null);
|
|
15853
16780
|
if (resolvedPath) {
|
|
15854
16781
|
const rel = path4__default.relative(this.projectRoot, resolvedPath);
|
|
15855
16782
|
if (!rel.startsWith("..") && !path4__default.isAbsolute(rel)) {
|
|
15856
16783
|
const stats = await stat(resolvedPath);
|
|
15857
16784
|
if (stats.size > MAX_CONTEXT_SIZE) {
|
|
15858
|
-
logger.warn("
|
|
16785
|
+
logger.warn("ax.index.json too large, ignoring", {
|
|
15859
16786
|
size: stats.size,
|
|
15860
16787
|
limit: MAX_CONTEXT_SIZE
|
|
15861
16788
|
});
|
|
15862
16789
|
} else {
|
|
15863
|
-
|
|
15864
|
-
|
|
15865
|
-
|
|
15866
|
-
|
|
16790
|
+
const indexContent = await readFile(resolvedPath, "utf-8");
|
|
16791
|
+
context.index = JSON.parse(indexContent);
|
|
16792
|
+
context.lastUpdated = stats.mtime;
|
|
16793
|
+
const age = Date.now() - stats.mtime.getTime();
|
|
16794
|
+
context.isStale = age > STALE_THRESHOLD_MS;
|
|
16795
|
+
logger.info("Loaded ax.index.json", {
|
|
16796
|
+
projectName: context.index.projectName,
|
|
16797
|
+
projectType: context.index.projectType,
|
|
16798
|
+
isStale: context.isStale,
|
|
16799
|
+
ageHours: Math.floor(age / (1e3 * 60 * 60))
|
|
15867
16800
|
});
|
|
15868
|
-
|
|
15869
|
-
|
|
15870
|
-
|
|
15871
|
-
|
|
16801
|
+
if (context.index.commands) {
|
|
16802
|
+
context.commands = {};
|
|
16803
|
+
for (const [name, cmd] of Object.entries(context.index.commands)) {
|
|
16804
|
+
context.commands[name] = cmd.script;
|
|
16805
|
+
}
|
|
16806
|
+
}
|
|
15872
16807
|
}
|
|
15873
16808
|
}
|
|
15874
16809
|
}
|
|
15875
16810
|
} catch (error) {
|
|
15876
16811
|
if (error && typeof error === "object" && "code" in error && error.code !== "ENOENT") {
|
|
15877
|
-
logger.warn("Error loading
|
|
16812
|
+
logger.warn("Error loading ax.index.json", { error });
|
|
15878
16813
|
}
|
|
15879
16814
|
}
|
|
15880
16815
|
try {
|
|
15881
|
-
const
|
|
15882
|
-
const resolvedPath = await realpath(
|
|
16816
|
+
const customMdPath = path4__default.join(this.projectRoot, ".automatosx", "CUSTOM.md");
|
|
16817
|
+
const resolvedPath = await realpath(customMdPath).catch(() => null);
|
|
15883
16818
|
if (resolvedPath) {
|
|
15884
16819
|
const rel = path4__default.relative(this.projectRoot, resolvedPath);
|
|
15885
16820
|
if (!rel.startsWith("..") && !path4__default.isAbsolute(rel)) {
|
|
15886
16821
|
const stats = await stat(resolvedPath);
|
|
15887
16822
|
if (stats.size > MAX_CONTEXT_SIZE) {
|
|
15888
|
-
logger.warn("
|
|
16823
|
+
logger.warn("CUSTOM.md too large, ignoring", {
|
|
15889
16824
|
size: stats.size,
|
|
15890
16825
|
limit: MAX_CONTEXT_SIZE
|
|
15891
16826
|
});
|
|
15892
16827
|
} else {
|
|
15893
|
-
|
|
15894
|
-
|
|
15895
|
-
|
|
15896
|
-
|
|
16828
|
+
context.customInstructions = await readFile(resolvedPath, "utf-8");
|
|
16829
|
+
logger.info("Loaded CUSTOM.md", {
|
|
16830
|
+
size: stats.size,
|
|
16831
|
+
lines: context.customInstructions.split("\n").length
|
|
15897
16832
|
});
|
|
15898
|
-
|
|
15899
|
-
context.commands = { ...context.commands, ...context.config.commands };
|
|
15900
|
-
}
|
|
15901
|
-
if (context.config.project) {
|
|
15902
|
-
context.metadata = { ...context.metadata, ...context.config.project };
|
|
15903
|
-
}
|
|
16833
|
+
context.guardrails = this.parseGuardrails(context.customInstructions);
|
|
15904
16834
|
}
|
|
15905
16835
|
}
|
|
15906
16836
|
}
|
|
15907
16837
|
} catch (error) {
|
|
15908
16838
|
if (error && typeof error === "object" && "code" in error && error.code !== "ENOENT") {
|
|
15909
|
-
logger.warn("Error loading
|
|
16839
|
+
logger.warn("Error loading CUSTOM.md", { error });
|
|
15910
16840
|
}
|
|
15911
16841
|
}
|
|
15912
16842
|
context.contextPrompt = this.buildContextPrompt(context);
|
|
15913
16843
|
this.cache = context;
|
|
15914
16844
|
this.cacheExpiry = Date.now() + this.cacheTTL;
|
|
15915
16845
|
logger.info("Project context loaded", {
|
|
15916
|
-
|
|
15917
|
-
|
|
15918
|
-
agentRules: context.agentRules?.length ?? 0,
|
|
16846
|
+
hasIndex: !!context.index,
|
|
16847
|
+
hasCustomInstructions: !!context.customInstructions,
|
|
15919
16848
|
guardrails: context.guardrails?.length ?? 0,
|
|
15920
|
-
commands: Object.keys(context.commands ?? {}).length
|
|
16849
|
+
commands: Object.keys(context.commands ?? {}).length,
|
|
16850
|
+
isStale: context.isStale
|
|
15921
16851
|
});
|
|
15922
16852
|
return context;
|
|
15923
16853
|
}
|
|
@@ -15933,8 +16863,8 @@ var ProjectContextLoader = class {
|
|
|
15933
16863
|
* Check if context exists (without loading)
|
|
15934
16864
|
*/
|
|
15935
16865
|
async exists() {
|
|
15936
|
-
const
|
|
15937
|
-
const
|
|
16866
|
+
const indexPath = path4__default.join(this.projectRoot, "ax.index.json");
|
|
16867
|
+
const customMdPath = path4__default.join(this.projectRoot, ".automatosx", "CUSTOM.md");
|
|
15938
16868
|
const checkExists = async (filePath) => {
|
|
15939
16869
|
try {
|
|
15940
16870
|
await access(filePath, constants.F_OK);
|
|
@@ -15943,57 +16873,48 @@ var ProjectContextLoader = class {
|
|
|
15943
16873
|
return false;
|
|
15944
16874
|
}
|
|
15945
16875
|
};
|
|
15946
|
-
const [
|
|
15947
|
-
checkExists(
|
|
15948
|
-
checkExists(
|
|
16876
|
+
const [indexExists, customMdExists] = await Promise.all([
|
|
16877
|
+
checkExists(indexPath),
|
|
16878
|
+
checkExists(customMdPath)
|
|
15949
16879
|
]);
|
|
15950
|
-
return
|
|
16880
|
+
return indexExists || customMdExists;
|
|
15951
16881
|
}
|
|
15952
16882
|
/**
|
|
15953
|
-
*
|
|
15954
|
-
|
|
15955
|
-
|
|
15956
|
-
|
|
15957
|
-
|
|
15958
|
-
|
|
15959
|
-
|
|
15960
|
-
|
|
15961
|
-
|
|
15962
|
-
|
|
15963
|
-
if (!match || !match[1]) {
|
|
15964
|
-
return rules;
|
|
15965
|
-
}
|
|
15966
|
-
const section = match[1];
|
|
15967
|
-
const lineRegex = /^[-*]\s+(.+?)\s+(?:→|->)+\s+(.+?)$/gm;
|
|
15968
|
-
let lineMatch;
|
|
15969
|
-
while ((lineMatch = lineRegex.exec(section)) !== null) {
|
|
15970
|
-
const taskType = lineMatch[1]?.trim() ?? "";
|
|
15971
|
-
const agentsText = lineMatch[2]?.trim() ?? "";
|
|
15972
|
-
const agents = agentsText.split(",").map((a) => a.trim()).filter(Boolean);
|
|
15973
|
-
const defaultAgent = agents[0];
|
|
15974
|
-
if (defaultAgent) {
|
|
15975
|
-
rules.push({
|
|
15976
|
-
taskType,
|
|
15977
|
-
patterns: [],
|
|
15978
|
-
// TODO: Parse file patterns if specified
|
|
15979
|
-
defaultAgent,
|
|
15980
|
-
autoReview: agents.length > 1
|
|
15981
|
-
});
|
|
15982
|
-
}
|
|
16883
|
+
* Check if ax.index.json is stale (older than 24 hours)
|
|
16884
|
+
*/
|
|
16885
|
+
async isStale() {
|
|
16886
|
+
try {
|
|
16887
|
+
const indexPath = path4__default.join(this.projectRoot, "ax.index.json");
|
|
16888
|
+
const stats = await stat(indexPath);
|
|
16889
|
+
const age = Date.now() - stats.mtime.getTime();
|
|
16890
|
+
return age > STALE_THRESHOLD_MS;
|
|
16891
|
+
} catch {
|
|
16892
|
+
return true;
|
|
15983
16893
|
}
|
|
15984
|
-
return rules;
|
|
15985
16894
|
}
|
|
15986
16895
|
/**
|
|
15987
|
-
* Parse guardrails
|
|
16896
|
+
* Parse guardrails from CUSTOM.md
|
|
15988
16897
|
*
|
|
15989
|
-
* Looks for
|
|
15990
|
-
* Extracts items marked with ⚠️ or under NEVER headings
|
|
16898
|
+
* Looks for DO/DON'T sections in ax-cli format
|
|
15991
16899
|
*/
|
|
15992
16900
|
parseGuardrails(markdown) {
|
|
15993
16901
|
const guardrails = [];
|
|
15994
|
-
const
|
|
16902
|
+
const dontRegex = /###\s+DON'T[^\n]*\n([\s\S]*?)(?=\n###|$)/i;
|
|
16903
|
+
const dontMatch = markdown.match(dontRegex);
|
|
16904
|
+
if (dontMatch && dontMatch[1]) {
|
|
16905
|
+
const section = dontMatch[1];
|
|
16906
|
+
const bulletRegex = /^[-*]\s+(.+?)$/gm;
|
|
16907
|
+
let bulletMatch;
|
|
16908
|
+
while ((bulletMatch = bulletRegex.exec(section)) !== null) {
|
|
16909
|
+
const rule = bulletMatch[1]?.trim();
|
|
16910
|
+
if (rule) {
|
|
16911
|
+
guardrails.push(rule);
|
|
16912
|
+
}
|
|
16913
|
+
}
|
|
16914
|
+
}
|
|
16915
|
+
const criticalRegex = /##\s+(Critical\s+Guardrails|Critical\s+Rules|Never)[^\n]*\n([\s\S]*?)(?=\n##|$)/gi;
|
|
15995
16916
|
let match;
|
|
15996
|
-
while ((match =
|
|
16917
|
+
while ((match = criticalRegex.exec(markdown)) !== null) {
|
|
15997
16918
|
const section = match[2];
|
|
15998
16919
|
if (!section) continue;
|
|
15999
16920
|
const bulletRegex = /^[-*]\s+(.+?)$/gm;
|
|
@@ -16003,106 +16924,58 @@ var ProjectContextLoader = class {
|
|
|
16003
16924
|
rule = rule.replace(/^[⚠️❌✅✓⚡🔒]+\s*/, "");
|
|
16004
16925
|
rule = rule.replace(/\*\*(.+?)\*\*/g, "$1");
|
|
16005
16926
|
rule = rule.replace(/`(.+?)`/g, "$1");
|
|
16006
|
-
if (rule.length > 0) {
|
|
16927
|
+
if (rule.length > 0 && !guardrails.includes(rule)) {
|
|
16007
16928
|
guardrails.push(rule);
|
|
16008
16929
|
}
|
|
16009
16930
|
}
|
|
16010
16931
|
}
|
|
16011
16932
|
return guardrails;
|
|
16012
16933
|
}
|
|
16013
|
-
/**
|
|
16014
|
-
* Parse commands from markdown code blocks
|
|
16015
|
-
*
|
|
16016
|
-
* Looks for "## Commands" or "## Canonical Commands" section
|
|
16017
|
-
*/
|
|
16018
|
-
parseCommands(markdown) {
|
|
16019
|
-
const commands = {};
|
|
16020
|
-
const sectionRegex = /##\s+(Canonical\s+)?Commands[^\n]*\n([\s\S]*?)(?=\n##|$)/i;
|
|
16021
|
-
const match = markdown.match(sectionRegex);
|
|
16022
|
-
if (!match) {
|
|
16023
|
-
return commands;
|
|
16024
|
-
}
|
|
16025
|
-
const section = match[2];
|
|
16026
|
-
if (!section) {
|
|
16027
|
-
return commands;
|
|
16028
|
-
}
|
|
16029
|
-
const codeBlockRegex = /```(?:bash|sh|shell)?\n([\s\S]*?)```/;
|
|
16030
|
-
const codeMatch = section.match(codeBlockRegex);
|
|
16031
|
-
if (codeMatch && codeMatch[1]) {
|
|
16032
|
-
const lines = codeMatch[1].split("\n");
|
|
16033
|
-
for (const line of lines) {
|
|
16034
|
-
const cmdMatch = line.match(/^([^\s#]+(?:\s+[^\s#]+)*)\s*#?\s*(.*)$/);
|
|
16035
|
-
if (cmdMatch && cmdMatch[1]) {
|
|
16036
|
-
const cmd = cmdMatch[1].trim();
|
|
16037
|
-
const desc = cmdMatch[2]?.trim() ?? "";
|
|
16038
|
-
const key = desc || cmd;
|
|
16039
|
-
commands[key] = cmd;
|
|
16040
|
-
}
|
|
16041
|
-
}
|
|
16042
|
-
}
|
|
16043
|
-
return commands;
|
|
16044
|
-
}
|
|
16045
|
-
/**
|
|
16046
|
-
* Parse project metadata from markdown frontmatter or first section
|
|
16047
|
-
*/
|
|
16048
|
-
parseMetadata(markdown) {
|
|
16049
|
-
const metadata = {};
|
|
16050
|
-
const lastUpdatedMatch = markdown.match(/>\s*Last\s+updated:\s*(.+?)$/im);
|
|
16051
|
-
if (lastUpdatedMatch && lastUpdatedMatch[1]) {
|
|
16052
|
-
metadata.lastUpdated = lastUpdatedMatch[1].trim();
|
|
16053
|
-
}
|
|
16054
|
-
const projectMatch = markdown.match(/>\s*Project:\s*(.+?)$/im);
|
|
16055
|
-
if (projectMatch && projectMatch[1]) {
|
|
16056
|
-
const parts = projectMatch[1].trim().split(/\s+v/);
|
|
16057
|
-
metadata.name = parts[0] || "";
|
|
16058
|
-
if (parts.length > 1 && parts[1]) {
|
|
16059
|
-
metadata.version = parts[1];
|
|
16060
|
-
}
|
|
16061
|
-
}
|
|
16062
|
-
const h1Match = markdown.match(/^#\s+(.+?)$/m);
|
|
16063
|
-
if (h1Match && h1Match[1] && !metadata.name) {
|
|
16064
|
-
metadata.name = h1Match[1].replace(/Project Context for AutomatosX/i, "").trim();
|
|
16065
|
-
}
|
|
16066
|
-
return metadata;
|
|
16067
|
-
}
|
|
16068
16934
|
/**
|
|
16069
16935
|
* Build formatted context prompt for agent injection
|
|
16070
16936
|
*/
|
|
16071
16937
|
buildContextPrompt(context) {
|
|
16072
|
-
if (!context.
|
|
16938
|
+
if (!context.index && !context.customInstructions) {
|
|
16073
16939
|
return "";
|
|
16074
16940
|
}
|
|
16075
16941
|
let prompt = "\n# PROJECT CONTEXT\n\n";
|
|
16076
|
-
if (context.
|
|
16077
|
-
prompt +=
|
|
16078
|
-
context.guardrails.forEach((rule) => {
|
|
16079
|
-
prompt += `- ${rule}
|
|
16942
|
+
if (context.index) {
|
|
16943
|
+
prompt += `**Project:** ${context.index.projectName} v${context.index.version}
|
|
16080
16944
|
`;
|
|
16081
|
-
}
|
|
16082
|
-
prompt += "\n";
|
|
16083
|
-
}
|
|
16084
|
-
if (context.agentRules && context.agentRules.length > 0) {
|
|
16085
|
-
prompt += "## Agent Delegation Rules:\n\n";
|
|
16086
|
-
context.agentRules.forEach((rule) => {
|
|
16087
|
-
prompt += `- ${rule.taskType} \u2192 ${rule.defaultAgent}
|
|
16945
|
+
prompt += `**Type:** ${context.index.projectType}
|
|
16088
16946
|
`;
|
|
16089
|
-
}
|
|
16090
|
-
|
|
16947
|
+
prompt += `**Language:** ${context.index.language}`;
|
|
16948
|
+
if (context.index.framework) {
|
|
16949
|
+
prompt += ` + ${context.index.framework}`;
|
|
16950
|
+
}
|
|
16951
|
+
prompt += "\n\n";
|
|
16952
|
+
if (context.index.modules.length > 0) {
|
|
16953
|
+
prompt += "## Project Structure:\n\n";
|
|
16954
|
+
for (const mod of context.index.modules.slice(0, 10)) {
|
|
16955
|
+
prompt += `- \`${mod.path}/\` - ${mod.purpose}
|
|
16956
|
+
`;
|
|
16957
|
+
}
|
|
16958
|
+
prompt += "\n";
|
|
16959
|
+
}
|
|
16960
|
+
if (context.commands && Object.keys(context.commands).length > 0) {
|
|
16961
|
+
prompt += "## Available Commands:\n\n";
|
|
16962
|
+
for (const [name, script] of Object.entries(context.commands).slice(0, 10)) {
|
|
16963
|
+
prompt += `- ${name}: \`${script}\`
|
|
16964
|
+
`;
|
|
16965
|
+
}
|
|
16966
|
+
prompt += "\n";
|
|
16967
|
+
}
|
|
16091
16968
|
}
|
|
16092
|
-
if (context.
|
|
16093
|
-
prompt += "##
|
|
16094
|
-
|
|
16095
|
-
prompt += `- ${
|
|
16969
|
+
if (context.guardrails && context.guardrails.length > 0) {
|
|
16970
|
+
prompt += "## CRITICAL RULES (NEVER VIOLATE):\n\n";
|
|
16971
|
+
for (const rule of context.guardrails) {
|
|
16972
|
+
prompt += `- ${rule}
|
|
16096
16973
|
`;
|
|
16097
|
-
}
|
|
16974
|
+
}
|
|
16098
16975
|
prompt += "\n";
|
|
16099
16976
|
}
|
|
16100
|
-
if (context.
|
|
16101
|
-
|
|
16102
|
-
const contextToAdd = context.markdown.length > MAX_PROMPT_LENGTH ? context.markdown.substring(0, MAX_PROMPT_LENGTH) + "\n\n[... context truncated for length ...]" : context.markdown;
|
|
16103
|
-
prompt += "## Full Project Context:\n\n";
|
|
16104
|
-
prompt += contextToAdd;
|
|
16105
|
-
prompt += "\n";
|
|
16977
|
+
if (context.isStale) {
|
|
16978
|
+
prompt += "\u26A0\uFE0F **Note:** Project index is stale (>24h old). Run `ax init` to update.\n\n";
|
|
16106
16979
|
}
|
|
16107
16980
|
return prompt;
|
|
16108
16981
|
}
|
|
@@ -16526,10 +17399,10 @@ var ContextManager = class {
|
|
|
16526
17399
|
return provider;
|
|
16527
17400
|
}
|
|
16528
17401
|
/**
|
|
16529
|
-
* Load project context from
|
|
17402
|
+
* Load project context from ax.index.json (v12.9.0+)
|
|
16530
17403
|
*
|
|
16531
|
-
* Loads project-specific
|
|
16532
|
-
* Falls back gracefully if
|
|
17404
|
+
* Loads project-specific context from ax.index.json and CUSTOM.md.
|
|
17405
|
+
* Falls back gracefully if files don't exist.
|
|
16533
17406
|
*
|
|
16534
17407
|
* @param projectDir - Project root directory
|
|
16535
17408
|
* @returns Project context or null if not found
|
|
@@ -16542,15 +17415,15 @@ var ContextManager = class {
|
|
|
16542
17415
|
const loader = this.projectContextLoader;
|
|
16543
17416
|
const exists = await loader.exists();
|
|
16544
17417
|
if (!exists) {
|
|
16545
|
-
logger.debug("No
|
|
17418
|
+
logger.debug("No ax.index.json or CUSTOM.md found, skipping project context");
|
|
16546
17419
|
return null;
|
|
16547
17420
|
}
|
|
16548
17421
|
const context = await loader.load();
|
|
16549
|
-
logger.debug("Project context loaded
|
|
16550
|
-
|
|
16551
|
-
|
|
16552
|
-
|
|
16553
|
-
|
|
17422
|
+
logger.debug("Project context loaded", {
|
|
17423
|
+
hasIndex: !!context.index,
|
|
17424
|
+
hasCustomInstructions: !!context.customInstructions,
|
|
17425
|
+
guardrails: context.guardrails?.length ?? 0,
|
|
17426
|
+
isStale: context.isStale
|
|
16554
17427
|
});
|
|
16555
17428
|
return context;
|
|
16556
17429
|
} catch (error) {
|
|
@@ -16798,6 +17671,1374 @@ function getPackageRoot(startDir) {
|
|
|
16798
17671
|
return startDir || __dirname3;
|
|
16799
17672
|
}
|
|
16800
17673
|
|
|
17674
|
+
// src/agents/cognitive/prompt-composer.ts
|
|
17675
|
+
init_esm_shims();
|
|
17676
|
+
|
|
17677
|
+
// src/agents/cognitive/reasoning-scaffolds.ts
|
|
17678
|
+
init_esm_shims();
|
|
17679
|
+
var PROVER_STEPS = [
|
|
17680
|
+
{
|
|
17681
|
+
id: "1_intake",
|
|
17682
|
+
name: "INTAKE",
|
|
17683
|
+
description: "Understand before acting",
|
|
17684
|
+
requiredActions: [
|
|
17685
|
+
"Restate the goal, constraints, and success criteria in your own words",
|
|
17686
|
+
"Read relevant files and cite them (path:line) - do NOT hypothesize without evidence",
|
|
17687
|
+
"List your assumptions and unknowns explicitly",
|
|
17688
|
+
"If blockers exist that prevent progress, ask 1-3 focused clarifying questions"
|
|
17689
|
+
],
|
|
17690
|
+
skipWhen: ["Task is trivial and self-explanatory"]
|
|
17691
|
+
},
|
|
17692
|
+
{
|
|
17693
|
+
id: "2_risk_scan",
|
|
17694
|
+
name: "RISK SCAN",
|
|
17695
|
+
description: "Anticipate failure modes before they occur",
|
|
17696
|
+
requiredActions: [
|
|
17697
|
+
"Run through your domain-specific checklist (see DOMAIN CHECKLIST section)",
|
|
17698
|
+
"Flag any high-risk items explicitly with [RISK] tag",
|
|
17699
|
+
"Propose mitigations for critical risks before proceeding",
|
|
17700
|
+
"If risks are unacceptable, STOP and discuss with user"
|
|
17701
|
+
]
|
|
17702
|
+
},
|
|
17703
|
+
{
|
|
17704
|
+
id: "3_options",
|
|
17705
|
+
name: "OPTIONS",
|
|
17706
|
+
description: "Consider alternatives before committing",
|
|
17707
|
+
requiredActions: [
|
|
17708
|
+
"Generate 2-3 viable approaches (skip only if truly trivial)",
|
|
17709
|
+
"Compare each against: complexity, performance, risk, maintainability",
|
|
17710
|
+
"Choose one approach with explicit rationale",
|
|
17711
|
+
"Document what was rejected and why (prevents revisiting)"
|
|
17712
|
+
],
|
|
17713
|
+
skipWhen: ["Single obvious solution exists", "Task is a simple bug fix"]
|
|
17714
|
+
},
|
|
17715
|
+
{
|
|
17716
|
+
id: "4_plan",
|
|
17717
|
+
name: "PLAN",
|
|
17718
|
+
description: "Decompose before executing",
|
|
17719
|
+
requiredActions: [
|
|
17720
|
+
"Break work into ordered steps (even if small)",
|
|
17721
|
+
"Identify dependencies between steps",
|
|
17722
|
+
"Note which steps are reversible vs. irreversible",
|
|
17723
|
+
'For trivial tasks: "Plan: Single-step execution"'
|
|
17724
|
+
]
|
|
17725
|
+
},
|
|
17726
|
+
{
|
|
17727
|
+
id: "5_execute",
|
|
17728
|
+
name: "EXECUTE",
|
|
17729
|
+
description: "Implement with discipline",
|
|
17730
|
+
requiredActions: [
|
|
17731
|
+
"Follow the plan step-by-step",
|
|
17732
|
+
"Cite existing patterns in codebase when applicable",
|
|
17733
|
+
"Keep changes minimal and focused - resist scope creep",
|
|
17734
|
+
"Document non-obvious decisions with brief inline comments",
|
|
17735
|
+
"If blocked during execution, update plan rather than improvising"
|
|
17736
|
+
]
|
|
17737
|
+
},
|
|
17738
|
+
{
|
|
17739
|
+
id: "6_validate",
|
|
17740
|
+
name: "VALIDATE",
|
|
17741
|
+
description: "Verify before delivering - never ship unvalidated work",
|
|
17742
|
+
requiredActions: [
|
|
17743
|
+
"Run verification commands (typecheck, tests, lint)",
|
|
17744
|
+
"State explicitly what WAS validated",
|
|
17745
|
+
"State explicitly what was NOT validated (gaps)",
|
|
17746
|
+
"Note residual risks that remain after validation",
|
|
17747
|
+
"If validation fails, diagnose and fix before reporting"
|
|
17748
|
+
]
|
|
17749
|
+
},
|
|
17750
|
+
{
|
|
17751
|
+
id: "7_report",
|
|
17752
|
+
name: "REPORT",
|
|
17753
|
+
description: "Structured delivery with full transparency",
|
|
17754
|
+
requiredActions: [
|
|
17755
|
+
"Use the OUTPUT FORMAT structure (see OUTPUT FORMAT section)",
|
|
17756
|
+
"Be concise but complete - no hand-waving",
|
|
17757
|
+
"Include file references with paths for all changes",
|
|
17758
|
+
"Specify concrete follow-up actions if any"
|
|
17759
|
+
]
|
|
17760
|
+
}
|
|
17761
|
+
];
|
|
17762
|
+
var PROVER_TEMPLATE = `## MANDATORY REASONING LOOP (PROVER)
|
|
17763
|
+
|
|
17764
|
+
For EVERY task, follow this sequence. Skipping steps leads to mistakes.
|
|
17765
|
+
|
|
17766
|
+
### 1. INTAKE (before touching code)
|
|
17767
|
+
**Purpose**: Understand before acting
|
|
17768
|
+
|
|
17769
|
+
- **Restate**: Goal, constraints, success criteria in your own words
|
|
17770
|
+
- **Recon**: Read relevant files (cite \`path:line\`) - do NOT hypothesize without evidence
|
|
17771
|
+
- **Unknowns**: List assumptions explicitly
|
|
17772
|
+
- **Blockers**: If blockers exist, ask 1-3 focused clarifying questions
|
|
17773
|
+
|
|
17774
|
+
### 2. RISK SCAN
|
|
17775
|
+
**Purpose**: Anticipate failure modes
|
|
17776
|
+
|
|
17777
|
+
- Run through your DOMAIN CHECKLIST (see below)
|
|
17778
|
+
- Flag high-risk items with [RISK] tag
|
|
17779
|
+
- Propose mitigations for critical risks
|
|
17780
|
+
- If risks are unacceptable, STOP and discuss
|
|
17781
|
+
|
|
17782
|
+
### 3. OPTIONS (skip if truly trivial)
|
|
17783
|
+
**Purpose**: Consider alternatives before committing
|
|
17784
|
+
|
|
17785
|
+
- Generate 2-3 viable approaches
|
|
17786
|
+
- Compare: complexity, performance, risk, maintainability
|
|
17787
|
+
- Choose one with explicit rationale
|
|
17788
|
+
- Note what was rejected and why
|
|
17789
|
+
|
|
17790
|
+
### 4. PLAN
|
|
17791
|
+
**Purpose**: Decompose before executing
|
|
17792
|
+
|
|
17793
|
+
- Break work into ordered steps
|
|
17794
|
+
- Identify dependencies between steps
|
|
17795
|
+
- Note reversible vs. irreversible steps
|
|
17796
|
+
- For trivial tasks: "Plan: Single-step execution"
|
|
17797
|
+
|
|
17798
|
+
### 5. EXECUTE
|
|
17799
|
+
**Purpose**: Implement with discipline
|
|
17800
|
+
|
|
17801
|
+
- Follow plan step-by-step
|
|
17802
|
+
- Cite existing patterns in codebase
|
|
17803
|
+
- Keep changes minimal - resist scope creep
|
|
17804
|
+
- If blocked, update plan rather than improvising
|
|
17805
|
+
|
|
17806
|
+
### 6. VALIDATE
|
|
17807
|
+
**Purpose**: Never ship unvalidated work
|
|
17808
|
+
|
|
17809
|
+
- Run: typecheck, tests, lint (as applicable)
|
|
17810
|
+
- State what WAS validated
|
|
17811
|
+
- State what was NOT validated (gaps)
|
|
17812
|
+
- If validation fails, fix before reporting
|
|
17813
|
+
|
|
17814
|
+
### 7. REPORT
|
|
17815
|
+
**Purpose**: Structured delivery
|
|
17816
|
+
|
|
17817
|
+
- Use the OUTPUT FORMAT structure
|
|
17818
|
+
- Include file paths for all changes
|
|
17819
|
+
- Specify follow-up actions
|
|
17820
|
+
|
|
17821
|
+
---
|
|
17822
|
+
|
|
17823
|
+
**CRITICAL**: If uncertain at any step, ASK rather than assume.
|
|
17824
|
+
If proceeding with assumptions, LIST THEM EXPLICITLY.
|
|
17825
|
+
`;
|
|
17826
|
+
var LITE_STEPS = [
|
|
17827
|
+
{
|
|
17828
|
+
id: "1_understand",
|
|
17829
|
+
name: "UNDERSTAND",
|
|
17830
|
+
description: "Quick comprehension",
|
|
17831
|
+
requiredActions: [
|
|
17832
|
+
"Confirm what needs to be done",
|
|
17833
|
+
"Check relevant file if needed"
|
|
17834
|
+
]
|
|
17835
|
+
},
|
|
17836
|
+
{
|
|
17837
|
+
id: "2_do",
|
|
17838
|
+
name: "DO",
|
|
17839
|
+
description: "Execute the task",
|
|
17840
|
+
requiredActions: [
|
|
17841
|
+
"Make the change",
|
|
17842
|
+
"Follow existing patterns"
|
|
17843
|
+
]
|
|
17844
|
+
},
|
|
17845
|
+
{
|
|
17846
|
+
id: "3_verify",
|
|
17847
|
+
name: "VERIFY",
|
|
17848
|
+
description: "Quick validation",
|
|
17849
|
+
requiredActions: [
|
|
17850
|
+
"Run typecheck/tests if applicable",
|
|
17851
|
+
"Note if verification was skipped and why"
|
|
17852
|
+
]
|
|
17853
|
+
},
|
|
17854
|
+
{
|
|
17855
|
+
id: "4_report",
|
|
17856
|
+
name: "REPORT",
|
|
17857
|
+
description: "Brief summary",
|
|
17858
|
+
requiredActions: [
|
|
17859
|
+
"State what was done",
|
|
17860
|
+
"Note any caveats or follow-ups"
|
|
17861
|
+
]
|
|
17862
|
+
}
|
|
17863
|
+
];
|
|
17864
|
+
var LITE_TEMPLATE = `## REASONING LOOP (LITE)
|
|
17865
|
+
|
|
17866
|
+
For simple tasks, follow this streamlined process:
|
|
17867
|
+
|
|
17868
|
+
### 1. UNDERSTAND
|
|
17869
|
+
- Confirm what needs to be done
|
|
17870
|
+
- Check relevant file if needed
|
|
17871
|
+
|
|
17872
|
+
### 2. DO
|
|
17873
|
+
- Make the change
|
|
17874
|
+
- Follow existing patterns
|
|
17875
|
+
|
|
17876
|
+
### 3. VERIFY
|
|
17877
|
+
- Run typecheck/tests if applicable
|
|
17878
|
+
- Note if skipped and why
|
|
17879
|
+
|
|
17880
|
+
### 4. REPORT
|
|
17881
|
+
- State what was done
|
|
17882
|
+
- Note any caveats
|
|
17883
|
+
|
|
17884
|
+
---
|
|
17885
|
+
|
|
17886
|
+
**Escalate to PROVER scaffold if task is more complex than expected.**
|
|
17887
|
+
`;
|
|
17888
|
+
var SCAFFOLDS = {
|
|
17889
|
+
prover: {
|
|
17890
|
+
id: "prover",
|
|
17891
|
+
name: "PROVER",
|
|
17892
|
+
description: "Full reasoning loop: Plan-Risk-Options-Validate-Execute-Report",
|
|
17893
|
+
steps: PROVER_STEPS,
|
|
17894
|
+
template: PROVER_TEMPLATE
|
|
17895
|
+
},
|
|
17896
|
+
lite: {
|
|
17897
|
+
id: "lite",
|
|
17898
|
+
name: "LITE",
|
|
17899
|
+
description: "Lightweight reasoning: Understand-Do-Verify-Report",
|
|
17900
|
+
steps: LITE_STEPS,
|
|
17901
|
+
template: LITE_TEMPLATE
|
|
17902
|
+
}
|
|
17903
|
+
};
|
|
17904
|
+
function getReasoningScaffold(type) {
|
|
17905
|
+
const scaffold = SCAFFOLDS[type];
|
|
17906
|
+
if (!scaffold) {
|
|
17907
|
+
throw new Error(`Unknown reasoning scaffold: ${type}`);
|
|
17908
|
+
}
|
|
17909
|
+
return scaffold;
|
|
17910
|
+
}
|
|
17911
|
+
function getScaffoldTemplate(type) {
|
|
17912
|
+
return getReasoningScaffold(type).template;
|
|
17913
|
+
}
|
|
17914
|
+
|
|
17915
|
+
// src/agents/cognitive/role-checklists.ts
|
|
17916
|
+
init_esm_shims();
|
|
17917
|
+
var BACKEND_CHECKLIST = {
|
|
17918
|
+
id: "backend",
|
|
17919
|
+
name: "Backend Checklist",
|
|
17920
|
+
role: "Backend Developer",
|
|
17921
|
+
categories: {
|
|
17922
|
+
security: [
|
|
17923
|
+
{ id: "be-sec-1", category: "security", text: "Authentication: Are endpoints properly protected?", severity: "critical", triggers: ["api", "endpoint", "route"] },
|
|
17924
|
+
{ id: "be-sec-2", category: "security", text: "Authorization: Is access control enforced (who can do what)?", severity: "critical", triggers: ["user", "role", "permission"] },
|
|
17925
|
+
{ id: "be-sec-3", category: "security", text: "Input validation: Are all inputs validated and sanitized?", severity: "critical", triggers: ["input", "request", "body", "params"] },
|
|
17926
|
+
{ id: "be-sec-4", category: "security", text: "Secrets: No hardcoded credentials, tokens, or keys?", severity: "critical", triggers: ["config", "env", "secret", "key"] }
|
|
17927
|
+
],
|
|
17928
|
+
data_integrity: [
|
|
17929
|
+
{ id: "be-data-1", category: "data_integrity", text: "Migrations: Are database migrations reversible and safe?", severity: "high", triggers: ["migration", "schema", "database", "table"] },
|
|
17930
|
+
{ id: "be-data-2", category: "data_integrity", text: "Transactions: Are operations atomic where needed?", severity: "high", triggers: ["transaction", "update", "insert", "delete"] },
|
|
17931
|
+
{ id: "be-data-3", category: "data_integrity", text: "Idempotency: Can operations be safely retried?", severity: "medium", triggers: ["retry", "idempotent", "duplicate"] },
|
|
17932
|
+
{ id: "be-data-4", category: "data_integrity", text: "Data validation: Are data constraints enforced at DB level?", severity: "medium", triggers: ["constraint", "schema", "validate"] }
|
|
17933
|
+
],
|
|
17934
|
+
performance: [
|
|
17935
|
+
{ id: "be-perf-1", category: "performance", text: "N+1 queries: Are database calls optimized (no loops of queries)?", severity: "high", triggers: ["query", "loop", "database", "fetch"] },
|
|
17936
|
+
{ id: "be-perf-2", category: "performance", text: "Caching: Is caching strategy appropriate for this data?", severity: "medium", triggers: ["cache", "redis", "memory"] },
|
|
17937
|
+
{ id: "be-perf-3", category: "performance", text: "Indexing: Are queries using appropriate indexes?", severity: "medium", triggers: ["query", "search", "filter", "where"] },
|
|
17938
|
+
{ id: "be-perf-4", category: "performance", text: "Connection pooling: Are database connections managed properly?", severity: "medium", triggers: ["connection", "pool", "database"] }
|
|
17939
|
+
],
|
|
17940
|
+
reliability: [
|
|
17941
|
+
{ id: "be-rel-1", category: "reliability", text: "Error handling: Are errors caught, logged, and handled gracefully?", severity: "high", triggers: ["error", "catch", "exception"] },
|
|
17942
|
+
{ id: "be-rel-2", category: "reliability", text: "Retry logic: Is there backoff for transient failures?", severity: "medium", triggers: ["retry", "backoff", "timeout"] },
|
|
17943
|
+
{ id: "be-rel-3", category: "reliability", text: "Circuit breakers: Are external service calls protected?", severity: "medium", triggers: ["external", "api", "service", "http"] },
|
|
17944
|
+
{ id: "be-rel-4", category: "reliability", text: "Observability: Are metrics, logs, and traces in place?", severity: "medium", triggers: ["log", "metric", "trace", "monitor"] }
|
|
17945
|
+
]
|
|
17946
|
+
},
|
|
17947
|
+
template: `## DOMAIN CHECKLIST: Backend
|
|
17948
|
+
|
|
17949
|
+
Before finalizing, verify each applicable item:
|
|
17950
|
+
|
|
17951
|
+
**Security** (CRITICAL)
|
|
17952
|
+
- [ ] Authentication: Are endpoints properly protected?
|
|
17953
|
+
- [ ] Authorization: Is access control enforced?
|
|
17954
|
+
- [ ] Input validation: Are all inputs sanitized?
|
|
17955
|
+
- [ ] Secrets: No hardcoded credentials?
|
|
17956
|
+
|
|
17957
|
+
**Data Integrity** (HIGH)
|
|
17958
|
+
- [ ] Migrations: Reversible and safe?
|
|
17959
|
+
- [ ] Transactions: Atomic where needed?
|
|
17960
|
+
- [ ] Idempotency: Safe to retry?
|
|
17961
|
+
- [ ] Data validation: Constraints enforced?
|
|
17962
|
+
|
|
17963
|
+
**Performance** (MEDIUM-HIGH)
|
|
17964
|
+
- [ ] N+1 queries: Optimized database calls?
|
|
17965
|
+
- [ ] Caching: Appropriate strategy?
|
|
17966
|
+
- [ ] Indexing: Queries using indexes?
|
|
17967
|
+
- [ ] Connection pooling: Managed properly?
|
|
17968
|
+
|
|
17969
|
+
**Reliability** (HIGH)
|
|
17970
|
+
- [ ] Error handling: Graceful failures?
|
|
17971
|
+
- [ ] Retry logic: Backoff for transient failures?
|
|
17972
|
+
- [ ] Circuit breakers: External calls protected?
|
|
17973
|
+
- [ ] Observability: Logs, metrics, traces?
|
|
17974
|
+
|
|
17975
|
+
Mark items as [x] when verified, or note [N/A] if not applicable.
|
|
17976
|
+
Flag any concerns with [RISK].
|
|
17977
|
+
`
|
|
17978
|
+
};
|
|
17979
|
+
var FRONTEND_CHECKLIST = {
|
|
17980
|
+
id: "frontend",
|
|
17981
|
+
name: "Frontend Checklist",
|
|
17982
|
+
role: "Frontend Developer",
|
|
17983
|
+
categories: {
|
|
17984
|
+
accessibility: [
|
|
17985
|
+
{ id: "fe-a11y-1", category: "accessibility", text: "Semantic HTML: Are elements properly labeled (headings, landmarks)?", severity: "high", triggers: ["html", "element", "component"] },
|
|
17986
|
+
{ id: "fe-a11y-2", category: "accessibility", text: "Keyboard navigation: Is everything navigable without mouse?", severity: "high", triggers: ["button", "link", "interactive", "focus"] },
|
|
17987
|
+
{ id: "fe-a11y-3", category: "accessibility", text: "Screen reader: Are ARIA labels and roles correct?", severity: "high", triggers: ["aria", "label", "role"] },
|
|
17988
|
+
{ id: "fe-a11y-4", category: "accessibility", text: "Color contrast: Does it meet WCAG AA standards?", severity: "medium", triggers: ["color", "text", "background", "style"] }
|
|
17989
|
+
],
|
|
17990
|
+
user_experience: [
|
|
17991
|
+
{ id: "fe-ux-1", category: "user_experience", text: "Loading states: Are async operations indicated to user?", severity: "high", triggers: ["async", "fetch", "load", "api"] },
|
|
17992
|
+
{ id: "fe-ux-2", category: "user_experience", text: "Error states: Are failures communicated clearly?", severity: "high", triggers: ["error", "fail", "catch"] },
|
|
17993
|
+
{ id: "fe-ux-3", category: "user_experience", text: "Empty states: Is there guidance when no data exists?", severity: "medium", triggers: ["empty", "no data", "list", "table"] },
|
|
17994
|
+
{ id: "fe-ux-4", category: "user_experience", text: "Responsive: Does it work on all screen sizes?", severity: "high", triggers: ["layout", "grid", "flex", "responsive"] }
|
|
17995
|
+
],
|
|
17996
|
+
performance: [
|
|
17997
|
+
{ id: "fe-perf-1", category: "performance", text: "Bundle size: Are imports optimized (no full library imports)?", severity: "medium", triggers: ["import", "library", "package"] },
|
|
17998
|
+
{ id: "fe-perf-2", category: "performance", text: "Lazy loading: Are heavy components/routes deferred?", severity: "medium", triggers: ["route", "component", "heavy", "large"] },
|
|
17999
|
+
{ id: "fe-perf-3", category: "performance", text: "Memoization: Are expensive renders cached (useMemo, React.memo)?", severity: "medium", triggers: ["render", "memo", "expensive", "computation"] },
|
|
18000
|
+
{ id: "fe-perf-4", category: "performance", text: "Images: Are they optimized and lazy-loaded?", severity: "medium", triggers: ["image", "img", "picture", "media"] }
|
|
18001
|
+
],
|
|
18002
|
+
security: [
|
|
18003
|
+
{ id: "fe-sec-1", category: "security", text: "XSS: Is user-generated content sanitized before rendering?", severity: "critical", triggers: ["user", "content", "html", "dangerously"] },
|
|
18004
|
+
{ id: "fe-sec-2", category: "security", text: "CSRF: Are forms and state-changing requests protected?", severity: "high", triggers: ["form", "submit", "post", "put", "delete"] },
|
|
18005
|
+
{ id: "fe-sec-3", category: "security", text: "Sensitive data: Is PII handled correctly (not logged, masked)?", severity: "high", triggers: ["password", "email", "personal", "sensitive"] },
|
|
18006
|
+
{ id: "fe-sec-4", category: "security", text: "Dependencies: No known vulnerable packages?", severity: "medium", triggers: ["dependency", "package", "npm"] }
|
|
18007
|
+
]
|
|
18008
|
+
},
|
|
18009
|
+
template: `## DOMAIN CHECKLIST: Frontend
|
|
18010
|
+
|
|
18011
|
+
Before finalizing, verify each applicable item:
|
|
18012
|
+
|
|
18013
|
+
**Accessibility** (HIGH)
|
|
18014
|
+
- [ ] Semantic HTML: Proper labels and landmarks?
|
|
18015
|
+
- [ ] Keyboard navigation: Works without mouse?
|
|
18016
|
+
- [ ] Screen reader: ARIA labels correct?
|
|
18017
|
+
- [ ] Color contrast: Meets WCAG AA?
|
|
18018
|
+
|
|
18019
|
+
**User Experience** (HIGH)
|
|
18020
|
+
- [ ] Loading states: Async operations indicated?
|
|
18021
|
+
- [ ] Error states: Failures communicated clearly?
|
|
18022
|
+
- [ ] Empty states: Guidance when no data?
|
|
18023
|
+
- [ ] Responsive: Works on all screen sizes?
|
|
18024
|
+
|
|
18025
|
+
**Performance** (MEDIUM)
|
|
18026
|
+
- [ ] Bundle size: Imports optimized?
|
|
18027
|
+
- [ ] Lazy loading: Heavy components deferred?
|
|
18028
|
+
- [ ] Memoization: Expensive renders cached?
|
|
18029
|
+
- [ ] Images: Optimized and lazy-loaded?
|
|
18030
|
+
|
|
18031
|
+
**Security** (CRITICAL-HIGH)
|
|
18032
|
+
- [ ] XSS: User content sanitized?
|
|
18033
|
+
- [ ] CSRF: Forms protected?
|
|
18034
|
+
- [ ] Sensitive data: PII handled correctly?
|
|
18035
|
+
- [ ] Dependencies: No known vulnerabilities?
|
|
18036
|
+
|
|
18037
|
+
Mark items as [x] when verified, or note [N/A] if not applicable.
|
|
18038
|
+
Flag any concerns with [RISK].
|
|
18039
|
+
`
|
|
18040
|
+
};
|
|
18041
|
+
var SECURITY_CHECKLIST = {
|
|
18042
|
+
id: "security",
|
|
18043
|
+
name: "Security Checklist",
|
|
18044
|
+
role: "Security Engineer",
|
|
18045
|
+
categories: {
|
|
18046
|
+
threat_model: [
|
|
18047
|
+
{ id: "sec-tm-1", category: "threat_model", text: "Attack surface: What can be attacked? (inputs, APIs, data stores)", severity: "critical", triggers: ["api", "input", "endpoint"] },
|
|
18048
|
+
{ id: "sec-tm-2", category: "threat_model", text: "Threat actors: Who would attack this? (script kiddies, insiders, nation states)", severity: "high", triggers: ["user", "access", "public"] },
|
|
18049
|
+
{ id: "sec-tm-3", category: "threat_model", text: "Assets: What valuable data/access is at risk?", severity: "critical", triggers: ["data", "pii", "credential", "secret"] },
|
|
18050
|
+
{ id: "sec-tm-4", category: "threat_model", text: "STRIDE: Spoofing, Tampering, Repudiation, Info Disclosure, DoS, Elevation?", severity: "high", triggers: ["security", "threat", "vulnerability"] }
|
|
18051
|
+
],
|
|
18052
|
+
owasp_top_10: [
|
|
18053
|
+
{ id: "sec-owasp-1", category: "owasp_top_10", text: "Injection: SQL, NoSQL, OS, LDAP injection possible?", severity: "critical", triggers: ["query", "sql", "database", "command"] },
|
|
18054
|
+
{ id: "sec-owasp-2", category: "owasp_top_10", text: "Broken Auth: Session management, credential handling secure?", severity: "critical", triggers: ["auth", "login", "session", "token"] },
|
|
18055
|
+
{ id: "sec-owasp-3", category: "owasp_top_10", text: "Sensitive Data: Encryption at rest and in transit?", severity: "critical", triggers: ["encrypt", "https", "data", "store"] },
|
|
18056
|
+
{ id: "sec-owasp-4", category: "owasp_top_10", text: "XXE: External entity processing disabled?", severity: "high", triggers: ["xml", "parse", "entity"] },
|
|
18057
|
+
{ id: "sec-owasp-5", category: "owasp_top_10", text: "Broken Access Control: Privilege escalation possible?", severity: "critical", triggers: ["role", "permission", "admin", "access"] },
|
|
18058
|
+
{ id: "sec-owasp-6", category: "owasp_top_10", text: "Misconfiguration: Default settings, errors exposed?", severity: "high", triggers: ["config", "default", "error", "debug"] },
|
|
18059
|
+
{ id: "sec-owasp-7", category: "owasp_top_10", text: "XSS: Reflected, stored, DOM-based XSS possible?", severity: "critical", triggers: ["html", "script", "render", "output"] },
|
|
18060
|
+
{ id: "sec-owasp-8", category: "owasp_top_10", text: "Deserialization: Untrusted data deserialized safely?", severity: "high", triggers: ["json", "deserialize", "parse", "object"] },
|
|
18061
|
+
{ id: "sec-owasp-9", category: "owasp_top_10", text: "Components: Using components with known vulnerabilities?", severity: "high", triggers: ["dependency", "package", "library", "npm"] },
|
|
18062
|
+
{ id: "sec-owasp-10", category: "owasp_top_10", text: "Logging: Insufficient monitoring and logging?", severity: "medium", triggers: ["log", "audit", "monitor", "alert"] }
|
|
18063
|
+
],
|
|
18064
|
+
secrets: [
|
|
18065
|
+
{ id: "sec-secret-1", category: "secrets", text: "No hardcoded secrets in code or config files?", severity: "critical", triggers: ["key", "token", "password", "secret"] },
|
|
18066
|
+
{ id: "sec-secret-2", category: "secrets", text: "Environment variables for sensitive config?", severity: "high", triggers: ["env", "config", "setting"] },
|
|
18067
|
+
{ id: "sec-secret-3", category: "secrets", text: "Secrets rotation policy in place?", severity: "medium", triggers: ["rotate", "expire", "refresh"] },
|
|
18068
|
+
{ id: "sec-secret-4", category: "secrets", text: "Audit logging for secret access?", severity: "medium", triggers: ["audit", "access", "log"] }
|
|
18069
|
+
]
|
|
18070
|
+
},
|
|
18071
|
+
template: `## DOMAIN CHECKLIST: Security
|
|
18072
|
+
|
|
18073
|
+
Before finalizing, verify each applicable item:
|
|
18074
|
+
|
|
18075
|
+
**Threat Model** (CRITICAL)
|
|
18076
|
+
- [ ] Attack surface: What can be attacked?
|
|
18077
|
+
- [ ] Threat actors: Who would attack this?
|
|
18078
|
+
- [ ] Assets: What valuable data is at risk?
|
|
18079
|
+
- [ ] STRIDE: Spoofing, Tampering, Repudiation, Info Disclosure, DoS, Elevation?
|
|
18080
|
+
|
|
18081
|
+
**OWASP Top 10** (CRITICAL)
|
|
18082
|
+
- [ ] Injection: SQL/NoSQL/OS/LDAP injection possible?
|
|
18083
|
+
- [ ] Broken Auth: Session/credential handling secure?
|
|
18084
|
+
- [ ] Sensitive Data: Encrypted at rest and in transit?
|
|
18085
|
+
- [ ] XXE: External entity processing disabled?
|
|
18086
|
+
- [ ] Broken Access Control: Privilege escalation possible?
|
|
18087
|
+
- [ ] Misconfiguration: Defaults secured, errors hidden?
|
|
18088
|
+
- [ ] XSS: Reflected/stored/DOM XSS prevented?
|
|
18089
|
+
- [ ] Deserialization: Untrusted data handled safely?
|
|
18090
|
+
- [ ] Components: No known vulnerable dependencies?
|
|
18091
|
+
- [ ] Logging: Sufficient monitoring and alerting?
|
|
18092
|
+
|
|
18093
|
+
**Secrets Management** (CRITICAL)
|
|
18094
|
+
- [ ] No hardcoded secrets in code?
|
|
18095
|
+
- [ ] Env vars for sensitive config?
|
|
18096
|
+
- [ ] Rotation policy exists?
|
|
18097
|
+
- [ ] Audit logging for access?
|
|
18098
|
+
|
|
18099
|
+
Mark items as [x] when verified, or note [N/A] if not applicable.
|
|
18100
|
+
Flag any concerns with [RISK].
|
|
18101
|
+
`
|
|
18102
|
+
};
|
|
18103
|
+
var QUALITY_CHECKLIST = {
|
|
18104
|
+
id: "quality",
|
|
18105
|
+
name: "Quality Checklist",
|
|
18106
|
+
role: "QA Engineer",
|
|
18107
|
+
categories: {
|
|
18108
|
+
test_scope: [
|
|
18109
|
+
{ id: "qa-scope-1", category: "test_scope", text: "Requirements: Are all requirements covered by tests?", severity: "high", triggers: ["requirement", "spec", "feature"] },
|
|
18110
|
+
{ id: "qa-scope-2", category: "test_scope", text: "Edge cases: Are boundary conditions tested?", severity: "high", triggers: ["edge", "boundary", "limit", "max", "min"] },
|
|
18111
|
+
{ id: "qa-scope-3", category: "test_scope", text: "Error paths: Are failure scenarios tested?", severity: "high", triggers: ["error", "fail", "exception", "invalid"] },
|
|
18112
|
+
{ id: "qa-scope-4", category: "test_scope", text: "Integration points: Are interfaces tested?", severity: "medium", triggers: ["api", "interface", "integration", "external"] }
|
|
18113
|
+
],
|
|
18114
|
+
test_quality: [
|
|
18115
|
+
{ id: "qa-qual-1", category: "test_quality", text: "Isolation: Are tests independent (no shared state)?", severity: "high", triggers: ["test", "describe", "it"] },
|
|
18116
|
+
{ id: "qa-qual-2", category: "test_quality", text: "Determinism: Do tests pass consistently (no flakiness)?", severity: "high", triggers: ["flaky", "random", "timeout", "intermittent"] },
|
|
18117
|
+
{ id: "qa-qual-3", category: "test_quality", text: "Speed: Are tests fast enough for CI feedback loop?", severity: "medium", triggers: ["slow", "timeout", "performance"] },
|
|
18118
|
+
{ id: "qa-qual-4", category: "test_quality", text: "Readability: Can failures be diagnosed quickly?", severity: "medium", triggers: ["message", "assert", "expect"] }
|
|
18119
|
+
],
|
|
18120
|
+
regression: [
|
|
18121
|
+
{ id: "qa-reg-1", category: "regression", text: "Existing tests: Do all existing tests still pass?", severity: "critical", triggers: ["change", "modify", "update"] },
|
|
18122
|
+
{ id: "qa-reg-2", category: "regression", text: "Coverage: Has test coverage decreased?", severity: "high", triggers: ["coverage", "uncovered", "gap"] },
|
|
18123
|
+
{ id: "qa-reg-3", category: "regression", text: "Breaking changes: Are APIs backward compatible?", severity: "high", triggers: ["api", "interface", "contract", "public"] },
|
|
18124
|
+
{ id: "qa-reg-4", category: "regression", text: "Performance: Has latency/memory regressed?", severity: "medium", triggers: ["performance", "latency", "memory", "slow"] }
|
|
18125
|
+
],
|
|
18126
|
+
validation: [
|
|
18127
|
+
{ id: "qa-val-1", category: "validation", text: "Reproducibility: Can the bug/behavior be reproduced?", severity: "high", triggers: ["bug", "issue", "reproduce"] },
|
|
18128
|
+
{ id: "qa-val-2", category: "validation", text: "Root cause: Is the fix addressing the root cause?", severity: "high", triggers: ["fix", "patch", "resolve"] },
|
|
18129
|
+
{ id: "qa-val-3", category: "validation", text: "Side effects: Are there unintended changes?", severity: "medium", triggers: ["change", "affect", "impact"] },
|
|
18130
|
+
{ id: "qa-val-4", category: "validation", text: "Documentation: Are test changes documented?", severity: "low", triggers: ["doc", "comment", "readme"] }
|
|
18131
|
+
]
|
|
18132
|
+
},
|
|
18133
|
+
template: `## DOMAIN CHECKLIST: Quality
|
|
18134
|
+
|
|
18135
|
+
Before finalizing, verify each applicable item:
|
|
18136
|
+
|
|
18137
|
+
**Test Scope** (HIGH)
|
|
18138
|
+
- [ ] Requirements: All requirements covered?
|
|
18139
|
+
- [ ] Edge cases: Boundary conditions tested?
|
|
18140
|
+
- [ ] Error paths: Failure scenarios tested?
|
|
18141
|
+
- [ ] Integration points: Interfaces tested?
|
|
18142
|
+
|
|
18143
|
+
**Test Quality** (HIGH)
|
|
18144
|
+
- [ ] Isolation: Tests independent (no shared state)?
|
|
18145
|
+
- [ ] Determinism: Tests pass consistently?
|
|
18146
|
+
- [ ] Speed: Fast enough for CI?
|
|
18147
|
+
- [ ] Readability: Failures diagnosable?
|
|
18148
|
+
|
|
18149
|
+
**Regression** (CRITICAL)
|
|
18150
|
+
- [ ] Existing tests: All still pass?
|
|
18151
|
+
- [ ] Coverage: Not decreased?
|
|
18152
|
+
- [ ] Breaking changes: APIs compatible?
|
|
18153
|
+
- [ ] Performance: No regression?
|
|
18154
|
+
|
|
18155
|
+
**Validation** (HIGH)
|
|
18156
|
+
- [ ] Reproducibility: Bug reproducible?
|
|
18157
|
+
- [ ] Root cause: Fix addresses cause?
|
|
18158
|
+
- [ ] Side effects: No unintended changes?
|
|
18159
|
+
- [ ] Documentation: Changes documented?
|
|
18160
|
+
|
|
18161
|
+
Mark items as [x] when verified, or note [N/A] if not applicable.
|
|
18162
|
+
Flag any concerns with [RISK].
|
|
18163
|
+
`
|
|
18164
|
+
};
|
|
18165
|
+
var ARCHITECTURE_CHECKLIST = {
|
|
18166
|
+
id: "architecture",
|
|
18167
|
+
name: "Architecture Checklist",
|
|
18168
|
+
role: "Software Architect",
|
|
18169
|
+
categories: {
|
|
18170
|
+
design: [
|
|
18171
|
+
{ id: "arch-des-1", category: "design", text: "Requirements alignment: Does it solve the right problem?", severity: "critical", triggers: ["design", "architecture", "system"] },
|
|
18172
|
+
{ id: "arch-des-2", category: "design", text: "Simplicity: Is this the simplest viable solution?", severity: "high", triggers: ["complex", "simple", "pattern"] },
|
|
18173
|
+
{ id: "arch-des-3", category: "design", text: "Extensibility: Can it evolve with future needs?", severity: "medium", triggers: ["future", "extend", "scale"] },
|
|
18174
|
+
{ id: "arch-des-4", category: "design", text: "Consistency: Does it follow existing patterns?", severity: "high", triggers: ["pattern", "convention", "style"] }
|
|
18175
|
+
],
|
|
18176
|
+
trade_offs: [
|
|
18177
|
+
{ id: "arch-trade-1", category: "trade_offs", text: "Performance vs. complexity trade-off documented?", severity: "high", triggers: ["performance", "complexity", "trade"] },
|
|
18178
|
+
{ id: "arch-trade-2", category: "trade_offs", text: "Build vs. buy decision documented?", severity: "medium", triggers: ["build", "buy", "library", "vendor"] },
|
|
18179
|
+
{ id: "arch-trade-3", category: "trade_offs", text: "Technology choices justified?", severity: "high", triggers: ["technology", "framework", "language"] },
|
|
18180
|
+
{ id: "arch-trade-4", category: "trade_offs", text: "Rejected alternatives documented?", severity: "medium", triggers: ["alternative", "option", "consider"] }
|
|
18181
|
+
],
|
|
18182
|
+
risk: [
|
|
18183
|
+
{ id: "arch-risk-1", category: "risk", text: "Single points of failure identified?", severity: "critical", triggers: ["single", "failure", "dependency"] },
|
|
18184
|
+
{ id: "arch-risk-2", category: "risk", text: "Scalability bottlenecks identified?", severity: "high", triggers: ["scale", "bottleneck", "limit"] },
|
|
18185
|
+
{ id: "arch-risk-3", category: "risk", text: "Security implications considered?", severity: "critical", triggers: ["security", "auth", "data"] },
|
|
18186
|
+
{ id: "arch-risk-4", category: "risk", text: "Operational complexity acceptable?", severity: "medium", triggers: ["ops", "deploy", "maintain"] }
|
|
18187
|
+
],
|
|
18188
|
+
governance: [
|
|
18189
|
+
{ id: "arch-gov-1", category: "governance", text: "ADR created for significant decisions?", severity: "high", triggers: ["decision", "adr", "architecture"] },
|
|
18190
|
+
{ id: "arch-gov-2", category: "governance", text: "Stakeholders consulted?", severity: "medium", triggers: ["stakeholder", "team", "review"] },
|
|
18191
|
+
{ id: "arch-gov-3", category: "governance", text: "Migration path defined?", severity: "high", triggers: ["migrate", "transition", "phase"] },
|
|
18192
|
+
{ id: "arch-gov-4", category: "governance", text: "Rollback strategy exists?", severity: "high", triggers: ["rollback", "revert", "undo"] }
|
|
18193
|
+
]
|
|
18194
|
+
},
|
|
18195
|
+
template: `## DOMAIN CHECKLIST: Architecture
|
|
18196
|
+
|
|
18197
|
+
Before finalizing, verify each applicable item:
|
|
18198
|
+
|
|
18199
|
+
**Design** (CRITICAL-HIGH)
|
|
18200
|
+
- [ ] Requirements alignment: Solves the right problem?
|
|
18201
|
+
- [ ] Simplicity: Simplest viable solution?
|
|
18202
|
+
- [ ] Extensibility: Can evolve with future needs?
|
|
18203
|
+
- [ ] Consistency: Follows existing patterns?
|
|
18204
|
+
|
|
18205
|
+
**Trade-offs** (HIGH)
|
|
18206
|
+
- [ ] Performance vs. complexity documented?
|
|
18207
|
+
- [ ] Build vs. buy decision documented?
|
|
18208
|
+
- [ ] Technology choices justified?
|
|
18209
|
+
- [ ] Rejected alternatives documented?
|
|
18210
|
+
|
|
18211
|
+
**Risk** (CRITICAL)
|
|
18212
|
+
- [ ] Single points of failure identified?
|
|
18213
|
+
- [ ] Scalability bottlenecks identified?
|
|
18214
|
+
- [ ] Security implications considered?
|
|
18215
|
+
- [ ] Operational complexity acceptable?
|
|
18216
|
+
|
|
18217
|
+
**Governance** (HIGH)
|
|
18218
|
+
- [ ] ADR created for significant decisions?
|
|
18219
|
+
- [ ] Stakeholders consulted?
|
|
18220
|
+
- [ ] Migration path defined?
|
|
18221
|
+
- [ ] Rollback strategy exists?
|
|
18222
|
+
|
|
18223
|
+
Mark items as [x] when verified, or note [N/A] if not applicable.
|
|
18224
|
+
Flag any concerns with [RISK].
|
|
18225
|
+
`
|
|
18226
|
+
};
|
|
18227
|
+
var DEVOPS_CHECKLIST = {
|
|
18228
|
+
id: "devops",
|
|
18229
|
+
name: "DevOps Checklist",
|
|
18230
|
+
role: "DevOps Engineer",
|
|
18231
|
+
categories: {
|
|
18232
|
+
deployment: [
|
|
18233
|
+
{ id: "devops-dep-1", category: "deployment", text: "Zero-downtime: Can deploy without service interruption?", severity: "high", triggers: ["deploy", "release", "rollout"] },
|
|
18234
|
+
{ id: "devops-dep-2", category: "deployment", text: "Rollback: Can quickly revert if issues arise?", severity: "critical", triggers: ["rollback", "revert", "fail"] },
|
|
18235
|
+
{ id: "devops-dep-3", category: "deployment", text: "Configuration: Env-specific configs separated from code?", severity: "high", triggers: ["config", "env", "environment"] },
|
|
18236
|
+
{ id: "devops-dep-4", category: "deployment", text: "Secrets: Managed securely (not in code/config)?", severity: "critical", triggers: ["secret", "key", "credential"] }
|
|
18237
|
+
],
|
|
18238
|
+
infrastructure: [
|
|
18239
|
+
{ id: "devops-infra-1", category: "infrastructure", text: "IaC: Infrastructure defined as code?", severity: "high", triggers: ["infrastructure", "terraform", "kubernetes"] },
|
|
18240
|
+
{ id: "devops-infra-2", category: "infrastructure", text: "Scaling: Auto-scaling configured correctly?", severity: "high", triggers: ["scale", "auto", "capacity"] },
|
|
18241
|
+
{ id: "devops-infra-3", category: "infrastructure", text: "Resources: CPU/memory limits appropriate?", severity: "medium", triggers: ["resource", "memory", "cpu", "limit"] },
|
|
18242
|
+
{ id: "devops-infra-4", category: "infrastructure", text: "Networking: Security groups and firewalls configured?", severity: "high", triggers: ["network", "firewall", "security group"] }
|
|
18243
|
+
],
|
|
18244
|
+
observability: [
|
|
18245
|
+
{ id: "devops-obs-1", category: "observability", text: "Logging: Structured logs with correlation IDs?", severity: "high", triggers: ["log", "logging", "trace"] },
|
|
18246
|
+
{ id: "devops-obs-2", category: "observability", text: "Metrics: Key metrics exposed and collected?", severity: "high", triggers: ["metric", "prometheus", "grafana"] },
|
|
18247
|
+
{ id: "devops-obs-3", category: "observability", text: "Alerting: Alerts configured for critical conditions?", severity: "high", triggers: ["alert", "notify", "oncall"] },
|
|
18248
|
+
{ id: "devops-obs-4", category: "observability", text: "Dashboards: Visibility into system health?", severity: "medium", triggers: ["dashboard", "monitor", "visualize"] }
|
|
18249
|
+
],
|
|
18250
|
+
reliability: [
|
|
18251
|
+
{ id: "devops-rel-1", category: "reliability", text: "Health checks: Liveness and readiness probes configured?", severity: "high", triggers: ["health", "probe", "check"] },
|
|
18252
|
+
{ id: "devops-rel-2", category: "reliability", text: "Disaster recovery: Backup and restore tested?", severity: "critical", triggers: ["backup", "restore", "disaster"] },
|
|
18253
|
+
{ id: "devops-rel-3", category: "reliability", text: "Failover: Multi-region/AZ redundancy?", severity: "high", triggers: ["failover", "redundancy", "region", "availability"] },
|
|
18254
|
+
{ id: "devops-rel-4", category: "reliability", text: "Runbooks: Incident response procedures documented?", severity: "medium", triggers: ["runbook", "incident", "procedure"] }
|
|
18255
|
+
]
|
|
18256
|
+
},
|
|
18257
|
+
template: `## DOMAIN CHECKLIST: DevOps
|
|
18258
|
+
|
|
18259
|
+
Before finalizing, verify each applicable item:
|
|
18260
|
+
|
|
18261
|
+
**Deployment** (CRITICAL-HIGH)
|
|
18262
|
+
- [ ] Zero-downtime: Deploy without interruption?
|
|
18263
|
+
- [ ] Rollback: Can quickly revert?
|
|
18264
|
+
- [ ] Configuration: Env-specific configs separated?
|
|
18265
|
+
- [ ] Secrets: Managed securely?
|
|
18266
|
+
|
|
18267
|
+
**Infrastructure** (HIGH)
|
|
18268
|
+
- [ ] IaC: Infrastructure as code?
|
|
18269
|
+
- [ ] Scaling: Auto-scaling configured?
|
|
18270
|
+
- [ ] Resources: CPU/memory limits appropriate?
|
|
18271
|
+
- [ ] Networking: Security groups configured?
|
|
18272
|
+
|
|
18273
|
+
**Observability** (HIGH)
|
|
18274
|
+
- [ ] Logging: Structured with correlation IDs?
|
|
18275
|
+
- [ ] Metrics: Key metrics collected?
|
|
18276
|
+
- [ ] Alerting: Critical alerts configured?
|
|
18277
|
+
- [ ] Dashboards: System health visible?
|
|
18278
|
+
|
|
18279
|
+
**Reliability** (CRITICAL-HIGH)
|
|
18280
|
+
- [ ] Health checks: Probes configured?
|
|
18281
|
+
- [ ] Disaster recovery: Backup/restore tested?
|
|
18282
|
+
- [ ] Failover: Multi-region redundancy?
|
|
18283
|
+
- [ ] Runbooks: Incident procedures documented?
|
|
18284
|
+
|
|
18285
|
+
Mark items as [x] when verified, or note [N/A] if not applicable.
|
|
18286
|
+
Flag any concerns with [RISK].
|
|
18287
|
+
`
|
|
18288
|
+
};
|
|
18289
|
+
var DATA_CHECKLIST = {
|
|
18290
|
+
id: "data",
|
|
18291
|
+
name: "Data Checklist",
|
|
18292
|
+
role: "Data Engineer",
|
|
18293
|
+
categories: {
|
|
18294
|
+
data_quality: [
|
|
18295
|
+
{ id: "data-qual-1", category: "data_quality", text: "Schema validation: Data conforms to expected schema?", severity: "high", triggers: ["schema", "type", "validate"] },
|
|
18296
|
+
{ id: "data-qual-2", category: "data_quality", text: "Null handling: Missing values handled appropriately?", severity: "high", triggers: ["null", "missing", "empty"] },
|
|
18297
|
+
{ id: "data-qual-3", category: "data_quality", text: "Duplicates: Deduplication strategy in place?", severity: "medium", triggers: ["duplicate", "unique", "distinct"] },
|
|
18298
|
+
{ id: "data-qual-4", category: "data_quality", text: "Freshness: Data SLAs defined and monitored?", severity: "medium", triggers: ["fresh", "stale", "latency", "sla"] }
|
|
18299
|
+
],
|
|
18300
|
+
pipeline: [
|
|
18301
|
+
{ id: "data-pipe-1", category: "pipeline", text: "Idempotency: Pipeline can be safely re-run?", severity: "high", triggers: ["pipeline", "etl", "process"] },
|
|
18302
|
+
{ id: "data-pipe-2", category: "pipeline", text: "Error handling: Failed records captured for review?", severity: "high", triggers: ["error", "fail", "dead letter"] },
|
|
18303
|
+
{ id: "data-pipe-3", category: "pipeline", text: "Backfill: Historical data can be reprocessed?", severity: "medium", triggers: ["backfill", "historical", "reprocess"] },
|
|
18304
|
+
{ id: "data-pipe-4", category: "pipeline", text: "Monitoring: Pipeline health and progress visible?", severity: "high", triggers: ["monitor", "alert", "status"] }
|
|
18305
|
+
],
|
|
18306
|
+
governance: [
|
|
18307
|
+
{ id: "data-gov-1", category: "governance", text: "Lineage: Data origin and transformations documented?", severity: "medium", triggers: ["lineage", "origin", "source"] },
|
|
18308
|
+
{ id: "data-gov-2", category: "governance", text: "Privacy: PII identified and protected?", severity: "critical", triggers: ["pii", "privacy", "gdpr", "personal"] },
|
|
18309
|
+
{ id: "data-gov-3", category: "governance", text: "Retention: Data lifecycle and deletion policies?", severity: "high", triggers: ["retention", "delete", "archive"] },
|
|
18310
|
+
{ id: "data-gov-4", category: "governance", text: "Access control: Data access properly restricted?", severity: "high", triggers: ["access", "permission", "role"] }
|
|
18311
|
+
],
|
|
18312
|
+
performance: [
|
|
18313
|
+
{ id: "data-perf-1", category: "performance", text: "Partitioning: Data partitioned for query efficiency?", severity: "high", triggers: ["partition", "query", "large"] },
|
|
18314
|
+
{ id: "data-perf-2", category: "performance", text: "Indexing: Appropriate indexes for access patterns?", severity: "high", triggers: ["index", "search", "filter"] },
|
|
18315
|
+
{ id: "data-perf-3", category: "performance", text: "Compression: Storage optimized with compression?", severity: "medium", triggers: ["compress", "storage", "size"] },
|
|
18316
|
+
{ id: "data-perf-4", category: "performance", text: "Caching: Frequently accessed data cached?", severity: "medium", triggers: ["cache", "frequent", "hot"] }
|
|
18317
|
+
]
|
|
18318
|
+
},
|
|
18319
|
+
template: `## DOMAIN CHECKLIST: Data
|
|
18320
|
+
|
|
18321
|
+
Before finalizing, verify each applicable item:
|
|
18322
|
+
|
|
18323
|
+
**Data Quality** (HIGH)
|
|
18324
|
+
- [ ] Schema validation: Conforms to expected schema?
|
|
18325
|
+
- [ ] Null handling: Missing values handled?
|
|
18326
|
+
- [ ] Duplicates: Deduplication in place?
|
|
18327
|
+
- [ ] Freshness: Data SLAs defined?
|
|
18328
|
+
|
|
18329
|
+
**Pipeline** (HIGH)
|
|
18330
|
+
- [ ] Idempotency: Safe to re-run?
|
|
18331
|
+
- [ ] Error handling: Failed records captured?
|
|
18332
|
+
- [ ] Backfill: Historical reprocessing possible?
|
|
18333
|
+
- [ ] Monitoring: Pipeline health visible?
|
|
18334
|
+
|
|
18335
|
+
**Governance** (CRITICAL-HIGH)
|
|
18336
|
+
- [ ] Lineage: Origin and transforms documented?
|
|
18337
|
+
- [ ] Privacy: PII identified and protected?
|
|
18338
|
+
- [ ] Retention: Lifecycle policies defined?
|
|
18339
|
+
- [ ] Access control: Properly restricted?
|
|
18340
|
+
|
|
18341
|
+
**Performance** (HIGH)
|
|
18342
|
+
- [ ] Partitioning: Query-efficient partitions?
|
|
18343
|
+
- [ ] Indexing: Appropriate indexes?
|
|
18344
|
+
- [ ] Compression: Storage optimized?
|
|
18345
|
+
- [ ] Caching: Hot data cached?
|
|
18346
|
+
|
|
18347
|
+
Mark items as [x] when verified, or note [N/A] if not applicable.
|
|
18348
|
+
Flag any concerns with [RISK].
|
|
18349
|
+
`
|
|
18350
|
+
};
|
|
18351
|
+
var PRODUCT_CHECKLIST = {
|
|
18352
|
+
id: "product",
|
|
18353
|
+
name: "Product Checklist",
|
|
18354
|
+
role: "Product Manager",
|
|
18355
|
+
categories: {
|
|
18356
|
+
requirements: [
|
|
18357
|
+
{ id: "prod-req-1", category: "requirements", text: "User problem: Is the problem clearly defined?", severity: "critical", triggers: ["user", "problem", "pain"] },
|
|
18358
|
+
{ id: "prod-req-2", category: "requirements", text: "Success criteria: How will we measure success?", severity: "high", triggers: ["success", "metric", "kpi"] },
|
|
18359
|
+
{ id: "prod-req-3", category: "requirements", text: "Scope: Is scope clearly bounded?", severity: "high", triggers: ["scope", "feature", "requirement"] },
|
|
18360
|
+
{ id: "prod-req-4", category: "requirements", text: 'Acceptance criteria: What defines "done"?', severity: "high", triggers: ["done", "accept", "criteria"] }
|
|
18361
|
+
],
|
|
18362
|
+
stakeholders: [
|
|
18363
|
+
{ id: "prod-stake-1", category: "stakeholders", text: "Alignment: Key stakeholders aligned on approach?", severity: "high", triggers: ["stakeholder", "team", "align"] },
|
|
18364
|
+
{ id: "prod-stake-2", category: "stakeholders", text: "Dependencies: Cross-team dependencies identified?", severity: "medium", triggers: ["dependency", "team", "coordinate"] },
|
|
18365
|
+
{ id: "prod-stake-3", category: "stakeholders", text: "Communication: Rollout communication planned?", severity: "medium", triggers: ["communicate", "announce", "rollout"] },
|
|
18366
|
+
{ id: "prod-stake-4", category: "stakeholders", text: "Feedback: User feedback collection planned?", severity: "medium", triggers: ["feedback", "user", "research"] }
|
|
18367
|
+
],
|
|
18368
|
+
delivery: [
|
|
18369
|
+
{ id: "prod-del-1", category: "delivery", text: "Timeline: Realistic timeline established?", severity: "high", triggers: ["timeline", "deadline", "schedule"] },
|
|
18370
|
+
{ id: "prod-del-2", category: "delivery", text: "Risks: Key risks identified and mitigated?", severity: "high", triggers: ["risk", "blocker", "issue"] },
|
|
18371
|
+
{ id: "prod-del-3", category: "delivery", text: "MVP: Minimum viable scope defined?", severity: "high", triggers: ["mvp", "minimum", "viable"] },
|
|
18372
|
+
{ id: "prod-del-4", category: "delivery", text: "Rollback: Can we undo if issues arise?", severity: "medium", triggers: ["rollback", "undo", "revert"] }
|
|
18373
|
+
]
|
|
18374
|
+
},
|
|
18375
|
+
template: `## DOMAIN CHECKLIST: Product
|
|
18376
|
+
|
|
18377
|
+
Before finalizing, verify each applicable item:
|
|
18378
|
+
|
|
18379
|
+
**Requirements** (CRITICAL-HIGH)
|
|
18380
|
+
- [ ] User problem: Problem clearly defined?
|
|
18381
|
+
- [ ] Success criteria: How measured?
|
|
18382
|
+
- [ ] Scope: Clearly bounded?
|
|
18383
|
+
- [ ] Acceptance criteria: What defines "done"?
|
|
18384
|
+
|
|
18385
|
+
**Stakeholders** (HIGH-MEDIUM)
|
|
18386
|
+
- [ ] Alignment: Key stakeholders aligned?
|
|
18387
|
+
- [ ] Dependencies: Cross-team deps identified?
|
|
18388
|
+
- [ ] Communication: Rollout planned?
|
|
18389
|
+
- [ ] Feedback: Collection planned?
|
|
18390
|
+
|
|
18391
|
+
**Delivery** (HIGH)
|
|
18392
|
+
- [ ] Timeline: Realistic?
|
|
18393
|
+
- [ ] Risks: Identified and mitigated?
|
|
18394
|
+
- [ ] MVP: Minimum scope defined?
|
|
18395
|
+
- [ ] Rollback: Can undo if needed?
|
|
18396
|
+
|
|
18397
|
+
Mark items as [x] when verified, or note [N/A] if not applicable.
|
|
18398
|
+
Flag any concerns with [RISK].
|
|
18399
|
+
`
|
|
18400
|
+
};
|
|
18401
|
+
var NONE_CHECKLIST = {
|
|
18402
|
+
id: "none",
|
|
18403
|
+
name: "No Checklist",
|
|
18404
|
+
role: "General",
|
|
18405
|
+
categories: {},
|
|
18406
|
+
template: ""
|
|
18407
|
+
};
|
|
18408
|
+
var CHECKLISTS = {
|
|
18409
|
+
backend: BACKEND_CHECKLIST,
|
|
18410
|
+
frontend: FRONTEND_CHECKLIST,
|
|
18411
|
+
security: SECURITY_CHECKLIST,
|
|
18412
|
+
quality: QUALITY_CHECKLIST,
|
|
18413
|
+
architecture: ARCHITECTURE_CHECKLIST,
|
|
18414
|
+
devops: DEVOPS_CHECKLIST,
|
|
18415
|
+
data: DATA_CHECKLIST,
|
|
18416
|
+
product: PRODUCT_CHECKLIST,
|
|
18417
|
+
none: NONE_CHECKLIST
|
|
18418
|
+
};
|
|
18419
|
+
function getRoleChecklist(type) {
|
|
18420
|
+
const checklist = CHECKLISTS[type];
|
|
18421
|
+
if (!checklist) {
|
|
18422
|
+
throw new Error(`Unknown checklist type: ${type}`);
|
|
18423
|
+
}
|
|
18424
|
+
return checklist;
|
|
18425
|
+
}
|
|
18426
|
+
function getChecklistTemplate(type) {
|
|
18427
|
+
return getRoleChecklist(type).template;
|
|
18428
|
+
}
|
|
18429
|
+
function applyChecklistOverrides(type, overrides) {
|
|
18430
|
+
let template = getChecklistTemplate(type);
|
|
18431
|
+
if (overrides.remove && overrides.remove.length > 0) {
|
|
18432
|
+
for (const item of overrides.remove) {
|
|
18433
|
+
const regex = new RegExp(`^- \\[ \\] .*${item}.*$`, "gm");
|
|
18434
|
+
template = template.replace(regex, "");
|
|
18435
|
+
}
|
|
18436
|
+
template = template.replace(/\n\n+/g, "\n\n");
|
|
18437
|
+
}
|
|
18438
|
+
if (overrides.add && overrides.add.length > 0) {
|
|
18439
|
+
const customSection = `
|
|
18440
|
+
**Custom Checks**
|
|
18441
|
+
${overrides.add.map((item) => `- [ ] ${item}`).join("\n")}
|
|
18442
|
+
`;
|
|
18443
|
+
template = template.replace(/Mark items as \[x\]/, customSection + "\nMark items as [x]");
|
|
18444
|
+
}
|
|
18445
|
+
return template;
|
|
18446
|
+
}
|
|
18447
|
+
|
|
18448
|
+
// src/agents/cognitive/output-contracts.ts
|
|
18449
|
+
init_esm_shims();
|
|
18450
|
+
var STANDARD_SECTIONS = [
|
|
18451
|
+
{
|
|
18452
|
+
name: "Context",
|
|
18453
|
+
required: true,
|
|
18454
|
+
description: "What was understood about the task",
|
|
18455
|
+
format: `**Context**
|
|
18456
|
+
- Goal: [restated objective in your own words]
|
|
18457
|
+
- Constraints: [key limitations or requirements]
|
|
18458
|
+
- Assumptions: [what was assumed - be explicit]`
|
|
18459
|
+
},
|
|
18460
|
+
{
|
|
18461
|
+
name: "Plan",
|
|
18462
|
+
required: true,
|
|
18463
|
+
description: "What will be/was done",
|
|
18464
|
+
format: `**Plan**
|
|
18465
|
+
1. [Step 1]
|
|
18466
|
+
2. [Step 2]
|
|
18467
|
+
3. [Step 3]
|
|
18468
|
+
...
|
|
18469
|
+
(For trivial tasks: "Plan: Single-step execution")`
|
|
18470
|
+
},
|
|
18471
|
+
{
|
|
18472
|
+
name: "Actions",
|
|
18473
|
+
required: true,
|
|
18474
|
+
description: "What was actually done",
|
|
18475
|
+
format: `**Actions**
|
|
18476
|
+
- [Action 1]: \`path/to/file.ts:line\` - [brief description]
|
|
18477
|
+
- [Action 2]: \`path/to/file.ts:line\` - [brief description]
|
|
18478
|
+
- [Command run]: \`pnpm test\` - [result summary]
|
|
18479
|
+
...`
|
|
18480
|
+
},
|
|
18481
|
+
{
|
|
18482
|
+
name: "Verification",
|
|
18483
|
+
required: true,
|
|
18484
|
+
description: "How the work was validated",
|
|
18485
|
+
format: `**Verification**
|
|
18486
|
+
- Validated:
|
|
18487
|
+
- [x] [What was tested/checked]
|
|
18488
|
+
- [x] [Another validation]
|
|
18489
|
+
- Commands run:
|
|
18490
|
+
- \`pnpm typecheck\` - [result]
|
|
18491
|
+
- \`pnpm test path/to/test\` - [result]
|
|
18492
|
+
- Gaps (not validated):
|
|
18493
|
+
- [ ] [What was NOT tested and why]`
|
|
18494
|
+
},
|
|
18495
|
+
{
|
|
18496
|
+
name: "Risks",
|
|
18497
|
+
required: true,
|
|
18498
|
+
description: "What could go wrong or needs attention",
|
|
18499
|
+
format: `**Risks**
|
|
18500
|
+
- [Risk 1]: [SEVERITY: LOW/MEDIUM/HIGH/CRITICAL] - [mitigation or note]
|
|
18501
|
+
- [Risk 2]: [SEVERITY] - [mitigation or note]
|
|
18502
|
+
(If none: "Risks: None identified for this change")`
|
|
18503
|
+
},
|
|
18504
|
+
{
|
|
18505
|
+
name: "Next Steps",
|
|
18506
|
+
required: true,
|
|
18507
|
+
description: "What should happen after this",
|
|
18508
|
+
format: `**Next Steps**
|
|
18509
|
+
- [ ] [Recommended action 1]
|
|
18510
|
+
- [ ] [Recommended action 2]
|
|
18511
|
+
(If complete: "Next Steps: Ready for review/merge")`
|
|
18512
|
+
}
|
|
18513
|
+
];
|
|
18514
|
+
var FAILURE_SECTIONS = [
|
|
18515
|
+
{
|
|
18516
|
+
name: "Failure",
|
|
18517
|
+
required: true,
|
|
18518
|
+
description: "What failed and why",
|
|
18519
|
+
format: `**Failure**
|
|
18520
|
+
- What failed: [description of the failure]
|
|
18521
|
+
- Root cause: [analysis of why it failed]
|
|
18522
|
+
- Attempted recovery: [what was tried to fix it]
|
|
18523
|
+
- Blocked: [yes/no] - [what's needed to proceed]`
|
|
18524
|
+
}
|
|
18525
|
+
];
|
|
18526
|
+
var STANDARD_CONTRACT = {
|
|
18527
|
+
id: "standard",
|
|
18528
|
+
name: "Standard Output",
|
|
18529
|
+
description: "Full structured output with all sections for complete transparency",
|
|
18530
|
+
sections: STANDARD_SECTIONS,
|
|
18531
|
+
failureSections: FAILURE_SECTIONS,
|
|
18532
|
+
template: `## OUTPUT FORMAT
|
|
18533
|
+
|
|
18534
|
+
Structure your response with these sections:
|
|
18535
|
+
|
|
18536
|
+
**Context**
|
|
18537
|
+
- Goal: [restated objective]
|
|
18538
|
+
- Constraints: [key limitations]
|
|
18539
|
+
- Assumptions: [what was assumed]
|
|
18540
|
+
|
|
18541
|
+
**Plan**
|
|
18542
|
+
1. [Step 1]
|
|
18543
|
+
2. [Step 2]
|
|
18544
|
+
(For trivial tasks: "Plan: Single-step execution")
|
|
18545
|
+
|
|
18546
|
+
**Actions**
|
|
18547
|
+
- [Action]: \`path/to/file.ts:line\` - [description]
|
|
18548
|
+
- [Command]: \`command\` - [result]
|
|
18549
|
+
|
|
18550
|
+
**Verification**
|
|
18551
|
+
- Validated:
|
|
18552
|
+
- [x] [What was tested]
|
|
18553
|
+
- Commands: \`pnpm typecheck\`, \`pnpm test\`
|
|
18554
|
+
- Gaps: [What was NOT tested]
|
|
18555
|
+
|
|
18556
|
+
**Risks**
|
|
18557
|
+
- [Risk]: [SEVERITY] - [mitigation]
|
|
18558
|
+
(If none: "Risks: None identified")
|
|
18559
|
+
|
|
18560
|
+
**Next Steps**
|
|
18561
|
+
- [ ] [Action item]
|
|
18562
|
+
(If complete: "Ready for review")
|
|
18563
|
+
|
|
18564
|
+
---
|
|
18565
|
+
|
|
18566
|
+
**If something fails, add:**
|
|
18567
|
+
|
|
18568
|
+
**Failure**
|
|
18569
|
+
- What failed: [description]
|
|
18570
|
+
- Root cause: [analysis]
|
|
18571
|
+
- Attempted recovery: [what was tried]
|
|
18572
|
+
- Blocked: [yes/no, what's needed]
|
|
18573
|
+
`
|
|
18574
|
+
};
|
|
18575
|
+
var MINIMAL_SECTIONS = [
|
|
18576
|
+
{
|
|
18577
|
+
name: "Done",
|
|
18578
|
+
required: true,
|
|
18579
|
+
description: "What was done",
|
|
18580
|
+
format: `**Done**
|
|
18581
|
+
- [Action]: \`file:line\``
|
|
18582
|
+
},
|
|
18583
|
+
{
|
|
18584
|
+
name: "Verified",
|
|
18585
|
+
required: true,
|
|
18586
|
+
description: "How it was verified",
|
|
18587
|
+
format: `**Verified**: [command or check]`
|
|
18588
|
+
},
|
|
18589
|
+
{
|
|
18590
|
+
name: "Note",
|
|
18591
|
+
required: false,
|
|
18592
|
+
description: "Any important notes",
|
|
18593
|
+
format: `**Note**: [anything important]`
|
|
18594
|
+
}
|
|
18595
|
+
];
|
|
18596
|
+
var MINIMAL_CONTRACT = {
|
|
18597
|
+
id: "minimal",
|
|
18598
|
+
name: "Minimal Output",
|
|
18599
|
+
description: "Condensed output for simple tasks",
|
|
18600
|
+
sections: MINIMAL_SECTIONS,
|
|
18601
|
+
template: `## OUTPUT FORMAT (MINIMAL)
|
|
18602
|
+
|
|
18603
|
+
For simple tasks, use this condensed format:
|
|
18604
|
+
|
|
18605
|
+
**Done**
|
|
18606
|
+
- [Action]: \`file:line\`
|
|
18607
|
+
|
|
18608
|
+
**Verified**: [command or "visual check"]
|
|
18609
|
+
|
|
18610
|
+
**Note**: [anything important, or omit if none]
|
|
18611
|
+
`
|
|
18612
|
+
};
|
|
18613
|
+
var DETAILED_SECTIONS = [
|
|
18614
|
+
...STANDARD_SECTIONS,
|
|
18615
|
+
{
|
|
18616
|
+
name: "Options Considered",
|
|
18617
|
+
required: false,
|
|
18618
|
+
description: "Alternatives that were evaluated",
|
|
18619
|
+
format: `**Options Considered**
|
|
18620
|
+
| Option | Pros | Cons | Why Chosen/Rejected |
|
|
18621
|
+
|--------|------|------|---------------------|
|
|
18622
|
+
| [Option 1] | [pros] | [cons] | [rationale] |
|
|
18623
|
+
| [Option 2] | [pros] | [cons] | [rationale] |`
|
|
18624
|
+
},
|
|
18625
|
+
{
|
|
18626
|
+
name: "Dependencies",
|
|
18627
|
+
required: false,
|
|
18628
|
+
description: "Dependencies and related changes",
|
|
18629
|
+
format: `**Dependencies**
|
|
18630
|
+
- Upstream: [what this depends on]
|
|
18631
|
+
- Downstream: [what depends on this]
|
|
18632
|
+
- Related: [related tickets/PRs]`
|
|
18633
|
+
},
|
|
18634
|
+
{
|
|
18635
|
+
name: "Rollback Plan",
|
|
18636
|
+
required: false,
|
|
18637
|
+
description: "How to undo if needed",
|
|
18638
|
+
format: `**Rollback Plan**
|
|
18639
|
+
1. [Step to revert]
|
|
18640
|
+
2. [Step to verify revert]`
|
|
18641
|
+
}
|
|
18642
|
+
];
|
|
18643
|
+
var DETAILED_CONTRACT = {
|
|
18644
|
+
id: "detailed",
|
|
18645
|
+
name: "Detailed Output",
|
|
18646
|
+
description: "Extended output for complex tasks requiring more documentation",
|
|
18647
|
+
sections: DETAILED_SECTIONS,
|
|
18648
|
+
failureSections: FAILURE_SECTIONS,
|
|
18649
|
+
template: `## OUTPUT FORMAT (DETAILED)
|
|
18650
|
+
|
|
18651
|
+
For complex tasks, use this extended format:
|
|
18652
|
+
|
|
18653
|
+
**Context**
|
|
18654
|
+
- Goal: [restated objective]
|
|
18655
|
+
- Constraints: [key limitations]
|
|
18656
|
+
- Assumptions: [what was assumed]
|
|
18657
|
+
|
|
18658
|
+
**Options Considered** (if applicable)
|
|
18659
|
+
| Option | Pros | Cons | Decision |
|
|
18660
|
+
|--------|------|------|----------|
|
|
18661
|
+
| [Option 1] | [pros] | [cons] | [Chosen/Rejected: why] |
|
|
18662
|
+
|
|
18663
|
+
**Plan**
|
|
18664
|
+
1. [Step 1]
|
|
18665
|
+
2. [Step 2]
|
|
18666
|
+
|
|
18667
|
+
**Actions**
|
|
18668
|
+
- [Action]: \`path/to/file.ts:line\` - [description]
|
|
18669
|
+
- [Command]: \`command\` - [result]
|
|
18670
|
+
|
|
18671
|
+
**Verification**
|
|
18672
|
+
- Validated:
|
|
18673
|
+
- [x] [What was tested]
|
|
18674
|
+
- Commands: \`pnpm typecheck\`, \`pnpm test\`
|
|
18675
|
+
- Gaps: [What was NOT tested]
|
|
18676
|
+
|
|
18677
|
+
**Dependencies** (if applicable)
|
|
18678
|
+
- Upstream: [what this depends on]
|
|
18679
|
+
- Downstream: [what depends on this]
|
|
18680
|
+
|
|
18681
|
+
**Risks**
|
|
18682
|
+
- [Risk]: [SEVERITY] - [mitigation]
|
|
18683
|
+
|
|
18684
|
+
**Rollback Plan** (if applicable)
|
|
18685
|
+
1. [How to undo]
|
|
18686
|
+
|
|
18687
|
+
**Next Steps**
|
|
18688
|
+
- [ ] [Action item]
|
|
18689
|
+
`
|
|
18690
|
+
};
|
|
18691
|
+
var CONTRACTS = {
|
|
18692
|
+
standard: STANDARD_CONTRACT,
|
|
18693
|
+
minimal: MINIMAL_CONTRACT,
|
|
18694
|
+
detailed: DETAILED_CONTRACT
|
|
18695
|
+
};
|
|
18696
|
+
function getOutputContract(type) {
|
|
18697
|
+
const contract = CONTRACTS[type];
|
|
18698
|
+
if (!contract) {
|
|
18699
|
+
throw new Error(`Unknown output contract: ${type}`);
|
|
18700
|
+
}
|
|
18701
|
+
return contract;
|
|
18702
|
+
}
|
|
18703
|
+
function getContractTemplate(type) {
|
|
18704
|
+
return getOutputContract(type).template;
|
|
18705
|
+
}
|
|
18706
|
+
|
|
18707
|
+
// src/agents/cognitive/uncertainty-protocol.ts
|
|
18708
|
+
init_esm_shims();
|
|
18709
|
+
var ASK_FIRST_PROTOCOL = {
|
|
18710
|
+
id: "ask_first",
|
|
18711
|
+
name: "Ask First",
|
|
18712
|
+
askWhen: [
|
|
18713
|
+
"Requirements are ambiguous or could be interpreted multiple ways",
|
|
18714
|
+
"Security or data implications require explicit authorization",
|
|
18715
|
+
"Change scope significantly exceeds the original request",
|
|
18716
|
+
"Irreversible actions are required (delete, migrate, deploy to production)",
|
|
18717
|
+
"You need access to resources, credentials, or information not available",
|
|
18718
|
+
"Multiple valid approaches exist and user preference is unknown",
|
|
18719
|
+
"The task involves user-facing changes where UX matters",
|
|
18720
|
+
"You are making assumptions about business logic"
|
|
18721
|
+
],
|
|
18722
|
+
proceedWhen: [
|
|
18723
|
+
"The request is completely unambiguous",
|
|
18724
|
+
"You are applying a well-documented standard or best practice",
|
|
18725
|
+
"The change is trivial and easily reversible"
|
|
18726
|
+
],
|
|
18727
|
+
assumptionFormat: `**Clarification Needed**
|
|
18728
|
+
|
|
18729
|
+
Before proceeding, I need to clarify:
|
|
18730
|
+
|
|
18731
|
+
1. [Question 1 - be specific about what you need to know]
|
|
18732
|
+
2. [Question 2 - if applicable]
|
|
18733
|
+
|
|
18734
|
+
This will help ensure I deliver exactly what you need.`,
|
|
18735
|
+
template: `## UNCERTAINTY HANDLING (ASK FIRST)
|
|
18736
|
+
|
|
18737
|
+
**Default behavior**: Ask for clarification when uncertain.
|
|
18738
|
+
|
|
18739
|
+
**Ask when** (any of these apply):
|
|
18740
|
+
- Requirements could be interpreted multiple ways
|
|
18741
|
+
- Security or data implications exist
|
|
18742
|
+
- Change scope exceeds original request
|
|
18743
|
+
- Irreversible actions required
|
|
18744
|
+
- Multiple valid approaches exist
|
|
18745
|
+
- Business logic assumptions needed
|
|
18746
|
+
|
|
18747
|
+
**Only proceed without asking when**:
|
|
18748
|
+
- Request is completely unambiguous
|
|
18749
|
+
- Applying documented standard/best practice
|
|
18750
|
+
- Change is trivial and reversible
|
|
18751
|
+
|
|
18752
|
+
**When asking, use this format:**
|
|
18753
|
+
|
|
18754
|
+
**Clarification Needed**
|
|
18755
|
+
|
|
18756
|
+
Before proceeding, I need to clarify:
|
|
18757
|
+
|
|
18758
|
+
1. [Specific question]
|
|
18759
|
+
2. [Specific question if needed]
|
|
18760
|
+
|
|
18761
|
+
This ensures I deliver exactly what you need.
|
|
18762
|
+
|
|
18763
|
+
---
|
|
18764
|
+
|
|
18765
|
+
**Confidence Tagging**: Tag recommendations with confidence level.
|
|
18766
|
+
- **[HIGH]**: Well-established pattern, verified approach
|
|
18767
|
+
- **[MEDIUM]**: Reasonable approach, some assumptions
|
|
18768
|
+
- **[LOW]**: Exploratory, needs validation
|
|
18769
|
+
`
|
|
18770
|
+
};
|
|
18771
|
+
var PROCEED_PROTOCOL = {
|
|
18772
|
+
id: "proceed_with_assumptions",
|
|
18773
|
+
name: "Proceed With Assumptions",
|
|
18774
|
+
askWhen: [
|
|
18775
|
+
"Security-critical decisions require explicit authorization",
|
|
18776
|
+
"Irreversible actions that cannot be undone (data deletion, production deploy)",
|
|
18777
|
+
"Change would break existing functionality or APIs",
|
|
18778
|
+
"You are completely blocked and cannot make progress"
|
|
18779
|
+
],
|
|
18780
|
+
proceedWhen: [
|
|
18781
|
+
"Best practice clearly applies to the situation",
|
|
18782
|
+
"Change is safely reversible (can be undone easily)",
|
|
18783
|
+
"Scope is well-defined and bounded",
|
|
18784
|
+
"Similar patterns exist in the codebase",
|
|
18785
|
+
"You can make reasonable assumptions based on context",
|
|
18786
|
+
"The risk of proceeding is low"
|
|
18787
|
+
],
|
|
18788
|
+
assumptionFormat: `**Assumptions Made**
|
|
18789
|
+
|
|
18790
|
+
I proceeded with these assumptions:
|
|
18791
|
+
- [Assumption 1]: [rationale for this assumption]
|
|
18792
|
+
- [Assumption 2]: [rationale]
|
|
18793
|
+
|
|
18794
|
+
If any are incorrect, let me know and I'll adjust.`,
|
|
18795
|
+
template: `## UNCERTAINTY HANDLING (PROCEED WITH ASSUMPTIONS)
|
|
18796
|
+
|
|
18797
|
+
**Default behavior**: Proceed and document assumptions.
|
|
18798
|
+
|
|
18799
|
+
**Only stop and ask when**:
|
|
18800
|
+
- Security-critical decisions need authorization
|
|
18801
|
+
- Irreversible actions that cannot be undone
|
|
18802
|
+
- Change would break existing functionality
|
|
18803
|
+
- Completely blocked with no path forward
|
|
18804
|
+
|
|
18805
|
+
**Proceed (with documented assumptions) when**:
|
|
18806
|
+
- Best practice clearly applies
|
|
18807
|
+
- Change is safely reversible
|
|
18808
|
+
- Similar patterns exist in codebase
|
|
18809
|
+
- Reasonable assumptions can be made
|
|
18810
|
+
- Risk of proceeding is low
|
|
18811
|
+
|
|
18812
|
+
**When proceeding with assumptions:**
|
|
18813
|
+
|
|
18814
|
+
**Assumptions Made**
|
|
18815
|
+
|
|
18816
|
+
I proceeded with these assumptions:
|
|
18817
|
+
- [Assumption 1]: [rationale]
|
|
18818
|
+
- [Assumption 2]: [rationale]
|
|
18819
|
+
|
|
18820
|
+
If any are incorrect, let me know and I'll adjust.
|
|
18821
|
+
|
|
18822
|
+
---
|
|
18823
|
+
|
|
18824
|
+
**Confidence Tagging**: Tag recommendations with confidence level.
|
|
18825
|
+
- **[HIGH]**: Well-established pattern, verified approach
|
|
18826
|
+
- **[MEDIUM]**: Reasonable approach, some assumptions
|
|
18827
|
+
- **[LOW]**: Exploratory, needs validation
|
|
18828
|
+
`
|
|
18829
|
+
};
|
|
18830
|
+
var BALANCED_PROTOCOL = {
|
|
18831
|
+
id: "balanced",
|
|
18832
|
+
name: "Balanced",
|
|
18833
|
+
askWhen: [
|
|
18834
|
+
"Security implications exist (auth, data access, secrets)",
|
|
18835
|
+
"Data integrity could be affected (migrations, deletions, updates)",
|
|
18836
|
+
"Irreversible actions are involved",
|
|
18837
|
+
"User explicitly requested confirmation before changes",
|
|
18838
|
+
"Multiple fundamentally different approaches exist",
|
|
18839
|
+
"You are unsure which of several options the user would prefer",
|
|
18840
|
+
"The scope is larger than expected (> 2x original estimate)"
|
|
18841
|
+
],
|
|
18842
|
+
proceedWhen: [
|
|
18843
|
+
"Clear best practice applies",
|
|
18844
|
+
"Change is low-risk and reversible",
|
|
18845
|
+
"You have high confidence in the approach",
|
|
18846
|
+
"Similar pattern exists in codebase",
|
|
18847
|
+
"Scope is well-defined and matches expectations",
|
|
18848
|
+
"Edge cases are handled or documented"
|
|
18849
|
+
],
|
|
18850
|
+
assumptionFormat: `**Assumptions**
|
|
18851
|
+
- [Assumption]: [brief rationale]
|
|
18852
|
+
|
|
18853
|
+
Proceeding with the above assumptions. Correct me if any are wrong.`,
|
|
18854
|
+
template: `## UNCERTAINTY HANDLING (BALANCED)
|
|
18855
|
+
|
|
18856
|
+
**Default behavior**: Use risk-based judgment.
|
|
18857
|
+
|
|
18858
|
+
**Stop and ask when** (HIGH RISK):
|
|
18859
|
+
- Security implications (auth, data, secrets)
|
|
18860
|
+
- Data integrity at risk (migrations, deletions)
|
|
18861
|
+
- Irreversible actions involved
|
|
18862
|
+
- User requested confirmation
|
|
18863
|
+
- Scope significantly larger than expected
|
|
18864
|
+
- Multiple fundamentally different approaches
|
|
18865
|
+
|
|
18866
|
+
**Proceed with documented assumptions when** (LOW RISK):
|
|
18867
|
+
- Clear best practice applies
|
|
18868
|
+
- Change is low-risk and reversible
|
|
18869
|
+
- High confidence in approach
|
|
18870
|
+
- Similar pattern in codebase
|
|
18871
|
+
- Scope matches expectations
|
|
18872
|
+
|
|
18873
|
+
**When proceeding with assumptions:**
|
|
18874
|
+
|
|
18875
|
+
**Assumptions**
|
|
18876
|
+
- [Assumption]: [brief rationale]
|
|
18877
|
+
|
|
18878
|
+
Proceeding with the above. Correct me if any are wrong.
|
|
18879
|
+
|
|
18880
|
+
---
|
|
18881
|
+
|
|
18882
|
+
**Risk Assessment Quick Check**:
|
|
18883
|
+
Before deciding to ask vs proceed, consider:
|
|
18884
|
+
1. What's the worst case if I'm wrong? (severity)
|
|
18885
|
+
2. How likely is it that I'm wrong? (probability)
|
|
18886
|
+
3. Can it be easily undone? (reversibility)
|
|
18887
|
+
|
|
18888
|
+
If severity HIGH or probability HIGH and reversibility LOW \u2192 ASK
|
|
18889
|
+
Otherwise \u2192 PROCEED with documented assumptions
|
|
18890
|
+
|
|
18891
|
+
---
|
|
18892
|
+
|
|
18893
|
+
**Confidence Tagging**: Tag recommendations with confidence level.
|
|
18894
|
+
- **[HIGH]**: Well-established pattern, verified approach
|
|
18895
|
+
- **[MEDIUM]**: Reasonable approach, some assumptions
|
|
18896
|
+
- **[LOW]**: Exploratory, needs validation
|
|
18897
|
+
`
|
|
18898
|
+
};
|
|
18899
|
+
var PROTOCOLS = {
|
|
18900
|
+
ask_first: ASK_FIRST_PROTOCOL,
|
|
18901
|
+
proceed_with_assumptions: PROCEED_PROTOCOL,
|
|
18902
|
+
balanced: BALANCED_PROTOCOL
|
|
18903
|
+
};
|
|
18904
|
+
function getUncertaintyProtocol(mode) {
|
|
18905
|
+
const protocol = PROTOCOLS[mode];
|
|
18906
|
+
if (!protocol) {
|
|
18907
|
+
throw new Error(`Unknown uncertainty mode: ${mode}`);
|
|
18908
|
+
}
|
|
18909
|
+
return protocol;
|
|
18910
|
+
}
|
|
18911
|
+
function getProtocolTemplate(mode) {
|
|
18912
|
+
return getUncertaintyProtocol(mode).template;
|
|
18913
|
+
}
|
|
18914
|
+
|
|
18915
|
+
// src/agents/cognitive/prompt-composer.ts
|
|
18916
|
+
function estimateTokens(text) {
|
|
18917
|
+
return Math.ceil(text.length / 4);
|
|
18918
|
+
}
|
|
18919
|
+
function cleanPersonaSection(basePrompt) {
|
|
18920
|
+
let cleaned = basePrompt;
|
|
18921
|
+
cleaned = cleaned.replace(
|
|
18922
|
+
/Your thinking patterns:[\s\S]*?(?=\n\n|\n##|\n\*\*[A-Z]|$)/gi,
|
|
18923
|
+
""
|
|
18924
|
+
);
|
|
18925
|
+
cleaned = cleaned.replace(
|
|
18926
|
+
/Thinking patterns:[\s\S]*?(?=\n\n|\n##|\n\*\*[A-Z]|$)/gi,
|
|
18927
|
+
""
|
|
18928
|
+
);
|
|
18929
|
+
cleaned = cleaned.replace(
|
|
18930
|
+
/## Thinking Patterns[\s\S]*?(?=\n##|$)/gi,
|
|
18931
|
+
""
|
|
18932
|
+
);
|
|
18933
|
+
const lines = cleaned.split("\n");
|
|
18934
|
+
const seenCommunicationStyle = /* @__PURE__ */ new Set();
|
|
18935
|
+
const dedupedLines = lines.filter((line) => {
|
|
18936
|
+
if (line.trim().startsWith("Communication style:")) {
|
|
18937
|
+
const key = line.trim();
|
|
18938
|
+
if (seenCommunicationStyle.has(key)) {
|
|
18939
|
+
return false;
|
|
18940
|
+
}
|
|
18941
|
+
seenCommunicationStyle.add(key);
|
|
18942
|
+
}
|
|
18943
|
+
return true;
|
|
18944
|
+
});
|
|
18945
|
+
cleaned = dedupedLines.join("\n");
|
|
18946
|
+
cleaned = cleaned.replace(/\n{3,}/g, "\n\n");
|
|
18947
|
+
return cleaned.trim();
|
|
18948
|
+
}
|
|
18949
|
+
function formatRepoContext(context) {
|
|
18950
|
+
const lines = ["**Repository Context**"];
|
|
18951
|
+
if (context.packageManager) {
|
|
18952
|
+
lines.push(`- Package manager: ${context.packageManager}`);
|
|
18953
|
+
}
|
|
18954
|
+
if (context.moduleSystem) {
|
|
18955
|
+
lines.push(`- Module system: ${context.moduleSystem}`);
|
|
18956
|
+
}
|
|
18957
|
+
if (context.testFramework) {
|
|
18958
|
+
lines.push(`- Test framework: ${context.testFramework}`);
|
|
18959
|
+
}
|
|
18960
|
+
if (context.tempDir) {
|
|
18961
|
+
lines.push(`- Temp directory: ${context.tempDir}`);
|
|
18962
|
+
}
|
|
18963
|
+
if (context.rules && context.rules.length > 0) {
|
|
18964
|
+
lines.push("- Additional rules:");
|
|
18965
|
+
for (const rule of context.rules) {
|
|
18966
|
+
lines.push(` - ${rule}`);
|
|
18967
|
+
}
|
|
18968
|
+
}
|
|
18969
|
+
return lines.join("\n");
|
|
18970
|
+
}
|
|
18971
|
+
function composePrompt(options) {
|
|
18972
|
+
const { basePrompt, config, additionalContext, repoContext } = options;
|
|
18973
|
+
const sections = [];
|
|
18974
|
+
const personaSection = cleanPersonaSection(basePrompt);
|
|
18975
|
+
if (personaSection) {
|
|
18976
|
+
sections.push(personaSection);
|
|
18977
|
+
}
|
|
18978
|
+
if (repoContext) {
|
|
18979
|
+
sections.push(formatRepoContext(repoContext));
|
|
18980
|
+
}
|
|
18981
|
+
if (additionalContext) {
|
|
18982
|
+
sections.push(additionalContext);
|
|
18983
|
+
}
|
|
18984
|
+
const scaffoldTemplate = getScaffoldTemplate(config.scaffold);
|
|
18985
|
+
sections.push(scaffoldTemplate);
|
|
18986
|
+
if (config.checklist !== "none") {
|
|
18987
|
+
let checklistTemplate = getChecklistTemplate(config.checklist);
|
|
18988
|
+
if (config.checklistOverrides) {
|
|
18989
|
+
checklistTemplate = applyChecklistOverrides(config.checklist, config.checklistOverrides);
|
|
18990
|
+
}
|
|
18991
|
+
if (config.customChecklist && config.customChecklist.length > 0) {
|
|
18992
|
+
const customSection = `
|
|
18993
|
+
**Custom Checks**
|
|
18994
|
+
${config.customChecklist.map((item) => `- [ ] ${item}`).join("\n")}
|
|
18995
|
+
`;
|
|
18996
|
+
checklistTemplate = checklistTemplate.replace(
|
|
18997
|
+
/Mark items as \[x\]/,
|
|
18998
|
+
customSection + "\nMark items as [x]"
|
|
18999
|
+
);
|
|
19000
|
+
}
|
|
19001
|
+
sections.push(checklistTemplate);
|
|
19002
|
+
}
|
|
19003
|
+
const contractTemplate = getContractTemplate(config.outputContract);
|
|
19004
|
+
sections.push(contractTemplate);
|
|
19005
|
+
const protocolTemplate = getProtocolTemplate(config.uncertaintyMode);
|
|
19006
|
+
sections.push(protocolTemplate);
|
|
19007
|
+
const fullText = sections.join("\n\n---\n\n");
|
|
19008
|
+
return {
|
|
19009
|
+
text: fullText,
|
|
19010
|
+
components: {
|
|
19011
|
+
persona: !!personaSection,
|
|
19012
|
+
scaffold: config.scaffold,
|
|
19013
|
+
checklist: config.checklist,
|
|
19014
|
+
outputContract: config.outputContract,
|
|
19015
|
+
uncertainty: config.uncertaintyMode
|
|
19016
|
+
},
|
|
19017
|
+
estimatedTokens: estimateTokens(fullText)
|
|
19018
|
+
};
|
|
19019
|
+
}
|
|
19020
|
+
var AUTOMATOSX_REPO_CONTEXT = {
|
|
19021
|
+
packageManager: "pnpm",
|
|
19022
|
+
moduleSystem: "ESM (strict, with .js extensions)",
|
|
19023
|
+
testFramework: "Vitest",
|
|
19024
|
+
tempDir: "automatosx/tmp/",
|
|
19025
|
+
rules: [
|
|
19026
|
+
"Use explicit .js extensions in imports",
|
|
19027
|
+
"Store temporary files in automatosx/tmp/",
|
|
19028
|
+
"Store PRD files in automatosx/PRD/",
|
|
19029
|
+
"Follow existing patterns in codebase"
|
|
19030
|
+
]
|
|
19031
|
+
};
|
|
19032
|
+
|
|
19033
|
+
// src/types/cognitive.ts
|
|
19034
|
+
init_esm_shims();
|
|
19035
|
+
var DEFAULT_COGNITIVE_CONFIG = {
|
|
19036
|
+
scaffold: "prover",
|
|
19037
|
+
checklist: "none",
|
|
19038
|
+
outputContract: "standard",
|
|
19039
|
+
uncertaintyMode: "balanced"
|
|
19040
|
+
};
|
|
19041
|
+
|
|
16801
19042
|
// src/agents/profile-loader.ts
|
|
16802
19043
|
var ProfileLoader = class {
|
|
16803
19044
|
profilesDir;
|
|
@@ -17487,6 +19728,75 @@ var ProfileLoader = class {
|
|
|
17487
19728
|
}
|
|
17488
19729
|
return void 0;
|
|
17489
19730
|
}
|
|
19731
|
+
/**
|
|
19732
|
+
* Compose cognitive prompt for an agent
|
|
19733
|
+
* v13.0.0+: Assembles the full prompt with reasoning scaffold, checklist, etc.
|
|
19734
|
+
*
|
|
19735
|
+
* @param agentName - Agent name or displayName
|
|
19736
|
+
* @param overrideConfig - Optional config overrides
|
|
19737
|
+
* @returns Composed prompt with all cognitive framework components
|
|
19738
|
+
*/
|
|
19739
|
+
async composeAgentPrompt(agentName, overrideConfig) {
|
|
19740
|
+
const profile = await this.loadProfile(agentName);
|
|
19741
|
+
let config = profile.cognitiveFramework ? { ...profile.cognitiveFramework } : this.inferCognitiveConfig(profile);
|
|
19742
|
+
if (overrideConfig) {
|
|
19743
|
+
config = { ...config, ...overrideConfig };
|
|
19744
|
+
}
|
|
19745
|
+
const composed = composePrompt({
|
|
19746
|
+
basePrompt: profile.systemPrompt,
|
|
19747
|
+
config,
|
|
19748
|
+
repoContext: AUTOMATOSX_REPO_CONTEXT
|
|
19749
|
+
});
|
|
19750
|
+
logger.debug("Composed cognitive prompt", {
|
|
19751
|
+
agent: agentName,
|
|
19752
|
+
scaffold: config.scaffold,
|
|
19753
|
+
checklist: config.checklist,
|
|
19754
|
+
outputContract: config.outputContract,
|
|
19755
|
+
estimatedTokens: composed.estimatedTokens
|
|
19756
|
+
});
|
|
19757
|
+
return composed;
|
|
19758
|
+
}
|
|
19759
|
+
/**
|
|
19760
|
+
* Infer cognitive config from agent profile when not explicitly specified
|
|
19761
|
+
* v13.0.0+: Smart defaults based on agent role and abilities
|
|
19762
|
+
*/
|
|
19763
|
+
inferCognitiveConfig(profile) {
|
|
19764
|
+
const role = profile.role.toLowerCase();
|
|
19765
|
+
const name = profile.name.toLowerCase();
|
|
19766
|
+
let checklist = "none";
|
|
19767
|
+
if (role.includes("backend") || name === "backend" || role.includes("api")) {
|
|
19768
|
+
checklist = "backend";
|
|
19769
|
+
} else if (role.includes("frontend") || name === "frontend" || role.includes("ui")) {
|
|
19770
|
+
checklist = "frontend";
|
|
19771
|
+
} else if (role.includes("security") || name === "security") {
|
|
19772
|
+
checklist = "security";
|
|
19773
|
+
} else if (role.includes("qa") || role.includes("quality") || name === "quality" || role.includes("test")) {
|
|
19774
|
+
checklist = "quality";
|
|
19775
|
+
} else if (role.includes("architect") || name === "architecture") {
|
|
19776
|
+
checklist = "architecture";
|
|
19777
|
+
} else if (role.includes("devops") || name === "devops" || role.includes("infrastructure")) {
|
|
19778
|
+
checklist = "devops";
|
|
19779
|
+
} else if (role.includes("data") || name === "data" || role.includes("pipeline")) {
|
|
19780
|
+
checklist = "data";
|
|
19781
|
+
} else if (role.includes("product") || name === "product") {
|
|
19782
|
+
checklist = "product";
|
|
19783
|
+
}
|
|
19784
|
+
return {
|
|
19785
|
+
...DEFAULT_COGNITIVE_CONFIG,
|
|
19786
|
+
checklist
|
|
19787
|
+
};
|
|
19788
|
+
}
|
|
19789
|
+
/**
|
|
19790
|
+
* Get the composed system prompt for an agent
|
|
19791
|
+
* v13.0.0+: Convenience method that returns just the prompt text
|
|
19792
|
+
*
|
|
19793
|
+
* @param agentName - Agent name or displayName
|
|
19794
|
+
* @returns Full composed prompt text
|
|
19795
|
+
*/
|
|
19796
|
+
async getComposedPrompt(agentName) {
|
|
19797
|
+
const composed = await this.composeAgentPrompt(agentName);
|
|
19798
|
+
return composed.text;
|
|
19799
|
+
}
|
|
17490
19800
|
};
|
|
17491
19801
|
|
|
17492
19802
|
// src/agents/abilities-manager.ts
|
|
@@ -20582,6 +22892,24 @@ ${context.task}`;
|
|
|
20582
22892
|
// src/agents/agent-selector.ts
|
|
20583
22893
|
init_esm_shims();
|
|
20584
22894
|
init_logger();
|
|
22895
|
+
var regexCache = /* @__PURE__ */ new Map();
|
|
22896
|
+
function getCachedRegex(pattern) {
|
|
22897
|
+
if (regexCache.has(pattern)) {
|
|
22898
|
+
return regexCache.get(pattern) ?? null;
|
|
22899
|
+
}
|
|
22900
|
+
try {
|
|
22901
|
+
const regex = new RegExp(pattern, "i");
|
|
22902
|
+
regexCache.set(pattern, regex);
|
|
22903
|
+
return regex;
|
|
22904
|
+
} catch (error) {
|
|
22905
|
+
logger.debug("Invalid regex pattern cached as null", {
|
|
22906
|
+
pattern,
|
|
22907
|
+
error: error instanceof Error ? error.message : String(error)
|
|
22908
|
+
});
|
|
22909
|
+
regexCache.set(pattern, null);
|
|
22910
|
+
return null;
|
|
22911
|
+
}
|
|
22912
|
+
}
|
|
20585
22913
|
function scoreAgent(task, profile) {
|
|
20586
22914
|
let score = 0;
|
|
20587
22915
|
const taskLower = task.toLowerCase();
|
|
@@ -20619,16 +22947,9 @@ function scoreAgent(task, profile) {
|
|
|
20619
22947
|
}
|
|
20620
22948
|
if (profile.selectionMetadata?.redirectWhen) {
|
|
20621
22949
|
for (const rule of profile.selectionMetadata.redirectWhen) {
|
|
20622
|
-
|
|
20623
|
-
|
|
20624
|
-
|
|
20625
|
-
score -= 15;
|
|
20626
|
-
}
|
|
20627
|
-
} catch (error) {
|
|
20628
|
-
logger.debug("Invalid regex pattern in redirectWhen rule", {
|
|
20629
|
-
pattern: rule.phrase,
|
|
20630
|
-
error: error instanceof Error ? error.message : String(error)
|
|
20631
|
-
});
|
|
22950
|
+
const regex = getCachedRegex(rule.phrase);
|
|
22951
|
+
if (regex && regex.test(task)) {
|
|
22952
|
+
score -= 15;
|
|
20632
22953
|
}
|
|
20633
22954
|
}
|
|
20634
22955
|
}
|
|
@@ -23218,8 +25539,8 @@ var BugDetector = class {
|
|
|
23218
25539
|
async loadRulesFromFile(filePath) {
|
|
23219
25540
|
try {
|
|
23220
25541
|
const content = await readFile(filePath, "utf-8");
|
|
23221
|
-
const
|
|
23222
|
-
const parsed =
|
|
25542
|
+
const yaml = await import('js-yaml');
|
|
25543
|
+
const parsed = yaml.load(content);
|
|
23223
25544
|
if (parsed.rules && Array.isArray(parsed.rules)) {
|
|
23224
25545
|
for (const rule of parsed.rules) {
|
|
23225
25546
|
this.addRule(rule);
|
|
@@ -23651,7 +25972,6 @@ var BugFixer = class {
|
|
|
23651
25972
|
}
|
|
23652
25973
|
const directSetIntervalPattern = /setInterval\s*\(/;
|
|
23653
25974
|
if (directSetIntervalPattern.test(line)) {
|
|
23654
|
-
line.match(/^(\s*)/)?.[1] || "";
|
|
23655
25975
|
const newLine = line.replace(
|
|
23656
25976
|
/(setInterval\s*\([^)]+\))/,
|
|
23657
25977
|
"const _interval = $1; if (_interval.unref) _interval.unref()"
|
|
@@ -23678,7 +25998,6 @@ var BugFixer = class {
|
|
|
23678
25998
|
const match = currentLine.match(classPattern);
|
|
23679
25999
|
if (match && match[1]) {
|
|
23680
26000
|
classStartLine = i;
|
|
23681
|
-
match[1];
|
|
23682
26001
|
break;
|
|
23683
26002
|
}
|
|
23684
26003
|
}
|
|
@@ -23730,7 +26049,7 @@ var BugFixer = class {
|
|
|
23730
26049
|
/**
|
|
23731
26050
|
* Apply use DisposableEventEmitter fix
|
|
23732
26051
|
*/
|
|
23733
|
-
applyUseDisposableEventEmitterFix(finding, originalContent,
|
|
26052
|
+
applyUseDisposableEventEmitterFix(finding, originalContent, _lines) {
|
|
23734
26053
|
let fixedContent = originalContent.replace(
|
|
23735
26054
|
/extends\s+EventEmitter\b/g,
|
|
23736
26055
|
"extends DisposableEventEmitter"
|
|
@@ -24652,7 +26971,7 @@ var DUPLICATION_RULES = [
|
|
|
24652
26971
|
suggestion: "Extract to a named constant"
|
|
24653
26972
|
}
|
|
24654
26973
|
];
|
|
24655
|
-
function detectDuplication(filePath, content, lines, ignoreState,
|
|
26974
|
+
function detectDuplication(filePath, content, lines, ignoreState, _config) {
|
|
24656
26975
|
const findings = [];
|
|
24657
26976
|
findings.push(...detectDuplicateBlocks(filePath, content, lines, ignoreState));
|
|
24658
26977
|
findings.push(...detectRepeatedConditionals(filePath, content, lines, ignoreState));
|
|
@@ -24679,7 +26998,7 @@ function detectDuplicateBlocks(filePath, content, lines, ignoreState) {
|
|
|
24679
26998
|
}
|
|
24680
26999
|
blockHashes.get(blockHash).push({ start: i + 1, end: i + MIN_BLOCK_SIZE });
|
|
24681
27000
|
}
|
|
24682
|
-
for (const [
|
|
27001
|
+
for (const [_hash, locations] of blockHashes) {
|
|
24683
27002
|
if (locations.length > 1) {
|
|
24684
27003
|
for (let i = 1; i < locations.length; i++) {
|
|
24685
27004
|
const loc = locations[i];
|
|
@@ -24728,7 +27047,7 @@ function detectRepeatedConditionals(filePath, content, lines, ignoreState) {
|
|
|
24728
27047
|
}
|
|
24729
27048
|
conditionPattern.lastIndex = 0;
|
|
24730
27049
|
}
|
|
24731
|
-
for (const [
|
|
27050
|
+
for (const [_condition, lineNums] of conditionalCounts) {
|
|
24732
27051
|
if (lineNums.length >= 2) {
|
|
24733
27052
|
const firstLine = lineNums[0];
|
|
24734
27053
|
const secondLine = lineNums[1];
|
|
@@ -24891,7 +27210,7 @@ var THRESHOLDS = {
|
|
|
24891
27210
|
maxCyclomaticComplexity: 10,
|
|
24892
27211
|
maxChainedCalls: 4
|
|
24893
27212
|
};
|
|
24894
|
-
function detectReadability(filePath, content, lines, ignoreState,
|
|
27213
|
+
function detectReadability(filePath, content, lines, ignoreState, _config) {
|
|
24895
27214
|
const findings = [];
|
|
24896
27215
|
findings.push(...detectLongFunctions(filePath, content, lines, ignoreState));
|
|
24897
27216
|
findings.push(...detectDeepNesting(filePath, content, lines, ignoreState));
|
|
@@ -25267,7 +27586,7 @@ var PERFORMANCE_RULES = [
|
|
|
25267
27586
|
suggestion: "Remove await - async functions automatically wrap return values in promises"
|
|
25268
27587
|
}
|
|
25269
27588
|
];
|
|
25270
|
-
function detectPerformance(filePath, content, lines, ignoreState,
|
|
27589
|
+
function detectPerformance(filePath, content, lines, ignoreState, _config) {
|
|
25271
27590
|
const findings = [];
|
|
25272
27591
|
findings.push(...detectSyncInAsync(filePath, content, lines, ignoreState));
|
|
25273
27592
|
findings.push(...detectNPlusOne(filePath, content, lines, ignoreState));
|
|
@@ -25682,7 +28001,7 @@ var HARDCODE_RULES = [
|
|
|
25682
28001
|
suggestion: "Extract timeout to a named constant or config"
|
|
25683
28002
|
}
|
|
25684
28003
|
];
|
|
25685
|
-
function detectHardcode(filePath, content, lines, ignoreState,
|
|
28004
|
+
function detectHardcode(filePath, content, lines, ignoreState, _config) {
|
|
25686
28005
|
const findings = [];
|
|
25687
28006
|
findings.push(...detectMagicNumbers(filePath, content, lines, ignoreState));
|
|
25688
28007
|
findings.push(...detectHardcodedUrls(filePath, content, lines, ignoreState));
|
|
@@ -26038,7 +28357,7 @@ var NAMING_RULES = [
|
|
|
26038
28357
|
suggestion: "Use is/has/can/should prefix for boolean variables"
|
|
26039
28358
|
}
|
|
26040
28359
|
];
|
|
26041
|
-
function detectNaming(filePath, content, lines, ignoreState,
|
|
28360
|
+
function detectNaming(filePath, content, lines, ignoreState, _config) {
|
|
26042
28361
|
const findings = [];
|
|
26043
28362
|
findings.push(...detectSingleLetterVariables(filePath, content, lines, ignoreState));
|
|
26044
28363
|
findings.push(...detectHungarianNotation(filePath, content, lines, ignoreState));
|
|
@@ -26321,7 +28640,7 @@ var CONDITIONAL_RULES = [
|
|
|
26321
28640
|
suggestion: "Use the condition directly (or negate it)"
|
|
26322
28641
|
}
|
|
26323
28642
|
];
|
|
26324
|
-
function detectConditionals(filePath, content, lines, ignoreState,
|
|
28643
|
+
function detectConditionals(filePath, content, lines, ignoreState, _config) {
|
|
26325
28644
|
const findings = [];
|
|
26326
28645
|
findings.push(...detectDeeplyNestedIf(filePath, content, lines, ignoreState));
|
|
26327
28646
|
findings.push(...detectComplexConditions(filePath, content, lines, ignoreState));
|
|
@@ -26634,7 +28953,7 @@ var DEAD_CODE_RULES = [
|
|
|
26634
28953
|
suggestion: "Implement function or add TODO comment"
|
|
26635
28954
|
}
|
|
26636
28955
|
];
|
|
26637
|
-
function detectDeadCode(filePath, content, lines, ignoreState,
|
|
28956
|
+
function detectDeadCode(filePath, content, lines, ignoreState, _config) {
|
|
26638
28957
|
const findings = [];
|
|
26639
28958
|
findings.push(...detectUnusedImports(filePath, content, lines, ignoreState));
|
|
26640
28959
|
findings.push(...detectUnusedVariables(filePath, content, lines, ignoreState));
|
|
@@ -26928,7 +29247,7 @@ var TYPE_SAFETY_RULES = [
|
|
|
26928
29247
|
fileExtensions: [".ts", ".tsx"]
|
|
26929
29248
|
}
|
|
26930
29249
|
];
|
|
26931
|
-
function detectTypeSafety(filePath, content, lines, ignoreState,
|
|
29250
|
+
function detectTypeSafety(filePath, content, lines, ignoreState, _config) {
|
|
26932
29251
|
const findings = [];
|
|
26933
29252
|
if (!filePath.endsWith(".ts") && !filePath.endsWith(".tsx")) {
|
|
26934
29253
|
return findings;
|
|
@@ -31137,7 +33456,7 @@ var createTaskSchema = {
|
|
|
31137
33456
|
// src/mcp/tools/task/run-task.ts
|
|
31138
33457
|
init_esm_shims();
|
|
31139
33458
|
init_logger();
|
|
31140
|
-
function createRunTaskHandler(
|
|
33459
|
+
function createRunTaskHandler(_deps) {
|
|
31141
33460
|
return async (input, context) => {
|
|
31142
33461
|
const startTime = Date.now();
|
|
31143
33462
|
if (context?.signal?.aborted) {
|
|
@@ -33687,6 +36006,17 @@ Use this tool first to understand what AutomatosX offers.`,
|
|
|
33687
36006
|
mode: "sdk"
|
|
33688
36007
|
}));
|
|
33689
36008
|
}
|
|
36009
|
+
if (config.providers["qwen"]?.enabled) {
|
|
36010
|
+
const { QwenProvider: QwenProvider2 } = await Promise.resolve().then(() => (init_qwen_provider(), qwen_provider_exports));
|
|
36011
|
+
const qwenConfig = config.providers["qwen"];
|
|
36012
|
+
providers.push(new QwenProvider2({
|
|
36013
|
+
name: "qwen",
|
|
36014
|
+
enabled: true,
|
|
36015
|
+
priority: qwenConfig.priority,
|
|
36016
|
+
timeout: qwenConfig.timeout,
|
|
36017
|
+
mode: qwenConfig.mode || "sdk"
|
|
36018
|
+
}));
|
|
36019
|
+
}
|
|
33690
36020
|
const healthCheckInterval = config.router?.healthCheckInterval;
|
|
33691
36021
|
this.router = new Router({
|
|
33692
36022
|
providers,
|