{"version":3,"file":"light.d.ts","sourceRoot":"","sources":["../../src/core/light.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAEjE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGtD,8CAA8C;AAC9C,eAAO,MAAM,gBAAgB,4CAA6C,CAAC;AAE3E;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,yMAEP,CAAC;AAE1B;;;;;GAKG;AACH,eAAO,MAAM,cAAc,kBAAkB,CAAC;AAE9C,+DAA+D;AAC/D,wBAAgB,cAAc,IAAI,OAAO,CAExC;AA4BD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAgDvE;AAED,6DAA6D;AAC7D,MAAM,WAAW,aAAa;IAC7B,uDAAuD;IACvD,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kEAAkE;IAClE,gBAAgB,EAAE,MAAM,CAAC;IACzB,6CAA6C;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC/C;AAOD;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAI9D;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE;IAC7C,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,IAAI,MAAM,EAAE,CAAC;IAC/B,WAAW,IAAI,QAAQ,EAAE,CAAC;CAC1B,GAAG,aAAa,CAchB","sourcesContent":["/**\n * Light mode — a minimal, low-token preset for small/local models.\n *\n * The preset restricts the session to the four core tools (read, write, edit,\n * bash) with shortened descriptions and undocumented parameter schemas,\n * replaces the default system prompt with a terse one, and disables\n * subagents, TodoWrite, skills, context files, and the mode-prompt appendix.\n * The goal is the smallest possible fixed per-turn surface (system prompt +\n * serialized tool schemas) so weak tool-callers waste no context on harness\n * boilerplate. bash subsumes the search tool: discovery happens via the shell.\n */\n\nimport type { AgentTool } from \"@kolisachint/hoocode-agent-core\";\nimport { Type } from \"typebox\";\nimport type { ToolInfo } from \"./extensions/types.js\";\nimport { createBashTool, createEditTool, createReadTool, createWriteTool } from \"./tools/index.js\";\n\n/** The only tools a light session exposes. */\nexport const LIGHT_TOOL_NAMES = [\"read\", \"write\", \"edit\", \"bash\"] as const;\n\n/**\n * Terse replacement for the default system prompt. buildSystemPrompt appends\n * the current date and working directory; nothing else rides along because\n * light mode also disables skills, context files, and the mode appendix.\n */\nexport const LIGHT_SYSTEM_PROMPT = `You are a coding agent. Use the tools to read, edit, and write files and run shell commands.\nSearch with bash (rg/find/ls). Prefer edit for changes; write for new files.\nBe concise. No preamble.`;\n\n/**\n * Environment flag signaling light mode to code that cannot see CLI flags or\n * settings — notably the hoo-core modes extension, which reads it to skip the\n * `<!-- hoo-core: mode= -->` system-prompt appendix. Same pattern as\n * WARM_SUBAGENTS_ENV / SUBAGENT_MAX_DEPTH_ENV.\n */\nexport const LIGHT_MODE_ENV = \"HOOCODE_LIGHT\";\n\n/** Whether light mode was signaled through the environment. */\nexport function isLightModeEnv(): boolean {\n\treturn process.env[LIGHT_MODE_ENV] === \"1\";\n}\n\n// Light parameter schemas: same shapes the real tools accept, minus the\n// per-property descriptions (that is where most schema tokens live).\nconst lightReadSchema = Type.Object({\n\tpath: Type.String(),\n\toffset: Type.Optional(Type.Number()),\n\tlimit: Type.Optional(Type.Number()),\n});\n\nconst lightWriteSchema = Type.Object({\n\tpath: Type.String(),\n\tcontent: Type.String(),\n});\n\n// Flat single-replacement shape instead of the full edits[] batch schema. The\n// execute shim below converts it to the batch form the real edit tool expects.\nconst lightEditSchema = Type.Object({\n\tpath: Type.String(),\n\toldText: Type.String(),\n\tnewText: Type.String(),\n});\n\nconst lightBashSchema = Type.Object({\n\tcommand: Type.String(),\n\ttimeout: Type.Optional(Type.Number()),\n});\n\n/**\n * Build the four light tools for `baseToolsOverride`: the real tool\n * implementations wearing short descriptions and stripped parameter schemas.\n */\nexport function createLightTools(cwd: string): Record<string, AgentTool> {\n\tconst read = createReadTool(cwd);\n\tconst write = createWriteTool(cwd);\n\tconst edit = createEditTool(cwd);\n\tconst bash = createBashTool(cwd);\n\n\tconst lightRead: AgentTool<typeof lightReadSchema> = {\n\t\t...read,\n\t\tdescription: \"Read a file. args: path, offset?, limit?\",\n\t\tparameters: lightReadSchema,\n\t};\n\n\tconst lightWrite: AgentTool<typeof lightWriteSchema> = {\n\t\t...write,\n\t\tdescription: \"Write file (overwrites). args: path, content\",\n\t\tparameters: lightWriteSchema,\n\t};\n\n\t// The real edit tool validates against its edits[] schema after\n\t// prepareArguments runs, so the flat light shape must skip the original\n\t// prepareArguments (validation sees the raw flat args against the flat\n\t// schema) and convert to the batch form at execute time instead.\n\tconst lightEdit: AgentTool<typeof lightEditSchema> = {\n\t\t...edit,\n\t\tdescription: \"Replace exact text. args: path, oldText, newText\",\n\t\tparameters: lightEditSchema,\n\t\tprepareArguments: undefined,\n\t\texecute: (toolCallId, params, signal, onUpdate) =>\n\t\t\tedit.execute(\n\t\t\t\ttoolCallId,\n\t\t\t\t{ path: params.path, edits: [{ oldText: params.oldText, newText: params.newText }] },\n\t\t\t\tsignal,\n\t\t\t\tonUpdate,\n\t\t\t),\n\t};\n\n\tconst lightBash: AgentTool<typeof lightBashSchema> = {\n\t\t...bash,\n\t\tdescription: \"Run a shell command. args: command, timeout?\",\n\t\tparameters: lightBashSchema,\n\t};\n\n\treturn {\n\t\tread: lightRead as AgentTool,\n\t\twrite: lightWrite as AgentTool,\n\t\tedit: lightEdit as AgentTool,\n\t\tbash: lightBash as AgentTool,\n\t};\n}\n\n/** Token breakdown of a session's fixed per-turn surface. */\nexport interface PromptSurface {\n\t/** Estimated tokens in the assembled system prompt. */\n\tsystemPromptTokens: number;\n\t/** Estimated tokens across the serialized active tool schemas. */\n\ttoolSchemaTokens: number;\n\t/** systemPromptTokens + toolSchemaTokens. */\n\ttotalTokens: number;\n\t/** Per-tool breakdown of the serialized schema estimate. */\n\ttools: Array<{ name: string; tokens: number }>;\n}\n\n/** Same conservative chars/4 heuristic the agent harness uses for context estimates. */\nfunction estimateStringTokens(text: string): number {\n\treturn Math.ceil(text.length / 4);\n}\n\n/**\n * What one tool costs on every request: its serialized `{name, description,\n * parameters}`, the three fields a provider re-sends each turn.\n *\n * Exported because the surface is worth showing for a tool that is *off* too —\n * `/settings` prices each toggle with it, and a disabled tool has no entry in a\n * measured surface precisely because it currently costs nothing.\n */\nexport function measureToolSchemaTokens(tool: ToolInfo): number {\n\treturn estimateStringTokens(\n\t\tJSON.stringify({ name: tool.name, description: tool.description, parameters: tool.parameters }),\n\t);\n}\n\n/**\n * Measure the fixed per-turn surface a session sends on every request: the\n * assembled system prompt plus the serialized schemas (name, description,\n * parameters) of the active tools. Providers add their own envelope on top,\n * so treat the result as a floor estimate.\n */\nexport function measurePromptSurface(session: {\n\tsystemPrompt: string;\n\tgetActiveToolNames(): string[];\n\tgetAllTools(): ToolInfo[];\n}): PromptSurface {\n\tconst activeNames = new Set(session.getActiveToolNames());\n\tconst tools = session\n\t\t.getAllTools()\n\t\t.filter((tool) => activeNames.has(tool.name))\n\t\t.map((tool) => ({ name: tool.name, tokens: measureToolSchemaTokens(tool) }));\n\tconst systemPromptTokens = estimateStringTokens(session.systemPrompt);\n\tconst toolSchemaTokens = tools.reduce((sum, tool) => sum + tool.tokens, 0);\n\treturn {\n\t\tsystemPromptTokens,\n\t\ttoolSchemaTokens,\n\t\ttotalTokens: systemPromptTokens + toolSchemaTokens,\n\t\ttools,\n\t};\n}\n"]}