/** * Intent Task Types — V2 * * Defines the dual-layer Intent Task System with multi-intent decomposition: * - Intent Layer: User messages decomposed into multiple intents, each classified by complexity (L0/L1/L2) * - Execution Layer: Task -> Run -> Span model for tracking work * - Association Layer: Schedule follow-up and project task linkage * * Key v2 change: One chat message can produce multiple intent tasks. * Tasks are grouped by messageId and displayed as a todo list. * * Token usage binds to task_id + run_id via TokenUsageService integration. * * @module types/intent-task */ /** * Intent classification types are owned by `v2/request.types.ts` — it's * the domain-shape file and `IntentLevel` / `IntentCategory` are properties * of `Request`. Re-exported here so existing import paths from this module * keep working. Issue #474. * * Imported locally below because subsequent type declarations in this * module reference these aliases; `export type {}` alone only re-exports * and doesn't bring the names into local scope. */ import type { IntentLevel, IntentCategory } from './v2/request.types.js'; export type { IntentLevel, IntentCategory }; /** * Lifecycle states for an intent task */ export type IntentTaskStatus = 'pending' | 'classified' | 'in_progress' | 'paused' | 'completed' | 'failed' | 'cancelled'; /** * Lifecycle states for a run within a task */ export type RunStatus = 'running' | 'completed' | 'failed' | 'cancelled'; /** * Span types for tracking granular execution steps */ export type SpanType = 'llm_call' | 'tool_call' | 'skill_call' | 'delegation' | 'waiting' | 'user_input'; /** * A span represents a single atomic operation within a run. * Spans track LLM calls, tool executions, and delegations. */ export interface TaskSpan { /** Unique span identifier */ id: string; /** Parent run ID */ runId: string; /** Type of operation */ type: SpanType; /** Human-readable label (e.g., tool name, model name) */ label: string; /** ISO timestamp when the span started */ startedAt: string; /** ISO timestamp when the span ended (null if still running) */ endedAt: string | null; /** Duration in milliseconds (computed on completion) */ durationMs: number | null; /** Input tokens consumed (for llm_call spans) */ inputTokens: number; /** Output tokens generated (for llm_call spans) */ outputTokens: number; /** Direct cost override in USD (for skill_call spans with non-token costs) */ costOverride?: number; /** Optional metadata (tool args preview, model name, etc.) */ metadata?: Record; } /** * A run represents a single execution attempt of a task. * A task may have multiple runs (retries, continuations). */ export interface TaskRun { /** Unique run identifier */ id: string; /** Parent task ID */ taskId: string; /** Run sequence number (1-based) */ runNumber: number; /** Agent session executing this run */ sessionName: string; /** Current status */ status: RunStatus; /** ISO timestamp when the run started */ startedAt: string; /** ISO timestamp when the run ended */ endedAt: string | null; /** Total input tokens across all spans */ totalInputTokens: number; /** Total output tokens across all spans */ totalOutputTokens: number; /** Computed LLM cost in USD */ cost: number; /** Computed skill cost in USD (API calls, browser automation, etc.) */ skillCost: number; /** Spans within this run */ spans: TaskSpan[]; /** Error message if failed */ error?: string; } /** * An intent task represents a single decomposed intent from a user message, * tracked through its lifecycle. * * V2: Multiple tasks can share the same messageId (from one chat message). */ export interface IntentTask { /** Unique task identifier */ id: string; /** ID of the originating chat message (groups tasks from the same message) */ messageId: string; /** Original user input / intent description */ intent: string; /** Classified complexity level */ level: IntentLevel; /** Intent category */ category: IntentCategory; /** Current lifecycle status */ status: IntentTaskStatus; /** ISO timestamp when created */ createdAt: string; /** ISO timestamp of last update */ updatedAt: string; /** ISO timestamp when completed/failed */ completedAt: string | null; /** Agent sessions involved */ assignedSessions: string[]; /** Execution runs */ runs: TaskRun[]; /** Aggregated input tokens across all runs */ totalInputTokens: number; /** Aggregated output tokens across all runs */ totalOutputTokens: number; /** Aggregated LLM cost in USD */ totalCost: number; /** Aggregated skill cost in USD (API calls, browser automation, etc.) */ totalSkillCost: number; /** Optional result summary */ result?: string; /** Optional parent task ID for sub-task relationships */ parentTaskId?: string; /** Optional tags for filtering */ tags?: string[]; /** Optional schedule ID for automatic follow-up checks */ scheduleId?: string; /** Optional project ticket id (.crewly/tickets/, e.g. APP-12) this task belongs to */ projectTaskId?: string; /** Order within the message (0-based, for display ordering) */ order: number; } /** * A single decomposed intent extracted from a user message. */ export interface DecomposedIntent { /** The extracted intent description */ intent: string; /** Auto-classified complexity level */ level: IntentLevel; /** Auto-classified category */ category: IntentCategory; } /** * Result of decomposing a user message into multiple intents. */ export interface DecomposeResult { /** The original user message */ originalMessage: string; /** Generated message ID for grouping */ messageId: string; /** Array of decomposed intents */ intents: DecomposedIntent[]; } /** * A message group containing all tasks from a single chat message. * Used for the todo-list UI display. */ export interface MessageGroup { /** Message ID shared by all tasks in this group */ messageId: string; /** The original user message (reconstructed or stored) */ originalMessage: string; /** ISO timestamp of the earliest task in this group */ createdAt: string; /** Tasks belonging to this message, ordered by their order field */ tasks: IntentTaskSummary[]; /** Number of completed tasks in this group */ completedCount: number; /** Total number of tasks in this group */ totalCount: number; } /** * Request body for creating a new intent task */ export interface CreateIntentTaskInput { /** User intent description */ intent: string; /** Message ID to group tasks from the same chat message */ messageId?: string; /** Optional pre-classified level (auto-classified if omitted) */ level?: IntentLevel; /** Optional category (auto-classified if omitted) */ category?: IntentCategory; /** Optional parent task ID */ parentTaskId?: string; /** Optional tags */ tags?: string[]; /** Optional schedule ID for follow-up */ scheduleId?: string; /** Optional project task ID */ projectTaskId?: string; /** Optional order within message group */ order?: number; } /** * Request body for decomposing a message into multiple intent tasks. */ export interface DecomposeMessageInput { /** The full user message to decompose */ message: string; /** Optional project task ID to associate all decomposed tasks with */ projectTaskId?: string; /** Optional tags to apply to all decomposed tasks */ tags?: string[]; /** Whether to auto-create schedule follow-ups for each task */ autoSchedule?: boolean; } /** * Request body for updating a task's status and metadata. * Supports updating intent description, level, and category * (useful when orchestrator LLM refines understanding). */ export interface UpdateIntentTaskInput { /** New status */ status?: IntentTaskStatus; /** Updated intent description (for LLM-driven refinement) */ intent?: string; /** Updated complexity level */ level?: IntentLevel; /** Updated category */ category?: IntentCategory; /** Result summary (when completing) */ result?: string; /** Additional sessions to assign */ assignedSessions?: string[]; /** Schedule ID to associate */ scheduleId?: string; } /** * Request body for creating multiple intent tasks in a single batch. * Used by the orchestrator to create all tasks from one chat message at once. */ export interface BatchCreateIntentTaskInput { /** Array of tasks to create */ tasks: CreateIntentTaskInput[]; /** The original user message that produced these tasks */ originalMessage?: string; } /** * Request body for starting a new run */ export interface StartRunInput { /** Agent session executing the run */ sessionName: string; } /** * Request body for recording a span */ export interface RecordSpanInput { /** Span type */ type: SpanType; /** Human-readable label */ label: string; /** Input tokens (for llm_call) */ inputTokens?: number; /** Output tokens (for llm_call) */ outputTokens?: number; /** Duration in milliseconds */ durationMs?: number; /** Direct cost override in USD (for skill_call spans with non-token costs) */ costOverride?: number; /** Optional metadata */ metadata?: Record; } /** * Summary view of a task for list display */ export interface IntentTaskSummary { /** Task ID */ id: string; /** Message ID for grouping */ messageId: string; /** Intent description (truncated) */ intent: string; /** Complexity level */ level: IntentLevel; /** Category */ category: IntentCategory; /** Current status */ status: IntentTaskStatus; /** When created */ createdAt: string; /** When last updated */ updatedAt: string; /** Number of runs */ runCount: number; /** Total tokens (input + output) */ totalTokens: number; /** Total LLM cost in USD */ totalCost: number; /** Total skill cost in USD */ totalSkillCost: number; /** Assigned sessions */ assignedSessions: string[]; /** Order within message group */ order: number; /** Schedule ID if associated */ scheduleId?: string; /** Project task ID if associated */ projectTaskId?: string; /** Original message text for this task's message group (preserves user input) */ originalMessage?: string; } /** * Status of a project task based on its linked intent tasks. */ export interface ProjectTaskStatus { /** Project task ID */ projectTaskId: string; /** Total linked intent tasks */ totalTasks: number; /** Completed intent tasks */ completedTasks: number; /** Whether all linked tasks are done */ allCompleted: boolean; /** List of linked task summaries */ tasks: IntentTaskSummary[]; } /** * Determines whether a text segment represents an actionable intent * that should become a task (vs. a question, greeting, acknowledgment, or discussion). * * @param text - The text segment to evaluate * @returns true if the text is actionable and should become a task */ export declare function isActionableIntent(text: string): boolean; /** * Heuristic rules for auto-classifying intent level into L0/L1/L2/L3. * * Decision order (highest precision first): * 1. **L0** — read-only / status / lookup; quantified read still L0. * 2. **L3** — sprint/OKR markers + system-level scope (§2.6 + §2.3). * 3. **L2** — quantifier-trigram (§2.1), doc/file/PR/migration triggers * (§2.2), build/system + deploy/env + e2e + coordinate (§2.3), * sequenced verbs / numbered list (§2.4), cross-system pivot (§2.5), * sprint markers alone (§2.6), or length floor (§2.7 — wordCount > 35 * OR charCount > 80 for ZH parity). * 4. **L1** — fallback (single bounded directive). * * Spec: `specs/2026-05-06-intent-classifier-rules.md` §1.2 + §2. * * @param intent - User intent text * @returns Classified intent level */ export declare function classifyIntentLevel(intent: string): IntentLevel; /** * Heuristic rules for auto-classifying intent category. * Uses prioritized pattern matching — first match wins. * * Bug A v0 (2026-05-06): each category fires on EITHER the EN pattern OR * the ZH parity pattern from {@link CATEGORY_KEYWORDS}. Order is preserved * from the pre-existing EN classifier so historical EN cases stay green. * * @param intent - User intent text * @returns Classified intent category */ export declare function classifyIntentCategory(intent: string): IntentCategory; /** * Decompose a user message into multiple individual actionable intents. * * Three-phase pipeline: * 1. **Split**: Single-pass regex split on conjunctions and sequential markers. * 2. **Filter**: Remove non-actionable segments (questions, greetings, feedback, filler). * 3. **Classify**: Independently classify each actionable segment by level and category. * * @param message - The full user message * @returns DecomposeResult with the original message and extracted actionable intents. * Returns empty intents array if no actionable content is found. * * @example * ```typescript * const result = decomposeIntents('Search for abc then make it into a PDF'); * // result.intents = [ * // { intent: 'Search for abc', level: 'L0', category: 'query' }, * // { intent: 'make it into a PDF', level: 'L1', category: 'code_change' }, * // ] * * // Non-actionable messages return empty * const result2 = decomposeIntents('Looks good, thanks!'); * // result2.intents = [] * ``` */ export declare function decomposeIntents(message: string): DecomposeResult; //# sourceMappingURL=intent-task.types.d.ts.map