@wrongstack/core 0.283.0 → 0.284.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/dist/{compactor-BxddyCFu.d.ts → compactor-DQLL4HTo.d.ts} +1 -1
- package/dist/{config-DkCbA3Bw.d.ts → config-MRqn1V-u.d.ts} +130 -22
- package/dist/coordination/index.d.ts +43 -20
- package/dist/coordination/index.js +1744 -912
- package/dist/coordination/index.js.map +1 -1
- package/dist/{default-config-Buho8yge.d.ts → default-config-B79_gJYv.d.ts} +7 -0
- package/dist/defaults/index.d.ts +25 -29
- package/dist/defaults/index.js +2546 -7396
- package/dist/defaults/index.js.map +1 -1
- package/dist/{director-state-B_GPa78Q.d.ts → director-state-CMS_bMs4.d.ts} +2 -0
- package/dist/{events-KmxSmvho.d.ts → events-Bgnh43r9.d.ts} +27 -10
- package/dist/execution/index.d.ts +15 -16
- package/dist/execution/index.js +534 -140
- package/dist/execution/index.js.map +1 -1
- package/dist/execution/prompt-enhancer.d.ts +1 -1
- package/dist/extension/index.d.ts +6 -6
- package/dist/{global-mailbox-rWVt8YlO.d.ts → global-mailbox-sZwyI6CS.d.ts} +13 -2
- package/dist/{goal-store-8owBXJT2.d.ts → goal-store-Datpp-ar.d.ts} +1 -1
- package/dist/hq/index.d.ts +35 -9
- package/dist/hq/index.js +80 -7
- package/dist/hq/index.js.map +1 -1
- package/dist/{index-BhCteHAF.d.ts → index--Gm41aBJ.d.ts} +26 -11
- package/dist/{index-BEFWNZYs.d.ts → index-CbyuOE5y.d.ts} +5 -1
- package/dist/index.d.ts +52 -1017
- package/dist/index.js +21053 -27778
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +9 -7
- package/dist/infrastructure/index.js +7 -2
- package/dist/infrastructure/index.js.map +1 -1
- package/dist/kernel/index.d.ts +11 -11
- package/dist/kernel/index.js.map +1 -1
- package/dist/{mcp-servers-BUx9A_AQ.d.ts → mcp-servers-DEV4s6Ks.d.ts} +3 -3
- package/dist/models/index.d.ts +4 -4
- package/dist/models/index.js +18 -3
- package/dist/models/index.js.map +1 -1
- package/dist/{agent-subagent-runner-BsuWhB28.d.ts → multi-agent-coordinator-4RCRZKjN.d.ts} +417 -9
- package/dist/{null-fleet-bus-D4e9R7Qc.d.ts → null-fleet-bus-CFoNVQEK.d.ts} +53 -12
- package/dist/observability/index.d.ts +3 -3
- package/dist/{parallel-eternal-engine-iY2uxocj.d.ts → parallel-eternal-engine-HUrtePLd.d.ts} +4 -5
- package/dist/{permission-B6YAtNFz.d.ts → permission-ByDKXEcG.d.ts} +1 -1
- package/dist/{pipeline-ixSFe5jg.d.ts → pipeline-DGDyIohT.d.ts} +28 -7
- package/dist/{provider-model-resolve-DIxKL_T-.d.ts → provider-model-resolve-o2hHLs79.d.ts} +3 -3
- package/dist/{provider-runner-oQhDaZmH.d.ts → provider-runner-ChL-kVg6.d.ts} +3 -3
- package/dist/{retry-policy-V67lBOJz.d.ts → retry-policy-CQ7KwXJa.d.ts} +2 -2
- package/dist/{secret-vault-D7jeyXUQ.d.ts → secret-vault-DxohkUBc.d.ts} +3 -2
- package/dist/security/index.d.ts +4 -4
- package/dist/security/index.js +232 -2
- package/dist/security/index.js.map +1 -1
- package/dist/{selector-Bx2HgUkU.d.ts → selector-D8O6B_Rm.d.ts} +1 -1
- package/dist/{session-event-bridge-Bkp7ORfc.d.ts → session-event-bridge-D_z_mBwk.d.ts} +3 -3
- package/dist/{session-reader-B-Fi9L6I.d.ts → session-reader-7Esxrkpw.d.ts} +1 -1
- package/dist/storage/index.d.ts +77 -39
- package/dist/storage/index.js +1223 -288
- package/dist/storage/index.js.map +1 -1
- package/dist/tasking/index.d.ts +124 -0
- package/dist/tasking/index.js +492 -0
- package/dist/tasking/index.js.map +1 -0
- package/dist/{todos-checkpoint-BwCrj4Cb.d.ts → todos-checkpoint-FY7PjmMx.d.ts} +13 -4
- package/dist/{tool-LVSLiE1s.d.ts → tool-BNlnIJvo.d.ts} +216 -17
- package/dist/{tool-executor-kElSEgO0.d.ts → tool-executor-CckSCM5E.d.ts} +12 -15
- package/dist/tools/index.d.ts +2 -2
- package/dist/tools/index.js.map +1 -1
- package/dist/types/index.d.ts +94 -19
- package/dist/types/index.js +76 -12
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +44 -10
- package/dist/utils/index.js +106 -17
- package/dist/utils/index.js.map +1 -1
- package/dist/{worktree-manager-BjyAW30D.d.ts → worktree-manager-DzwxKE35.d.ts} +1 -1
- package/instructions/coordination/subagent-baseline.md +5 -0
- package/instructions/llm/autonomy-brain.md +3 -2
- package/instructions/system.md +4 -0
- package/package.json +10 -3
- package/skills/mailbox-bridge/SKILL.md +33 -0
- package/dist/multi-agent-coordinator-CrjeTB9i.d.ts +0 -357
- package/dist/sdd/index.d.ts +0 -1993
- package/dist/sdd/index.js +0 -9500
- package/dist/sdd/index.js.map +0 -1
- package/dist/spec-TBi3Jr6T.d.ts +0 -78
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/tasking/task-store.ts","../../src/types/task-graph.ts","../../src/utils/error.ts","../../src/types/errors.ts","../../src/tasking/task-tracker.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { TaskGraph } from '../types/task-graph.js';\nimport type { TaskStore } from './task-tracker.js';\n\n/**\n * In-memory task-graph store used by AutoPhase and tests.\n *\n * The store clones the graph container on read/write so callers cannot replace\n * its Maps/arrays behind the store's back. Task nodes themselves intentionally\n * remain shared: TaskTracker owns node mutation and persists after each change.\n */\nexport class DefaultTaskStore implements TaskStore {\n private readonly graphs = new Map<string, TaskGraph>();\n\n async saveGraph(graph: TaskGraph): Promise<void> {\n this.graphs.set(graph.id, this.cloneGraph(graph));\n }\n\n async loadGraph(id: string): Promise<TaskGraph | null> {\n const graph = this.graphs.get(id);\n return graph ? this.cloneGraph(graph) : null;\n }\n\n async listGraphs(): Promise<Array<{ id: string; title: string; updatedAt: number }>> {\n return Array.from(this.graphs.values()).map((graph) => ({\n id: graph.id,\n title: graph.title,\n updatedAt: graph.updatedAt,\n }));\n }\n\n async deleteGraph(id: string): Promise<void> {\n this.graphs.delete(id);\n }\n\n private cloneGraph(graph: TaskGraph): TaskGraph {\n return {\n ...graph,\n nodes: new Map(graph.nodes),\n edges: [...graph.edges],\n rootNodes: [...graph.rootNodes],\n };\n }\n}\n","export type TaskStatus = 'pending' | 'in_progress' | 'blocked' | 'failed' | 'review' | 'completed';\nexport type TaskPriority = 'critical' | 'high' | 'medium' | 'low';\nexport type TaskType = 'feature' | 'bugfix' | 'refactor' | 'docs' | 'test' | 'chore';\n\nexport interface TaskNode {\n id: string;\n title: string;\n description: string;\n type: TaskType;\n priority: TaskPriority;\n status: TaskStatus;\n assignee?: string | undefined;\n estimateHours?: number | undefined;\n actualHours?: number | undefined;\n tags?: string[] | undefined;\n specRequirementId?: string | undefined;\n parentId?: string | undefined;\n children?: string[] | undefined;\n createdAt: number;\n updatedAt: number;\n startedAt?: number | undefined; // set when status → in_progress\n completedAt?: number | undefined;\n metadata?: Record<string, unknown>;\n}\n\nexport interface TaskEdge {\n id: string;\n from: string;\n to: string;\n type: 'blocks' | 'depends_on' | 'relates_to' | 'implements';\n weight?: number | undefined;\n}\n\nexport interface TaskGraph {\n id: string;\n specId: string;\n title: string;\n nodes: Map<string, TaskNode>;\n edges: TaskEdge[];\n rootNodes: string[];\n createdAt: number;\n updatedAt: number;\n}\n\nexport interface TaskDependency {\n taskId: string;\n blockedBy: string[];\n blocking: string[];\n}\n\nexport interface TaskAssignment {\n taskId: string;\n assignee: string;\n assignedAt: number;\n}\n\nexport interface TaskProgress {\n total: number;\n pending: number;\n inProgress: number;\n blocked: number;\n failed: number;\n review: number;\n completed: number;\n percentComplete: number;\n estimatedHours: number;\n actualHours: number;\n}\n\nexport interface TaskFilter {\n status?: TaskStatus[] | undefined;\n priority?: TaskPriority[] | undefined;\n type?: TaskType[] | undefined;\n assignee?: string[] | undefined;\n tags?: string[] | undefined;\n specRequirementId?: string | undefined;\n}\n\nexport interface TaskSort {\n field: 'priority' | 'createdAt' | 'updatedAt' | 'status';\n direction: 'asc' | 'desc';\n}\n\nexport interface CriticalPathResult {\n taskIds: string[];\n totalEstimateHours: number;\n bottleneckTasks: string[];\n}\n\nexport function computeTaskProgress(graph: TaskGraph): TaskProgress {\n let completed = 0;\n let pending = 0;\n let inProgress = 0;\n let blocked = 0;\n let failed = 0;\n let review = 0;\n let estimatedHours = 0;\n let actualHours = 0;\n for (const n of graph.nodes.values()) {\n switch (n.status) {\n case 'completed':\n completed++;\n break;\n case 'pending':\n pending++;\n break;\n case 'in_progress':\n inProgress++;\n break;\n case 'blocked':\n blocked++;\n break;\n case 'failed':\n failed++;\n break;\n case 'review':\n review++;\n break;\n }\n estimatedHours += n.estimateHours ?? 0;\n actualHours += n.actualHours ?? 0;\n }\n const total = graph.nodes.size;\n\n return {\n total,\n pending,\n inProgress,\n blocked,\n failed,\n review,\n completed,\n percentComplete: total > 0 ? Math.round((completed / total) * 100) : 0,\n estimatedHours,\n actualHours,\n };\n}\n\nexport function findCriticalPath(graph: TaskGraph): CriticalPathResult {\n const nodes = Array.from(graph.nodes.values());\n const criticalNodes = nodes.filter((n) => n.priority === 'critical');\n const bottleneckTasks = criticalNodes\n .filter((n) => graph.edges.some((e) => e.to === n.id && e.type === 'depends_on'))\n .map((n) => n.id);\n\n const totalEstimateHours = criticalNodes.reduce((sum, n) => sum + (n.estimateHours ?? 0), 0);\n\n return {\n taskIds: criticalNodes.map((n) => n.id),\n totalEstimateHours,\n bottleneckTasks,\n };\n}\n\nexport function topologicalSort(graph: TaskGraph): string[] {\n const visited = new Set<string>();\n const inStack = new Set<string>();\n const result: string[] = [];\n\n function visit(id: string): void {\n // Cycle: callers must detect cycles up-front if they care; we just stop recursing.\n if (inStack.has(id)) return;\n if (visited.has(id)) return;\n if (!graph.nodes.has(id)) return;\n\n visited.add(id);\n inStack.add(id);\n\n for (const edge of graph.edges) {\n if (edge.from === id) visit(edge.to);\n }\n\n inStack.delete(id);\n result.push(id);\n }\n\n for (const rootId of graph.rootNodes) {\n visit(rootId);\n }\n\n return result;\n}\n\nexport type SerializableTaskGraphNodes =\n | TaskNode[]\n | Array<[string, TaskNode]>\n | Record<string, TaskNode>;\n\nexport type SerializableTaskGraph = Omit<TaskGraph, 'nodes'> & {\n nodes: SerializableTaskGraphNodes;\n};\n\nexport type SerializedTaskGraph = Omit<TaskGraph, 'nodes'> & {\n nodes: TaskNode[];\n};\n\nexport function serializeTaskGraph(graph: TaskGraph): SerializedTaskGraph {\n return {\n ...graph,\n nodes: Array.from(graph.nodes.values()),\n };\n}\n\nexport function deserializeTaskGraph(input: SerializableTaskGraph): TaskGraph {\n const nodes = new Map<string, TaskNode>();\n if (Array.isArray(input.nodes)) {\n for (const entry of input.nodes) {\n if (Array.isArray(entry)) nodes.set(entry[0], { ...entry[1], id: entry[1].id || entry[0] });\n else nodes.set(entry.id, entry);\n }\n } else {\n for (const [id, node] of Object.entries(input.nodes)) {\n nodes.set(id, { ...node, id: node.id || id });\n }\n }\n return { ...input, nodes };\n}\n","/**\n * Converts an unknown error value to a human-readable string.\n * Used in 40+ files across the codebase to normalize error messaging.\n */\nexport function toErrorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n","import { toErrorMessage } from '../utils/index.js';\n\n/**\n * WrongStack error hierarchy.\n *\n * Every error thrown by the framework is a `WrongStackError` with a\n * machine-readable `code`, a `subsystem` tag, and a `severity` level.\n * This lets consumers (CLI, TUI, plugins, tests) branch on structured\n * data instead of parsing error messages.\n */\n\n// ── Error codes ──────────────────────────────────────────────────────\n\n/**\n * Machine-readable error codes as frozen constants.\n *\n * Use `ERROR_CODES.X` instead of raw string literals for:\n * - IDE autocomplete and compile-time validation\n * - Safe refactoring (rename updates all usages)\n * - Plugin extensibility (extend the object to add custom codes)\n *\n * The `ErrorCode` type is derived from this object, so adding a new\n * code here automatically updates the type without extra changes.\n */\nexport const ERROR_CODES = {\n // Provider\n PROVIDER_RATE_LIMITED: 'PROVIDER_RATE_LIMITED',\n PROVIDER_AUTH_FAILED: 'PROVIDER_AUTH_FAILED',\n PROVIDER_OVERLOADED: 'PROVIDER_OVERLOADED',\n PROVIDER_INVALID_REQUEST: 'PROVIDER_INVALID_REQUEST',\n PROVIDER_SERVER_ERROR: 'PROVIDER_SERVER_ERROR',\n PROVIDER_NETWORK_ERROR: 'PROVIDER_NETWORK_ERROR',\n PROVIDER_CONTEXT_OVERFLOW: 'PROVIDER_CONTEXT_OVERFLOW',\n // Tool\n TOOL_NOT_FOUND: 'TOOL_NOT_FOUND',\n TOOL_PERMISSION_DENIED: 'TOOL_PERMISSION_DENIED',\n TOOL_EXECUTION_FAILED: 'TOOL_EXECUTION_FAILED',\n TOOL_TIMEOUT: 'TOOL_TIMEOUT',\n TOOL_INPUT_INVALID: 'TOOL_INPUT_INVALID',\n // Config\n CONFIG_INVALID: 'CONFIG_INVALID',\n CONFIG_NOT_FOUND: 'CONFIG_NOT_FOUND',\n CONFIG_PARSE_FAILED: 'CONFIG_PARSE_FAILED',\n CONFIG_MIGRATION_NEEDED: 'CONFIG_MIGRATION_NEEDED',\n // Plugin\n PLUGIN_LOAD_FAILED: 'PLUGIN_LOAD_FAILED',\n PLUGIN_API_MISMATCH: 'PLUGIN_API_MISMATCH',\n PLUGIN_MISSING_DEPENDENCY: 'PLUGIN_MISSING_DEPENDENCY',\n // Agent\n AGENT_ITERATION_LIMIT: 'AGENT_ITERATION_LIMIT',\n AGENT_CONTEXT_OVERFLOW: 'AGENT_CONTEXT_OVERFLOW',\n AGENT_ABORTED: 'AGENT_ABORTED',\n AGENT_RUN_FAILED: 'AGENT_RUN_FAILED',\n // Session\n SESSION_NOT_FOUND: 'SESSION_NOT_FOUND',\n SESSION_CORRUPTED: 'SESSION_CORRUPTED',\n SESSION_WRITE_FAILED: 'SESSION_WRITE_FAILED',\n // Container / Registry\n CONTAINER_TOKEN_ALREADY_BOUND: 'CONTAINER_TOKEN_ALREADY_BOUND',\n CONTAINER_TOKEN_NOT_BOUND: 'CONTAINER_TOKEN_NOT_BOUND',\n CONTAINER_CIRCULAR_DEPENDENCY: 'CONTAINER_CIRCULAR_DEPENDENCY',\n REGISTRY_DUPLICATE: 'REGISTRY_DUPLICATE',\n REGISTRY_NOT_FOUND: 'REGISTRY_NOT_FOUND',\n REGISTRY_INVALID: 'REGISTRY_INVALID',\n // File system\n FS_READ_FAILED: 'FS_READ_FAILED',\n FS_WRITE_FAILED: 'FS_WRITE_FAILED',\n FS_MKDIR_FAILED: 'FS_MKDIR_FAILED',\n FS_DELETE_FAILED: 'FS_DELETE_FAILED',\n FS_ATOMIC_WRITE_FAILED: 'FS_ATOMIC_WRITE_FAILED',\n // SDD (Spec-Driven Development)\n SDD_VALIDATION_FAILED: 'SDD_VALIDATION_FAILED',\n SDD_PARSE_FAILED: 'SDD_PARSE_FAILED',\n SDD_INVALID_STATE: 'SDD_INVALID_STATE',\n SDD_NOT_READY: 'SDD_NOT_READY',\n // General\n VALIDATION_ERROR: 'VALIDATION_ERROR',\n PARSE_FAILED: 'PARSE_FAILED',\n UNKNOWN: 'UNKNOWN',\n} as const;\n\n/**\n * Union type derived from `ERROR_CODES`. Using `typeof ERROR_CODES[keyof typeof ERROR_CODES]`\n * instead of a string literal union means TypeScript auto-updates the type whenever\n * a new code is added to `ERROR_CODES` — no need to keep two lists in sync.\n */\nexport type ErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES];\n\nexport type ErrorSubsystem =\n | 'provider'\n | 'tool'\n | 'config'\n | 'plugin'\n | 'agent'\n | 'session'\n | 'sdd'\n | 'container'\n | 'fs'\n | 'general';\nexport type ErrorSeverity = 'fatal' | 'error' | 'warning';\n\n// ── Base error class ─────────────────────────────────────────────────\n\nexport class WrongStackError extends Error {\n readonly code: ErrorCode;\n readonly subsystem: ErrorSubsystem;\n readonly severity: ErrorSeverity;\n readonly recoverable: boolean;\n readonly context?: Record<string, unknown> | undefined;\n\n constructor(opts: {\n message: string;\n code: ErrorCode;\n subsystem: ErrorSubsystem;\n severity?: ErrorSeverity | undefined;\n recoverable?: boolean | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super(opts.message, { cause: opts.cause });\n this.name = 'WrongStackError';\n this.code = opts.code;\n this.subsystem = opts.subsystem;\n this.severity = opts.severity ?? 'error';\n this.recoverable = opts.recoverable ?? false;\n this.context = opts.context;\n }\n\n /**\n * Render a one-line user-facing description.\n * Subclasses should override for domain-specific formatting.\n */\n describe(): string {\n const ctx = this.context ? ` ${formatContext(this.context)}` : '';\n return `${this.code}: ${this.message}${ctx}`;\n }\n}\n\nfunction formatContext(ctx: Record<string, unknown>): string {\n const parts = Object.entries(ctx)\n .filter(([, v]) => v !== undefined)\n .slice(0, 3)\n .map(([k, v]) => `${k}=${String(v)}`);\n return parts.length > 0 ? `[${parts.join(' ')}]` : '';\n}\n\n// ── Specific error classes ───────────────────────────────────────────\n\n/**\n * Tool execution errors — thrown by ToolExecutor and individual tools.\n */\nexport class ToolError extends WrongStackError {\n readonly toolName: string;\n\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n | 'TOOL_NOT_FOUND'\n | 'TOOL_PERMISSION_DENIED'\n | 'TOOL_EXECUTION_FAILED'\n | 'TOOL_TIMEOUT'\n | 'TOOL_INPUT_INVALID'\n >;\n toolName: string;\n recoverable?: boolean | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'tool',\n recoverable: opts.recoverable,\n context: { tool: opts.toolName, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'ToolError';\n this.toolName = opts.toolName;\n }\n}\n\n/**\n * Config loading / validation errors.\n */\nexport class ConfigError extends WrongStackError {\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n 'CONFIG_INVALID' | 'CONFIG_NOT_FOUND' | 'CONFIG_PARSE_FAILED' | 'CONFIG_MIGRATION_NEEDED'\n >;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'config',\n severity: 'fatal',\n recoverable: false,\n context: opts.context,\n cause: opts.cause,\n });\n this.name = 'ConfigError';\n }\n}\n\n/**\n * Plugin loading / lifecycle errors.\n */\nexport class PluginError extends WrongStackError {\n readonly pluginName: string;\n\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n 'PLUGIN_LOAD_FAILED' | 'PLUGIN_API_MISMATCH' | 'PLUGIN_MISSING_DEPENDENCY'\n >;\n pluginName: string;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'plugin',\n severity: 'error',\n recoverable: opts.code === ERROR_CODES.PLUGIN_MISSING_DEPENDENCY,\n context: { plugin: opts.pluginName, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'PluginError';\n this.pluginName = opts.pluginName;\n }\n}\n\n/**\n * Agent runtime errors — thrown by Agent.run when a non-WrongStackError\n * escapes the inner loop, so callers always see a structured error.\n */\nexport class AgentError extends WrongStackError {\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n 'AGENT_ITERATION_LIMIT' | 'AGENT_CONTEXT_OVERFLOW' | 'AGENT_ABORTED' | 'AGENT_RUN_FAILED'\n >;\n recoverable?: boolean | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'agent',\n severity: opts.code === ERROR_CODES.AGENT_ABORTED ? 'warning' : 'error',\n recoverable: opts.recoverable ?? opts.code === ERROR_CODES.AGENT_ITERATION_LIMIT,\n context: opts.context,\n cause: opts.cause,\n });\n this.name = 'AgentError';\n }\n}\n\n/**\n * Wrap an arbitrary thrown value into a `WrongStackError` so the caller\n * always gets a structured error. Pass-throughs WrongStackError instances\n * unchanged; raw `Error`s and primitives get an `AGENT_RUN_FAILED` wrapper\n * with the original preserved as `cause`.\n */\nexport function toWrongStackError(\n err: unknown,\n code: Extract<ErrorCode, 'AGENT_RUN_FAILED' | 'AGENT_ABORTED' | 'UNKNOWN'> = ERROR_CODES.AGENT_RUN_FAILED,\n): WrongStackError {\n if (err instanceof WrongStackError) return err;\n const message = toErrorMessage(err);\n return new AgentError({\n message,\n code: code === 'UNKNOWN' ? ERROR_CODES.AGENT_RUN_FAILED : code,\n cause: err,\n });\n}\n\n/**\n * Session storage errors.\n */\nexport class SessionError extends WrongStackError {\n readonly sessionId?: string | undefined;\n\n constructor(opts: {\n message: string;\n code: Extract<ErrorCode, 'SESSION_NOT_FOUND' | 'SESSION_CORRUPTED' | 'SESSION_WRITE_FAILED'>;\n sessionId?: string | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'session',\n severity: opts.code === ERROR_CODES.SESSION_WRITE_FAILED ? 'error' : 'warning',\n recoverable: opts.code !== ERROR_CODES.SESSION_CORRUPTED,\n context: { sessionId: opts.sessionId, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'SessionError';\n this.sessionId = opts.sessionId;\n }\n}\n\n/**\n * SDD (Spec-Driven Development) errors — spec validation, parsing, and\n * state machine violations in the AISpecBuilder, TaskFlow, and TaskTracker.\n */\nexport class SddError extends WrongStackError {\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n 'SDD_VALIDATION_FAILED' | 'SDD_PARSE_FAILED' | 'SDD_INVALID_STATE' | 'SDD_NOT_READY'\n >;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'sdd',\n severity: opts.code === ERROR_CODES.SDD_PARSE_FAILED ? 'warning' : 'error',\n recoverable: opts.code === ERROR_CODES.SDD_NOT_READY,\n context: opts.context,\n cause: opts.cause,\n });\n this.name = 'SddError';\n }\n}\n\n/**\n * File system operation errors.\n */\nexport class FsError extends WrongStackError {\n readonly path?: string | undefined;\n\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n 'FS_READ_FAILED' | 'FS_WRITE_FAILED' | 'FS_MKDIR_FAILED' | 'FS_DELETE_FAILED' | 'FS_ATOMIC_WRITE_FAILED'\n >;\n path?: string | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'fs',\n severity: 'error',\n recoverable: opts.code !== ERROR_CODES.FS_READ_FAILED,\n context: { path: opts.path, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'FsError';\n this.path = opts.path;\n }\n}\n\n/**\n * HTTP fetch error — thrown when a network request returns a non-OK status.\n * Carries the response status so {@link classifyToolError} can branch on it\n * (429 → transient, 404 → not_found, 401 → permission) without duck-typing\n * the error via `'response' in err`.\n *\n * P3 #18 (before-release.md): the previous `'response' in err` check caught\n * any Error with a `response` property, including custom errors, proxy\n * objects, or mocked errors in tests. `instanceof FetchError` is reliable.\n *\n * Tools and providers that make HTTP requests and need the executor to\n * classify their failures should throw `new FetchError({ status, message })`\n * instead of a bare `Error` with an ad-hoc `response` field.\n */\nexport class FetchError extends WrongStackError {\n readonly status: number;\n\n constructor(opts: {\n message: string;\n status: number;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: ERROR_CODES.VALIDATION_ERROR,\n subsystem: 'general',\n severity: 'error',\n recoverable: opts.status === 429 || opts.status >= 500,\n context: { status: opts.status, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'FetchError';\n this.status = opts.status;\n }\n}\n\n/**\n * Tool input validation error — thrown when a tool's input fails a validation\n * check that the JSON Schema cannot express (e.g. `old_string === new_string`\n * in edit, or a cross-field invariant). Use this instead of a bare\n * `throw new Error('...validation...')` so {@link classifyToolError} can\n * match on `instanceof` rather than a locale-dependent message substring.\n *\n * P2 #6 (before-release.md): the previous `err.message.includes('validation')`\n * check misclassified any error whose message happened to contain \"validation\"\n * (e.g. a third-party \"input validation timeout\") as a VALIDATION error.\n *\n * Named `ToolValidationError` (not `ValidationError`) to avoid colliding with\n * the existing `ValidationError` interface exported by json-schema-validate.ts\n * (a validation-result shape, not an Error subclass).\n */\nexport class ToolValidationError extends WrongStackError {\n constructor(opts: {\n message: string;\n /** Field path or tool name that failed validation, for diagnostics. */\n field?: string | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: ERROR_CODES.VALIDATION_ERROR,\n subsystem: 'general',\n severity: 'error',\n recoverable: false,\n context: { field: opts.field, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'ToolValidationError';\n }\n}\n\n/**\n * Response / payload parse error — thrown when an upstream HTTP response,\n * file, or data structure is well-formed at the transport layer (HTTP 200,\n * valid JSON) but is missing required fields or has an unexpected shape.\n *\n * Distinct from `ConfigError(CONFIG_PARSE_FAILED)` (which is specifically\n * for config-file parsing) and `FetchError` (which covers HTTP non-OK\n * responses). `ParseError` fills the gap: the request succeeded but the\n * response body couldn't be interpreted.\n *\n * Common sites: OAuth token responses missing `access_token`, device-code\n * responses missing `device_code`, registry responses with unexpected\n * schemas.\n */\nexport class ParseError extends WrongStackError {\n readonly source?: string | undefined;\n\n constructor(opts: {\n message: string;\n /**\n * What was being parsed — e.g. `'oauth-token-response'`,\n * `'device-code-response'`. Lets consumers distinguish parse failures\n * from different upstream APIs without parsing the message.\n */\n source?: string | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: ERROR_CODES.PARSE_FAILED,\n subsystem: 'general',\n severity: 'error',\n recoverable: false,\n context: { source: opts.source, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'ParseError';\n this.source = opts.source;\n }\n}\n\n// ── Type guards ──────────────────────────────────────────────────────\n\nexport function isWrongStackError(err: unknown): err is WrongStackError {\n return err instanceof WrongStackError;\n}\n\nexport function isToolError(err: unknown): err is ToolError {\n return err instanceof ToolError;\n}\n\nexport function isConfigError(err: unknown): err is ConfigError {\n return err instanceof ConfigError;\n}\n\nexport function isPluginError(err: unknown): err is PluginError {\n return err instanceof PluginError;\n}\n\nexport function isSessionError(err: unknown): err is SessionError {\n return err instanceof SessionError;\n}\n\nexport function isAgentError(err: unknown): err is AgentError {\n return err instanceof AgentError;\n}\n\nexport function isFsError(err: unknown): err is FsError {\n return err instanceof FsError;\n}\n\nexport function isToolValidationError(err: unknown): err is ToolValidationError {\n return err instanceof ToolValidationError;\n}\n\nexport function isFetchError(err: unknown): err is FetchError {\n return err instanceof FetchError;\n}\n\nexport function isParseError(err: unknown): err is ParseError {\n return err instanceof ParseError;\n}\n\nexport function isSddError(err: unknown): err is SddError {\n return err instanceof SddError;\n}\n","import type {\n TaskFilter,\n TaskGraph,\n TaskNode,\n TaskProgress,\n TaskSort,\n} from '../types/task-graph.js';\nimport { computeTaskProgress } from '../types/task-graph.js';\nimport { ERROR_CODES, SddError } from '../types/errors.js';\nimport { toErrorMessage } from '../utils/error.js';\n\nexport interface TaskStore {\n saveGraph(graph: TaskGraph): Promise<void>;\n loadGraph(id: string): Promise<TaskGraph | null>;\n listGraphs(): Promise<{ id: string; title: string; updatedAt: number }[]>;\n deleteGraph(id: string): Promise<void>;\n}\n\nexport interface TaskTrackerOptions {\n store: TaskStore;\n /**\n * Called when an in-the-background persistence (`saveGraph`) rejects.\n * The synchronous TaskTracker methods (addNode/addEdge/updateNodeStatus)\n * fire-and-forget their writes; without this, a failing store silently\n * loses graph mutations. Defaults to a console.warn.\n */\n onPersistError?: (((err: unknown) => void)) | undefined;\n}\n\nexport interface TaskTransition {\n from: TaskNode['status'];\n to: TaskNode['status'];\n timestamp: number;\n reason?: string | undefined;\n}\n\n/** A change notification emitted to `TaskTracker.subscribe` listeners. */\nexport interface TaskTrackerChange {\n type: 'node_added' | 'node_updated' | 'status_changed' | 'node_removed';\n nodeId: string;\n /** For `node_removed` this is the node as it was just before deletion. */\n node: TaskNode;\n transition?: TaskTransition | undefined;\n}\n\nexport type TaskTrackerListener = (change: TaskTrackerChange) => void;\n\nexport class TaskTracker {\n private graph: TaskGraph | null = null;\n private transitions: TaskTransition[] = [];\n private listeners: TaskTrackerListener[] = [];\n\n constructor(private readonly opts: TaskTrackerOptions) {}\n\n /**\n * Subscribe to live task mutations (add / update / status change). Returns an\n * unsubscribe fn. This is the hook the board projector uses to stream a live\n * snapshot — the tracker was previously fire-and-forget with no observability.\n */\n subscribe(listener: TaskTrackerListener): () => void {\n this.listeners.push(listener);\n return () => {\n const i = this.listeners.indexOf(listener);\n if (i >= 0) this.listeners.splice(i, 1);\n };\n }\n\n private notifyChange(change: TaskTrackerChange): void {\n for (const l of this.listeners) {\n try {\n l(change);\n } catch {\n // A faulty listener must never break a tracker mutation.\n }\n }\n }\n\n /**\n * Attach an existing graph (used by PhaseOrchestrator to associate a tracker\n * with a phase's pre-built task graph without re-creating it).\n */\n setGraph(graph: TaskGraph): void {\n this.graph = graph;\n }\n\n async createGraph(specId: string, title: string): Promise<TaskGraph> {\n this.graph = {\n id: crypto.randomUUID(),\n specId,\n title,\n nodes: new Map(),\n edges: [],\n rootNodes: [],\n createdAt: Date.now(),\n updatedAt: Date.now(),\n };\n await this.opts.store.saveGraph(this.graph);\n return this.graph;\n }\n\n async loadGraph(id: string): Promise<TaskGraph | null> {\n this.graph = await this.opts.store.loadGraph(id);\n return this.graph;\n }\n\n addNode(node: Omit<TaskNode, 'id' | 'createdAt' | 'updatedAt'>): TaskNode {\n if (!this.graph) throw new SddError({\n message: 'No graph loaded',\n code: ERROR_CODES.SDD_INVALID_STATE,\n });\n\n const now = Date.now();\n const newNode: TaskNode = {\n ...node,\n id: crypto.randomUUID(),\n status: node.status ?? 'pending',\n createdAt: now,\n updatedAt: now,\n };\n\n this.graph.nodes.set(newNode.id, newNode);\n\n if (!node.parentId) {\n this.graph.rootNodes.push(newNode.id);\n }\n\n this.graph.updatedAt = now;\n this.persist();\n this.notifyChange({ type: 'node_added', nodeId: newNode.id, node: newNode });\n\n return newNode;\n }\n\n addEdge(from: string, to: string, type: TaskGraph['edges'][0]['type'] = 'depends_on'): void {\n if (!this.graph) throw new SddError({\n message: 'No graph loaded',\n code: ERROR_CODES.SDD_INVALID_STATE,\n });\n\n this.graph.edges.push({\n id: crypto.randomUUID(),\n from,\n to,\n type,\n });\n this.graph.updatedAt = Date.now();\n this.persist();\n }\n\n /**\n * Declare that `taskId` depends on `depId` (a `depends_on` edge `depId → taskId`),\n * guarding against self-loops, duplicates, missing nodes, and cycles. Returns\n * true if the dependency now holds (added or already present), false if it was\n * rejected (would create a cycle / unknown node). This is the safe entry point\n * for wiring agent-declared `dependsOn` references into the graph.\n */\n addDependency(depId: string, taskId: string): boolean {\n if (!this.graph) return false;\n if (depId === taskId) return false;\n if (!this.graph.nodes.has(depId) || !this.graph.nodes.has(taskId)) return false;\n // Already a blocker — idempotent success.\n if (this.getBlockers(taskId).includes(depId)) return true;\n // Cycle guard: if `depId` already (transitively) depends on `taskId`, adding\n // `taskId → depId` would close a loop. Reject rather than deadlock the run.\n if (this.dependsOnTransitively(depId, taskId, new Set())) return false;\n this.addEdge(depId, taskId, 'depends_on');\n return true;\n }\n\n /** True when `taskId` transitively depends on `targetId` (follows depends_on blockers). */\n private dependsOnTransitively(taskId: string, targetId: string, seen: Set<string>): boolean {\n if (taskId === targetId) return true;\n if (seen.has(taskId)) return false;\n seen.add(taskId);\n for (const blocker of this.getBlockers(taskId)) {\n if (this.dependsOnTransitively(blocker, targetId, seen)) return true;\n }\n return false;\n }\n\n /**\n * Merge `patch` into a node's `metadata` (used for per-task model/provider/\n * fallback assignment and the cancel marker). Persists + notifies as a node\n * update. No-op if the node is missing.\n */\n patchMetadata(id: string, patch: Record<string, unknown>): void {\n if (!this.graph) return;\n const node = this.graph.nodes.get(id);\n if (!node) return;\n node.metadata = { ...node.metadata, ...patch };\n node.updatedAt = Date.now();\n this.graph.updatedAt = node.updatedAt;\n this.persist();\n this.notifyChange({ type: 'node_updated', nodeId: id, node });\n }\n\n /**\n * Remove a node and every edge touching it. Intended for deleting a task that\n * has not started yet — callers must gate on status (do not remove a running\n * task). Dependents simply lose this blocker (re-evaluated by `canStart`).\n * Returns true if a node was removed.\n */\n removeNode(id: string): boolean {\n if (!this.graph) return false;\n const node = this.graph.nodes.get(id);\n if (!node) return false;\n this.graph.nodes.delete(id);\n this.graph.edges = this.graph.edges.filter((e) => e.from !== id && e.to !== id);\n this.graph.rootNodes = this.graph.rootNodes.filter((r) => r !== id);\n // Detach from any parent's children list.\n for (const n of this.graph.nodes.values()) {\n if (n.children?.includes(id)) n.children = n.children.filter((c) => c !== id);\n }\n this.graph.updatedAt = Date.now();\n this.persist();\n this.notifyChange({ type: 'node_removed', nodeId: id, node });\n return true;\n }\n\n updateNodeStatus(id: string, status: TaskNode['status'], reason?: string): void {\n if (!this.graph) throw new SddError({\n message: 'No graph loaded',\n code: ERROR_CODES.SDD_INVALID_STATE,\n });\n\n const node = this.graph.nodes.get(id);\n if (!node) throw new SddError({\n message: `Node ${id} not found`,\n code: ERROR_CODES.SDD_NOT_READY,\n context: { nodeId: id },\n });\n\n const from = node.status;\n const now = Date.now();\n node.status = status;\n node.updatedAt = now;\n\n if (status === 'completed') {\n node.completedAt = now;\n node.startedAt = node.startedAt ?? now; // ensure startedAt is set\n }\n if (status === 'in_progress') {\n node.startedAt = now;\n }\n\n this.transitions.push({ from, to: status, timestamp: now, reason });\n\n // Auto-unblock dependents\n if (status === 'completed') {\n this.unblockDependents(id);\n }\n\n // Auto-block blockers\n if (status === 'in_progress') {\n this.checkAndBlockIfNeeded(id);\n }\n\n this.graph.updatedAt = now;\n this.persist();\n this.notifyChange({\n type: 'status_changed',\n nodeId: id,\n node,\n transition: { from, to: status, timestamp: now, reason },\n });\n }\n\n updateNode(id: string, patch: Partial<Pick<TaskNode, 'title' | 'description' | 'priority' | 'estimateHours' | 'tags' | 'assignee'>>): void {\n if (!this.graph) throw new SddError({\n message: 'No graph loaded',\n code: ERROR_CODES.SDD_INVALID_STATE,\n });\n\n const node = this.graph.nodes.get(id);\n if (!node) throw new SddError({\n message: `Node ${id} not found`,\n code: ERROR_CODES.SDD_NOT_READY,\n context: { nodeId: id },\n });\n\n if (patch.title !== undefined) node.title = patch.title;\n if (patch.description !== undefined) node.description = patch.description;\n if (patch.priority !== undefined) node.priority = patch.priority;\n if (patch.estimateHours !== undefined) node.estimateHours = patch.estimateHours;\n if (patch.tags !== undefined) node.tags = patch.tags;\n if (patch.assignee !== undefined) node.assignee = patch.assignee;\n node.updatedAt = Date.now();\n this.graph.updatedAt = node.updatedAt;\n this.persist();\n this.notifyChange({ type: 'node_updated', nodeId: id, node });\n }\n\n getNode(id: string): TaskNode | undefined {\n return this.graph?.nodes.get(id);\n }\n\n getAllNodes(filter?: TaskFilter, sort?: TaskSort): TaskNode[] {\n if (!this.graph) return [];\n\n let nodes = Array.from(this.graph.nodes.values());\n\n if (filter) {\n nodes = nodes.filter((n) => {\n if (filter.status?.length && !filter.status.includes(n.status)) return false;\n if (filter.priority?.length && !filter.priority.includes(n.priority)) return false;\n if (filter.type?.length && !filter.type.includes(n.type)) return false;\n if (filter.assignee?.length && n.assignee && !filter.assignee.includes(n.assignee))\n return false;\n if (filter.tags?.length && n.tags && !n.tags.some((t) => filter.tags?.includes(t)))\n return false;\n if (filter.specRequirementId && n.specRequirementId !== filter.specRequirementId)\n return false;\n return true;\n });\n }\n\n if (sort) {\n nodes.sort((a, b) => {\n const cmp = compareByField(a, b, sort.field);\n return sort.direction === 'asc' ? cmp : -cmp;\n });\n }\n\n return nodes;\n }\n\n getChildren(parentId: string): TaskNode[] {\n if (!this.graph) return [];\n return Array.from(this.graph.nodes.values()).filter((n) => n.parentId === parentId);\n }\n\n getDependents(taskId: string): string[] {\n if (!this.graph) return [];\n return this.graph.edges\n .filter((e) => e.from === taskId && e.type === 'depends_on')\n .map((e) => e.to);\n }\n\n getBlockers(taskId: string): string[] {\n if (!this.graph) return [];\n return this.graph.edges\n .filter((e) => e.to === taskId && e.type === 'depends_on')\n .map((e) => e.from);\n }\n\n canStart(taskId: string): boolean {\n const blockers = this.getBlockers(taskId);\n return blockers.every((id) => {\n const node = this.graph?.nodes.get(id);\n // A task can start when all blockers are either completed or failed.\n // Failed blockers should not permanently deadlock dependent tasks.\n return node?.status === 'completed' || node?.status === 'failed';\n });\n }\n\n getProgress(): TaskProgress {\n if (!this.graph) {\n return {\n total: 0,\n pending: 0,\n inProgress: 0,\n blocked: 0,\n failed: 0,\n review: 0,\n completed: 0,\n percentComplete: 0,\n estimatedHours: 0,\n actualHours: 0,\n };\n }\n return computeTaskProgress(this.graph);\n }\n\n getTransitions(_taskId?: string): TaskTransition[] {\n return [...this.transitions];\n }\n\n private unblockDependents(completedId: string): void {\n if (!this.graph) return;\n const dependents = this.getDependents(completedId);\n for (const depId of dependents) {\n const dep = this.graph.nodes.get(depId);\n if (dep?.status === 'blocked') {\n // Check if all blockers are now completed\n const remainingBlockers = this.getBlockers(depId);\n const allUnblocked = remainingBlockers.every((id) => {\n const blocker = this.graph?.nodes.get(id);\n return blocker?.status === 'completed' || blocker?.status === 'failed';\n });\n if (allUnblocked) {\n dep.status = 'pending';\n dep.updatedAt = Date.now();\n }\n }\n }\n }\n\n private checkAndBlockIfNeeded(taskId: string): void {\n if (!this.graph) return;\n const blockers = this.getBlockers(taskId);\n const someBlocked = blockers.some((id) => {\n const blocker = this.graph?.nodes.get(id);\n // A task is only blocked by incomplete blockers that haven't failed.\n // Failed tasks should not block their dependents.\n return blocker?.status !== 'completed' && blocker?.status !== 'failed';\n });\n if (someBlocked) {\n const node = this.graph.nodes.get(taskId);\n if (node) {\n node.status = 'blocked';\n node.updatedAt = Date.now();\n }\n }\n }\n\n /**\n * Fire-and-forget persistence with attached error handler.\n * Synchronous mutators (addNode/addEdge/updateNodeStatus) use this to\n * avoid forcing an async cascade through every caller; if the store\n * is missing or throwing, the error is surfaced via onPersistError.\n */\n private persist(): void {\n if (!this.graph) return;\n this.opts.store.saveGraph(this.graph).catch((err) => {\n this.opts.onPersistError\n ? this.opts.onPersistError(err)\n : console.warn(JSON.stringify({\n level: 'warn',\n event: 'task_tracker.save_graph_failed',\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }));\n });\n }\n}\n\n// Sort comparison helpers\nconst PRIORITY_RANK: Record<TaskNode['priority'], number> = {\n critical: 0,\n high: 1,\n medium: 2,\n low: 3,\n};\nconst STATUS_RANK: Record<TaskNode['status'], number> = {\n in_progress: 0,\n pending: 1,\n review: 2,\n blocked: 3,\n failed: 4,\n completed: 5,\n};\n\nfunction compareByField(a: TaskNode, b: TaskNode, field: TaskSort['field']): number {\n switch (field) {\n case 'priority': return PRIORITY_RANK[a.priority] - PRIORITY_RANK[b.priority];\n case 'status': return STATUS_RANK[a.status] - STATUS_RANK[b.status];\n case 'createdAt': return a.createdAt - b.createdAt;\n case 'updatedAt': return a.updatedAt - b.updatedAt;\n }\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { A as AttachmentStore, a as AddAttachmentInput, b as AttachmentRef, c as Attachment } from './session-reader-
|
|
2
|
-
import { i as ContentBlock, u as ConversationState, k as SessionStore, S as SessionEvent, j as SessionMetadata, b as SessionWriter, v as
|
|
3
|
-
import { E as EventBus, M as MemoryScope, b as MemoryEntry, c as MemoryStore, d as MemoryRelevanceContext, S as ScoredEntry } from './events-
|
|
4
|
-
import {
|
|
1
|
+
import { A as AttachmentStore, a as AddAttachmentInput, b as AttachmentRef, c as Attachment } from './session-reader-7Esxrkpw.js';
|
|
2
|
+
import { i as ContentBlock, u as ConversationState, k as SessionStore, S as SessionEvent, j as SessionMetadata, b as SessionWriter, v as SessionForkOptions, F as ForkedSession, W as WorkspaceCheckpointRef, w as WorkspaceMaterializationResult, x as ResumedSession, y as SessionData, z as SessionSummary, A as TodoItem } from './tool-BNlnIJvo.js';
|
|
3
|
+
import { E as EventBus, M as MemoryScope, b as MemoryEntry, c as MemoryStore, d as MemoryRelevanceContext, S as ScoredEntry } from './events-Bgnh43r9.js';
|
|
4
|
+
import { j as Config, l as ConfigLoader, m as SyncConfig, n as ConfigStore } from './config-MRqn1V-u.js';
|
|
5
5
|
import { S as SecretVault } from './secret-vault-BAKpgFw_.js';
|
|
6
6
|
import { W as WstackPaths } from './wstack-paths-C3K40Qst.js';
|
|
7
7
|
import { S as SecretScrubber } from './secret-scrubber-3MHDDAtm.js';
|
|
@@ -606,6 +606,11 @@ declare class SessionAnalyzer {
|
|
|
606
606
|
|
|
607
607
|
interface SessionStoreOptions {
|
|
608
608
|
dir: string;
|
|
609
|
+
/**
|
|
610
|
+
* Active project root used to revalidate persisted file-observation hashes
|
|
611
|
+
* during resume. Omit for stores that only inspect/archive transcripts.
|
|
612
|
+
*/
|
|
613
|
+
projectRoot?: string | undefined;
|
|
609
614
|
/** Optional EventBus for emitting session diagnostics. */
|
|
610
615
|
events?: EventBus | undefined;
|
|
611
616
|
/**
|
|
@@ -632,6 +637,8 @@ declare class DefaultSessionStore implements SessionStore {
|
|
|
632
637
|
private readonly dir;
|
|
633
638
|
private readonly events?;
|
|
634
639
|
private readonly secretScrubber?;
|
|
640
|
+
private readonly projectRoot?;
|
|
641
|
+
private readonly checkpointCas?;
|
|
635
642
|
private readonly isSessionInUse?;
|
|
636
643
|
/**
|
|
637
644
|
* In-memory cache for load() results, keyed by session ID. The cache is
|
|
@@ -671,6 +678,8 @@ declare class DefaultSessionStore implements SessionStore {
|
|
|
671
678
|
*/
|
|
672
679
|
private ensureShardDir;
|
|
673
680
|
create(meta: Omit<SessionMetadata, 'startedAt'>): Promise<SessionWriter>;
|
|
681
|
+
fork(id: string, opts?: SessionForkOptions): Promise<ForkedSession>;
|
|
682
|
+
materializeWorkspaceCheckpoint(checkpoint: WorkspaceCheckpointRef, targetRoot: string): Promise<WorkspaceMaterializationResult>;
|
|
674
683
|
resume(id: string): Promise<ResumedSession>;
|
|
675
684
|
load(id: string): Promise<SessionData>;
|
|
676
685
|
/**
|
|
@@ -483,6 +483,15 @@ interface Usage {
|
|
|
483
483
|
cacheWrite5m?: number | undefined;
|
|
484
484
|
cacheWrite1h?: number | undefined;
|
|
485
485
|
}
|
|
486
|
+
/**
|
|
487
|
+
* Effective prompt tokens loaded by the model for one request.
|
|
488
|
+
*
|
|
489
|
+
* Provider adapters normalize `Usage` to disjoint fields: `input` is fresh
|
|
490
|
+
* full-rate tokens, `cacheRead` is cached prefix tokens, and `cacheWrite` is
|
|
491
|
+
* the cache-written prefix segment. Context-window pressure cares about the
|
|
492
|
+
* full prompt the model saw, not only the bill-at-full-rate slice.
|
|
493
|
+
*/
|
|
494
|
+
declare function effectiveInputTokens(usage: Usage): number;
|
|
486
495
|
interface ReasoningRequest {
|
|
487
496
|
enabled?: boolean | undefined;
|
|
488
497
|
effort?: ReasoningEffort | undefined;
|
|
@@ -695,14 +704,47 @@ interface ProviderErrorBody {
|
|
|
695
704
|
/** Original length of the response body in bytes, when `truncated` is true. */
|
|
696
705
|
rawLength?: number | undefined;
|
|
697
706
|
}
|
|
707
|
+
/**
|
|
708
|
+
* Canonical provider-failure taxonomy. Computed ONCE at error-construction
|
|
709
|
+
* time (`classifyProviderError`) and carried on `ProviderError.kind` so
|
|
710
|
+
* every downstream consumer — retry policy, cross-provider fallback,
|
|
711
|
+
* recovery strategies, the subagent error classifier — branches on the
|
|
712
|
+
* same classification instead of re-deriving it from status codes and
|
|
713
|
+
* message regexes. When a new provider's error format needs special
|
|
714
|
+
* handling, this module is the only place to teach it.
|
|
715
|
+
*/
|
|
716
|
+
type ProviderErrorKind = 'rate_limit' | 'overloaded' | 'server' | 'timeout' | 'network' | 'stream_hang' | 'auth' | 'context_overflow' | 'content_filter' | 'invalid_request' | 'unknown';
|
|
717
|
+
/**
|
|
718
|
+
* Classify a provider HTTP failure into the canonical taxonomy from its
|
|
719
|
+
* status code plus the parsed error body (and, for message-only errors
|
|
720
|
+
* without a structured body, the error message itself). Pure and total —
|
|
721
|
+
* always returns a kind, never throws.
|
|
722
|
+
*/
|
|
723
|
+
declare function classifyProviderError(status: number, body?: ProviderErrorBody, message?: string): ProviderErrorKind;
|
|
724
|
+
/**
|
|
725
|
+
* Whether a kind is worth retrying against the SAME provider/model.
|
|
726
|
+
* `context_overflow` is deliberately false — the request must shrink first;
|
|
727
|
+
* `auth`/`invalid_request`/`content_filter` won't improve on replay.
|
|
728
|
+
*
|
|
729
|
+
* Exhaustive by construction (`Record<ProviderErrorKind, …>`): adding a new
|
|
730
|
+
* kind refuses to compile until it is classified here. Every kind→X mapping
|
|
731
|
+
* in the codebase follows this drift-guard pattern — see also KIND_TO_CODE
|
|
732
|
+
* below, DefaultRetryPolicy.maxAttempts, fallback-model shouldFallback, and
|
|
733
|
+
* the coordinator's providerErrorToSubagentError.
|
|
734
|
+
*/
|
|
735
|
+
declare function isRetryableKind(kind: ProviderErrorKind): boolean;
|
|
698
736
|
declare class ProviderError extends WrongStackError {
|
|
699
737
|
readonly status: number;
|
|
700
738
|
readonly retryable: boolean;
|
|
701
739
|
readonly providerId: string;
|
|
740
|
+
/** Canonical failure classification — see {@link ProviderErrorKind}. */
|
|
741
|
+
readonly kind: ProviderErrorKind;
|
|
702
742
|
readonly body?: ProviderErrorBody | undefined;
|
|
703
743
|
constructor(message: string, status: number, retryable: boolean, providerId: string, opts?: {
|
|
704
744
|
body?: ProviderErrorBody | undefined;
|
|
705
745
|
cause?: unknown | undefined;
|
|
746
|
+
/** Override the computed classification (rarely needed — tests, custom wires). */
|
|
747
|
+
kind?: ProviderErrorKind | undefined;
|
|
706
748
|
});
|
|
707
749
|
/**
|
|
708
750
|
* Render a one-line, user-facing description. Designed for the CLI/TUI
|
|
@@ -758,6 +800,14 @@ interface SessionMetadata {
|
|
|
758
800
|
endedAt?: string | undefined;
|
|
759
801
|
/** Set when a session is closed with open tool calls — used to restore pending state on resume. */
|
|
760
802
|
pendingToolUses?: string[] | undefined;
|
|
803
|
+
/** Parent journal metadata when this session was created by fork(). */
|
|
804
|
+
forkedFrom?: {
|
|
805
|
+
sessionId: string;
|
|
806
|
+
checkpointPromptIndex?: number | undefined;
|
|
807
|
+
checkpointHash: string;
|
|
808
|
+
workspace: 'shared-current';
|
|
809
|
+
workspaceCheckpointHash?: string | undefined;
|
|
810
|
+
} | undefined;
|
|
761
811
|
}
|
|
762
812
|
/**
|
|
763
813
|
* SessionEvent — per-session persistent JSONL audit + reconstruct log.
|
|
@@ -765,8 +815,8 @@ interface SessionMetadata {
|
|
|
765
815
|
* ## Two-Tier Model (see Config.session.auditLevel)
|
|
766
816
|
*
|
|
767
817
|
* **Core Reconstruct Set** (always persisted, minimal & reliable):
|
|
768
|
-
* - `session_start`, `session_resumed`, `user_input`, `llm_response`, `tool_result`
|
|
769
|
-
* - `checkpoint`, `file_snapshot`, `rewound`
|
|
818
|
+
* - `session_start`, `session_resumed`, `session_forked`, `user_input`, `llm_response`, `tool_result`
|
|
819
|
+
* - `context_snapshot`, `checkpoint`, `file_snapshot`, `file_observation`, `rewound`
|
|
770
820
|
* - `in_flight_start` / `in_flight_end`, `session_end`
|
|
771
821
|
*
|
|
772
822
|
* These events are **required** for correct resume, rewind, crash recovery
|
|
@@ -784,8 +834,9 @@ interface SessionMetadata {
|
|
|
784
834
|
* ## Guarantees
|
|
785
835
|
* - All appends are best-effort. A failed write logs a throttled warning but
|
|
786
836
|
* never aborts the agent loop.
|
|
787
|
-
* - Sensitive content in `user_input
|
|
788
|
-
* the configured SecretScrubber before
|
|
837
|
+
* - Sensitive content in `user_input`, `llm_response`, and
|
|
838
|
+
* `context_snapshot` is passed through the configured SecretScrubber before
|
|
839
|
+
* being written or summarized.
|
|
789
840
|
* - The log is append-only JSONL. Individual lines may be malformed after
|
|
790
841
|
* hard crashes; `DefaultSessionStore.load()` silently skips bad lines.
|
|
791
842
|
*
|
|
@@ -807,6 +858,15 @@ type SessionEvent = {
|
|
|
807
858
|
id: string;
|
|
808
859
|
model: string;
|
|
809
860
|
provider: string;
|
|
861
|
+
} | {
|
|
862
|
+
type: 'session_forked';
|
|
863
|
+
ts: string;
|
|
864
|
+
parentSessionId: string;
|
|
865
|
+
parentCheckpointPromptIndex?: number | undefined;
|
|
866
|
+
parentCheckpointHash: string;
|
|
867
|
+
/** The child journal is isolated; filesystem state remains shared. */
|
|
868
|
+
workspace: 'shared-current';
|
|
869
|
+
workspaceCheckpointHash?: string | undefined;
|
|
810
870
|
} | {
|
|
811
871
|
type: 'user_input';
|
|
812
872
|
ts: string;
|
|
@@ -838,6 +898,16 @@ type SessionEvent = {
|
|
|
838
898
|
id: string;
|
|
839
899
|
content: unknown;
|
|
840
900
|
isError: boolean;
|
|
901
|
+
} | {
|
|
902
|
+
/**
|
|
903
|
+
* Exact post-rewrite conversation state. Replay replaces all messages
|
|
904
|
+
* reconstructed before this event, then continues applying later events.
|
|
905
|
+
* Currently emitted after compaction.
|
|
906
|
+
*/
|
|
907
|
+
type: 'context_snapshot';
|
|
908
|
+
ts: string;
|
|
909
|
+
reason: 'compaction';
|
|
910
|
+
messages: Message[];
|
|
841
911
|
} | {
|
|
842
912
|
type: 'compaction';
|
|
843
913
|
ts: string;
|
|
@@ -996,11 +1066,25 @@ type SessionEvent = {
|
|
|
996
1066
|
ts: string;
|
|
997
1067
|
promptIndex: number;
|
|
998
1068
|
promptPreview: string;
|
|
1069
|
+
/** Content-addressed Git HEAD + dirty/untracked workspace manifest. */
|
|
1070
|
+
workspaceCheckpoint?: WorkspaceCheckpointRef | undefined;
|
|
999
1071
|
} | {
|
|
1000
1072
|
type: 'file_snapshot';
|
|
1001
1073
|
ts: string;
|
|
1002
1074
|
promptIndex: number;
|
|
1003
1075
|
files: FileSnapshot[];
|
|
1076
|
+
} | {
|
|
1077
|
+
/**
|
|
1078
|
+
* Hash of a file version observed by a tool. The latest observation per
|
|
1079
|
+
* path is revalidated when the session resumes so stale tool context is
|
|
1080
|
+
* surfaced to the model before it continues.
|
|
1081
|
+
*/
|
|
1082
|
+
type: 'file_observation';
|
|
1083
|
+
ts: string;
|
|
1084
|
+
path: string;
|
|
1085
|
+
hash: string;
|
|
1086
|
+
mtimeMs: number;
|
|
1087
|
+
source: 'user' | 'write';
|
|
1004
1088
|
} | {
|
|
1005
1089
|
type: 'rewound';
|
|
1006
1090
|
ts: string;
|
|
@@ -1013,9 +1097,10 @@ type SessionEvent = {
|
|
|
1013
1097
|
* Marks the start of "the process is currently working on this
|
|
1014
1098
|
* point in the log". If the process exits cleanly, a matching
|
|
1015
1099
|
* `in_flight_end` follows. If the process dies (crash, OOM,
|
|
1016
|
-
* machine sleep, SIGKILL)
|
|
1017
|
-
*
|
|
1018
|
-
*
|
|
1100
|
+
* machine sleep, SIGKILL), ordinary request/response/tool events may
|
|
1101
|
+
* follow the start marker but no later lifecycle boundary closes it.
|
|
1102
|
+
* `SessionRecovery.detectStale` scans for that latest unmatched
|
|
1103
|
+
* lifecycle boundary and flags the session as resumable.
|
|
1019
1104
|
*
|
|
1020
1105
|
* `context` is a free-form description of the current
|
|
1021
1106
|
* operation (e.g. "iteration 14 / tool: read / id: tu-7") so
|
|
@@ -1050,6 +1135,39 @@ type FileSnapshot = {
|
|
|
1050
1135
|
before: string | null;
|
|
1051
1136
|
after: string | null;
|
|
1052
1137
|
};
|
|
1138
|
+
interface WorkspaceCheckpointRef {
|
|
1139
|
+
manifestHash: string;
|
|
1140
|
+
baseHead: string;
|
|
1141
|
+
entryCount: number;
|
|
1142
|
+
unresolvedCount: number;
|
|
1143
|
+
capturedAt: string;
|
|
1144
|
+
/** Base Git tree plus every non-ignored changed/untracked path. */
|
|
1145
|
+
coverage: 'git-head-plus-dirty';
|
|
1146
|
+
}
|
|
1147
|
+
interface WorkspaceMaterializationResult {
|
|
1148
|
+
targetRoot: string;
|
|
1149
|
+
writtenFiles: string[];
|
|
1150
|
+
deletedFiles: string[];
|
|
1151
|
+
errors: string[];
|
|
1152
|
+
}
|
|
1153
|
+
type ResumeFileStatus = 'modified' | 'deleted' | 'unreadable' | 'outside_project';
|
|
1154
|
+
interface ResumeFileValidationEntry {
|
|
1155
|
+
/** Absolute path recorded by the original tool observation. */
|
|
1156
|
+
path: string;
|
|
1157
|
+
/** Timestamp of the latest observation that was checked. */
|
|
1158
|
+
observedAt: string;
|
|
1159
|
+
status: ResumeFileStatus;
|
|
1160
|
+
expectedHash: string;
|
|
1161
|
+
actualHash?: string | undefined;
|
|
1162
|
+
detail?: string | undefined;
|
|
1163
|
+
}
|
|
1164
|
+
interface ResumeValidation {
|
|
1165
|
+
checkedAt: string;
|
|
1166
|
+
/** Number of distinct paths with a valid persisted observation. */
|
|
1167
|
+
checkedFileCount: number;
|
|
1168
|
+
/** Changed, missing, unreadable, or out-of-scope paths. */
|
|
1169
|
+
staleFiles: ResumeFileValidationEntry[];
|
|
1170
|
+
}
|
|
1053
1171
|
interface SessionSummary {
|
|
1054
1172
|
id: string;
|
|
1055
1173
|
title: string;
|
|
@@ -1098,11 +1216,29 @@ interface SessionData {
|
|
|
1098
1216
|
outputTokens?: number | undefined;
|
|
1099
1217
|
outputLines?: number | undefined;
|
|
1100
1218
|
}>;
|
|
1219
|
+
/** Present on resume when the store is configured with a project root. */
|
|
1220
|
+
resumeValidation?: ResumeValidation | undefined;
|
|
1101
1221
|
}
|
|
1102
1222
|
interface ResumedSession {
|
|
1103
1223
|
writer: SessionWriter;
|
|
1104
1224
|
data: SessionData;
|
|
1105
1225
|
}
|
|
1226
|
+
interface SessionForkOptions {
|
|
1227
|
+
/** Omit to fork the latest persisted event boundary. */
|
|
1228
|
+
checkpointPromptIndex?: number | undefined;
|
|
1229
|
+
}
|
|
1230
|
+
interface ForkedSession {
|
|
1231
|
+
id: string;
|
|
1232
|
+
data: SessionData;
|
|
1233
|
+
parentSessionId: string;
|
|
1234
|
+
checkpointPromptIndex?: number | undefined;
|
|
1235
|
+
/** SHA-256 of the exact parent event prefix used to create this branch. */
|
|
1236
|
+
checkpointHash: string;
|
|
1237
|
+
/** Session history is isolated, but both branches still see the same files. */
|
|
1238
|
+
workspace: 'shared-current';
|
|
1239
|
+
/** Available for checkpoint forks captured by workspace-CAS-aware writers. */
|
|
1240
|
+
workspaceCheckpoint?: WorkspaceCheckpointRef | undefined;
|
|
1241
|
+
}
|
|
1106
1242
|
interface SessionStore {
|
|
1107
1243
|
create(meta: Omit<SessionMetadata, 'startedAt'>): Promise<SessionWriter>;
|
|
1108
1244
|
load(id: string): Promise<SessionData>;
|
|
@@ -1113,6 +1249,14 @@ interface SessionStore {
|
|
|
1113
1249
|
* `session_resumed` marker is appended for audit.
|
|
1114
1250
|
*/
|
|
1115
1251
|
resume(id: string): Promise<ResumedSession>;
|
|
1252
|
+
/**
|
|
1253
|
+
* Create a non-destructive child journal from a persisted parent boundary.
|
|
1254
|
+
* Parent file snapshots are intentionally not inherited as rewind authority;
|
|
1255
|
+
* filesystem isolation is the caller's worktree/CAS responsibility.
|
|
1256
|
+
*/
|
|
1257
|
+
fork?(id: string, opts?: SessionForkOptions): Promise<ForkedSession>;
|
|
1258
|
+
/** Apply a captured workspace manifest to an already-isolated checkout. */
|
|
1259
|
+
materializeWorkspaceCheckpoint?(checkpoint: WorkspaceCheckpointRef, targetRoot: string): Promise<WorkspaceMaterializationResult>;
|
|
1116
1260
|
list(limit?: number): Promise<SessionSummary[]>;
|
|
1117
1261
|
/**
|
|
1118
1262
|
* Set or clear a user-supplied name on a session. An empty/whitespace
|
|
@@ -1200,9 +1344,19 @@ interface SessionWriter {
|
|
|
1200
1344
|
* Flush any buffered events to disk immediately. Use after critical
|
|
1201
1345
|
* events (user_input, llm_response) to ensure they survive a crash
|
|
1202
1346
|
* or SIGKILL that would otherwise leave them in the in-memory buffer.
|
|
1203
|
-
* Idempotent — safe to call even when the buffer is empty.
|
|
1347
|
+
* Idempotent — safe to call even when the buffer is empty. File-backed
|
|
1348
|
+
* writers reject on a failed disk append while retaining the batch for a
|
|
1349
|
+
* later retry; callers may log/degrade without losing event chronology.
|
|
1204
1350
|
*/
|
|
1205
1351
|
flush(): Promise<void>;
|
|
1352
|
+
/**
|
|
1353
|
+
* Last-gasp synchronous drain for hard-exit paths (e.g. `process.exit`
|
|
1354
|
+
* after rapid Ctrl+C) where the async `flush()` cannot be awaited.
|
|
1355
|
+
* Writes whatever is still in the in-memory buffer with a blocking
|
|
1356
|
+
* append. Best-effort — errors are swallowed. Optional: in-memory
|
|
1357
|
+
* writers have nothing durable to drain.
|
|
1358
|
+
*/
|
|
1359
|
+
flushSync?(): void;
|
|
1206
1360
|
close(): Promise<void>;
|
|
1207
1361
|
/**
|
|
1208
1362
|
* Register a file change for later snapshotting.
|
|
@@ -1214,6 +1368,17 @@ interface SessionWriter {
|
|
|
1214
1368
|
before: string | null;
|
|
1215
1369
|
after: string | null;
|
|
1216
1370
|
}): void;
|
|
1371
|
+
/**
|
|
1372
|
+
* Persist the hash of a file version observed by a tool. Optional for
|
|
1373
|
+
* alternate/in-memory writers; file-backed writers use it for stale-file
|
|
1374
|
+
* validation during resume.
|
|
1375
|
+
*/
|
|
1376
|
+
recordFileObservation?(input: {
|
|
1377
|
+
path: string;
|
|
1378
|
+
hash: string;
|
|
1379
|
+
mtimeMs: number;
|
|
1380
|
+
source: 'user' | 'write';
|
|
1381
|
+
}): void;
|
|
1217
1382
|
/**
|
|
1218
1383
|
* Record a structured side effect for audit (P2 #5). Implementations
|
|
1219
1384
|
* append a `side_effect` event to the session JSONL. Best-effort —
|
|
@@ -1354,22 +1519,23 @@ interface TokenCounter {
|
|
|
1354
1519
|
/** Optional live session binding used by token.accounted events. */
|
|
1355
1520
|
setSessionId?(sessionId: string | (() => string | undefined) | undefined): void;
|
|
1356
1521
|
/**
|
|
1357
|
-
*
|
|
1358
|
-
*
|
|
1359
|
-
* ctx bar) — tokenCounter.total() is cumulative across all
|
|
1360
|
-
* and cannot be compared meaningfully against a per-request
|
|
1361
|
-
* ceiling.
|
|
1522
|
+
* Disjoint token counts from the most recently-accounted request. Sum
|
|
1523
|
+
* input + cacheRead + cacheWrite for per-request context pressure tracking
|
|
1524
|
+
* (e.g. status bar ctx bar) — tokenCounter.total() is cumulative across all
|
|
1525
|
+
* requests and cannot be compared meaningfully against a per-request
|
|
1526
|
+
* maxContext ceiling.
|
|
1362
1527
|
*/
|
|
1363
1528
|
currentRequestTokens(): {
|
|
1364
1529
|
input: number;
|
|
1365
1530
|
cacheRead: number;
|
|
1531
|
+
cacheWrite: number;
|
|
1366
1532
|
};
|
|
1367
1533
|
/**
|
|
1368
1534
|
* Override the last-request token snapshot. Used by slash commands like
|
|
1369
1535
|
* /compact that modify ctx.messages without making an API request —
|
|
1370
1536
|
* after calling this, the TUI/REPL context bar reflects the new size.
|
|
1371
1537
|
*/
|
|
1372
|
-
setCurrentRequestTokens(input: number, cacheRead?: number): void;
|
|
1538
|
+
setCurrentRequestTokens(input: number, cacheRead?: number, cacheWrite?: number): void;
|
|
1373
1539
|
total(): Usage;
|
|
1374
1540
|
estimateCost(): {
|
|
1375
1541
|
input: number;
|
|
@@ -1425,10 +1591,13 @@ interface ReadonlyConversationState {
|
|
|
1425
1591
|
declare class ConversationState {
|
|
1426
1592
|
private readonly ctx;
|
|
1427
1593
|
private readonly listeners;
|
|
1594
|
+
private _revision;
|
|
1428
1595
|
constructor(ctx: Context);
|
|
1429
1596
|
get messages(): readonly Message[];
|
|
1430
1597
|
get todos(): readonly TodoItem[];
|
|
1431
1598
|
get meta(): Readonly<Record<string, unknown>>;
|
|
1599
|
+
/** Monotonic mutation counter for consumers that need to detect rewrites. */
|
|
1600
|
+
get revision(): number;
|
|
1432
1601
|
/**
|
|
1433
1602
|
* Cheap immutable snapshot. Useful for tests and for compaction passes
|
|
1434
1603
|
* that need a stable view across an async boundary.
|
|
@@ -1609,6 +1778,18 @@ declare class Context implements RunEnv {
|
|
|
1609
1778
|
*/
|
|
1610
1779
|
writtenFiles: Set<string>;
|
|
1611
1780
|
fileMtimes: Map<string, number>;
|
|
1781
|
+
/**
|
|
1782
|
+
* sha-256 (hex) of file content at the last recorded read/write, when the
|
|
1783
|
+
* recording tool had the content in hand. Used by `edit` as the authoritative
|
|
1784
|
+
* staleness arbiter: mtime comparison has a 2 s tolerance window on Windows
|
|
1785
|
+
* (FAT/NTFS granularity) during which an external modification is invisible,
|
|
1786
|
+
* and conversely a bare `touch` bumps mtime without changing content. Hash
|
|
1787
|
+
* equality resolves both cases exactly. Entries are dropped whenever a
|
|
1788
|
+
* hash-less `recordRead` observes a *different* mtime (content may have
|
|
1789
|
+
* changed under us — fall back to the mtime heuristic rather than trust a
|
|
1790
|
+
* stale hash).
|
|
1791
|
+
*/
|
|
1792
|
+
fileHashes: Map<string, string>;
|
|
1612
1793
|
/**
|
|
1613
1794
|
* Structured side-effect records accumulated during the current run
|
|
1614
1795
|
* (P2 #5). Populated by `recordSideEffect()` — read by /diag for an
|
|
@@ -1707,8 +1888,16 @@ declare class Context implements RunEnv {
|
|
|
1707
1888
|
* approved the new content (P1 #1, before-release.md).
|
|
1708
1889
|
*
|
|
1709
1890
|
* `fileMtimes` is updated in both cases so mtime-based staleness checks work.
|
|
1710
|
-
|
|
1711
|
-
|
|
1891
|
+
*
|
|
1892
|
+
* `contentHash` (sha-256 hex of the exact content seen) is optional so
|
|
1893
|
+
* existing callers keep working. When provided it is stored in `fileHashes`
|
|
1894
|
+
* and becomes the authoritative staleness arbiter for later edits. When
|
|
1895
|
+
* omitted, a previously stored hash survives only if the observed mtime is
|
|
1896
|
+
* unchanged — a different mtime with no fresh hash means the content may
|
|
1897
|
+
* have changed, so the stale hash is dropped and staleness checks fall back
|
|
1898
|
+
* to mtime comparison.
|
|
1899
|
+
*/
|
|
1900
|
+
recordRead(absPath: string, mtimeMs: number, source?: 'user' | 'write', contentHash?: string): void;
|
|
1712
1901
|
/** Clear accumulated file-read metadata after compaction or at boundaries
|
|
1713
1902
|
* where stale read history could cause tools to skip legitimate re-reads.
|
|
1714
1903
|
* The agent re-populates this naturally on the next file access. */
|
|
@@ -1734,6 +1923,9 @@ declare class Context implements RunEnv {
|
|
|
1734
1923
|
/** True if `edit`/`write` wrote this file in the current session. */
|
|
1735
1924
|
hasWritten(absPath: string): boolean;
|
|
1736
1925
|
lastReadMtime(absPath: string): number | undefined;
|
|
1926
|
+
/** sha-256 (hex) of the content at the last recorded read/write, if the
|
|
1927
|
+
* recording tool supplied one. See `fileHashes` for drop semantics. */
|
|
1928
|
+
lastReadHash(absPath: string): string | undefined;
|
|
1737
1929
|
/**
|
|
1738
1930
|
* Change the working directory for path resolution. Resolves relative paths
|
|
1739
1931
|
* against `projectRoot` and validates the result is within the project root.
|
|
@@ -1817,6 +2009,13 @@ interface Tool<I = unknown, O = unknown> {
|
|
|
1817
2009
|
*/
|
|
1818
2010
|
_estDefTokens?: number | undefined;
|
|
1819
2011
|
usageHint?: string | undefined;
|
|
2012
|
+
/** Structured guidance for choosing between similar tools. */
|
|
2013
|
+
selection?: {
|
|
2014
|
+
/** A concise boundary where this tool should not be selected. */
|
|
2015
|
+
doNotUseWhen: string;
|
|
2016
|
+
/** Tool names the model should prefer for that boundary. */
|
|
2017
|
+
useInstead?: readonly string[] | undefined;
|
|
2018
|
+
} | undefined;
|
|
1820
2019
|
/** Optional category for grouping in help lists and system prompts. */
|
|
1821
2020
|
category?: string | undefined;
|
|
1822
2021
|
inputSchema: JSONSchema;
|
|
@@ -1988,4 +2187,4 @@ interface ToolErrorInfo {
|
|
|
1988
2187
|
readonly detail?: string;
|
|
1989
2188
|
}
|
|
1990
2189
|
|
|
1991
|
-
export { type
|
|
2190
|
+
export { type FileSnapshot as $, type TodoItem as A, type ToolUseBlock as B, type CacheStats as C, type ToolResultBlock as D, AgentError as E, type ForkedSession as F, type CompletedWorkEvidence as G, type CompletedWorkSource as H, ConfigError as I, type JSONSchema as J, type ContextEvidenceState as K, type ContextFileEvidence as L, type Message as M, type ContextInit as N, type ContextIntentEvidence as O, type Provider as P, type ContextRepeatedReadEvidence as Q, type ReasoningRequest as R, type SessionEvent as S, type TokenCounter as T, type Usage as U, ERROR_CODES as V, type WorkspaceCheckpointRef as W, type ErrorCode as X, type ErrorSeverity as Y, type ErrorSubsystem as Z, FetchError as _, type ReasoningConfig as a, FsError as a0, type ImageBlock as a1, type JsonSchemaSpec as a2, type MessageRole as a3, ParseError as a4, PluginError as a5, type ProviderErrorBody as a6, type ProviderErrorKind as a7, type ReadonlyConversationState as a8, type RequestCacheControl as a9, effectiveInputTokens as aA, extractRunEnv as aB, isAgentError as aC, isConfigError as aD, isFetchError as aE, isFsError as aF, isImageBlock as aG, isParseError as aH, isPluginError as aI, isRetryableKind as aJ, isSddError as aK, isSessionError as aL, isTextBlock as aM, isToolError as aN, isToolResultBlock as aO, isToolUseBlock as aP, isToolValidationError as aQ, isWrongStackError as aR, toWrongStackError as aS, wrapAsState as aT, type ResponseFormat as aa, type ResumeFileStatus as ab, type ResumeFileValidationEntry as ac, type ResumeValidation as ad, type RunEnv as ae, type SafetySetting as af, SddError as ag, SessionError as ah, type SideEffect as ai, type SideEffectRisk as aj, type StateChange as ak, type StateChangeHandler as al, type StopReason as am, type StreamEvent as an, StreamHangError as ao, type ThinkingBlock as ap, type ToolCallContext as aq, ToolError as ar, type ToolErrorInfo as as, type ToolEvidenceStatus as at, type ToolFinalEvent as au, type ToolIconId as av, type ToolStreamEvent as aw, ToolValidationError as ax, WrongStackError as ay, classifyProviderError as az, type SessionWriter as b, type Request as c, Context as d, type Response as e, type Permission as f, type Tool as g, ProviderError as h, type ContentBlock as i, type SessionMetadata as j, type SessionStore as k, ToolErrorCategory as l, type ToolProgressEvent as m, type RiskTier as n, type ToolOutputMetadata as o, type ReasoningEffort as p, type CacheTtl as q, type Capabilities as r, type TextBlock as s, type RunOptions as t, ConversationState as u, type SessionForkOptions as v, type WorkspaceMaterializationResult as w, type ResumedSession as x, type SessionData as y, type SessionSummary as z };
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { d as Context, c as Request, P as Provider, h as ProviderError, g as Tool,
|
|
2
|
-
import { E as EventBus } from './events-
|
|
3
|
-
import { M as MiddlewareHandler, b as Middleware } from './pipeline-
|
|
4
|
-
import { S as SessionEventBridge } from './session-event-bridge-
|
|
5
|
-
import { C as Compactor, a as CompactReport } from './compactor-
|
|
6
|
-
import {
|
|
7
|
-
import { A as Agent,
|
|
8
|
-
import {
|
|
9
|
-
import { D as DesignStack, a as DesignStudioState, b as DesignKitLoader, c as DesignKitManifest, d as DesignKitEntry, e as DesignKitTokens } from './parallel-eternal-engine-
|
|
10
|
-
import { E as ErrorHandler, a as RecoveryDecision, R as RetryPolicy } from './retry-policy-
|
|
11
|
-
import { M as MessageSelector } from './selector-
|
|
1
|
+
import { d as Context, c as Request, P as Provider, h as ProviderError, g as Tool, B as ToolUseBlock, D as ToolResultBlock } from './tool-BNlnIJvo.js';
|
|
2
|
+
import { E as EventBus } from './events-Bgnh43r9.js';
|
|
3
|
+
import { M as MiddlewareHandler, b as Middleware } from './pipeline-DGDyIohT.js';
|
|
4
|
+
import { S as SessionEventBridge } from './session-event-bridge-D_z_mBwk.js';
|
|
5
|
+
import { C as Compactor, a as CompactReport } from './compactor-DQLL4HTo.js';
|
|
6
|
+
import { o as ContextWindowAggressiveOn, p as ContextWindowPolicy, M as ModelsRegistry, j as Config } from './config-MRqn1V-u.js';
|
|
7
|
+
import { A as Agent, c as DoneCondition } from './multi-agent-coordinator-4RCRZKjN.js';
|
|
8
|
+
import { f as RunResult, S as SystemPromptContributor, A as AgentPipelines, T as ToolCallPipelinePayload, U as UserInputPayload, g as ToolExecutorOptions, h as ToolExecutorStrategy, i as ToolBatchResult } from './index--Gm41aBJ.js';
|
|
9
|
+
import { D as DesignStack, a as DesignStudioState, b as DesignKitLoader, c as DesignKitManifest, d as DesignKitEntry, e as DesignKitTokens } from './parallel-eternal-engine-HUrtePLd.js';
|
|
10
|
+
import { E as ErrorHandler, a as RecoveryDecision, R as RetryPolicy } from './retry-policy-CQ7KwXJa.js';
|
|
11
|
+
import { M as MessageSelector } from './selector-D8O6B_Rm.js';
|
|
12
12
|
import { S as SkillLoader, a as SkillManifest, b as SkillEntry } from './skill-DHniprNl.js';
|
|
13
13
|
import { W as WstackPaths } from './wstack-paths-C3K40Qst.js';
|
|
14
14
|
import { P as PromptLoader, a as PromptEntry, b as PromptSearchOptions, c as PromptCategoryCount } from './prompt-DLd35n4Q.js';
|
|
@@ -492,10 +492,7 @@ declare const DEFAULT_RECOVERY_STRATEGIES: RecoveryStrategy[];
|
|
|
492
492
|
declare class DefaultErrorHandler implements ErrorHandler {
|
|
493
493
|
private readonly strategies;
|
|
494
494
|
constructor(strategies?: RecoveryStrategy[]);
|
|
495
|
-
classify(err: unknown):
|
|
496
|
-
kind: 'rate_limit' | 'overloaded' | 'server' | 'client' | 'network' | 'abort' | 'context_overflow' | 'unknown';
|
|
497
|
-
retryable: boolean;
|
|
498
|
-
};
|
|
495
|
+
classify(err: unknown): ReturnType<ErrorHandler['classify']>;
|
|
499
496
|
recover(err: unknown, ctx: Context): Promise<RecoveryDecision | null>;
|
|
500
497
|
}
|
|
501
498
|
|