"use strict";const T=require("./telemetry-C8yrvnwb.cjs"),d=require("./shared-types-B8BH5zz1.cjs"),u=require("./stream-BfNQDS2Z.cjs"),b=require("./transformers-BwHJBLex.cjs"),k=require("@aws/codewhisperer-streaming-client"),v=require("./logger-BN0ZR9CS.cjs");class x extends d.KiroError{constructor(){super("Unexpected response format from model")}get userFacingSessionErrorMessage(){return"Intent could not be detected, unexpected response."}}var L=Object.defineProperty,S=Object.getOwnPropertyDescriptor,I=(c,t,e,s)=>{for(var n=S(t,e),o=c.length-1,a;o>=0;o--)(a=c[o])&&(n=a(t,e,n)||n);return n&&L(t,e,n),n};const p=T.getMetricReporterOrNoOp(d.TelemetryNamespace.Agent,"IntentDetection"),l=class y{modelClient;static modelId;CONFIDENCE_THRESHOLD=.8;DEFAULT_WEIGHTS={chat:1,do:1,spec:1};BIAS_FACTOR=1.5;HISTORY_DEPTH=2;systemPrompt=`
You are an intent classifier for a language model.

Your job is to classify the user's intent based on their conversation history into one of two main categories:

1. **Do mode** (default for most requests)
2. **Spec mode** (only for specific specification/planning requests)

Return ONLY a JSON object with 3 properties (chat, do, spec) representing your confidence in each category. The values must always sum to 1.

### Category Definitions

#### 1. Do mode (DEFAULT CHOICE)
Input belongs in do mode if it:
- Is NOT explicitly about creating or working with specifications
- Requests modifications to code or the workspace
- Is an imperative sentence asking for action
- Starts with a base-form verb (e.g., "Write," "Create," "Generate")
- Has an implied subject ("you" is understood)
- Requests to run commands or make changes to files
- Asks for information, explanation, or clarification
- Ends with a question mark (?)
- Seeks information or explanation
- Starts with interrogative words like "who," "what," "where," "when," "why," or "how"
- Begins with a helping verb for yes/no questions, like "Is," "Are," "Can," "Should"
- Asks for explanation of code or concepts
- Examples include:
  - "Write a function to reverse a string."
  - "Create a new file called index.js."
  - "Fix the syntax errors in this function."
  - "Refactor this code to be more efficient."
  - "What is the capital of France?"
  - "How do promises work in JavaScript?"
  - "Can you explain this code?"
  - "Tell me about design patterns"

#### 2. Spec mode (ONLY for specification requests)
Input belongs in spec mode ONLY if it EXPLICITLY:
- Asks to create a specification (or spec) 
- Uses the word "spec" or "specification" to request creating a formal spec
- Mentions creating a formal requirements document
- Involves executing tasks from existing specs
- Examples include:
  - "Create a spec for this feature"
  - "Generate a specification for the login system"
  - "Let's create a formal spec document for this project"
  - "Implement a spec based on this conversation"
  - "Execute task 3.2 from my-feature spec"
  - "Execute task 2 from My Feature"
  - "Start task 1 for the spec"
  - "Start the next task"
  - "What is the next task in the <feature name> spec?"

IMPORTANT: When in doubt, classify as "Do" mode. Only classify as "Spec" when the user is explicitly requesting to create or work with a formal specification document.

Ensure you look at the historical conversation between you and the user in addition to the latest user message when making your decision.
Previous messages may have context that is important to consider when combined with the user's latest reply.

IMPORTANT: Respond ONLY with a raw JSON object. No explanation, no commentary, no additional text, no markdown formatting, no code fences (\`\`\`), no backticks.

Example response (exactly this format):
{"chat": 0.0, "do": 0.9, "spec": 0.1}

Here is the last user message:
`;constructor(t,e){y.modelId=t,this.modelClient=e}detectLocalIntent(t){const e=this.localClassification(t),s=this.getClassificationFromIntent(e);return{intent:e,classification:s}}localClassification(t){const e=t.trim(),s=e.toLowerCase(),n=/^(who|what|where|when|why|how)\b/i,o=/^(explain|summarize|is|are|can|should|would|could|does|did|has|have|will|was|were|show)\b/i;if(e.endsWith("?")||n.test(e)||o.test(e))return{chat:1,do:0,spec:0};const i=new Set(["do","write","generate","create","build","validate","check","test","refactor","convert","translate","implement","analyze","debug","document","compile","run","simulate","optimize"]),r=s.split(/\s+/)[0],m=/[.!]$/.test(e);return i.has(r)&&!n.test(e)&&!o.test(e)&&(m||!e.includes("?"))?{chat:0,do:1,spec:0}:["requirement","requirements","design","plan","spec","specs","specification","architecture","implementation","user story","feature","component","task","use case","algorithm","api","schema"].some(M=>s.includes(M))?{chat:0,do:0,spec:1}:{chat:0,do:0,spec:0}}async detectLLMIntent(t,e,s,n,o){const{intent:a,usageSummaryEntry:i}=await this.classifyIntent(t,e,s,n,o),r=this.getClassificationFromIntent(a);return{intent:a,classification:r,usageSummaryEntry:i}}finalizeIntent(t,e,s){const n=e?.intent??this.DEFAULT_WEIGHTS;if(!e)return{localIntent:t.intent,llmIntent:n,finalIntent:t.intent,classification:t.classification,clarificationQuestion:void 0};const o=s??this.DEFAULT_WEIGHTS,a={chat:n.chat*o.chat,do:n.do*o.do,spec:n.spec*o.spec},i=this.normalize(a),r=this.getClassificationFromIntent(i);return p.reportCountMetrics({localIntentChat:t.intent.chat,localIntentDo:t.intent.do,localIntentSpec:t.intent.spec,llmIntentChat:n.chat||0,llmIntentDo:n.do||0,llmIntentSpec:n.spec||0,intentDisagreed:t.classification!==r,localIntentAmbiguous:t.classification==="ambiguous",chatWeight:o.chat,doWeight:o.do,specWeight:o.spec},{[d.TelemetryAttributes.ModelId]:y.modelId}),{localIntent:t.intent,llmIntent:n,finalIntent:i,classification:r,clarificationQuestion:e.clarificationQuestion}}getUserMessagesFromConversationHistory(t){const e=t.filter(n=>!n.forcedRole&&(n.role==="human"||n.role==="bot")).map(n=>{const o=n.role,a=[];for(const r of n.entries)r.type==="text"&&a.push(r.text);const i=a.join(`

`);return o==="bot"?new u.AIMessage({content:i}):new u.HumanMessage({content:i})}),s=this.trimMessageHistory(e);s.length>0&&(s[0].getType()!=="human"&&s.unshift(new u.HumanMessage({content:"continue"})),s[s.length-1].getType()!=="human"&&s.push(new u.HumanMessage({content:"continue"})));for(const n of s)n.content===""&&(n.content=n.getType()==="human"?"continue":"understood");return s}trimMessageHistory(t){if(t.length===0)return[];const e=b.mergeMessageRuns(t),s=[],n=[];for(let i=0;i<e.length-1;i++)e[i].getType()==="human"&&e[i+1].getType()==="ai"&&(n.push({human:e[i],ai:e[i+1]}),i++);const o=n.slice(-1);for(const i of o)s.push(i.human),s.push(i.ai);const a=e[e.length-1];if(a.getType()==="human"&&(o.some(r=>r.human===a)||s.push(a)),s.length===0&&t.length>0){const i=[...e].reverse().find(r=>r.getType()==="human");return i?[i]:[new u.HumanMessage({content:"continue"})]}return s}async classifyIntent(t,e,s,n,o){const a=`${this.systemPrompt}${t}`,i=b.mergeMessageRuns([new u.HumanMessage({content:a}),new u.AIMessage({content:"I will follow these instructions"}),...this.getUserMessagesFromConversationHistory(e)]);for(const r of i)r.additional_kwargs.conversationId=n,r.additional_kwargs.continuationId=o,r.additional_kwargs.taskType=k.AgentTaskType.VIBE;try{const r=await this.doLLMIntentClassification(i,s),m=r.content;if(typeof m!="string")throw new x;const w=C(m);let f;try{f=JSON.parse(w)}catch(g){throw g instanceof SyntaxError?new x:g}return{intent:this.normalize(f),usageSummaryEntry:r.additional_kwargs.usageSummaryEntry}}catch(r){return v.logger.error("Error classifying intent with LLM:",r),{intent:{chat:0,do:0,spec:0}}}}async doLLMIntentClassification(t,e){return await this.modelClient.invoke(t,{signal:e})}normalize(t){const e=Object.values(t).reduce((o,a)=>o+a,0);if(e===0)return{chat:.33,do:.33,spec:.33};const s={chat:Number((t.chat/e).toPrecision(2)),do:Number((t.do/e).toPrecision(2)),spec:Number((t.spec/e).toPrecision(2))},n=Object.values(s).reduce((o,a)=>o+a,0);if(n!==1){const o=h(s);s[o]+=Number((1-n).toPrecision(2))}return s}getClassificationFromIntent(t){const e={chat:Number(t.chat.toPrecision(2)),do:Number(t.do.toPrecision(2)),spec:Number(t.spec.toPrecision(2))},s=h(e);return e[s]>=this.CONFIDENCE_THRESHOLD?s:"ambiguous"}generateClarificationQuestion(t){const e=h(t);return{chat:"It seems like you want to chat with me. Is that correct?",do:"It looks like you want me to modify code or perform an action in your workspace. Is that right?",spec:"I think you want to work on requirements or design planning. Is that what you need?"}[e]}};I([p.Trace("detectLocalIntent",()=>({[d.TelemetryAttributes.ModelId]:l.modelId}))],l.prototype,"detectLocalIntent");I([p.Trace("detectLLMIntent",()=>({[d.TelemetryAttributes.ModelId]:l.modelId}))],l.prototype,"detectLLMIntent");I([p.Trace("doLLMIntentClassification",()=>({[d.TelemetryAttributes.ModelId]:l.modelId}))],l.prototype,"doLLMIntentClassification");let E=l;function h(c){let t="chat",e=c.chat;return c.do>e&&(e=c.do,t="do"),c.spec>e&&(t="spec"),t}function C(c){return c.replace(/^```(?:json)?\s*\n?/i,"").replace(/\n?```\s*$/i,"").trim()}exports.IntentDetectionService=E;exports.findMaxIntent=h;exports.stripMarkdownCodeFences=C;
//# sourceMappingURL=intent-detection-service-DP1cQxy7.cjs.map
