@vfarcic/dot-ai 0.158.0 → 0.160.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 +3 -1
- package/dist/core/ai-provider-factory.d.ts.map +1 -1
- package/dist/core/ai-provider-factory.js +7 -0
- package/dist/core/capability-scan-workflow.d.ts.map +1 -1
- package/dist/core/capability-scan-workflow.js +21 -2
- package/dist/core/model-config.d.ts +1 -0
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +1 -0
- package/dist/core/packaging.d.ts.map +1 -1
- package/dist/core/packaging.js +12 -4
- package/dist/core/providers/host-provider.d.ts +43 -0
- package/dist/core/providers/host-provider.d.ts.map +1 -0
- package/dist/core/providers/host-provider.js +314 -0
- package/dist/core/providers/tool-utils.d.ts +21 -0
- package/dist/core/providers/tool-utils.d.ts.map +1 -0
- package/dist/core/providers/tool-utils.js +57 -0
- package/dist/core/schema.js +1 -1
- package/dist/interfaces/mcp.d.ts +2 -0
- package/dist/interfaces/mcp.d.ts.map +1 -1
- package/dist/interfaces/mcp.js +39 -1
- package/dist/tools/answer-question.d.ts.map +1 -1
- package/dist/tools/answer-question.js +24 -28
- package/dist/tools/choose-solution.d.ts.map +1 -1
- package/dist/tools/choose-solution.js +6 -1
- package/dist/tools/remediate.js +2 -2
- package/package.json +2 -1
- package/prompts/host-tools.md +15 -0
- package/prompts/intent-refinement-guidance.md +15 -0
package/README.md
CHANGED
|
@@ -31,6 +31,8 @@ DevOps AI Toolkit brings AI-powered intelligence to platform engineering, Kubern
|
|
|
31
31
|
|
|
32
32
|
Built on the Model Context Protocol (MCP), it integrates seamlessly with Claude Code, Cursor, and VS Code to provide conversational interaction for complex DevOps and development tasks.
|
|
33
33
|
|
|
34
|
+

|
|
35
|
+
|
|
34
36
|
## Mission
|
|
35
37
|
|
|
36
38
|
DevOps AI Toolkit democratizes platform engineering and cloud native operations by making complex workflows accessible through AI-powered automation. We eliminate the expertise barrier that prevents teams from adopting best practices in Kubernetes operations, repository governance, and standardized development workflows—making professional-grade DevOps accessible through natural language interaction.
|
|
@@ -85,7 +87,7 @@ Access curated prompts as native slash commands (`/dot-ai:prompt-name`) in your
|
|
|
85
87
|
📖 [Learn more →](./docs/guides/mcp-prompts-guide.md)
|
|
86
88
|
|
|
87
89
|
### ⚡ AI Integration
|
|
88
|
-
Works with Claude Code, Cursor, VS Code via Model Context Protocol. Supports multiple AI providers (Claude, GPT, Gemini) for flexibility and cost optimization.
|
|
90
|
+
Works with Claude Code, Cursor, VS Code via Model Context Protocol. Supports multiple AI providers (Claude, GPT, Gemini, Host LLM) for flexibility and cost optimization.
|
|
89
91
|
📖 [AI Model Configuration](./docs/setup/mcp-setup.md#ai-model-configuration)
|
|
90
92
|
|
|
91
93
|
## Quick Start
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-provider-factory.d.ts","sourceRoot":"","sources":["../../src/core/ai-provider-factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,UAAU,EACV,gBAAgB,EACjB,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"ai-provider-factory.d.ts","sourceRoot":"","sources":["../../src/core/ai-provider-factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,UAAU,EACV,gBAAgB,EACjB,MAAM,yBAAyB,CAAC;AA4BjC;;;;;;;;;;;;;;GAcG;AACH,qBAAa,iBAAiB;IAC5B;;;;;;OAMG;IACH,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,GAAG,UAAU;IA2BnD;;;;;;;;;;OAUG;IACH,MAAM,CAAC,aAAa,IAAI,UAAU;IAgFlC;;;;;OAKG;IACH,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAMrD;;;;OAIG;IACH,MAAM,CAAC,qBAAqB,IAAI,MAAM,EAAE;IAMxC;;;;;OAKG;IACH,MAAM,CAAC,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;CAGxD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,UAAU,CAE7C"}
|
|
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.AIProviderFactory = void 0;
|
|
13
13
|
exports.createAIProvider = createAIProvider;
|
|
14
14
|
const vercel_provider_1 = require("./providers/vercel-provider");
|
|
15
|
+
const host_provider_1 = require("./providers/host-provider");
|
|
15
16
|
const noop_provider_1 = require("./providers/noop-provider");
|
|
16
17
|
const model_config_1 = require("./model-config");
|
|
17
18
|
/**
|
|
@@ -53,6 +54,9 @@ class AIProviderFactory {
|
|
|
53
54
|
* @throws Error if provider type is unsupported or configuration is invalid
|
|
54
55
|
*/
|
|
55
56
|
static create(config) {
|
|
57
|
+
if (config.provider === model_config_1.CURRENT_MODELS.host) {
|
|
58
|
+
return new host_provider_1.HostProvider();
|
|
59
|
+
}
|
|
56
60
|
// Validate configuration
|
|
57
61
|
if (!config.apiKey) {
|
|
58
62
|
throw new Error(`API key is required for ${config.provider} provider`);
|
|
@@ -101,6 +105,9 @@ class AIProviderFactory {
|
|
|
101
105
|
// AWS credentials checked at runtime by AWS SDK (env vars, ~/.aws/credentials, IAM roles)
|
|
102
106
|
apiKey = 'bedrock-uses-aws-credentials';
|
|
103
107
|
}
|
|
108
|
+
else if (providerType === model_config_1.CURRENT_MODELS.host) {
|
|
109
|
+
return new host_provider_1.HostProvider();
|
|
110
|
+
}
|
|
104
111
|
else {
|
|
105
112
|
const apiKeyEnvVar = PROVIDER_ENV_KEYS[providerType];
|
|
106
113
|
if (!apiKeyEnvVar) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capability-scan-workflow.d.ts","sourceRoot":"","sources":["../../src/core/capability-scan-workflow.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAMtE,MAAM,MAAM,6BAA6B,GAAG,CAAC,OAAO,EAAE,qBAAqB,EAAE,QAAQ,EAAE,qBAAqB,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,qBAAqB,CAAC,EAAE,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;AACzL,MAAM,MAAM,0BAA0B,GAAG,CAAC,OAAO,EAAE,qBAAqB,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;AAChI,MAAM,MAAM,sBAAsB,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,MAAM,CAAC;AAC1F,MAAM,MAAM,wCAAwC,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,GAAG,CAAC;AAoBlN,UAAU,qBAAqB;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,oBAAoB,GAAG,wBAAwB,GAAG,UAAU,GAAG,UAAU,CAAC;IACvF,iBAAiB,CAAC,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC3F;AAsBD;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,qBAAqB,EAC9B,IAAI,EAAE,GAAG,EACT,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,iBAAiB,EAAE,uBAAuB,EAC1C,oBAAoB,EAAE,sBAAsB,EAC5C,2BAA2B,EAAE,6BAA6B,EAC1D,wBAAwB,EAAE,0BAA0B,EACpD,sCAAsC,EAAE,wCAAwC,EAChF,gBAAgB,EAAE,CAAC,OAAO,EAAE,qBAAqB,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,2BAA2B,EAAE,6BAA6B,EAAE,wBAAwB,EAAE,0BAA0B,EAAE,sCAAsC,EAAE,wCAAwC,KAAK,OAAO,CAAC,GAAG,CAAC,GAC7Y,OAAO,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"capability-scan-workflow.d.ts","sourceRoot":"","sources":["../../src/core/capability-scan-workflow.ts"],"names":[],"mappings":"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"}
|
|
@@ -87,8 +87,27 @@ async function handleResourceSelection(session, args, logger, requestId, capabil
|
|
|
87
87
|
selectedResources: 'all',
|
|
88
88
|
currentResourceIndex: 0 // Start with first resource
|
|
89
89
|
}, args);
|
|
90
|
-
//
|
|
91
|
-
|
|
90
|
+
// Start scanning in background (don't await) to avoid MCP timeout
|
|
91
|
+
handleScanningFn(session, { ...args, response: undefined }, logger, requestId, capabilityService, parseNumericResponse, transitionCapabilitySession, cleanupCapabilitySession, createCapabilityScanCompletionResponse)
|
|
92
|
+
.catch(error => {
|
|
93
|
+
logger.error('Background capability scan failed', error, {
|
|
94
|
+
requestId,
|
|
95
|
+
sessionId: session.sessionId
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
// Return immediately - user can check progress with operation: 'progress'
|
|
99
|
+
return {
|
|
100
|
+
success: true,
|
|
101
|
+
operation: 'scan',
|
|
102
|
+
dataType: 'capabilities',
|
|
103
|
+
status: 'started',
|
|
104
|
+
sessionId: session.sessionId,
|
|
105
|
+
message: 'Capability scan started. Use operation "progress" to check status.',
|
|
106
|
+
checkProgress: {
|
|
107
|
+
dataType: 'capabilities',
|
|
108
|
+
operation: 'progress'
|
|
109
|
+
}
|
|
110
|
+
};
|
|
92
111
|
}
|
|
93
112
|
if (normalizedResponse === 'specific') {
|
|
94
113
|
// Transition to resource specification
|
|
@@ -13,6 +13,7 @@ export declare const CURRENT_MODELS: {
|
|
|
13
13
|
readonly kimi: "kimi-k2-0905-preview";
|
|
14
14
|
readonly kimi_thinking: "kimi-k2-thinking";
|
|
15
15
|
readonly xai: "grok-4";
|
|
16
|
+
readonly host: "host";
|
|
16
17
|
readonly openrouter: "anthropic/claude-haiku-4.5";
|
|
17
18
|
readonly custom: "gpt-5.1-codex";
|
|
18
19
|
readonly amazon_bedrock: "global.anthropic.claude-sonnet-4-20250514-v1:0";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-config.d.ts","sourceRoot":"","sources":["../../src/core/model-config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,cAAc
|
|
1
|
+
{"version":3,"file":"model-config.d.ts","sourceRoot":"","sources":["../../src/core/model-config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,cAAc;;;;;;;;;;;;;CAajB,CAAC;AAEX;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,OAAO,cAAc,GAAG,MAAM,CAE7E"}
|
|
@@ -17,6 +17,7 @@ exports.CURRENT_MODELS = {
|
|
|
17
17
|
kimi: 'kimi-k2-0905-preview', // PRD #237: Moonshot AI Kimi K2 - standard model with 256K context
|
|
18
18
|
kimi_thinking: 'kimi-k2-thinking', // PRD #237: Moonshot AI Kimi K2 - extended thinking variant
|
|
19
19
|
xai: 'grok-4',
|
|
20
|
+
host: 'host', // Delegates generation to the client via MCP Sampling
|
|
20
21
|
openrouter: 'anthropic/claude-haiku-4.5', // PRD #194: OpenRouter default model (overridden by AI_MODEL env var)
|
|
21
22
|
custom: 'gpt-5.1-codex', // PRD #194: Custom endpoint default model (overridden by AI_MODEL env var)
|
|
22
23
|
amazon_bedrock: 'global.anthropic.claude-sonnet-4-20250514-v1:0' // PRD #175: Amazon Bedrock default model (overridden by AI_MODEL env var)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packaging.d.ts","sourceRoot":"","sources":["../../src/core/packaging.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,MAAM,GAAG,WAAW,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,MAAM,EAAE,YAAY,CAAC;CACtB;AAED;;GAEG;AACH,UAAU,qBAAqB;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;CACzB;
|
|
1
|
+
{"version":3,"file":"packaging.d.ts","sourceRoot":"","sources":["../../src/core/packaging.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,MAAM,GAAG,WAAW,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,MAAM,EAAE,YAAY,CAAC;CACtB;AAED;;GAEG;AACH,UAAU,qBAAqB;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;CACzB;AAwOD;;;;;;;;;;;;GAYG;AACH,wBAAsB,gBAAgB,CACpC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,GAAG,EACb,YAAY,EAAE,YAAY,EAC1B,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,qBAAqB,EACpC,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,eAAe,CAAC,CA+D1B"}
|
package/dist/core/packaging.js
CHANGED
|
@@ -29,6 +29,8 @@ Generate the following files:
|
|
|
29
29
|
- Use the actual values from user answers as defaults
|
|
30
30
|
|
|
31
31
|
3. **templates/*.yaml** - One file per Kubernetes resource type
|
|
32
|
+
- **CRITICAL**: Include ALL manifests from the raw input - do not filter out any resources
|
|
33
|
+
- This includes custom resources (CRDs) like Solution, Crossplane resources, etc.
|
|
32
34
|
- Use \`{{ .Release.Name }}\` for resource names
|
|
33
35
|
- Use \`{{ .Release.Namespace }}\` when namespace is referenced
|
|
34
36
|
- Use \`{{ .Values.xxx }}\` for externalized configuration
|
|
@@ -74,16 +76,17 @@ Generate a production-ready Kustomize structure with base/ and overlays/ directo
|
|
|
74
76
|
- List all resource files in \`resources:\` section (e.g., \`- deployment.yaml\`)
|
|
75
77
|
- Do NOT include namespace, patches, or images here - base should be generic/reusable
|
|
76
78
|
|
|
77
|
-
2. **base/*.yaml** - Base Kubernetes manifests
|
|
79
|
+
2. **base/*.yaml** - Base Kubernetes manifests (generic, reusable)
|
|
78
80
|
- One file per Kubernetes resource (deployment.yaml, service.yaml, etc.)
|
|
79
|
-
- Include complete, valid manifests
|
|
81
|
+
- Include complete, valid manifests WITHOUT namespace in metadata
|
|
80
82
|
- For container images: use ONLY the repository (e.g., \`image: nginx\` or \`image: ghcr.io/org/app\`) WITHOUT any tag - tags are set in overlays
|
|
81
83
|
- Resource names should be consistent across all files
|
|
84
|
+
- **IMPORTANT**: Resources with namespace-specific internal references (e.g., spec fields referencing other namespaced resources) should go in overlays, not base, since kustomize only transforms metadata.namespace
|
|
82
85
|
|
|
83
86
|
3. **overlays/production/kustomization.yaml** - Production overlay (THE KEY FILE FOR CUSTOMIZATION)
|
|
84
87
|
- \`apiVersion: kustomize.config.k8s.io/v1beta1\`
|
|
85
88
|
- \`kind: Kustomization\`
|
|
86
|
-
- Reference base: \`resources: [../../base]\`
|
|
89
|
+
- Reference base AND any overlay-specific resources: \`resources: [../../base, solution.yaml]\`
|
|
87
90
|
- Use \`namespace:\` field with the user-specified namespace
|
|
88
91
|
- **REQUIRED**: Use \`images:\` section to set image tags from user answers:
|
|
89
92
|
\`\`\`yaml
|
|
@@ -94,7 +97,12 @@ Generate a production-ready Kustomize structure with base/ and overlays/ directo
|
|
|
94
97
|
- Use \`replicas:\` section if replicas were customized
|
|
95
98
|
- Use \`patches:\` for other customizations (resources, env vars, etc.)
|
|
96
99
|
|
|
97
|
-
4. **
|
|
100
|
+
4. **overlays/production/*.yaml** - Environment-specific resources
|
|
101
|
+
- Place resources with namespace-specific internal references here (e.g., Solution CRD with spec.resources[].namespace)
|
|
102
|
+
- These resources contain namespace values that kustomize won't transform
|
|
103
|
+
- This allows different overlays (staging, dev) to have their own versions
|
|
104
|
+
|
|
105
|
+
5. **kustomization.yaml** (root) - Points to production overlay for easy deployment
|
|
98
106
|
- Simple file that references the production overlay: \`resources: [overlays/production]\`
|
|
99
107
|
|
|
100
108
|
**WHY THIS STRUCTURE**:
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { AIProvider, AIResponse, AgenticResult, ToolLoopConfig } from '../ai-provider.interface';
|
|
2
|
+
export interface SamplingMessage {
|
|
3
|
+
role: 'user' | 'assistant';
|
|
4
|
+
content: {
|
|
5
|
+
type: 'text';
|
|
6
|
+
text: string;
|
|
7
|
+
} | string;
|
|
8
|
+
}
|
|
9
|
+
export interface SamplingResult {
|
|
10
|
+
content: {
|
|
11
|
+
type: 'text';
|
|
12
|
+
text: string;
|
|
13
|
+
} | string;
|
|
14
|
+
}
|
|
15
|
+
export type SamplingHandler = (messages: SamplingMessage[], systemPrompt?: string, options?: any) => Promise<SamplingResult>;
|
|
16
|
+
export declare class HostProvider implements AIProvider {
|
|
17
|
+
private static samplingHandler?;
|
|
18
|
+
private debugMode;
|
|
19
|
+
constructor();
|
|
20
|
+
setSamplingHandler(handler: SamplingHandler): void;
|
|
21
|
+
isInitialized(): boolean;
|
|
22
|
+
getDefaultModel(): string;
|
|
23
|
+
getProviderType(): string;
|
|
24
|
+
getModelName(): string;
|
|
25
|
+
private logDebugIfEnabled;
|
|
26
|
+
sendMessage(message: string, operation?: string, evaluationContext?: {
|
|
27
|
+
user_intent?: string;
|
|
28
|
+
interaction_id?: string;
|
|
29
|
+
}): Promise<AIResponse>;
|
|
30
|
+
/**
|
|
31
|
+
* Execute a tool loop with the host model
|
|
32
|
+
*
|
|
33
|
+
* The tool loop relies on a specific JSON format embedded in markdown code blocks:
|
|
34
|
+
* ```json
|
|
35
|
+
* {
|
|
36
|
+
* "tool": "toolName",
|
|
37
|
+
* "arguments": { ... }
|
|
38
|
+
* }
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
toolLoop(config: ToolLoopConfig): Promise<AgenticResult>;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=host-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-provider.d.ts","sourceRoot":"","sources":["../../../src/core/providers/host-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,UAAU,EACV,aAAa,EACb,cAAc,EACf,MAAM,0BAA0B,CAAC;AAkBlC,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC;CAClD;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC;CAClD;AAED,MAAM,MAAM,eAAe,GAAG,CAC5B,QAAQ,EAAE,eAAe,EAAE,EAC3B,YAAY,CAAC,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE,GAAG,KACV,OAAO,CAAC,cAAc,CAAC,CAAC;AAE7B,qBAAa,YAAa,YAAW,UAAU;IAC7C,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,CAAkB;IACjD,OAAO,CAAC,SAAS,CAAU;;IAM3B,kBAAkB,CAAC,OAAO,EAAE,eAAe;IAI3C,aAAa,IAAI,OAAO;IAIxB,eAAe,IAAI,MAAM;IAIzB,eAAe,IAAI,MAAM;IAIzB,YAAY,IAAI,MAAM;IAItB,OAAO,CAAC,iBAAiB;IAwBnB,WAAW,CACf,OAAO,EAAE,MAAM,EACf,SAAS,GAAE,MAAkB,EAC7B,iBAAiB,CAAC,EAAE;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB,GACA,OAAO,CAAC,UAAU,CAAC;IA4HtB;;;;;;;;;;OAUG;IACG,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;CA0K/D"}
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.HostProvider = void 0;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const prompts_1 = require("../../tools/prompts");
|
|
39
|
+
const model_config_1 = require("../model-config");
|
|
40
|
+
const provider_debug_utils_1 = require("./provider-debug-utils");
|
|
41
|
+
const ai_tracing_1 = require("../tracing/ai-tracing");
|
|
42
|
+
const tool_utils_1 = require("./tool-utils");
|
|
43
|
+
class HostProvider {
|
|
44
|
+
static samplingHandler;
|
|
45
|
+
debugMode;
|
|
46
|
+
constructor() {
|
|
47
|
+
this.debugMode = process.env.DEBUG_DOT_AI === 'true';
|
|
48
|
+
}
|
|
49
|
+
setSamplingHandler(handler) {
|
|
50
|
+
HostProvider.samplingHandler = handler;
|
|
51
|
+
}
|
|
52
|
+
isInitialized() {
|
|
53
|
+
return !!HostProvider.samplingHandler;
|
|
54
|
+
}
|
|
55
|
+
getDefaultModel() {
|
|
56
|
+
return model_config_1.CURRENT_MODELS.host;
|
|
57
|
+
}
|
|
58
|
+
getProviderType() {
|
|
59
|
+
return model_config_1.CURRENT_MODELS.host;
|
|
60
|
+
}
|
|
61
|
+
getModelName() {
|
|
62
|
+
return model_config_1.CURRENT_MODELS.host;
|
|
63
|
+
}
|
|
64
|
+
logDebugIfEnabled(operation, prompt, response) {
|
|
65
|
+
if (!this.debugMode)
|
|
66
|
+
return null;
|
|
67
|
+
const debugId = (0, provider_debug_utils_1.generateDebugId)(operation);
|
|
68
|
+
(0, provider_debug_utils_1.debugLogInteraction)(debugId, prompt, response, operation, this.getProviderType(), this.getModelName(), this.debugMode);
|
|
69
|
+
return {
|
|
70
|
+
promptFile: `${debugId}_prompt.md`,
|
|
71
|
+
responseFile: `${debugId}_response.md`,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
async sendMessage(message, operation = 'generic', evaluationContext) {
|
|
75
|
+
if (!HostProvider.samplingHandler) {
|
|
76
|
+
throw new Error('Host provider is not connected to MCP server');
|
|
77
|
+
}
|
|
78
|
+
return await (0, ai_tracing_1.withAITracing)({
|
|
79
|
+
provider: this.getProviderType(),
|
|
80
|
+
model: this.getModelName(),
|
|
81
|
+
operation: 'chat',
|
|
82
|
+
}, async () => {
|
|
83
|
+
const startTime = Date.now();
|
|
84
|
+
const messages = [
|
|
85
|
+
{ role: 'user', content: { type: 'text', text: message } },
|
|
86
|
+
];
|
|
87
|
+
try {
|
|
88
|
+
const result = await HostProvider.samplingHandler(messages, undefined, {
|
|
89
|
+
operation,
|
|
90
|
+
evaluationContext,
|
|
91
|
+
});
|
|
92
|
+
let content = '';
|
|
93
|
+
if (typeof result.content === 'object' && result.content.type === 'text') {
|
|
94
|
+
content = result.content.text;
|
|
95
|
+
}
|
|
96
|
+
else if (typeof result.content === 'string') {
|
|
97
|
+
content = result.content;
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
content = JSON.stringify(result.content);
|
|
101
|
+
}
|
|
102
|
+
const response = {
|
|
103
|
+
content,
|
|
104
|
+
usage: {
|
|
105
|
+
input_tokens: 0,
|
|
106
|
+
output_tokens: 0,
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
const durationMs = Date.now() - startTime;
|
|
110
|
+
// Debug log the interaction if enabled
|
|
111
|
+
if (this.debugMode) {
|
|
112
|
+
this.logDebugIfEnabled(operation, message, response);
|
|
113
|
+
const evaluationMetrics = {
|
|
114
|
+
operation,
|
|
115
|
+
sdk: this.getProviderType(),
|
|
116
|
+
inputTokens: response.usage.input_tokens,
|
|
117
|
+
outputTokens: response.usage.output_tokens,
|
|
118
|
+
durationMs,
|
|
119
|
+
iterationCount: 1,
|
|
120
|
+
toolCallCount: 0,
|
|
121
|
+
status: 'completed',
|
|
122
|
+
completionReason: 'stop',
|
|
123
|
+
modelVersion: this.getModelName(),
|
|
124
|
+
test_scenario: operation,
|
|
125
|
+
ai_response_summary: response.content,
|
|
126
|
+
user_intent: evaluationContext?.user_intent || '',
|
|
127
|
+
interaction_id: evaluationContext?.interaction_id || '',
|
|
128
|
+
};
|
|
129
|
+
(0, provider_debug_utils_1.logEvaluationDataset)(evaluationMetrics, this.debugMode);
|
|
130
|
+
}
|
|
131
|
+
return response;
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
135
|
+
if (this.debugMode) {
|
|
136
|
+
const debugId = (0, provider_debug_utils_1.generateDebugId)(operation);
|
|
137
|
+
(0, provider_debug_utils_1.debugLogPromptOnly)(debugId, message, operation, this.getProviderType(), this.getModelName(), this.debugMode);
|
|
138
|
+
if (evaluationContext) {
|
|
139
|
+
const failureMetrics = {
|
|
140
|
+
operation,
|
|
141
|
+
user_intent: evaluationContext.user_intent || '',
|
|
142
|
+
ai_response_summary: `Error: ${errorMessage}`,
|
|
143
|
+
durationMs: Date.now() - startTime,
|
|
144
|
+
inputTokens: 0,
|
|
145
|
+
outputTokens: 0,
|
|
146
|
+
iterationCount: 0,
|
|
147
|
+
toolCallCount: 0,
|
|
148
|
+
status: 'failed',
|
|
149
|
+
completionReason: 'error',
|
|
150
|
+
sdk: this.getProviderType(),
|
|
151
|
+
modelVersion: this.getModelName(),
|
|
152
|
+
test_scenario: operation,
|
|
153
|
+
interaction_id: evaluationContext.interaction_id ||
|
|
154
|
+
(0, provider_debug_utils_1.generateDebugId)(operation),
|
|
155
|
+
failure_analysis: {
|
|
156
|
+
failure_type: 'error',
|
|
157
|
+
failure_reason: `Host API error: ${errorMessage}`,
|
|
158
|
+
time_to_failure: Date.now() - startTime,
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
(0, provider_debug_utils_1.logEvaluationDataset)(failureMetrics, this.debugMode);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
throw new Error(`Host sampling error: ${errorMessage}`);
|
|
165
|
+
}
|
|
166
|
+
}, (response) => ({
|
|
167
|
+
inputTokens: response.usage.input_tokens,
|
|
168
|
+
outputTokens: response.usage.output_tokens,
|
|
169
|
+
}));
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Execute a tool loop with the host model
|
|
173
|
+
*
|
|
174
|
+
* The tool loop relies on a specific JSON format embedded in markdown code blocks:
|
|
175
|
+
* ```json
|
|
176
|
+
* {
|
|
177
|
+
* "tool": "toolName",
|
|
178
|
+
* "arguments": { ... }
|
|
179
|
+
* }
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
async toolLoop(config) {
|
|
183
|
+
if (!HostProvider.samplingHandler) {
|
|
184
|
+
throw new Error('Host provider is not connected to MCP server');
|
|
185
|
+
}
|
|
186
|
+
return await (0, ai_tracing_1.withAITracing)({
|
|
187
|
+
provider: this.getProviderType(),
|
|
188
|
+
model: this.getModelName(),
|
|
189
|
+
operation: 'tool_loop',
|
|
190
|
+
}, async () => {
|
|
191
|
+
const maxIterations = config.maxIterations || 20;
|
|
192
|
+
const messages = [
|
|
193
|
+
{ role: 'user', content: { type: 'text', text: config.userMessage } },
|
|
194
|
+
];
|
|
195
|
+
// Construct system prompt with tool definitions
|
|
196
|
+
const promptPath = path.join(__dirname, '..', '..', '..', 'prompts', 'host-tools.md');
|
|
197
|
+
const promptTemplate = (0, prompts_1.loadPromptFile)(promptPath).content;
|
|
198
|
+
const toolDefinitions = (0, tool_utils_1.formatToolDefinitions)(config.tools);
|
|
199
|
+
const systemPrompt = config.systemPrompt +
|
|
200
|
+
'\n\n' +
|
|
201
|
+
promptTemplate.replace('{{TOOL_DEFINITIONS}}', toolDefinitions);
|
|
202
|
+
const toolCallsExecuted = [];
|
|
203
|
+
let iterations = 0;
|
|
204
|
+
while (iterations < maxIterations) {
|
|
205
|
+
iterations++;
|
|
206
|
+
try {
|
|
207
|
+
const result = await HostProvider.samplingHandler(messages, systemPrompt, {
|
|
208
|
+
operation: config.operation,
|
|
209
|
+
evaluationContext: config.evaluationContext,
|
|
210
|
+
interaction_id: config.interaction_id,
|
|
211
|
+
});
|
|
212
|
+
let content = '';
|
|
213
|
+
if (typeof result.content === 'object' && result.content.type === 'text') {
|
|
214
|
+
content = result.content.text;
|
|
215
|
+
}
|
|
216
|
+
else if (typeof result.content === 'string') {
|
|
217
|
+
content = result.content;
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
content = JSON.stringify(result.content);
|
|
221
|
+
}
|
|
222
|
+
// Add assistant response to history
|
|
223
|
+
messages.push({
|
|
224
|
+
role: 'assistant',
|
|
225
|
+
content: { type: 'text', text: content },
|
|
226
|
+
});
|
|
227
|
+
// Check for tool calls
|
|
228
|
+
const toolCalls = (0, tool_utils_1.extractToolCalls)(content);
|
|
229
|
+
if (toolCalls.length > 0) {
|
|
230
|
+
for (const toolCall of toolCalls) {
|
|
231
|
+
try {
|
|
232
|
+
const toolName = toolCall.tool;
|
|
233
|
+
const toolArgs = toolCall.arguments || {};
|
|
234
|
+
// Validate tool exists
|
|
235
|
+
const toolExists = config.tools.some(t => t.name === toolName);
|
|
236
|
+
if (!toolExists) {
|
|
237
|
+
messages.push({
|
|
238
|
+
role: 'user',
|
|
239
|
+
content: {
|
|
240
|
+
type: 'text',
|
|
241
|
+
text: `Unknown tool '${toolName}'. Available tools: ${config.tools.map(t => t.name).join(', ')}`,
|
|
242
|
+
},
|
|
243
|
+
});
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
// Execute tool
|
|
247
|
+
const toolOutput = await config.toolExecutor(toolName, toolArgs);
|
|
248
|
+
toolCallsExecuted.push({
|
|
249
|
+
tool: toolName,
|
|
250
|
+
input: toolArgs,
|
|
251
|
+
output: toolOutput,
|
|
252
|
+
});
|
|
253
|
+
// Add tool result to history
|
|
254
|
+
messages.push({
|
|
255
|
+
role: 'user',
|
|
256
|
+
content: {
|
|
257
|
+
type: 'text',
|
|
258
|
+
text: (0, tool_utils_1.formatToolOutput)(toolName, toolOutput),
|
|
259
|
+
},
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
catch (executionError) {
|
|
263
|
+
messages.push({
|
|
264
|
+
role: 'user',
|
|
265
|
+
content: {
|
|
266
|
+
type: 'text',
|
|
267
|
+
text: `Error executing tool '${toolCall.tool}': ${executionError instanceof Error ? executionError.message : String(executionError)}`,
|
|
268
|
+
},
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
if (config.onIteration) {
|
|
273
|
+
try {
|
|
274
|
+
config.onIteration(iterations, toolCallsExecuted);
|
|
275
|
+
}
|
|
276
|
+
catch (error) {
|
|
277
|
+
// Ignore errors in callback
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
// No tool call, assume final response
|
|
283
|
+
return {
|
|
284
|
+
finalMessage: content,
|
|
285
|
+
iterations,
|
|
286
|
+
toolCallsExecuted,
|
|
287
|
+
totalTokens: { input: 0, output: 0 },
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
catch (error) {
|
|
292
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
293
|
+
throw new Error(`Host sampling error in tool loop: ${message}`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
const lastMessage = messages[messages.length - 1];
|
|
297
|
+
const lastContent = typeof lastMessage.content === 'string'
|
|
298
|
+
? lastMessage.content
|
|
299
|
+
: (lastMessage.content?.text ?? '');
|
|
300
|
+
return {
|
|
301
|
+
finalMessage: lastContent,
|
|
302
|
+
iterations,
|
|
303
|
+
toolCallsExecuted,
|
|
304
|
+
totalTokens: { input: 0, output: 0 },
|
|
305
|
+
status: 'timeout',
|
|
306
|
+
completionReason: 'max_iterations',
|
|
307
|
+
};
|
|
308
|
+
}, (result) => ({
|
|
309
|
+
inputTokens: result.totalTokens.input,
|
|
310
|
+
outputTokens: result.totalTokens.output,
|
|
311
|
+
}));
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
exports.HostProvider = HostProvider;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { AITool } from '../ai-provider.interface';
|
|
2
|
+
/**
|
|
3
|
+
* Formats tool definitions into a markdown string for system prompts.
|
|
4
|
+
* Used by providers that don't support native tool calling or need manual prompting.
|
|
5
|
+
*/
|
|
6
|
+
export declare function formatToolDefinitions(tools: AITool[]): string;
|
|
7
|
+
/**
|
|
8
|
+
* Formats a tool execution result for inclusion in conversation history.
|
|
9
|
+
*/
|
|
10
|
+
export declare function formatToolOutput(toolName: string, output: any): string;
|
|
11
|
+
/**
|
|
12
|
+
* Regex for extracting tool calls from markdown code blocks.
|
|
13
|
+
* Matches: ```json ... ``` and captures the content.
|
|
14
|
+
*/
|
|
15
|
+
export declare const TOOL_CALL_REGEX: RegExp;
|
|
16
|
+
/**
|
|
17
|
+
* Extracts tool calls from a string containing markdown code blocks.
|
|
18
|
+
* Handles nested objects and malformed JSON gracefully.
|
|
19
|
+
*/
|
|
20
|
+
export declare function extractToolCalls(content: string): any[];
|
|
21
|
+
//# sourceMappingURL=tool-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-utils.d.ts","sourceRoot":"","sources":["../../../src/core/providers/tool-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAElD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAO7D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,MAAM,CAEtE;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,QAAgC,CAAC;AAE7D;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,GAAG,EAAE,CAuBvD"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TOOL_CALL_REGEX = void 0;
|
|
4
|
+
exports.formatToolDefinitions = formatToolDefinitions;
|
|
5
|
+
exports.formatToolOutput = formatToolOutput;
|
|
6
|
+
exports.extractToolCalls = extractToolCalls;
|
|
7
|
+
/**
|
|
8
|
+
* Formats tool definitions into a markdown string for system prompts.
|
|
9
|
+
* Used by providers that don't support native tool calling or need manual prompting.
|
|
10
|
+
*/
|
|
11
|
+
function formatToolDefinitions(tools) {
|
|
12
|
+
let toolDefinitions = '';
|
|
13
|
+
for (const tool of tools) {
|
|
14
|
+
toolDefinitions += `### ${tool.name}\n${tool.description}\n`;
|
|
15
|
+
toolDefinitions += `Schema: ${JSON.stringify(tool.inputSchema)}\n\n`;
|
|
16
|
+
}
|
|
17
|
+
return toolDefinitions;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Formats a tool execution result for inclusion in conversation history.
|
|
21
|
+
*/
|
|
22
|
+
function formatToolOutput(toolName, output) {
|
|
23
|
+
return `Tool '${toolName}' output:\n${JSON.stringify(output, null, 2)}`;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Regex for extracting tool calls from markdown code blocks.
|
|
27
|
+
* Matches: ```json ... ``` and captures the content.
|
|
28
|
+
*/
|
|
29
|
+
exports.TOOL_CALL_REGEX = /```json\s*([\s\S]*?)\s*```/g;
|
|
30
|
+
/**
|
|
31
|
+
* Extracts tool calls from a string containing markdown code blocks.
|
|
32
|
+
* Handles nested objects and malformed JSON gracefully.
|
|
33
|
+
*/
|
|
34
|
+
function extractToolCalls(content) {
|
|
35
|
+
const toolCalls = [];
|
|
36
|
+
const matches = [...content.matchAll(exports.TOOL_CALL_REGEX)];
|
|
37
|
+
for (const match of matches) {
|
|
38
|
+
try {
|
|
39
|
+
const jsonContent = match[1];
|
|
40
|
+
const parsed = JSON.parse(jsonContent);
|
|
41
|
+
if (Array.isArray(parsed)) {
|
|
42
|
+
for (const item of parsed) {
|
|
43
|
+
if (item && typeof item === 'object' && item.tool) {
|
|
44
|
+
toolCalls.push(item);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else if (parsed && typeof parsed === 'object' && parsed.tool) {
|
|
49
|
+
toolCalls.push(parsed);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch (e) {
|
|
53
|
+
// Ignore parse errors
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return toolCalls;
|
|
57
|
+
}
|
package/dist/core/schema.js
CHANGED
|
@@ -58,7 +58,7 @@ exports.OUTPUT_FORMAT_QUESTION = {
|
|
|
58
58
|
type: 'select',
|
|
59
59
|
options: ['raw', 'helm', 'kustomize'],
|
|
60
60
|
placeholder: 'Select output format',
|
|
61
|
-
suggestedAnswer: '
|
|
61
|
+
suggestedAnswer: 'kustomize',
|
|
62
62
|
validation: { required: true }
|
|
63
63
|
};
|
|
64
64
|
exports.OUTPUT_PATH_QUESTION = {
|
package/dist/interfaces/mcp.d.ts
CHANGED
|
@@ -39,6 +39,8 @@ export declare class MCPServer {
|
|
|
39
39
|
* Register prompts capability with McpServer
|
|
40
40
|
*/
|
|
41
41
|
private registerPrompts;
|
|
42
|
+
private configureHostProvider;
|
|
43
|
+
private handleSamplingRequest;
|
|
42
44
|
private generateRequestId;
|
|
43
45
|
start(): Promise<void>;
|
|
44
46
|
private startStdioTransport;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/interfaces/mcp.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAkDtC,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,UAAU,GAAG,WAAW,CAAC;CACxC;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,UAAU,CAAC,CAAkC;IACrD,OAAO,CAAC,aAAa,CAAC,CAAgC;IACtD,OAAO,CAAC,YAAY,CAAmB;IACvC,OAAO,CAAC,aAAa,CAAgB;gBAEzB,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe;
|
|
1
|
+
{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/interfaces/mcp.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAkDtC,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,UAAU,GAAG,WAAW,CAAC;CACxC;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,UAAU,CAAC,CAAkC;IACrD,OAAO,CAAC,aAAa,CAAC,CAAgC;IACtD,OAAO,CAAC,YAAY,CAAmB;IACvC,OAAO,CAAC,aAAa,CAAgB;gBAEzB,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe;IAyCjD;;OAEG;IACH,OAAO,CAAC,YAAY;IA8BpB;;OAEG;IACH,OAAO,CAAC,aAAa;IA6HrB;;OAEG;IACH,OAAO,CAAC,eAAe;IAqCvB,OAAO,CAAC,qBAAqB;YAgBf,qBAAqB;IAuBnC,OAAO,CAAC,iBAAiB;IAInB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAkBd,mBAAmB;YAMnB,kBAAkB;YAmHlB,gBAAgB;IAexB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB3B,OAAO,IAAI,OAAO;CAGnB"}
|
package/dist/interfaces/mcp.js
CHANGED
|
@@ -52,6 +52,8 @@ class MCPServer {
|
|
|
52
52
|
prompts: {},
|
|
53
53
|
},
|
|
54
54
|
});
|
|
55
|
+
// Configure HostProvider if active
|
|
56
|
+
this.configureHostProvider();
|
|
55
57
|
this.logger.info('Initializing MCP Server', {
|
|
56
58
|
name: config.name,
|
|
57
59
|
version: config.version,
|
|
@@ -73,7 +75,10 @@ class MCPServer {
|
|
|
73
75
|
return await (0, tracing_1.withToolTracing)(name, args, handler);
|
|
74
76
|
};
|
|
75
77
|
// Register traced handler with MCP server
|
|
76
|
-
this.server.
|
|
78
|
+
this.server.registerTool(name, {
|
|
79
|
+
description,
|
|
80
|
+
inputSchema
|
|
81
|
+
}, tracedHandler);
|
|
77
82
|
// Register traced handler with REST registry
|
|
78
83
|
this.restRegistry.registerTool({
|
|
79
84
|
name,
|
|
@@ -164,6 +169,39 @@ class MCPServer {
|
|
|
164
169
|
endpoints: ['prompts/list', 'prompts/get'],
|
|
165
170
|
});
|
|
166
171
|
}
|
|
172
|
+
configureHostProvider() {
|
|
173
|
+
// Configure HostProvider if active
|
|
174
|
+
// We use capability detection (duck typing) to avoid strict class dependency
|
|
175
|
+
// and handle potential class loading issues
|
|
176
|
+
const aiProvider = this.dotAI.ai;
|
|
177
|
+
if (typeof aiProvider.setSamplingHandler === 'function') {
|
|
178
|
+
this.logger.info('Configuring Host AI Provider with Sampling capability');
|
|
179
|
+
aiProvider.setSamplingHandler(this.handleSamplingRequest.bind(this));
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
this.logger.info('Using configured AI Provider', {
|
|
183
|
+
type: this.dotAI.ai.getProviderType ? this.dotAI.ai.getProviderType() : 'unknown'
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
async handleSamplingRequest(messages, systemPrompt, options) {
|
|
188
|
+
try {
|
|
189
|
+
if (!this.server.server.createMessage) {
|
|
190
|
+
throw new Error('Server does not support createMessage (sampling)');
|
|
191
|
+
}
|
|
192
|
+
return await this.server.server.createMessage({
|
|
193
|
+
messages,
|
|
194
|
+
systemPrompt,
|
|
195
|
+
includeContext: 'none',
|
|
196
|
+
maxTokens: options?.maxTokens || 4096,
|
|
197
|
+
...options
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
this.logger.error('Sampling request failed', error);
|
|
202
|
+
throw error;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
167
205
|
generateRequestId() {
|
|
168
206
|
return `mcp_${Date.now()}_${++this.requestIdCounter}`;
|
|
169
207
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"answer-question.d.ts","sourceRoot":"","sources":["../../src/tools/answer-question.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAOhD,eAAO,MAAM,wBAAwB,mBAAmB,CAAC;AACzD,eAAO,MAAM,+BAA+B,8HAA4H,CAAC;AAGzK,eAAO,MAAM,gCAAgC;;;;;;;;;;CAK5C,CAAC;
|
|
1
|
+
{"version":3,"file":"answer-question.d.ts","sourceRoot":"","sources":["../../src/tools/answer-question.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAOhD,eAAO,MAAM,wBAAwB,mBAAmB,CAAC;AACzD,eAAO,MAAM,+BAA+B,8HAA4H,CAAC;AAGzK,eAAO,MAAM,gCAAgC;;;;;;;;;;CAK5C,CAAC;AAwhBF;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,EACtI,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE,CAAC,CAgUxD"}
|
|
@@ -79,16 +79,16 @@ function validateAnswer(answer, question) {
|
|
|
79
79
|
function getStageSpecificInstructions(stage, isHelm = false) {
|
|
80
80
|
switch (stage) {
|
|
81
81
|
case 'required':
|
|
82
|
-
return 'STAGE: REQUIRED - All questions must be answered before proceeding.
|
|
82
|
+
return 'STAGE: REQUIRED - Present ALL questions to the user and collect answers. All questions must be answered before proceeding.';
|
|
83
83
|
case 'basic':
|
|
84
|
-
return 'STAGE: BASIC -
|
|
84
|
+
return 'STAGE: BASIC - Present ALL questions to the user. Show defaults where available but ask user to confirm or change each one. User must review all questions before proceeding to advanced stage.';
|
|
85
85
|
case 'advanced':
|
|
86
86
|
// For Helm, don't mention open stage since it's skipped
|
|
87
87
|
return isHelm
|
|
88
|
-
? 'STAGE: ADVANCED -
|
|
89
|
-
: 'STAGE: ADVANCED -
|
|
88
|
+
? 'STAGE: ADVANCED - Present ALL questions to the user. Show defaults where available but ask user to confirm or change each one. User must review all questions before proceeding to manifest generation.'
|
|
89
|
+
: 'STAGE: ADVANCED - Present ALL questions to the user. Show defaults where available but ask user to confirm or change each one. User must review all questions before proceeding to open stage.';
|
|
90
90
|
case 'open':
|
|
91
|
-
return 'STAGE: OPEN - Final configuration stage.
|
|
91
|
+
return 'STAGE: OPEN - Final configuration stage. Ask user for any additional requirements or constraints. User can say "N/A" if none.';
|
|
92
92
|
default:
|
|
93
93
|
return 'STAGE: UNKNOWN - Present questions to the user and wait for their response.';
|
|
94
94
|
}
|
|
@@ -100,25 +100,21 @@ function getAgentInstructions(stage, isHelm = false) {
|
|
|
100
100
|
const antiCascadeRule = 'CRITICAL ANTI-CASCADE RULE: When user says "skip" for ANY stage, only skip THAT specific stage and present the NEXT stage questions to the user. NEVER automatically skip multiple stages in sequence.';
|
|
101
101
|
const mandatoryWorkflow = `
|
|
102
102
|
MANDATORY CLIENT AGENT WORKFLOW:
|
|
103
|
-
1. Present
|
|
104
|
-
2.
|
|
105
|
-
3.
|
|
106
|
-
4.
|
|
107
|
-
5. NEVER
|
|
108
|
-
6. NEVER assume what the user wants for
|
|
109
|
-
|
|
110
|
-
const strictConstraints = isHelm ? `
|
|
103
|
+
1. Present ALL questions from this stage to the user - do not skip any
|
|
104
|
+
2. For each question, show the default value if one exists and ask user to confirm or change it
|
|
105
|
+
3. Wait for explicit user response on EVERY question
|
|
106
|
+
4. Only call answerQuestion after user has reviewed and responded to all questions
|
|
107
|
+
5. NEVER auto-fill answers without user confirmation, even if you can deduce values
|
|
108
|
+
6. NEVER assume what the user wants for any question or stage`;
|
|
109
|
+
const strictConstraints = `
|
|
111
110
|
STRICT BEHAVIORAL CONSTRAINTS:
|
|
112
111
|
- DO NOT call answerQuestion automatically
|
|
113
|
-
- DO NOT
|
|
114
|
-
- DO NOT
|
|
115
|
-
-
|
|
116
|
-
|
|
117
|
-
-
|
|
118
|
-
-
|
|
119
|
-
- DO NOT call answerQuestion with empty open stage answers unless user explicitly provides them
|
|
120
|
-
- DO NOT interpret "skip" as "automatically proceed to next stage"
|
|
121
|
-
- MUST present each stage's questions individually and wait for user response`;
|
|
112
|
+
- DO NOT skip questions - present ALL questions even if they have defaults
|
|
113
|
+
- DO NOT assume user wants default values - always ask for confirmation
|
|
114
|
+
- DO NOT fill in values you deduced without asking user first
|
|
115
|
+
- DO NOT interpret "skip" as permission to auto-fill remaining questions
|
|
116
|
+
- MUST present each question individually and collect user's explicit response
|
|
117
|
+
- If a question has a default, show it as a suggestion but still ask user to confirm`;
|
|
122
118
|
const stageSpecific = getStageSpecificInstructions(stage, isHelm);
|
|
123
119
|
return `${antiCascadeRule}\n${mandatoryWorkflow}\n${strictConstraints}\n\n${stageSpecific}`;
|
|
124
120
|
}
|
|
@@ -294,18 +290,18 @@ function getStageMessage(stage) {
|
|
|
294
290
|
function getStageGuidance(stage, isHelm = false) {
|
|
295
291
|
switch (stage) {
|
|
296
292
|
case 'required':
|
|
297
|
-
return '
|
|
293
|
+
return 'Present all required questions to the user. All must be answered to proceed.';
|
|
298
294
|
case 'basic':
|
|
299
|
-
return '
|
|
295
|
+
return 'Present all basic questions to the user. Show default values as suggestions but ask user to confirm each one.';
|
|
300
296
|
case 'advanced':
|
|
301
297
|
// For Helm, don't mention the open stage since it's skipped
|
|
302
298
|
return isHelm
|
|
303
|
-
? '
|
|
304
|
-
: '
|
|
299
|
+
? 'Present all advanced questions to the user. Show default values as suggestions but ask user to confirm each one. After this stage: manifest generation.'
|
|
300
|
+
: 'Present all advanced questions to the user. Show default values as suggestions but ask user to confirm each one. After this stage: open stage.';
|
|
305
301
|
case 'open':
|
|
306
|
-
return '
|
|
302
|
+
return 'Ask user for any additional requirements or constraints. User can say "N/A" if none.';
|
|
307
303
|
default:
|
|
308
|
-
return '
|
|
304
|
+
return 'Present all questions to the user and collect their responses.';
|
|
309
305
|
}
|
|
310
306
|
}
|
|
311
307
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"choose-solution.d.ts","sourceRoot":"","sources":["../../src/tools/choose-solution.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAKhD,eAAO,MAAM,wBAAwB,mBAAmB,CAAC;AACzD,eAAO,MAAM,+BAA+B,uEAAuE,CAAC;AAGpH,eAAO,MAAM,gCAAgC;;CAE5C,CAAC;AAIF;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,EAC5B,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"choose-solution.d.ts","sourceRoot":"","sources":["../../src/tools/choose-solution.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAKhD,eAAO,MAAM,wBAAwB,mBAAmB,CAAC;AACzD,eAAO,MAAM,+BAA+B,uEAAuE,CAAC;AAGpH,eAAO,MAAM,gCAAgC;;CAE5C,CAAC;AAIF;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,EAC5B,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE,CAAC,CAmIxD"}
|
|
@@ -89,7 +89,12 @@ async function handleChooseSolutionTool(args, dotAI, logger, requestId) {
|
|
|
89
89
|
nextStage: 'basic',
|
|
90
90
|
message: 'Please provide the required configuration for your application.',
|
|
91
91
|
nextAction: 'Call recommend tool with stage: answerQuestion:required',
|
|
92
|
-
guidance: '
|
|
92
|
+
guidance: 'Present ALL required questions to the user. All must be answered before proceeding.',
|
|
93
|
+
agentInstructions: `MANDATORY: Present ALL questions from this stage to the user - do not skip any.
|
|
94
|
+
For each question, show the default value if one exists and ask user to confirm or change it.
|
|
95
|
+
Wait for explicit user response on EVERY question before calling answerQuestion.
|
|
96
|
+
NEVER auto-fill answers without user confirmation, even if you can deduce values.
|
|
97
|
+
NEVER assume what the user wants - always ask.`,
|
|
93
98
|
timestamp: new Date().toISOString()
|
|
94
99
|
};
|
|
95
100
|
logger.info('Choose solution completed successfully', {
|
package/dist/tools/remediate.js
CHANGED
|
@@ -400,9 +400,9 @@ async function executeRemediationCommands(session, sessionManager, logger, reque
|
|
|
400
400
|
logger.info('Waiting for Kubernetes to apply changes before validation', {
|
|
401
401
|
requestId,
|
|
402
402
|
sessionId: session.sessionId,
|
|
403
|
-
delayMs:
|
|
403
|
+
delayMs: 30000
|
|
404
404
|
});
|
|
405
|
-
await new Promise(resolve => setTimeout(resolve,
|
|
405
|
+
await new Promise(resolve => setTimeout(resolve, 30000));
|
|
406
406
|
}
|
|
407
407
|
logger.info('Running post-execution validation', {
|
|
408
408
|
requestId,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vfarcic/dot-ai",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.160.0",
|
|
4
4
|
"description": "AI-powered development productivity platform that enhances software development workflows through intelligent automation and AI-driven assistance",
|
|
5
5
|
"mcpName": "io.github.vfarcic/dot-ai",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"test:integration:teardown": "./tests/integration/infrastructure/teardown-cluster.sh",
|
|
18
18
|
"test:integration:server": "KUBECONFIG=./kubeconfig-test.yaml PORT=3456 DOT_AI_SESSION_DIR=./tmp/sessions TRANSPORT_TYPE=http QDRANT_URL=http://localhost:6335 QDRANT_CAPABILITIES_COLLECTION=capabilities-policies ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY OPENAI_API_KEY=$OPENAI_API_KEY node dist/mcp/server.js",
|
|
19
19
|
"test:integration": "./tests/integration/infrastructure/run-integration-tests.sh",
|
|
20
|
+
"test:unit": "vitest --config=vitest.unit.config.ts",
|
|
20
21
|
"test:integration:watch": "vitest --config=vitest.integration.config.ts --test-timeout=1200000",
|
|
21
22
|
"test:integration:sonnet": "AI_PROVIDER=anthropic DEBUG_DOT_AI=true ./tests/integration/infrastructure/run-integration-tests.sh",
|
|
22
23
|
"test:integration:opus": "AI_PROVIDER=anthropic_opus DEBUG_DOT_AI=true ./tests/integration/infrastructure/run-integration-tests.sh",
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: host-tools
|
|
3
|
+
description: System prompt for host tools execution loop
|
|
4
|
+
category: core
|
|
5
|
+
---
|
|
6
|
+
## Available Tools
|
|
7
|
+
|
|
8
|
+
You have access to the following tools. To use a tool, output a JSON block with the format:
|
|
9
|
+
```json
|
|
10
|
+
{ "tool": "tool_name", "arguments": { ... } }
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
{{TOOL_DEFINITIONS}}
|
|
14
|
+
|
|
15
|
+
When you have gathered enough information, provide your final answer without any tool calls.
|
|
@@ -51,3 +51,18 @@ Once you and the user have agreed on what they want to do and the relevant detai
|
|
|
51
51
|
## What Makes a Good Intent
|
|
52
52
|
|
|
53
53
|
A detailed intent describes what the user wants to do with relevant specifics. What details matter depends entirely on what they're trying to accomplish. The more relevant detail you provide, the better.
|
|
54
|
+
|
|
55
|
+
## What NOT to Include
|
|
56
|
+
|
|
57
|
+
**Do NOT specify Kubernetes resource types** (e.g., "need a Deployment", "use Ingress", "create a Service"). The recommendation engine's job is to analyze your intent and find the BEST Kubernetes resources for your needs. Pre-specifying resources prevents it from recommending better alternatives like:
|
|
58
|
+
|
|
59
|
+
- Operators and CRDs (Knative Service, Crossplane resources, etc.)
|
|
60
|
+
- Platform-specific solutions (OpenShift Routes vs Ingress, etc.)
|
|
61
|
+
- Better-fit resource types (StatefulSet vs Deployment for stateful apps)
|
|
62
|
+
- Organization-specific patterns
|
|
63
|
+
|
|
64
|
+
**Good intent**: "Deploy a Python Flask API that connects to PostgreSQL. Container listens on port 5000, needs 512Mi memory, requires DATABASE_URL environment variable. Expose publicly at api.example.com"
|
|
65
|
+
|
|
66
|
+
**Bad intent**: "Deploy Flask API. Need Kubernetes Deployment, Service, and Ingress to expose..."
|
|
67
|
+
|
|
68
|
+
Focus on: WHAT you're deploying, the technical context (ports, runtime, requirements), and the desired outcome. Let the recommendation engine determine HOW.
|