@x-otto/tools 0.1.0-alpha.18 → 0.1.0-alpha.19

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/index.js CHANGED
@@ -110,26 +110,26 @@ import{z as e}from"zod";import{API_IMAGE_DIMENSION_LIMIT_PX as t,PROVIDER_IMAGE_
110
110
  `)}]}}let t=await Z(e.filePath,async t=>await t.documentSymbols(e.filePath));if(!t||t.length===0)return{content:[{type:`text`,text:`No symbols found`}]};let n=t.length,r=Math.min(e.limit??200,200),i=n>r,a=i?t.slice(0,r):t,o=[];return i&&o.push(`Found ${n} symbols (showing first ${r}):`),a[0]&&`range`in a[0]?o.push(...a.map(e=>qr(e))):o.push(...a.map(Jr)),{content:[{type:`text`,text:o.join(`
111
111
  `)}]}}}}const Ci=e.object({filePath:e.string().describe(`Absolute path to the file`),severity:e.enum([`error`,`warning`,`information`,`hint`,`all`]).optional().describe(`Filter by severity level`)});function wi(e){return{name:`lsp_diagnostics`,description:`Get errors, warnings, hints from language server BEFORE running build.`,parameters:Ci,pathParams:[`filePath`],readonly:!0,async execute({params:e}){let t=await Z(e.filePath,async t=>await t.diagnostics(e.filePath)),n=[];if(t&&(Array.isArray(t)?n=t:t.items&&(n=t.items)),n=Xr(n,e.severity),n.length===0)return{content:[{type:`text`,text:`No diagnostics found`}]};let r=n.length,i=r>200,a=(i?n.slice(0,200):n).map(Yr);return i&&a.unshift(`Found ${r} diagnostics (showing first 200):`),{content:[{type:`text`,text:a.join(`
112
112
  `)}]}}}}const Ti=e.object({filePath:e.string().describe(`Absolute path to the file`),line:e.number().int().min(1).describe(`1-based line number`),character:e.number().int().min(0).describe(`0-based character offset`)});function Ei(e){return{name:`lsp_prepare_rename`,description:`Check if rename is valid. Use BEFORE lsp_rename.`,parameters:Ti,pathParams:[`filePath`],async execute({params:e}){return{content:[{type:`text`,text:Zr(await Z(e.filePath,async t=>await t.prepareRename(e.filePath,e.line,e.character)))}]}}}}const Di=e.object({filePath:e.string().describe(`Absolute path to the file`),line:e.number().int().min(1).describe(`1-based line number`),character:e.number().int().min(0).describe(`0-based character offset`),newName:e.string().describe(`New symbol name`)});function Oi(e){return{name:`lsp_rename`,description:`Rename symbol across entire workspace. APPLIES changes to all files.`,parameters:Di,pathParams:[`filePath`],async execute({params:t}){return{content:[{type:`text`,text:Qr(await Ur(await Z(t.filePath,async e=>await e.rename(t.filePath,t.line,t.character,t.newName)),e))}]}}}}const ki=e.object({action:e.enum([`list`,`create`,`remove`,`compact`]).describe(`Session management action to perform`),sessionId:e.string().optional().describe(`Session ID (required for remove/compact)`),title:e.string().optional().describe(`New session title (optional when creating)`)});function Ai(e){let{sessionManager:t}=e;return{name:`session_manager`,description:`Manage conversation sessions: list, create, remove, compact.`,parameters:ki,async execute({params:e}){if(!t)throw Error(`SessionManager is not provided in options`);return await ji(e.action,t,e.sessionId,e.title)}}}async function ji(e,t,n,r){switch(e){case`list`:{let e=await t.list();return{content:[{type:`text`,text:e.length===0?`No sessions found.`:e.map(e=>`- ${e.id}: ${e.title} (${e.messageCount} messages)`).join(`
113
- `)}]}}case`create`:return{content:[{type:`text`,text:`Session created: ${(await t.create(r)).id}`}]};case`remove`:{if(!n)throw Error(`sessionId required for remove`);let e=await t.remove(n);return{content:[{type:`text`,text:e?`Session ${n} removed`:`Session not found`}],isError:!e}}case`compact`:{if(!n)throw Error(`sessionId required for compact`);let e=await t.compact(n);return{content:[{type:`text`,text:e?`Session ${n} compacted`:`Compact failed`}],isError:!e}}}}const Mi=e.object({action:e.enum([`load`,`execute`]).describe(`'load' to register a skill; 'execute' to run it (auto-loads if needed)`),path:e.string().optional().describe(`SKILL.md file path, relative to project root (load action)`),name:e.string().optional().describe(`Skill name (execute action; if path is also given, loads first)`)});function Ni(e,t,n,r){return{name:`skill`,description:`Load or execute a reusable skill (workflow template). Use action=load to register a SKILL.md; use action=execute to run a loaded skill (auto-loads via path if not yet registered).`,parameters:Mi,pathParams:[`path`],resolvePath:t=>P(e,t),async execute({params:e,sessionId:i}){let a=i??r;switch(e.action){case`load`:{if(!e.path)return{content:[{type:`text`,text:`path is required for load action`}],isError:!0,errorKind:`validation`};let n=await t(e.path);return n.success?{content:[{type:`text`,text:`Skill "${n.name}" loaded from ${e.path}`}]}:{content:[{type:`text`,text:`Failed to load skill: ${n.error}`}],isError:!0,errorKind:`runtime`}}case`execute`:if(!n)return K(`skill(execute)`);if(e.path){let r=await t(e.path);if(!r.success)return{content:[{type:`text`,text:`Failed to load skill: ${r.error}`}],isError:!0,errorKind:`runtime`};let i=r.name??e.name;return i?Pi(await n(i,a)):{content:[{type:`text`,text:`Cannot execute: no skill name resolved from path or argument`}],isError:!0,errorKind:`validation`}}return e.name?Pi(await n(e.name,a)):{content:[{type:`text`,text:`name or path is required for execute action`}],isError:!0,errorKind:`validation`}}}}}function Pi(e){return e.success?{content:[{type:`text`,text:e.content??`Skill executed successfully`}]}:{content:[{type:`text`,text:`Skill failed: ${e.error}`}],isError:!0,errorKind:`runtime`}}const Fi=e.object({name:e.string().describe(`Short, stable memory title (used as the lookup key)`),description:e.string().describe(`One-line hook shown in the always-visible memory index`),content:e.string().describe(`The full fact to remember across sessions`),scope:e.enum([`workspace`,`local`,`project-shared`]).optional().default(`workspace`).describe(`Memory scope (default 'workspace'): 'workspace' = durable facts portable across machines, 'local' = machine-specific (never synced), 'project-shared' = team-visible AGENTS.md conventions.`)});function Ii(e){return{name:`memory_record`,description:`Persist a fact across sessions (auto-memory). The memory index is injected into future sessions; use memory_read to retrieve full entries.`,parameters:Fi,async execute({params:t}){return e?(await e(t),{content:[{type:`text`,text:`Memory "${t.name}" recorded.`}]}):{content:[{type:`text`,text:`Auto-memory is not configured. Set storage.memory in createApp() options.`}],isError:!0,errorKind:`runtime`}}}}const Li=e.object({name:e.string().describe(`The memory title as shown in the memory index`)});function Ri(e){return{name:`memory_read`,description:`Read the full content of a persisted memory entry by its name (see the memory index in the system prompt).`,parameters:Li,readonly:!0,async execute({params:t}){if(!e)return{content:[{type:`text`,text:`Auto-memory is not configured. Set storage.memory in createApp() options.`}],isError:!0,errorKind:`runtime`};let n=await e(t.name);return n===null?{content:[{type:`text`,text:`Memory "${t.name}" not found.`}],isError:!0,errorKind:`not_found`}:{content:[{type:`text`,text:n}]}}}}const zi=/^archive:(.+):(\d+)$/;function Bi(e){let t=zi.exec(e);return t?{sessionId:t[1],index:Number.parseInt(t[2],10)}:null}const Vi=e.object({archivePath:e.string().describe(`The archive id shown in a compaction summary, in the form "archive:<sessionId>:<n>".`)}),Hi=e.object({}),Ui=`Conversation archive recall is not available in this session (no session-entry backed storage).`;function Wi(e,t){let n=Bi(e);return n?!t||n.sessionId!==t?{content:[{type:`text`,text:`This archive belongs to a different conversation and cannot be read from here.`}],isError:!0,errorKind:`permission`}:null:{content:[{type:`text`,text:`Invalid archive id "${e}". Expected the form "archive:<sessionId>:<n>" exactly as shown in the compaction summary.`}],isError:!0,errorKind:`validation`}}function Gi(e){return{name:`memory_archive_read`,description:`Read the full original messages behind a compaction summary. Use this when a summary is marked low-fidelity, or when you need details the summary does not cover. Pass the archive id shown in the summary.`,parameters:Vi,readonly:!0,async execute({params:t,sessionId:n}){if(!e)return{content:[{type:`text`,text:Ui}],isError:!0,errorKind:`runtime`};let r=Wi(t.archivePath,n);if(r)return r;let i=await e(t.archivePath);return i?{content:[{type:`text`,text:i}]}:{content:[{type:`text`,text:`Archive "${t.archivePath}" not found in this conversation.`}],isError:!0,errorKind:`not_found`}}}}function Ki(e){return{name:`memory_archive_list`,description:`List the compaction archives of the current conversation (each entry = one folded chunk of earlier history, with its archive id and a summary preview).`,parameters:Hi,readonly:!0,async execute({sessionId:t}){if(!e||!t)return{content:[{type:`text`,text:Ui}],isError:!0,errorKind:`runtime`};let n=await e(t);return n.length===0?{content:[{type:`text`,text:`No compaction archives yet in this conversation.`}]}:{content:[{type:`text`,text:n.map(e=>`- ${e.path} — ${e.messageCount} messages, ${new Date(e.timestamp).toISOString()}\n ${e.summary}`).join(`
114
- `)}]}}}}e.object({cron:e.string().describe(`5-field cron expression (minute hour dom month dow). Examples: "0 9 * * 1-5" = weekdays 9am, "*/30 * * * *" = every 30 min`),prompt:e.string().describe(`Natural language instruction for the agent to execute at the scheduled time`),recurring:e.boolean().describe(`true = run on schedule repeatedly, false = one-shot (delete after first fire)`),name:e.string().optional().describe(`Short label for the task (shown in schedule list)`),maxDurationMs:e.number().int().positive().optional().describe(`Timeout in milliseconds for a single fire attempt (default 300000 = 5 minutes). Raise this for tasks expected to take longer.`),target:e.enum([`job`,`session`]).optional().describe(`Where the prompt fires. Default "job": isolated git worktree, produces a diff for /job apply — for tasks that change files, need independent review, or should stay decoupled from this conversation (e.g. "scan dependencies for updates every morning"). "session": injects into THIS conversation when it fires (no worktree, no diff) — for polling/check-in/report-back tasks that continue this conversation and typically do not change files. A visible notice is shown on first creation and each fire.`),modelId:e.string().optional().describe(`Model to run this scheduled task with, e.g. "deepseek/deepseek-v4-flash". Defaults to the current session model. Invalid ids are rejected at creation time.`),thinkingLevel:e.enum([`low`,`medium`,`high`,`xhigh`,`max`]).optional().describe(`Thinking level for the model (defaults to the provider default).`),onEvent:e.enum([`job.applied`,`job.failed`,`job.canceled`]).optional().describe(`Fire when an in-process event happens instead of on the cron schedule. "job.applied" = when any background job's diff gets applied; "job.failed"/"job.canceled" similarly. Requires target:"session" (injects into THIS conversation) — event triggers cannot dispatch isolated jobs. Use for "wait until the current work lands, then continue" flows. When set, "cron" is ignored (pass any valid placeholder like "0 0 * * *").`)}),e.object({task_id:e.string().describe(`ID of the scheduled task to delete`)}),e.object({task_id:e.string().describe(`ID of the scheduled task to run immediately`)}),e.object({task_id:e.string().describe(`ID of the scheduled task whose currently running job should be canceled`)});const qi=e.object({type:e.enum([`create`,`list`,`delete`,`run`,`cancel`]).describe(`Schedule action to perform: "create" (new task), "list" (view all), "delete" (remove task), "run" (trigger immediately), "cancel" (stop running job). See tool description for per-action parameters.`),cron:e.string().optional().describe(`5-field cron expression (minute hour dom month dow). Examples: "0 9 * * 1-5" = weekdays 9am, "*/30 * * * *" = every 30 min. Required for create.`),prompt:e.string().optional().describe(`Natural language instruction for the agent to execute at the scheduled time. Required for create.`),recurring:e.boolean().optional().describe(`true = run on schedule repeatedly, false = one-shot (delete after first fire). Required for create.`),name:e.string().optional().describe(`Short label for the task (shown in schedule list). Optional for create.`),maxDurationMs:e.number().int().positive().optional().describe(`Timeout in milliseconds for a single fire attempt (default 300000 = 5 minutes). Raise for long tasks. Optional for create.`),target:e.enum([`job`,`session`]).optional().describe(`Where the prompt fires. Default "job": isolated worktree, produces a diff for /job apply. "session": injects into THIS conversation. Optional for create.`),modelId:e.string().optional().describe(`Model to run this scheduled task with, e.g. "deepseek/deepseek-v4-flash". Defaults to current session model. Optional for create.`),thinkingLevel:e.enum([`low`,`medium`,`high`,`xhigh`,`max`]).optional().describe(`Thinking level for the model. Optional for create.`),onEvent:e.enum([`job.applied`,`job.failed`,`job.canceled`]).optional().describe(`Fire on an in-process event instead of cron (requires target:"session"). Optional for create.`),task_id:e.string().optional().describe(`ID of the scheduled task. Required for delete/run/cancel.`)});function Ji(e){return{name:`schedule`,description:`Manage scheduled tasks: create (new cron/event task), list (view all), delete (remove), run (trigger immediately), cancel (stop running job). Use the "type" field to select the action; per-action parameters are shown above.`,parameters:qi,execute:async({params:t})=>{if(!e)return{content:[{type:`text`,text:`Schedule scheduling is not available in this session.`}],isError:!0};let{type:n,...r}=t;switch(n){case`create`:{let{onEvent:t,...n}=r;if(!n.cron||!n.prompt||n.recurring===void 0)return{content:[{type:`text`,text:`schedule create requires cron, prompt, recurring`}],isError:!0};let i={...n,eventTrigger:t?{source:`job`,event:t.slice(4)}:void 0};try{let t=e.create(i),n=t.target===`session`?` (fires into this conversation)`:``;return{content:[{type:`text`,text:`Schedule created: ${t.taskId} — "${t.name}"${n}
113
+ `)}]}}case`create`:return{content:[{type:`text`,text:`Session created: ${(await t.create(r)).id}`}]};case`remove`:{if(!n)throw Error(`sessionId required for remove`);let e=await t.remove(n);return{content:[{type:`text`,text:e?`Session ${n} removed`:`Session not found`}],isError:!e}}case`compact`:{if(!n)throw Error(`sessionId required for compact`);let e=await t.compact(n);return{content:[{type:`text`,text:e?`Session ${n} compacted`:`Compact failed`}],isError:!e}}}}const Mi=e.object({name:e.string().describe(`Name of a registered skill (see the Available Skills catalog)`)}),Ni=e.object({action:e.enum([`load`,`execute`]).describe(`'load' to register a skill; 'execute' to load then run it`),path:e.string().describe(`SKILL.md file path, relative to project root`),name:e.string().optional().describe(`Override skill name for execute action`)});function Pi(e,t){return{name:`skill`,description:`Execute a registered skill (workflow template) by name. Skills listed in the Available Skills catalog can be run directly; this tool does not read files.`,parameters:Mi,async execute({params:n,sessionId:r}){return e?Ii(await e(n.name,r??t)):K(`skill(execute)`)}}}function Fi(e,t,n,r){return{name:`skill_load`,description:`Register a skill from a SKILL.md file path (action=load), or load then run it (action=execute). Use this only for skills not yet in the Available Skills catalog.`,parameters:Ni,pathParams:[`path`],resolvePath:t=>P(e,t),async execute({params:e,sessionId:i}){let a=i??r,o=await t(e.path);if(!o.success)return{content:[{type:`text`,text:`Failed to load skill: ${o.error}`}],isError:!0,errorKind:`runtime`};if(e.action===`load`)return{content:[{type:`text`,text:`Skill "${o.name}" loaded from ${e.path}`}]};if(!n)return K(`skill_load(execute)`);let s=e.name??o.name;return s?Ii(await n(s,a)):{content:[{type:`text`,text:`Cannot execute: no skill name resolved from path or argument`}],isError:!0,errorKind:`validation`}}}}function Ii(e){return e.success?{content:[{type:`text`,text:e.content??`Skill executed successfully`}]}:{content:[{type:`text`,text:`Skill failed: ${e.error}`}],isError:!0,errorKind:`runtime`}}const Li=e.object({name:e.string().describe(`Short, stable memory title (used as the lookup key)`),description:e.string().describe(`One-line hook shown in the always-visible memory index`),content:e.string().describe(`The full fact to remember across sessions`),scope:e.enum([`workspace`,`local`,`project-shared`]).optional().default(`workspace`).describe(`Memory scope (default 'workspace'): 'workspace' = durable facts portable across machines, 'local' = machine-specific (never synced), 'project-shared' = team-visible AGENTS.md conventions.`)});function Ri(e){return{name:`memory_record`,description:`Persist a fact across sessions (auto-memory). The memory index is injected into future sessions; use memory_read to retrieve full entries.`,parameters:Li,async execute({params:t}){return e?(await e(t),{content:[{type:`text`,text:`Memory "${t.name}" recorded.`}]}):{content:[{type:`text`,text:`Auto-memory is not configured. Set storage.memory in createApp() options.`}],isError:!0,errorKind:`runtime`}}}}const zi=e.object({name:e.string().describe(`The memory title as shown in the memory index`)});function Bi(e){return{name:`memory_read`,description:`Read the full content of a persisted memory entry by its name (see the memory index in the system prompt).`,parameters:zi,readonly:!0,async execute({params:t}){if(!e)return{content:[{type:`text`,text:`Auto-memory is not configured. Set storage.memory in createApp() options.`}],isError:!0,errorKind:`runtime`};let n=await e(t.name);return n===null?{content:[{type:`text`,text:`Memory "${t.name}" not found.`}],isError:!0,errorKind:`not_found`}:{content:[{type:`text`,text:n}]}}}}const Vi=/^archive:(.+):(\d+)$/;function Hi(e){let t=Vi.exec(e);return t?{sessionId:t[1],index:Number.parseInt(t[2],10)}:null}const Ui=e.object({archivePath:e.string().describe(`The archive id shown in a compaction summary, in the form "archive:<sessionId>:<n>".`)}),Wi=e.object({}),Gi=`Conversation archive recall is not available in this session (no session-entry backed storage).`;function Ki(e,t){let n=Hi(e);return n?!t||n.sessionId!==t?{content:[{type:`text`,text:`This archive belongs to a different conversation and cannot be read from here.`}],isError:!0,errorKind:`permission`}:null:{content:[{type:`text`,text:`Invalid archive id "${e}". Expected the form "archive:<sessionId>:<n>" exactly as shown in the compaction summary.`}],isError:!0,errorKind:`validation`}}function qi(e){return{name:`memory_archive_read`,description:`Read the full original messages behind a compaction summary. Use this when a summary is marked low-fidelity, or when you need details the summary does not cover. Pass the archive id shown in the summary.`,parameters:Ui,readonly:!0,async execute({params:t,sessionId:n}){if(!e)return{content:[{type:`text`,text:Gi}],isError:!0,errorKind:`runtime`};let r=Ki(t.archivePath,n);if(r)return r;let i=await e(t.archivePath);return i?{content:[{type:`text`,text:i}]}:{content:[{type:`text`,text:`Archive "${t.archivePath}" not found in this conversation.`}],isError:!0,errorKind:`not_found`}}}}function Ji(e){return{name:`memory_archive_list`,description:`List the compaction archives of the current conversation (each entry = one folded chunk of earlier history, with its archive id and a summary preview).`,parameters:Wi,readonly:!0,async execute({sessionId:t}){if(!e||!t)return{content:[{type:`text`,text:Gi}],isError:!0,errorKind:`runtime`};let n=await e(t);return n.length===0?{content:[{type:`text`,text:`No compaction archives yet in this conversation.`}]}:{content:[{type:`text`,text:n.map(e=>`- ${e.path} — ${e.messageCount} messages, ${new Date(e.timestamp).toISOString()}\n ${e.summary}`).join(`
114
+ `)}]}}}}e.object({cron:e.string().describe(`5-field cron expression (minute hour dom month dow). Examples: "0 9 * * 1-5" = weekdays 9am, "*/30 * * * *" = every 30 min`),prompt:e.string().describe(`Natural language instruction for the agent to execute at the scheduled time`),recurring:e.boolean().describe(`true = run on schedule repeatedly, false = one-shot (delete after first fire)`),name:e.string().optional().describe(`Short label for the task (shown in schedule list)`),maxDurationMs:e.number().int().positive().optional().describe(`Timeout in milliseconds for a single fire attempt (default 300000 = 5 minutes). Raise this for tasks expected to take longer.`),target:e.enum([`job`,`session`]).optional().describe(`Where the prompt fires. Default "job": isolated git worktree, produces a diff for /job apply — for tasks that change files, need independent review, or should stay decoupled from this conversation (e.g. "scan dependencies for updates every morning"). "session": injects into THIS conversation when it fires (no worktree, no diff) — for polling/check-in/report-back tasks that continue this conversation and typically do not change files. A visible notice is shown on first creation and each fire.`),modelId:e.string().optional().describe(`Model to run this scheduled task with, e.g. "deepseek/deepseek-v4-flash". Defaults to the current session model. Invalid ids are rejected at creation time.`),thinkingLevel:e.enum([`low`,`medium`,`high`,`xhigh`,`max`]).optional().describe(`Thinking level for the model (defaults to the provider default).`),onEvent:e.enum([`job.applied`,`job.failed`,`job.canceled`]).optional().describe(`Fire when an in-process event happens instead of on the cron schedule. "job.applied" = when any background job's diff gets applied; "job.failed"/"job.canceled" similarly. Requires target:"session" (injects into THIS conversation) — event triggers cannot dispatch isolated jobs. Use for "wait until the current work lands, then continue" flows. When set, "cron" is ignored (pass any valid placeholder like "0 0 * * *").`)}),e.object({task_id:e.string().describe(`ID of the scheduled task to delete`)}),e.object({task_id:e.string().describe(`ID of the scheduled task to run immediately`)}),e.object({task_id:e.string().describe(`ID of the scheduled task whose currently running job should be canceled`)});const Yi=e.object({type:e.enum([`create`,`list`,`delete`,`run`,`cancel`]).describe(`Schedule action to perform: "create" (new task), "list" (view all), "delete" (remove task), "run" (trigger immediately), "cancel" (stop running job). See tool description for per-action parameters.`),cron:e.string().optional().describe(`5-field cron expression (minute hour dom month dow). Examples: "0 9 * * 1-5" = weekdays 9am, "*/30 * * * *" = every 30 min. Required for create.`),prompt:e.string().optional().describe(`Natural language instruction for the agent to execute at the scheduled time. Required for create.`),recurring:e.boolean().optional().describe(`true = run on schedule repeatedly, false = one-shot (delete after first fire). Required for create.`),name:e.string().optional().describe(`Short label for the task (shown in schedule list). Optional for create.`),maxDurationMs:e.number().int().positive().optional().describe(`Timeout in milliseconds for a single fire attempt (default 300000 = 5 minutes). Raise for long tasks. Optional for create.`),target:e.enum([`job`,`session`]).optional().describe(`Where the prompt fires. Default "job": isolated worktree, produces a diff for /job apply. "session": injects into THIS conversation. Optional for create.`),modelId:e.string().optional().describe(`Model to run this scheduled task with, e.g. "deepseek/deepseek-v4-flash". Defaults to current session model. Optional for create.`),thinkingLevel:e.enum([`low`,`medium`,`high`,`xhigh`,`max`]).optional().describe(`Thinking level for the model. Optional for create.`),onEvent:e.enum([`job.applied`,`job.failed`,`job.canceled`]).optional().describe(`Fire on an in-process event instead of cron (requires target:"session"). Optional for create.`),task_id:e.string().optional().describe(`ID of the scheduled task. Required for delete/run/cancel.`)});function Xi(e){return{name:`schedule`,description:`Manage scheduled tasks: create (new cron/event task), list (view all), delete (remove), run (trigger immediately), cancel (stop running job). Use the "type" field to select the action; per-action parameters are shown above.`,parameters:Yi,execute:async({params:t})=>{if(!e)return{content:[{type:`text`,text:`Schedule scheduling is not available in this session.`}],isError:!0};let{type:n,...r}=t;switch(n){case`create`:{let{onEvent:t,...n}=r;if(!n.cron||!n.prompt||n.recurring===void 0)return{content:[{type:`text`,text:`schedule create requires cron, prompt, recurring`}],isError:!0};let i={...n,eventTrigger:t?{source:`job`,event:t.slice(4)}:void 0};try{let t=e.create(i),n=t.target===`session`?` (fires into this conversation)`:``;return{content:[{type:`text`,text:`Schedule created: ${t.taskId} — "${t.name}"${n}
115
115
  Next fire: ${new Date(t.nextFireAt).toLocaleString()}
116
116
  Use schedule (type:list) to view all schedules, schedule (type:delete) to remove.`}]}}catch(e){return{content:[{type:`text`,text:e instanceof Error?e.message:String(e)}],isError:!0}}}case`list`:{let t=e.list();return t.length===0?{content:[{type:`text`,text:`No scheduled tasks.`}]}:{content:[{type:`text`,text:t.map(e=>`- ${e.id}: ${e.name} (${e.recurring?e.cronExpression:`one-shot`}) next: ${new Date(e.nextFireAt).toLocaleString()}`).join(`
117
- `)}]}}case`delete`:return r.task_id?{content:[{type:`text`,text:e.delete(r.task_id)?`Schedule ${r.task_id} deleted.`:`Schedule ${r.task_id} not found.`}]}:{content:[{type:`text`,text:`schedule delete requires task_id`}],isError:!0};case`run`:if(!r.task_id)return{content:[{type:`text`,text:`schedule run requires task_id`}],isError:!0};try{return e.run(r.task_id),{content:[{type:`text`,text:`Triggering schedule ${r.task_id}…`}]}}catch(e){return{content:[{type:`text`,text:e instanceof Error?e.message:String(e)}],isError:!0}}case`cancel`:{if(!r.task_id)return{content:[{type:`text`,text:`schedule cancel requires task_id`}],isError:!0};let t=e.cancel(r.task_id);return{content:[{type:`text`,text:t.ok?`Schedule ${r.task_id} canceled.`:`Could not cancel ${r.task_id}: ${t.reason??`unknown`}`}]}}default:return{content:[{type:`text`,text:`unknown schedule action "${n}"`}],isError:!0}}}}}const Q=(...e)=>e,Yi=[`Prefer edit over write for modifying existing files — edit replaces exact text and is safer.`,`For edit: provide enough surrounding context to avoid ambiguous matches.`].join(`
118
- `),Xi=[`Use bash for running tests, installing dependencies, build commands, git operations, and system tasks that have no dedicated tool.`,"For long-lived processes (dev servers, watchers), pass run_in_background:true instead of blocking or trailing `&`; it returns immediately with a background id.","Read accumulated output with bash_output; stop with kill_shell. Background processes are auto-killed at session end — no cleanup of `&` jobs.",`Prefer dedicated tools (read, write, edit, grep, find) over shell equivalents (cat, sed, grep) for file operations.`,`Always check the exit code; on failure, inspect stdout/stderr before deciding next steps.`].join(`
119
- `),Zi=[`Use find to locate files by name or glob pattern; use grep to search file contents by text or regex.`,"Start broad (find) then narrow (grep → read) to efficiently navigate unfamiliar codebases. There is no dedicated listing tool — for ad-hoc directory listing run `ls` via bash.",`Combine grep results with read to understand full context around matches.`,`Use precise grep patterns; prefer regex alternation over many separate searches.`].join(`
120
- `),Qi=[`Use web_fetch to read specific URLs when you know the page address.`,`Prefer web_search → web_fetch workflow: search first, then fetch specific results. (See the Factual Verification rule in the base instructions for when verification is required.)`,`web_fetch cannot render JavaScript-heavy pages (SPAs). Use for documentation, articles, APIs.`].join(`
121
- `),$i=[`Use task_delegate to route tasks to more suitable sub-agents by category — useful for specialization or lifecycle management. Provide clear, complete context — sub-agents start with a blank slate.`,`Use write_todos for complex tasks to build and maintain a step list first, then work it to completion. Optional "title" labels the list (defaults to "Task"). Unfinished todos = reported incomplete.`,`Break complex tasks into small, independently verifiable subtasks (2-5 minutes each) before delegating.`,`Do not delegate tasks that require the current conversation context or interactive clarification.`].join(`
122
- `),ea=[`Use task_delegate for delegation — tracked:false for lightweight synchronous agent opinions, default (tracked) for background or stateful execution with retries.`,`Use task_inspect to check task status and output before acting; use task_control to cancel or retry tasks.`,`Use grill_me to ask the human ONE key decision (detailed background + required recommendation) when a fork genuinely needs a human steer. Advisory only — never authorizes side effects.`,`Use capture_file_state when conversation is long and you need to refresh understanding of workspace changes.`,`Use learn to record reusable insights (patterns, mistakes, strategies) — not routine progress notes.`].join(`
123
- `),ta=[`Use session management to organize separate conversation threads per task or topic.`,`Compact sessions proactively when conversation history grows long to avoid context window exhaustion.`,`Do not create excessive sessions — reuse existing ones when the topic is the same.`].join(`
124
- `),na=[`Use skill to load or execute reusable workflow templates. Skills are auto-loaded on first execute if a path is given.`,`Prefer invoking a matching skill over ad-hoc multi-step workflows when one exists.`,`Skills encapsulate best practices — follow their structure rather than shortcutting steps.`].join(`
125
- `),ra=[`Use memory_record to persist durable facts (user preferences, environment quirks, project constraints) across sessions.`,`The memory index is always visible in the system prompt; fetch full entries on demand with memory_read.`,`Scope choice and what to remember: see <memory_guidelines> (injected with the memory index).`].join(`
126
- `),ia=[`When a conversation summary is marked low-fidelity (only part of the history made it into the summary), use memory_archive_read to pull back the original messages instead of guessing or asking the user to repeat themselves.`,`Use memory_archive_list to see which chunks of earlier history are available and pick the right archive id.`,`Archives are scoped to the current conversation — you cannot read another session's history.`].join(`
127
- `),aa=[{names:[`read`,`write`,`edit`],preset:`minimal`,category:`fs`,guidance:Yi,create:e=>Q(dn(e.projectRoot),_n(e.projectRoot),Fn(e.projectRoot))},{names:[`bash`],preset:`minimal`,category:`shell`,guidance:Xi,create:e=>Q(Nt(e.projectRoot,void 0,e.features.sandbox,e.features.processRegistry,void 0,e.features.shellEnv))},{names:[`bash_output`,`kill_shell`],preset:`standard`,category:`shell`,when:e=>!!e.features.processRegistry,create:e=>Q(Wt(e.features.processRegistry),Kt(e.features.processRegistry))},{names:[`find`,`grep`],preset:`standard`,category:`search`,guidance:Zi,create:e=>Q(Yt(e.projectRoot,{binaryExecutorRegistry:e.registry.getBinaryToolExecutors()}),nn(e.projectRoot,{binaryToolExecutorRegistry:e.registry.getBinaryToolExecutors(),processTracker:e.processTracker}))},{names:[`web_fetch`,`web_search`],preset:`standard`,category:`web`,guidance:Qi,create:e=>Q(tr(e.projectRoot),lr(e.projectRoot,e.features.webSearch))},{names:[`tool_search`],preset:`standard`,category:`orchestration`,guidance:`Use tool_search to discover deferred tools by name or keyword and load their full parameter schema.`,create:e=>Q(Fr(()=>e.registry.project(`full`).deferred))},{names:[`task_delegate`,`delegate_job`,`write_todos`],preset:`standard`,category:`orchestration`,guidance:$i,create:e=>Q(vr(e.projectRoot,e.orchestration.dispatchTask,e.orchestration.writeTodos,e.fork?.fork,e.team?.runTeam,void 0,e.agents.callAgent,e.agentProfiles??[]),br(e.orchestration.startJob),kr(e.orchestration.writeTodos))},{names:[`lsp_goto_definition`,`lsp_find_references`,`lsp_symbols`,`lsp_diagnostics`,`lsp_prepare_rename`,`lsp_rename`],preset:`standard`,category:`lsp`,when:e=>!!e.features.enableLsp,create:e=>(e.processTracker&&Y.setProcessTracker(e.processTracker),Q(vi(e.projectRoot),bi(e.projectRoot),Si(e.projectRoot),wi(e.projectRoot),Ei(e.projectRoot),Oi(e.projectRoot)))},{names:[`list_models`,`task_inspect`,`task_control`,`grill_me`,`capture_file_state`,`learn`],preset:`full`,category:`orchestration`,guidance:ea,create:e=>Q(Er(e.features.listModels,e.features.sessionId),Sr(e.projectRoot,{get:e.orchestration.getTask,list:e.orchestration.listTasks,output:e.orchestration.getBackgroundOutput}),wr(e.projectRoot,{update:e.orchestration.updateTask,cancelBackground:e.orchestration.cancelBackground}),Ue(e.projectRoot,e.features.grill),jr(e.features.captureFileState),Nr(e.features.sessionId??``,e.features.learn))},{names:[`session_manager`],preset:`full`,category:`session`,guidance:ta,when:e=>!!e.session,create:e=>{let t=e.session;return t?Q(Ai({sessionManager:t.manager})):Q()}},{names:[`skill`],preset:`full`,category:`skill`,guidance:na,create:e=>Q(Ni(e.projectRoot,e.loadSkill,e.executeSkill,e.features.sessionId))},{names:[`memory_record`,`memory_read`],preset:`full`,category:`memory`,guidance:ra,create:e=>Q(Ii(e.memory?.recordMemory),Ri(e.memory?.readMemory))},{names:[`memory_archive_read`,`memory_archive_list`],preset:`full`,category:`memory`,when:e=>!!e.memory?.archive,guidance:ia,create:e=>Q(Gi(e.memory?.archive?.read),Ki(e.memory?.archive?.list))},{names:[`schedule`],preset:`full`,category:`schedule`,guidance:`Schedule tool — manage timer tasks (create/list/delete/run/cancel) via the "type" action field. Semantics are in the tool description.`,when:e=>!!e.schedule,create:e=>Q(Ji(e.schedule))}],oa=`Skill provider not configured. Pass skillProvider to createApp().`;function sa(e,t){let n=t.map(e=>e.name).sort(),r=[...e.names].sort();if(n.length!==r.length||n.some((e,t)=>e!==r[t]))throw Error(`TOOL_NODES drift in category "${e.category}": declared [${r.join(`, `)}] but factory produced [${n.join(`, `)}]`)}function ca(e,t,n){let{orchestration:r,agents:i,features:a={}}=n,o={projectRoot:t,registry:e,orchestration:r,agents:i,features:a,loadSkill:n.skills?.loadSkill??(async()=>({success:!1,error:oa})),executeSkill:n.skills?.executeSkill??(async()=>({success:!1,error:oa})),fork:n.fork,team:n.team,memory:n.memory,session:n.session,agentProfiles:n.agentProfiles,schedule:n.schedule,processTracker:n.processTracker};for(let t of aa){if(t.when&&!t.when(o))continue;let n=t.create(o);sa(t,n),e.register(n,{preset:t.preset,category:t.category,builtin:!0,guideline:t.guidance})}}const $={minimal:new Set([`minimal`]),standard:new Set([`minimal`,`standard`]),full:new Set([`minimal`,`standard`,`full`])};function la(e){if(!e||typeof e!=`object`)return!1;let t=e,n=t.description;return typeof t.name==`string`&&(typeof n==`string`||typeof n==`function`)&&typeof t.execute==`function`&&t.parameters!==void 0}var ua=class e{tools=new Map;binaryToolExecutors=null;disposers=[];onMutation;get size(){return this.tools.size}setBinaryToolExecutors(e){this.binaryToolExecutors=e}getBinaryToolExecutors(){if(!this.binaryToolExecutors)throw Error(`BinaryToolExecutorRegistry is not set in ToolRegistry`);return this.binaryToolExecutors}registerDisposer(e){this.disposers.push(e)}register(e,t={}){let n={preset:t.preset??`full`,category:t.category,builtin:t.builtin??!1,snippet:t.snippet,guideline:t.guideline,source:t.source},r=Array.isArray(e)?e:[e];for(let e of r){if(!la(e))throw Error(`Invalid tool registration input`);let r=e,i=typeof r.description==`function`?r.description({projectRoot:t.projectRoot??``}):r.description,a={...r,description:i,metadata:n};this.tools.set(r.name,a)}this.onMutation?.({added:r.map(e=>e.name),source:t.source})}unregister(e){let t=[];if(Array.isArray(e)){let n=!0;for(let r of e)this.tools.delete(r)?t.push(r):n=!1;return t.length>0&&this.onMutation?.({removed:t}),n}let n=this.tools.delete(e);return n&&this.onMutation?.({removed:[e]}),n}unregisterBySource(e){let t=[...this.tools.values()].filter(t=>t.metadata.source===e).map(e=>e.name);for(let e of t)this.tools.delete(e);return t.length>0&&this.onMutation?.({removed:t,source:e}),t.length}get(e){return this.tools.get(e)}has(e){return this.tools.has(e)}listRegenerableNames(){let e=[];for(let t of this.tools.values())t.regenerableOutput===!0&&e.push(t.name);return e}getAll(){return[...this.tools.values()].sort((e,t)=>e.name.localeCompare(t.name))}getAvailable(e=`standard`){let t=$[e]??$.standard;return this.getAll().filter(e=>t.has(e.metadata.preset))}project(e=`standard`){let t=$[e]??$.standard,n=[],r=[];for(let e of this.getAll())t.has(e.metadata.preset)&&(e.exposure===`deferred`?r.push(e):e.exposure!==`hidden`&&n.push(e));return{direct:n,deferred:r}}static TOOL_GUIDANCE_BUDGET_TOKENS=5e3;static estimatedTokens(e){let t=0;for(let n of e)/[\u3000-\u9fff\uff00-\uffef]/.test(n)&&t++;return Math.ceil(t+(e.length-t)/4)}buildToolGuidance(t=`standard`){let{direct:n,deferred:r}=this.project(t);if(n.length===0&&r.length===0)return``;let i=new Map;for(let e of n){let{snippet:t,guideline:n,category:r}=e.metadata,a=n?`${r??``}\u0000${n}`:`\u0000tool:${e.name}`,o=i.get(a);if(o||(o={guideline:n,toolNames:[],entries:[]},i.set(a,o)),n){o.toolNames.push(e.name),t&&o.entries.push(`#### ${e.name}\nExample:\n\`\`\`\n${t}\n\`\`\``);continue}let s=[`#### ${e.name}`];t?s.push(`Example:\n\`\`\`\n${t}\n\`\`\``):s.push(e.description),o.entries.push(s.join(`
117
+ `)}]}}case`delete`:return r.task_id?{content:[{type:`text`,text:e.delete(r.task_id)?`Schedule ${r.task_id} deleted.`:`Schedule ${r.task_id} not found.`}]}:{content:[{type:`text`,text:`schedule delete requires task_id`}],isError:!0};case`run`:if(!r.task_id)return{content:[{type:`text`,text:`schedule run requires task_id`}],isError:!0};try{return e.run(r.task_id),{content:[{type:`text`,text:`Triggering schedule ${r.task_id}…`}]}}catch(e){return{content:[{type:`text`,text:e instanceof Error?e.message:String(e)}],isError:!0}}case`cancel`:{if(!r.task_id)return{content:[{type:`text`,text:`schedule cancel requires task_id`}],isError:!0};let t=e.cancel(r.task_id);return{content:[{type:`text`,text:t.ok?`Schedule ${r.task_id} canceled.`:`Could not cancel ${r.task_id}: ${t.reason??`unknown`}`}]}}default:return{content:[{type:`text`,text:`unknown schedule action "${n}"`}],isError:!0}}}}}const Q=(...e)=>e,Zi=[`Prefer edit over write for modifying existing files — edit replaces exact text and is safer.`,`For edit: provide enough surrounding context to avoid ambiguous matches.`].join(`
118
+ `),Qi=[`Use bash for running tests, installing dependencies, build commands, git operations, and system tasks that have no dedicated tool.`,"For long-lived processes (dev servers, watchers), pass run_in_background:true instead of blocking or trailing `&`; it returns immediately with a background id.","Read accumulated output with bash_output; stop with kill_shell. Background processes are auto-killed at session end — no cleanup of `&` jobs.",`Prefer dedicated tools (read, write, edit, grep, find) over shell equivalents (cat, sed, grep) for file operations.`,`Always check the exit code; on failure, inspect stdout/stderr before deciding next steps.`].join(`
119
+ `),$i=[`Use find to locate files by name or glob pattern; use grep to search file contents by text or regex.`,"Start broad (find) then narrow (grep → read) to efficiently navigate unfamiliar codebases. There is no dedicated listing tool — for ad-hoc directory listing run `ls` via bash.",`Combine grep results with read to understand full context around matches.`,`Use precise grep patterns; prefer regex alternation over many separate searches.`].join(`
120
+ `),ea=[`Use web_fetch to read specific URLs when you know the page address.`,`Prefer web_search → web_fetch workflow: search first, then fetch specific results. (See the Factual Verification rule in the base instructions for when verification is required.)`,`web_fetch cannot render JavaScript-heavy pages (SPAs). Use for documentation, articles, APIs.`].join(`
121
+ `),ta=[`Use task_delegate to route tasks to more suitable sub-agents by category — useful for specialization or lifecycle management. Provide clear, complete context — sub-agents start with a blank slate.`,`Use write_todos for complex tasks to build and maintain a step list first, then work it to completion. Optional "title" labels the list (defaults to "Task"). Unfinished todos = reported incomplete.`,`Break complex tasks into small, independently verifiable subtasks (2-5 minutes each) before delegating.`,`Do not delegate tasks that require the current conversation context or interactive clarification.`].join(`
122
+ `),na=[`Use task_delegate for delegation — tracked:false for lightweight synchronous agent opinions, default (tracked) for background or stateful execution with retries.`,`Use task_inspect to check task status and output before acting; use task_control to cancel or retry tasks.`,`Use grill_me to ask the human ONE key decision (detailed background + required recommendation) when a fork genuinely needs a human steer. Advisory only — never authorizes side effects.`,`Use capture_file_state when conversation is long and you need to refresh understanding of workspace changes.`,`Use learn to record reusable insights (patterns, mistakes, strategies) — not routine progress notes.`].join(`
123
+ `),ra=[`Use session management to organize separate conversation threads per task or topic.`,`Compact sessions proactively when conversation history grows long to avoid context window exhaustion.`,`Do not create excessive sessions — reuse existing ones when the topic is the same.`].join(`
124
+ `),ia=[`Use skill to execute a registered workflow template by name; use skill_load only to register a SKILL.md that is not yet in the catalog.`,`Prefer invoking a matching skill over ad-hoc multi-step workflows when one exists.`,`Skills encapsulate best practices — follow their structure rather than shortcutting steps.`].join(`
125
+ `),aa=[`Use memory_record to persist durable facts (user preferences, environment quirks, project constraints) across sessions.`,`The memory index is always visible in the system prompt; fetch full entries on demand with memory_read.`,`Scope choice and what to remember: see <memory_guidelines> (injected with the memory index).`].join(`
126
+ `),oa=[`When a conversation summary is marked low-fidelity (only part of the history made it into the summary), use memory_archive_read to pull back the original messages instead of guessing or asking the user to repeat themselves.`,`Use memory_archive_list to see which chunks of earlier history are available and pick the right archive id.`,`Archives are scoped to the current conversation — you cannot read another session's history.`].join(`
127
+ `),sa=[{names:[`read`,`write`,`edit`],preset:`minimal`,category:`fs`,guidance:Zi,create:e=>Q(dn(e.projectRoot),_n(e.projectRoot),Fn(e.projectRoot))},{names:[`bash`],preset:`minimal`,category:`shell`,guidance:Qi,create:e=>Q(Nt(e.projectRoot,void 0,e.features.sandbox,e.features.processRegistry,void 0,e.features.shellEnv))},{names:[`bash_output`,`kill_shell`],preset:`standard`,category:`shell`,when:e=>!!e.features.processRegistry,create:e=>Q(Wt(e.features.processRegistry),Kt(e.features.processRegistry))},{names:[`find`,`grep`],preset:`standard`,category:`search`,guidance:$i,create:e=>Q(Yt(e.projectRoot,{binaryExecutorRegistry:e.registry.getBinaryToolExecutors()}),nn(e.projectRoot,{binaryToolExecutorRegistry:e.registry.getBinaryToolExecutors(),processTracker:e.processTracker}))},{names:[`web_fetch`,`web_search`],preset:`standard`,category:`web`,guidance:ea,create:e=>Q(tr(e.projectRoot),lr(e.projectRoot,e.features.webSearch))},{names:[`tool_search`],preset:`standard`,category:`orchestration`,guidance:`Use tool_search to discover deferred tools by name or keyword and load their full parameter schema.`,create:e=>Q(Fr(()=>e.registry.project(`full`).deferred))},{names:[`task_delegate`,`delegate_job`,`write_todos`],preset:`standard`,category:`orchestration`,guidance:ta,create:e=>Q(vr(e.projectRoot,e.orchestration.dispatchTask,e.orchestration.writeTodos,e.fork?.fork,e.team?.runTeam,void 0,e.agents.callAgent,e.agentProfiles??[]),br(e.orchestration.startJob),kr(e.orchestration.writeTodos))},{names:[`lsp_goto_definition`,`lsp_find_references`,`lsp_symbols`,`lsp_diagnostics`,`lsp_prepare_rename`,`lsp_rename`],preset:`standard`,category:`lsp`,when:e=>!!e.features.enableLsp,create:e=>(e.processTracker&&Y.setProcessTracker(e.processTracker),Q(vi(e.projectRoot),bi(e.projectRoot),Si(e.projectRoot),wi(e.projectRoot),Ei(e.projectRoot),Oi(e.projectRoot)))},{names:[`list_models`,`task_inspect`,`task_control`,`grill_me`,`capture_file_state`,`learn`],preset:`full`,category:`orchestration`,guidance:na,create:e=>Q(Er(e.features.listModels,e.features.sessionId),Sr(e.projectRoot,{get:e.orchestration.getTask,list:e.orchestration.listTasks,output:e.orchestration.getBackgroundOutput}),wr(e.projectRoot,{update:e.orchestration.updateTask,cancelBackground:e.orchestration.cancelBackground}),Ue(e.projectRoot,e.features.grill),jr(e.features.captureFileState),Nr(e.features.sessionId??``,e.features.learn))},{names:[`session_manager`],preset:`full`,category:`session`,guidance:ra,when:e=>!!e.session,create:e=>{let t=e.session;return t?Q(Ai({sessionManager:t.manager})):Q()}},{names:[`skill`,`skill_load`],preset:`full`,category:`skill`,guidance:ia,create:e=>Q(Pi(e.executeSkill,e.features.sessionId),Fi(e.projectRoot,e.loadSkill,e.executeSkill,e.features.sessionId))},{names:[`memory_record`,`memory_read`],preset:`full`,category:`memory`,guidance:aa,create:e=>Q(Ri(e.memory?.recordMemory),Bi(e.memory?.readMemory))},{names:[`memory_archive_read`,`memory_archive_list`],preset:`full`,category:`memory`,when:e=>!!e.memory?.archive,guidance:oa,create:e=>Q(qi(e.memory?.archive?.read),Ji(e.memory?.archive?.list))},{names:[`schedule`],preset:`full`,category:`schedule`,guidance:`Schedule tool — manage timer tasks (create/list/delete/run/cancel) via the "type" action field. Semantics are in the tool description.`,when:e=>!!e.schedule,create:e=>Q(Xi(e.schedule))}],ca=`Skill provider not configured. Pass skillProvider to createApp().`;function la(e,t){let n=t.map(e=>e.name).sort(),r=[...e.names].sort();if(n.length!==r.length||n.some((e,t)=>e!==r[t]))throw Error(`TOOL_NODES drift in category "${e.category}": declared [${r.join(`, `)}] but factory produced [${n.join(`, `)}]`)}function ua(e,t,n){let{orchestration:r,agents:i,features:a={}}=n,o={projectRoot:t,registry:e,orchestration:r,agents:i,features:a,loadSkill:n.skills?.loadSkill??(async()=>({success:!1,error:ca})),executeSkill:n.skills?.executeSkill??(async()=>({success:!1,error:ca})),fork:n.fork,team:n.team,memory:n.memory,session:n.session,agentProfiles:n.agentProfiles,schedule:n.schedule,processTracker:n.processTracker};for(let t of sa){if(t.when&&!t.when(o))continue;let n=t.create(o);la(t,n),e.register(n,{preset:t.preset,category:t.category,builtin:!0,guideline:t.guidance})}}const $={minimal:new Set([`minimal`]),standard:new Set([`minimal`,`standard`]),full:new Set([`minimal`,`standard`,`full`])};function da(e){if(!e||typeof e!=`object`)return!1;let t=e,n=t.description;return typeof t.name==`string`&&(typeof n==`string`||typeof n==`function`)&&typeof t.execute==`function`&&t.parameters!==void 0}var fa=class e{tools=new Map;binaryToolExecutors=null;disposers=[];onMutation;get size(){return this.tools.size}setBinaryToolExecutors(e){this.binaryToolExecutors=e}getBinaryToolExecutors(){if(!this.binaryToolExecutors)throw Error(`BinaryToolExecutorRegistry is not set in ToolRegistry`);return this.binaryToolExecutors}registerDisposer(e){this.disposers.push(e)}register(e,t={}){let n={preset:t.preset??`full`,category:t.category,builtin:t.builtin??!1,snippet:t.snippet,guideline:t.guideline,source:t.source},r=Array.isArray(e)?e:[e];for(let e of r){if(!da(e))throw Error(`Invalid tool registration input`);let r=e,i=typeof r.description==`function`?r.description({projectRoot:t.projectRoot??``}):r.description,a={...r,description:i,metadata:n};this.tools.set(r.name,a)}this.onMutation?.({added:r.map(e=>e.name),source:t.source})}unregister(e){let t=[];if(Array.isArray(e)){let n=!0;for(let r of e)this.tools.delete(r)?t.push(r):n=!1;return t.length>0&&this.onMutation?.({removed:t}),n}let n=this.tools.delete(e);return n&&this.onMutation?.({removed:[e]}),n}unregisterBySource(e){let t=[...this.tools.values()].filter(t=>t.metadata.source===e).map(e=>e.name);for(let e of t)this.tools.delete(e);return t.length>0&&this.onMutation?.({removed:t,source:e}),t.length}get(e){return this.tools.get(e)}has(e){return this.tools.has(e)}listRegenerableNames(){let e=[];for(let t of this.tools.values())t.regenerableOutput===!0&&e.push(t.name);return e}getAll(){return[...this.tools.values()].sort((e,t)=>e.name.localeCompare(t.name))}getAvailable(e=`standard`){let t=$[e]??$.standard;return this.getAll().filter(e=>t.has(e.metadata.preset))}project(e=`standard`){let t=$[e]??$.standard,n=[],r=[];for(let e of this.getAll())t.has(e.metadata.preset)&&(e.exposure===`deferred`?r.push(e):e.exposure!==`hidden`&&n.push(e));return{direct:n,deferred:r}}static TOOL_GUIDANCE_BUDGET_TOKENS=5e3;static estimatedTokens(e){let t=0;for(let n of e)/[\u3000-\u9fff\uff00-\uffef]/.test(n)&&t++;return Math.ceil(t+(e.length-t)/4)}buildToolGuidance(t=`standard`){let{direct:n,deferred:r}=this.project(t);if(n.length===0&&r.length===0)return``;let i=new Map;for(let e of n){let{snippet:t,guideline:n,category:r}=e.metadata,a=n?`${r??``}\u0000${n}`:`\u0000tool:${e.name}`,o=i.get(a);if(o||(o={guideline:n,toolNames:[],entries:[]},i.set(a,o)),n){o.toolNames.push(e.name),t&&o.entries.push(`#### ${e.name}\nExample:\n\`\`\`\n${t}\n\`\`\``);continue}let s=[`#### ${e.name}`];t?s.push(`Example:\n\`\`\`\n${t}\n\`\`\``):s.push(e.description),o.entries.push(s.join(`
128
128
  `))}let a=[];for(let e of i.values()){let t=[];e.guideline&&t.push(e.guideline),t.push(...e.entries),a.push(t.join(`
129
129
 
130
130
  `))}let o=e.TOOL_GUIDANCE_BUDGET_TOKENS,s=0,c=[],l=0;for(let t of a){let n=e.estimatedTokens(t);s+n<=o?(c.push(t),s+=n):l++}return l>0&&c.push(`> ⚠ [${l} additional tool guidance section(s) omitted — guidance budget (${o} tokens) reached; use tool_search or the tool's own description]`),r.length>0&&c.push(`> ${r.length} additional tool(s) discoverable via tool_search (not shown here to keep this section focused; use tool_search to look them up by name or capability).`),c.length===0?``:`### Tool Reference (per category)\n\n${c.join(`
131
131
 
132
- `)}`}clear(){this.tools.size>0&&this.tools.clear()}dispose(){this.clear(),this.binaryToolExecutors&&=(this.binaryToolExecutors.dispose(),null);for(let e of this.disposers.splice(0))Promise.resolve().then(e).catch(()=>void 0)}};const da=(e,t)=>{let n=new ua,r=ht(e,t.processTracker);return n.setBinaryToolExecutors(r),ca(n,e,t),n},fa=new Set([`task_delegate`]),pa=new class{name=`noop`;wrap(e){return{command:e.command,args:e.args,options:e.options}}async dispose(){}};function ma(){return pa}var ha=class{name=`macos-seatbelt`;options;profilePathByContent=new Map;constructor(e={}){this.options={network:e.network??`allow`,writablePaths:e.writablePaths??[],denyReadPaths:e.denyReadPaths??[]}}wrap(e){let t=this.buildProfile(e.projectRoot);return{command:`/usr/bin/sandbox-exec`,args:[`-f`,this.ensureProfileSync(t),e.command,...e.args],options:{...e.options}}}async dispose(){let e=[...this.profilePathByContent.values()];this.profilePathByContent.clear(),await Promise.allSettled(e.map(e=>xe(e).catch(()=>void 0)))}buildProfile(e){let t=P(e),n=ie(),r=new Set;for(let e of[t,n,...this.options.writablePaths.map(e=>P(e))]){r.add(e);try{r.add(me(e))}catch{}}let i=e=>e.replace(/\\/g,`\\\\`).replace(/"/g,`\\"`),a=[...r].map(e=>`(subpath "${i(e)}")`).join(`
132
+ `)}`}clear(){this.tools.size>0&&this.tools.clear()}dispose(){this.clear(),this.binaryToolExecutors&&=(this.binaryToolExecutors.dispose(),null);for(let e of this.disposers.splice(0))Promise.resolve().then(e).catch(()=>void 0)}};const pa=(e,t)=>{let n=new fa,r=ht(e,t.processTracker);return n.setBinaryToolExecutors(r),ua(n,e,t),n},ma=new Set([`task_delegate`]),ha=new class{name=`noop`;wrap(e){return{command:e.command,args:e.args,options:e.options}}async dispose(){}};function ga(){return ha}var _a=class{name=`macos-seatbelt`;options;profilePathByContent=new Map;constructor(e={}){this.options={network:e.network??`allow`,writablePaths:e.writablePaths??[],denyReadPaths:e.denyReadPaths??[]}}wrap(e){let t=this.buildProfile(e.projectRoot);return{command:`/usr/bin/sandbox-exec`,args:[`-f`,this.ensureProfileSync(t),e.command,...e.args],options:{...e.options}}}async dispose(){let e=[...this.profilePathByContent.values()];this.profilePathByContent.clear(),await Promise.allSettled(e.map(e=>xe(e).catch(()=>void 0)))}buildProfile(e){let t=P(e),n=ie(),r=new Set;for(let e of[t,n,...this.options.writablePaths.map(e=>P(e))]){r.add(e);try{r.add(me(e))}catch{}}let i=e=>e.replace(/\\/g,`\\\\`).replace(/"/g,`\\"`),a=[...r].map(e=>`(subpath "${i(e)}")`).join(`
133
133
  `),o=this.options.network===`deny`?`(deny network*)
134
134
  `:`(allow network*)
135
135
  `,s=new Set;for(let e of this.options.denyReadPaths){let t=P(e);s.add(t);try{s.add(me(t))}catch{}}return`(version 1)
@@ -152,5 +152,5 @@ ${s.size>0?`
152
152
  ; credential read isolation (opt-in) — last match wins, denies even within writable roots
153
153
  `+[...s].map(e=>`(deny file-read* (subpath "${i(e)}"))`).join(`
154
154
  `)+`
155
- `:``}`}ensureProfileSync(e){let t=this.profilePathByContent.get(e);if(t&&D(t))return t;let n=`${ie()}/otto-sandbox-${Ce()}.sb`;return _e(n,e,`utf-8`),this.profilePathByContent.set(e,n),n}};function ga(e){return new ha(e)}var _a=class{name=`bubblewrap`;options;constructor(e={}){this.options={network:e.network??`allow`,writablePaths:e.writablePaths??[],denyReadPaths:e.denyReadPaths??[]}}wrap(e){let t=P(e.projectRoot),n=P(e.options.cwd??t),r=[`--unshare-all`,`--cap-drop`,`ALL`,`--die-with-parent`];for(let e of va)D(e)&&r.push(`--ro-bind`,e,e);r.push(`--tmpfs`,`/tmp`),r.push(`--bind`,t,t);let i=[t];for(let e of this.options.writablePaths){let t=P(e);i.push(t),r.push(`--bind`,t,t)}for(let e of this.options.denyReadPaths){let t=P(e);i.some(e=>t===e||t.startsWith(`${e}/`))&&r.push(`--tmpfs`,t)}return r.push(`--proc`,`/proc`),this.options.network===`deny`?r.push(`--unshare-net`):r.push(`--share-net`),r.push(`--chdir`,n),r.push(e.command,...e.args),{command:`bwrap`,args:r,options:{...e.options}}}async dispose(){}};const va=[`/usr`,`/bin`,`/lib`,`/lib64`,`/etc`,`/dev`,`/sys`];function ya(e){return new _a(e)}function ba(){let e=re(),t=process.env.OTTO_AUTH_PATH;return[M(e,`.ssh`),M(e,`.aws`),M(e,`.gnupg`),t?j(t):M(e,`.config`,`otto`)]}function xa(e={}){switch(e.force??Sa()){case`seatbelt`:return ga({network:e.network,writablePaths:e.writablePaths,denyReadPaths:e.denyReadPaths});case`bubblewrap`:return ya({network:e.network,writablePaths:e.writablePaths,denyReadPaths:e.denyReadPaths});default:return ma()}}function Sa(){return process.platform===`darwin`?`seatbelt`:process.platform===`linux`?`bubblewrap`:`noop`}function Ca(){let e=Sa();return e===`seatbelt`?D(`/usr/bin/sandbox-exec`):e===`bubblewrap`?[`/usr/bin/bwrap`,`/usr/local/bin/bwrap`,`/bin/bwrap`].some(e=>D(e))?!0:(process.env.PATH??``).split(`:`).filter(Boolean).some(e=>D(`${e}/bwrap`)):!1}export{mt as BinaryToolExecutorRegistry,ii as LSPClient,fa as ORCHESTRATION_TOOL_NAMES,aa as TOOL_NODES,ua as ToolRegistry,ur as buildDelegationAgentListDescription,ht as createBinaryToolExecutorRegistry,ya as createBubblewrapSandbox,jr as createCaptureFileState,Fn as createEdit,Ue as createGrillMe,Nr as createLearn,vi as createLspDefinition,wi as createLspDiagnostics,Ei as createLspPrepareRename,bi as createLspReferences,Oi as createLspRename,Si as createLspSymbols,ga as createMacOsSeatbeltSandbox,ma as createNoopSandbox,xa as createPlatformSandbox,dn as createRead,Ai as createSessionManagerTool,wr as createTaskControl,Sr as createTaskInspect,da as createToolRegistry,Fr as createToolSearch,tr as createWebFetch,lr as createWebSearch,_n as createWrite,kr as createWriteTodos,ba as credentialDenyReadPaths,hi as findWorkspaceRoot,Ca as isPlatformSandboxAvailable,Y as lspManager,ca as registerBuiltinTools,Z as withLspClient};
155
+ `:``}`}ensureProfileSync(e){let t=this.profilePathByContent.get(e);if(t&&D(t))return t;let n=`${ie()}/otto-sandbox-${Ce()}.sb`;return _e(n,e,`utf-8`),this.profilePathByContent.set(e,n),n}};function va(e){return new _a(e)}var ya=class{name=`bubblewrap`;options;constructor(e={}){this.options={network:e.network??`allow`,writablePaths:e.writablePaths??[],denyReadPaths:e.denyReadPaths??[]}}wrap(e){let t=P(e.projectRoot),n=P(e.options.cwd??t),r=[`--unshare-all`,`--cap-drop`,`ALL`,`--die-with-parent`];for(let e of ba)D(e)&&r.push(`--ro-bind`,e,e);r.push(`--tmpfs`,`/tmp`),r.push(`--bind`,t,t);let i=[t];for(let e of this.options.writablePaths){let t=P(e);i.push(t),r.push(`--bind`,t,t)}for(let e of this.options.denyReadPaths){let t=P(e);i.some(e=>t===e||t.startsWith(`${e}/`))&&r.push(`--tmpfs`,t)}return r.push(`--proc`,`/proc`),this.options.network===`deny`?r.push(`--unshare-net`):r.push(`--share-net`),r.push(`--chdir`,n),r.push(e.command,...e.args),{command:`bwrap`,args:r,options:{...e.options}}}async dispose(){}};const ba=[`/usr`,`/bin`,`/lib`,`/lib64`,`/etc`,`/dev`,`/sys`];function xa(e){return new ya(e)}function Sa(){let e=re(),t=process.env.OTTO_AUTH_PATH;return[M(e,`.ssh`),M(e,`.aws`),M(e,`.gnupg`),t?j(t):M(e,`.config`,`otto`)]}function Ca(e={}){switch(e.force??wa()){case`seatbelt`:return va({network:e.network,writablePaths:e.writablePaths,denyReadPaths:e.denyReadPaths});case`bubblewrap`:return xa({network:e.network,writablePaths:e.writablePaths,denyReadPaths:e.denyReadPaths});default:return ga()}}function wa(){return process.platform===`darwin`?`seatbelt`:process.platform===`linux`?`bubblewrap`:`noop`}function Ta(){let e=wa();return e===`seatbelt`?D(`/usr/bin/sandbox-exec`):e===`bubblewrap`?[`/usr/bin/bwrap`,`/usr/local/bin/bwrap`,`/bin/bwrap`].some(e=>D(e))?!0:(process.env.PATH??``).split(`:`).filter(Boolean).some(e=>D(`${e}/bwrap`)):!1}export{mt as BinaryToolExecutorRegistry,ii as LSPClient,ma as ORCHESTRATION_TOOL_NAMES,sa as TOOL_NODES,fa as ToolRegistry,ur as buildDelegationAgentListDescription,ht as createBinaryToolExecutorRegistry,xa as createBubblewrapSandbox,jr as createCaptureFileState,Fn as createEdit,Ue as createGrillMe,Nr as createLearn,vi as createLspDefinition,wi as createLspDiagnostics,Ei as createLspPrepareRename,bi as createLspReferences,Oi as createLspRename,Si as createLspSymbols,va as createMacOsSeatbeltSandbox,ga as createNoopSandbox,Ca as createPlatformSandbox,dn as createRead,Ai as createSessionManagerTool,wr as createTaskControl,Sr as createTaskInspect,pa as createToolRegistry,Fr as createToolSearch,tr as createWebFetch,lr as createWebSearch,_n as createWrite,kr as createWriteTodos,Sa as credentialDenyReadPaths,hi as findWorkspaceRoot,Ta as isPlatformSandboxAvailable,Y as lspManager,ua as registerBuiltinTools,Z as withLspClient};
156
156
  //# sourceMappingURL=index.js.map