zidane 5.13.22 → 5.13.23

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.
@@ -1 +1 @@
1
- {"version":3,"file":"presets-BVUwZhtJ.js","names":[],"sources":["../src/presets/basic.ts","../src/presets/index.ts"],"sourcesContent":["import { definePreset } from '.'\nimport { edit, listFiles, multiEdit, readFile, shell, shellKill, waitTask, writeFile } from '../tools'\nimport { createSpawnTool } from '../tools/spawn'\n\n/**\n * Core tools available in every basic preset (without spawn).\n *\n * `edit` and `multi_edit` ship in the basic set because surgical edits are the\n * default modality for production agents — `write_file` is for full overwrites.\n * `glob` and `grep` are exported but opt-in: not every agent needs codebase\n * search, and shipping them by default would force `tool:gate` work onto\n * consumers that prefer the model to use `shell` + classic Unix tools.\n */\nexport const basicTools = { shell, shellKill, waitTask, readFile, writeFile, listFiles, edit, multiEdit }\n\nexport default definePreset({\n name: 'basic',\n system: 'You are a helpful assistant with access to shell, file reading, file writing, surgical and multi-edit tools, directory listing, and sub-agent spawning. Prefer `edit` / `multi_edit` for in-place changes and `write_file` for full file overwrites. Use them to accomplish tasks in the project directory.',\n // `tools` is a getter so each access (every `{ ...basic }` spread into\n // `createAgent`) mints a FRESH spawn tool. `createSpawnTool()` carries\n // per-instance state (running children, concurrency counter, child-stats\n // accumulator); a module-level singleton instance would be shared by every\n // agent in the process, breaking concurrent rollouts.\n //\n // `persist: true` shares the parent's session with every child agent — child\n // turns land in `session.turns` tagged with their own `runId`, and the run\n // itself is recorded in `session.runs` with `parentRunId` + `depth`. That's\n // what lets a reloaded TUI session reconstruct the full subagent tree (see\n // `eventsFromTurns` in `tui/store.ts`). Hosts that want children in-memory\n // only can construct their own preset with `createSpawnTool()`.\n get tools() {\n return { ...basicTools, spawn: createSpawnTool({ persist: true }) }\n },\n})\n","import type { AgentHooks, AgentOptions } from '../agent'\n\nexport type { AgentHookMap } from '../agent'\n\n/**\n * A preset is a reusable slice of `AgentOptions` — spread it into `createAgent()`\n * to configure tools, a default system prompt, aliases, behavior defaults, and\n * agent-lifetime hooks.\n *\n * `provider`, `execution`, `session`, and `mcpConnector` are excluded — they're\n * ambient / per-invocation runtime wiring (a custom `mcpConnector` is the MCP\n * connection seam, often closure-bound to a transport / auth provider), so\n * presets stay shareable and composable.\n *\n * ```ts\n * import { basic } from 'zidane/presets'\n * createAgent({ ...basic, provider })\n * ```\n *\n * ### Composing multiple presets\n *\n * Bare `...spread` is shallow — `{ ...a, ...b }` overwrites every key `b`\n * defines, including `hooks`. Use {@link composePresets} when you want\n * field-aware merging (per-event hook concat, tools shallow-merge, etc.):\n *\n * ```ts\n * createAgent({ ...composePresets(basic, telemetry, mine), provider })\n * ```\n */\nexport type Preset = Omit<Partial<AgentOptions>, 'provider' | 'execution' | 'session' | 'mcpConnector'>\n\n/**\n * Identity helper for type inference when defining a preset.\n */\nexport function definePreset(config: Preset): Preset {\n return config\n}\n\n/**\n * Field-aware composition of presets. Right-most preset wins for scalar fields;\n * objects shallow-merge; arrays and hook handler lists concatenate. Designed so\n * stacking presets does the obvious thing without the spread-collision footgun:\n *\n * - `name`, `system`, `eager`, `skills` → last-defined wins\n * - `tools`, `toolAliases`, `behavior` → shallow-merge (later keys override)\n * - `behavior.dedupTools`, `behavior.toolBudgets` → **deep-merge** (per-tool-name; later wins on collision)\n * - `mcpServers` → concat with last-wins on `name` collision\n * - `hooks` → per-event concat; every handler fires\n *\n * `hooks` always emerges as `event → handler[]` so downstream registration\n * (in `createAgent`) sees a uniform shape. Order of handlers within an event\n * follows preset order: earlier presets register first.\n *\n * `mcpServers` is deduped by `name` because shipping two servers with the same\n * name would trip the connector at runtime — a later preset overriding an\n * earlier preset's `github` server is the practical intent.\n *\n * `behavior.dedupTools` and `behavior.toolBudgets` get the same per-key deep-merge\n * because they are tool-name-keyed records — a preset that ships a dedup hasher\n * for one tool should not erase a hasher another preset ships for a different\n * tool. Last-wins still applies on a per-tool collision so a downstream preset\n * can override an upstream preset's policy for one specific tool. Other\n * `behavior` fields keep last-wins semantics.\n */\nexport function composePresets(...presets: Preset[]): Preset {\n const out: Preset = {}\n const hooksByEvent: { [K in keyof AgentHooks]?: AgentHooks[K][] } = {}\n // Keep mcpServers in source-order on first sight, but allow later\n // declarations to override earlier ones with the same `name`. A `Map`\n // keyed by name gives O(1) override + stable iteration.\n const mcpByName = new Map<string, NonNullable<Preset['mcpServers']>[number]>()\n\n for (const p of presets) {\n if (p.name !== undefined)\n out.name = p.name\n if (p.system !== undefined)\n out.system = p.system\n if (p.eager !== undefined)\n out.eager = p.eager\n if (p.skills !== undefined)\n out.skills = p.skills\n if (p.tools)\n out.tools = { ...out.tools, ...p.tools }\n if (p.toolAliases)\n out.toolAliases = { ...out.toolAliases, ...p.toolAliases }\n if (p.behavior) {\n // Top-level shallow-merge first; then deep-merge the two tool-name-keyed\n // sub-records so per-tool entries from earlier presets aren't clobbered.\n const merged: NonNullable<Preset['behavior']> = { ...out.behavior, ...p.behavior }\n if (out.behavior?.dedupTools || p.behavior.dedupTools) {\n merged.dedupTools = { ...out.behavior?.dedupTools, ...p.behavior.dedupTools }\n }\n if (out.behavior?.toolBudgets || p.behavior.toolBudgets) {\n merged.toolBudgets = { ...out.behavior?.toolBudgets, ...p.behavior.toolBudgets }\n }\n out.behavior = merged\n }\n if (p.mcpServers) {\n for (const server of p.mcpServers)\n mcpByName.set(server.name, server)\n }\n if (p.hooks) {\n for (const [event, handler] of Object.entries(p.hooks)) {\n if (handler === undefined)\n continue\n const list = Array.isArray(handler) ? handler : [handler]\n const key = event as keyof AgentHooks\n // Safe cast: we read the loose `AgentHookMap` shape (handler-or-array)\n // and re-emit only as arrays. Each `list` element matches the event's\n // handler signature by construction (the input was typed `AgentHookMap`).\n const bucket = (hooksByEvent[key] ??= []) as unknown[]\n bucket.push(...(list as unknown[]))\n }\n }\n }\n\n if (mcpByName.size > 0)\n out.mcpServers = [...mcpByName.values()]\n\n if (Object.keys(hooksByEvent).length > 0)\n out.hooks = hooksByEvent\n\n return out\n}\n\nexport { default as basic, basicTools } from './basic'\n"],"mappings":";;;;;;;;;;;AAaA,MAAa,aAAa;CAAE;CAAO;CAAW;CAAU;CAAU;CAAW;CAAW;CAAM;AAAU;AAExG,IAAA,gBAAe,aAAa;CAC1B,MAAM;CACN,QAAQ;CAaR,IAAI,QAAQ;EACV,OAAO;GAAE,GAAG;GAAY,OAAO,gBAAgB,EAAE,SAAS,KAAK,CAAC;EAAE;CACpE;AACF,CAAC;;;;;;ACCD,SAAgB,aAAa,QAAwB;CACnD,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,eAAe,GAAG,SAA2B;CAC3D,MAAM,MAAc,CAAC;CACrB,MAAM,eAA8D,CAAC;CAIrE,MAAM,4BAAY,IAAI,IAAuD;CAE7E,KAAK,MAAM,KAAK,SAAS;EACvB,IAAI,EAAE,SAAS,KAAA,GACb,IAAI,OAAO,EAAE;EACf,IAAI,EAAE,WAAW,KAAA,GACf,IAAI,SAAS,EAAE;EACjB,IAAI,EAAE,UAAU,KAAA,GACd,IAAI,QAAQ,EAAE;EAChB,IAAI,EAAE,WAAW,KAAA,GACf,IAAI,SAAS,EAAE;EACjB,IAAI,EAAE,OACJ,IAAI,QAAQ;GAAE,GAAG,IAAI;GAAO,GAAG,EAAE;EAAM;EACzC,IAAI,EAAE,aACJ,IAAI,cAAc;GAAE,GAAG,IAAI;GAAa,GAAG,EAAE;EAAY;EAC3D,IAAI,EAAE,UAAU;GAGd,MAAM,SAA0C;IAAE,GAAG,IAAI;IAAU,GAAG,EAAE;GAAS;GACjF,IAAI,IAAI,UAAU,cAAc,EAAE,SAAS,YACzC,OAAO,aAAa;IAAE,GAAG,IAAI,UAAU;IAAY,GAAG,EAAE,SAAS;GAAW;GAE9E,IAAI,IAAI,UAAU,eAAe,EAAE,SAAS,aAC1C,OAAO,cAAc;IAAE,GAAG,IAAI,UAAU;IAAa,GAAG,EAAE,SAAS;GAAY;GAEjF,IAAI,WAAW;EACjB;EACA,IAAI,EAAE,YACJ,KAAK,MAAM,UAAU,EAAE,YACrB,UAAU,IAAI,OAAO,MAAM,MAAM;EAErC,IAAI,EAAE,OACJ,KAAK,MAAM,CAAC,OAAO,YAAY,OAAO,QAAQ,EAAE,KAAK,GAAG;GACtD,IAAI,YAAY,KAAA,GACd;GACF,MAAM,OAAO,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO;GACxD,MAAM,MAAM;GAKZ,CADgB,aAAa,SAAS,CAAC,GAChC,KAAK,GAAI,IAAkB;EACpC;CAEJ;CAEA,IAAI,UAAU,OAAO,GACnB,IAAI,aAAa,CAAC,GAAG,UAAU,OAAO,CAAC;CAEzC,IAAI,OAAO,KAAK,YAAY,EAAE,SAAS,GACrC,IAAI,QAAQ;CAEd,OAAO;AACT"}
1
+ {"version":3,"file":"presets-D3xdMjQB.js","names":[],"sources":["../src/presets/basic.ts","../src/presets/index.ts"],"sourcesContent":["import { definePreset } from '.'\nimport { edit, listFiles, multiEdit, readFile, shell, shellKill, waitTask, writeFile } from '../tools'\nimport { createSpawnTool } from '../tools/spawn'\n\n/**\n * Core tools available in every basic preset (without spawn).\n *\n * `edit` and `multi_edit` ship in the basic set because surgical edits are the\n * default modality for production agents — `write_file` is for full overwrites.\n * `glob` and `grep` are exported but opt-in: not every agent needs codebase\n * search, and shipping them by default would force `tool:gate` work onto\n * consumers that prefer the model to use `shell` + classic Unix tools.\n */\nexport const basicTools = { shell, shellKill, waitTask, readFile, writeFile, listFiles, edit, multiEdit }\n\nexport default definePreset({\n name: 'basic',\n system: 'You are a helpful assistant with access to shell, file reading, file writing, surgical and multi-edit tools, directory listing, and sub-agent spawning. Prefer `edit` / `multi_edit` for in-place changes and `write_file` for full file overwrites. Use them to accomplish tasks in the project directory.',\n // `tools` is a getter so each access (every `{ ...basic }` spread into\n // `createAgent`) mints a FRESH spawn tool. `createSpawnTool()` carries\n // per-instance state (running children, concurrency counter, child-stats\n // accumulator); a module-level singleton instance would be shared by every\n // agent in the process, breaking concurrent rollouts.\n //\n // `persist: true` shares the parent's session with every child agent — child\n // turns land in `session.turns` tagged with their own `runId`, and the run\n // itself is recorded in `session.runs` with `parentRunId` + `depth`. That's\n // what lets a reloaded TUI session reconstruct the full subagent tree (see\n // `eventsFromTurns` in `tui/store.ts`). Hosts that want children in-memory\n // only can construct their own preset with `createSpawnTool()`.\n get tools() {\n return { ...basicTools, spawn: createSpawnTool({ persist: true }) }\n },\n})\n","import type { AgentHooks, AgentOptions } from '../agent'\n\nexport type { AgentHookMap } from '../agent'\n\n/**\n * A preset is a reusable slice of `AgentOptions` — spread it into `createAgent()`\n * to configure tools, a default system prompt, aliases, behavior defaults, and\n * agent-lifetime hooks.\n *\n * `provider`, `execution`, `session`, and `mcpConnector` are excluded — they're\n * ambient / per-invocation runtime wiring (a custom `mcpConnector` is the MCP\n * connection seam, often closure-bound to a transport / auth provider), so\n * presets stay shareable and composable.\n *\n * ```ts\n * import { basic } from 'zidane/presets'\n * createAgent({ ...basic, provider })\n * ```\n *\n * ### Composing multiple presets\n *\n * Bare `...spread` is shallow — `{ ...a, ...b }` overwrites every key `b`\n * defines, including `hooks`. Use {@link composePresets} when you want\n * field-aware merging (per-event hook concat, tools shallow-merge, etc.):\n *\n * ```ts\n * createAgent({ ...composePresets(basic, telemetry, mine), provider })\n * ```\n */\nexport type Preset = Omit<Partial<AgentOptions>, 'provider' | 'execution' | 'session' | 'mcpConnector'>\n\n/**\n * Identity helper for type inference when defining a preset.\n */\nexport function definePreset(config: Preset): Preset {\n return config\n}\n\n/**\n * Field-aware composition of presets. Right-most preset wins for scalar fields;\n * objects shallow-merge; arrays and hook handler lists concatenate. Designed so\n * stacking presets does the obvious thing without the spread-collision footgun:\n *\n * - `name`, `system`, `eager`, `skills` → last-defined wins\n * - `tools`, `toolAliases`, `behavior` → shallow-merge (later keys override)\n * - `behavior.dedupTools`, `behavior.toolBudgets` → **deep-merge** (per-tool-name; later wins on collision)\n * - `mcpServers` → concat with last-wins on `name` collision\n * - `hooks` → per-event concat; every handler fires\n *\n * `hooks` always emerges as `event → handler[]` so downstream registration\n * (in `createAgent`) sees a uniform shape. Order of handlers within an event\n * follows preset order: earlier presets register first.\n *\n * `mcpServers` is deduped by `name` because shipping two servers with the same\n * name would trip the connector at runtime — a later preset overriding an\n * earlier preset's `github` server is the practical intent.\n *\n * `behavior.dedupTools` and `behavior.toolBudgets` get the same per-key deep-merge\n * because they are tool-name-keyed records — a preset that ships a dedup hasher\n * for one tool should not erase a hasher another preset ships for a different\n * tool. Last-wins still applies on a per-tool collision so a downstream preset\n * can override an upstream preset's policy for one specific tool. Other\n * `behavior` fields keep last-wins semantics.\n */\nexport function composePresets(...presets: Preset[]): Preset {\n const out: Preset = {}\n const hooksByEvent: { [K in keyof AgentHooks]?: AgentHooks[K][] } = {}\n // Keep mcpServers in source-order on first sight, but allow later\n // declarations to override earlier ones with the same `name`. A `Map`\n // keyed by name gives O(1) override + stable iteration.\n const mcpByName = new Map<string, NonNullable<Preset['mcpServers']>[number]>()\n\n for (const p of presets) {\n if (p.name !== undefined)\n out.name = p.name\n if (p.system !== undefined)\n out.system = p.system\n if (p.eager !== undefined)\n out.eager = p.eager\n if (p.skills !== undefined)\n out.skills = p.skills\n if (p.tools)\n out.tools = { ...out.tools, ...p.tools }\n if (p.toolAliases)\n out.toolAliases = { ...out.toolAliases, ...p.toolAliases }\n if (p.behavior) {\n // Top-level shallow-merge first; then deep-merge the two tool-name-keyed\n // sub-records so per-tool entries from earlier presets aren't clobbered.\n const merged: NonNullable<Preset['behavior']> = { ...out.behavior, ...p.behavior }\n if (out.behavior?.dedupTools || p.behavior.dedupTools) {\n merged.dedupTools = { ...out.behavior?.dedupTools, ...p.behavior.dedupTools }\n }\n if (out.behavior?.toolBudgets || p.behavior.toolBudgets) {\n merged.toolBudgets = { ...out.behavior?.toolBudgets, ...p.behavior.toolBudgets }\n }\n out.behavior = merged\n }\n if (p.mcpServers) {\n for (const server of p.mcpServers)\n mcpByName.set(server.name, server)\n }\n if (p.hooks) {\n for (const [event, handler] of Object.entries(p.hooks)) {\n if (handler === undefined)\n continue\n const list = Array.isArray(handler) ? handler : [handler]\n const key = event as keyof AgentHooks\n // Safe cast: we read the loose `AgentHookMap` shape (handler-or-array)\n // and re-emit only as arrays. Each `list` element matches the event's\n // handler signature by construction (the input was typed `AgentHookMap`).\n const bucket = (hooksByEvent[key] ??= []) as unknown[]\n bucket.push(...(list as unknown[]))\n }\n }\n }\n\n if (mcpByName.size > 0)\n out.mcpServers = [...mcpByName.values()]\n\n if (Object.keys(hooksByEvent).length > 0)\n out.hooks = hooksByEvent\n\n return out\n}\n\nexport { default as basic, basicTools } from './basic'\n"],"mappings":";;;;;;;;;;;AAaA,MAAa,aAAa;CAAE;CAAO;CAAW;CAAU;CAAU;CAAW;CAAW;CAAM;AAAU;AAExG,IAAA,gBAAe,aAAa;CAC1B,MAAM;CACN,QAAQ;CAaR,IAAI,QAAQ;EACV,OAAO;GAAE,GAAG;GAAY,OAAO,gBAAgB,EAAE,SAAS,KAAK,CAAC;EAAE;CACpE;AACF,CAAC;;;;;;ACCD,SAAgB,aAAa,QAAwB;CACnD,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,eAAe,GAAG,SAA2B;CAC3D,MAAM,MAAc,CAAC;CACrB,MAAM,eAA8D,CAAC;CAIrE,MAAM,4BAAY,IAAI,IAAuD;CAE7E,KAAK,MAAM,KAAK,SAAS;EACvB,IAAI,EAAE,SAAS,KAAA,GACb,IAAI,OAAO,EAAE;EACf,IAAI,EAAE,WAAW,KAAA,GACf,IAAI,SAAS,EAAE;EACjB,IAAI,EAAE,UAAU,KAAA,GACd,IAAI,QAAQ,EAAE;EAChB,IAAI,EAAE,WAAW,KAAA,GACf,IAAI,SAAS,EAAE;EACjB,IAAI,EAAE,OACJ,IAAI,QAAQ;GAAE,GAAG,IAAI;GAAO,GAAG,EAAE;EAAM;EACzC,IAAI,EAAE,aACJ,IAAI,cAAc;GAAE,GAAG,IAAI;GAAa,GAAG,EAAE;EAAY;EAC3D,IAAI,EAAE,UAAU;GAGd,MAAM,SAA0C;IAAE,GAAG,IAAI;IAAU,GAAG,EAAE;GAAS;GACjF,IAAI,IAAI,UAAU,cAAc,EAAE,SAAS,YACzC,OAAO,aAAa;IAAE,GAAG,IAAI,UAAU;IAAY,GAAG,EAAE,SAAS;GAAW;GAE9E,IAAI,IAAI,UAAU,eAAe,EAAE,SAAS,aAC1C,OAAO,cAAc;IAAE,GAAG,IAAI,UAAU;IAAa,GAAG,EAAE,SAAS;GAAY;GAEjF,IAAI,WAAW;EACjB;EACA,IAAI,EAAE,YACJ,KAAK,MAAM,UAAU,EAAE,YACrB,UAAU,IAAI,OAAO,MAAM,MAAM;EAErC,IAAI,EAAE,OACJ,KAAK,MAAM,CAAC,OAAO,YAAY,OAAO,QAAQ,EAAE,KAAK,GAAG;GACtD,IAAI,YAAY,KAAA,GACd;GACF,MAAM,OAAO,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO;GACxD,MAAM,MAAM;GAKZ,CADgB,aAAa,SAAS,CAAC,GAChC,KAAK,GAAI,IAAkB;EACpC;CAEJ;CAEA,IAAI,UAAU,OAAO,GACnB,IAAI,aAAa,CAAC,GAAG,UAAU,OAAO,CAAC;CAEzC,IAAI,OAAO,KAAK,YAAY,EAAE,SAAS,GACrC,IAAI,QAAQ;CAEd,OAAO;AACT"}
package/dist/presets.js CHANGED
@@ -1,2 +1,2 @@
1
- import { i as basic_default, n as definePreset, r as basicTools, t as composePresets } from "./presets-BVUwZhtJ.js";
1
+ import { i as basic_default, n as definePreset, r as basicTools, t as composePresets } from "./presets-D3xdMjQB.js";
2
2
  export { basic_default as basic, basicTools, composePresets, definePreset };
@@ -7172,6 +7172,97 @@ function installLazyDisclosureGate(hooks, lazyCanonicalNames, unlocked, discover
7172
7172
  });
7173
7173
  }
7174
7174
  /**
7175
+ * Rebuild skill activation state from a session's `skills_use` tool_calls,
7176
+ * honoring the most recent `mode` per skill (`activate` wins unless a later
7177
+ * `deactivate` overrides it). Idempotent: `activate()` is a no-op for
7178
+ * already-active skills, so re-running is safe and only fires `skills:activate`
7179
+ * (`via: 'resume'`) for skills it newly activates. Shared by the run-start
7180
+ * resume rehydration and the mid-loop durable-replay gate below.
7181
+ */
7182
+ async function rehydrateActiveSkillsFromTurns(session, resolvedSkills, state, hooks) {
7183
+ const skillsByName = new Map(resolvedSkills.map((s) => [s.name, s]));
7184
+ const lastModeBySkill = /* @__PURE__ */ new Map();
7185
+ for (const turn of session.turns) {
7186
+ if (turn.role !== "assistant") continue;
7187
+ for (const block of turn.content) {
7188
+ if (block.type !== "tool_call" || block.name !== "skills_use") continue;
7189
+ const input = block.input;
7190
+ const skillName = input?.name;
7191
+ if (!skillName) continue;
7192
+ lastModeBySkill.set(skillName, input?.mode === "deactivate" ? "deactivate" : "activate");
7193
+ }
7194
+ }
7195
+ for (const [skillName, mode] of lastModeBySkill) {
7196
+ if (mode !== "activate") continue;
7197
+ const skill = skillsByName.get(skillName);
7198
+ if (!skill) continue;
7199
+ if (state.activate(skill, "resume") === "ok") await hooks.callHook("skills:activate", {
7200
+ skill,
7201
+ via: "resume"
7202
+ });
7203
+ }
7204
+ }
7205
+ /**
7206
+ * Skill-activation pre-hydration, as a `tool:gate` hook. Same hazard shape as
7207
+ * `installReadBeforeEditHydrationGate`: `skills_read` / `skills_run_script`
7208
+ * refuse inside their (possibly journaled) `execute` body when the named skill
7209
+ * isn't active, but activation lives in an in-memory state machine populated by
7210
+ * `skills_use`'s LIVE body. Under durable replay, a `skills_use` from earlier in
7211
+ * the SAME run is replayed from the journal (its `state.activate` never re-runs),
7212
+ * and the run-start resume rehydration only saw the pre-run turns — so the later
7213
+ * `skills_read` runs live with the skill inactive and journals a permanent
7214
+ * "skill is not active" refusal.
7215
+ *
7216
+ * This gate fires in the loop before the body, re-runs on every replay, and
7217
+ * rebuilds activation from the in-memory `session.turns` (which replay
7218
+ * repopulates with the within-run `skills_use`) when the target skill is
7219
+ * inactive. It never blocks — the body keeps the authoritative check.
7220
+ */
7221
+ function installSkillsActivationHydrationGate(hooks, deps) {
7222
+ const session = deps.session;
7223
+ if (!session) return () => {};
7224
+ return hooks.hook("tool:gate", async (ctx) => {
7225
+ if (ctx.name !== "skills_read" && ctx.name !== "skills_run_script") return;
7226
+ const resolvedSkills = deps.getResolvedSkills();
7227
+ if (!resolvedSkills || resolvedSkills.length === 0) return;
7228
+ const skillName = typeof ctx.input?.name === "string" ? ctx.input.name : void 0;
7229
+ if (!skillName || deps.state.isActive(skillName)) return;
7230
+ try {
7231
+ await rehydrateActiveSkillsFromTurns(session, resolvedSkills, deps.state, hooks);
7232
+ } catch {}
7233
+ });
7234
+ }
7235
+ /**
7236
+ * Lazy-tool-disclosure unlock pre-hydration, as a `tool:gate` hook. Same hazard
7237
+ * shape again: `tool_search`'s LIVE body adds matched tools to the in-memory
7238
+ * `unlocked` set, but under durable replay a `tool_search` from earlier in the
7239
+ * SAME run is replayed from the journal (its `unlocked.add` never re-runs) and
7240
+ * the run-start resume replay only covered pre-run turns. So `installLazyDisclosureGate`
7241
+ * would then see the tool as locked and refuse it — diverging from the original
7242
+ * (live) execution that ran it.
7243
+ *
7244
+ * Registered BEFORE `installLazyDisclosureGate` so its rebuild lands before the
7245
+ * block decision. When a locked lazy tool is dispatched, it replays every
7246
+ * successfully-resolved `tool_search` in the in-memory `session.turns` back
7247
+ * through `applyToolSearchToUnlocked` (idempotent), so the unlock set reflects
7248
+ * what the model was already shown.
7249
+ */
7250
+ function installLazyDisclosureHydrationGate(hooks, deps) {
7251
+ const { enabled, session, lazyCanonicalNames, lazyEntries, unlocked, recordUnlock, defaultLimit } = deps;
7252
+ if (!enabled || !session || lazyCanonicalNames.size === 0) return () => {};
7253
+ return hooks.hook("tool:gate", (ctx) => {
7254
+ if (ctx.block) return;
7255
+ if (!lazyCanonicalNames.has(ctx.name) || unlocked.has(ctx.name)) return;
7256
+ const resolvedCallIds = /* @__PURE__ */ new Set();
7257
+ for (const turn of session.turns) for (const block of turn.content) if (block.type === "tool_result" && !block.isError) resolvedCallIds.add(block.callId);
7258
+ for (const turn of session.turns) for (const block of turn.content) {
7259
+ if (block.type !== "tool_call" || block.name !== "tool_search") continue;
7260
+ if (!resolvedCallIds.has(block.id)) continue;
7261
+ applyToolSearchToUnlocked(lazyEntries, block.input, unlocked, defaultLimit, recordUnlock);
7262
+ }
7263
+ });
7264
+ }
7265
+ /**
7175
7266
  * Read-before-edit read-state pre-hydration, as a `tool:gate` hook.
7176
7267
  *
7177
7268
  * The `requireReadBeforeEdit` verdict lives inside `edit` / `multi_edit`'s
@@ -7479,30 +7570,7 @@ function createAgent({ provider, name: agentName, system: agentSystem, tools: ag
7479
7570
  maxWallMs: resolvedBehavior.maxWallMs
7480
7571
  });
7481
7572
  await ensureSkillsResolved();
7482
- if (resolvedSkills && session && session.turns.length > 0 && skillActivationState.active().length === 0) {
7483
- const skillsByName = new Map(resolvedSkills.map((s) => [s.name, s]));
7484
- const lastModeBySkill = /* @__PURE__ */ new Map();
7485
- for (const turn of session.turns) {
7486
- if (turn.role !== "assistant") continue;
7487
- for (const block of turn.content) {
7488
- if (block.type !== "tool_call" || block.name !== "skills_use") continue;
7489
- const input = block.input;
7490
- const skillName = input?.name;
7491
- if (!skillName) continue;
7492
- const mode = input?.mode === "deactivate" ? "deactivate" : "activate";
7493
- lastModeBySkill.set(skillName, mode);
7494
- }
7495
- }
7496
- for (const [skillName, mode] of lastModeBySkill) {
7497
- if (mode !== "activate") continue;
7498
- const skill = skillsByName.get(skillName);
7499
- if (!skill) continue;
7500
- if (skillActivationState.activate(skill, "resume") === "ok") await hooks.callHook("skills:activate", {
7501
- skill,
7502
- via: "resume"
7503
- });
7504
- }
7505
- }
7573
+ if (resolvedSkills && session && session.turns.length > 0 && skillActivationState.active().length === 0) await rehydrateActiveSkillsFromTurns(session, resolvedSkills, skillActivationState, hooks);
7506
7574
  const thinking = options.thinking ?? "off";
7507
7575
  const model = options.model ?? provider.meta.defaultModel;
7508
7576
  if (provider.meta?.clearsContextServerSide) resolvedBehavior.dedupReads = false;
@@ -7808,6 +7876,15 @@ function createAgent({ provider, name: agentName, system: agentSystem, tools: ag
7808
7876
  const uninstallToolBudgets = installToolBudgetsGate(hooks, () => toolBudgets, (msg) => toolBudgetNudgeQueue.push(msg));
7809
7877
  const uninstallRepeatGuard = installRepeatGuard(hooks, () => repeatGuard, () => abortController?.abort());
7810
7878
  const uninstallDedupTools = installDedupToolsGate(hooks, () => dedupTools, () => session ?? void 0);
7879
+ const uninstallLazyDisclosureHydration = installLazyDisclosureHydrationGate(hooks, {
7880
+ enabled: shouldInjectToolSearch && disclosure.lazyEntries.length > 0,
7881
+ session: session ?? void 0,
7882
+ lazyCanonicalNames: disclosure.lazyCanonicalNames,
7883
+ lazyEntries: disclosure.lazyEntries,
7884
+ unlocked,
7885
+ recordUnlock: recordDynamicUnlock,
7886
+ defaultLimit: toolSearch?.limit
7887
+ });
7811
7888
  const uninstallLazyDisclosureGate = installLazyDisclosureGate(hooks, disclosure.lazyCanonicalNames, unlocked, discoveryToolName);
7812
7889
  const uninstallReadBeforeEditHydration = installReadBeforeEditHydrationGate(hooks, resolvedBehavior.requireReadBeforeEdit === true, {
7813
7890
  session: session ?? void 0,
@@ -7816,6 +7893,11 @@ function createAgent({ provider, name: agentName, system: agentSystem, tools: ag
7816
7893
  aliasMaps,
7817
7894
  defaultLineNumbers: resolvedBehavior.readLineNumbers ?? true
7818
7895
  });
7896
+ const uninstallSkillsActivationHydration = installSkillsActivationHydrationGate(hooks, {
7897
+ session: session ?? void 0,
7898
+ getResolvedSkills: () => resolvedSkills,
7899
+ state: skillActivationState
7900
+ });
7819
7901
  const runStartMs = runStartedAt;
7820
7902
  const runDepth = typeof options.depth === "number" ? options.depth : 0;
7821
7903
  const usageMirror = {
@@ -8027,8 +8109,10 @@ function createAgent({ provider, name: agentName, system: agentSystem, tools: ag
8027
8109
  uninstallDedupTools();
8028
8110
  uninstallRepeatGuard();
8029
8111
  uninstallToolBudgets();
8112
+ uninstallLazyDisclosureHydration();
8030
8113
  uninstallLazyDisclosureGate();
8031
8114
  uninstallReadBeforeEditHydration();
8115
+ uninstallSkillsActivationHydration();
8032
8116
  unregisterSpawnHook();
8033
8117
  unregisterTurnSync?.();
8034
8118
  unregisterToolResultsSync?.();
@@ -10125,4 +10209,4 @@ const writeFile$1 = {
10125
10209
  //#endregion
10126
10210
  export { sliceForCompaction as $, PERSISTED_STUB_PREFIX as A, selectFilesFromSession as B, normalizeShellCommand as C, TOOL_USE_CANCELLED_MESSAGE as D, SHELL_CASCADE_CANCEL_MESSAGE as E, resolveMcpWarningsDir as F, TRAILER as G, compactConversation as H, resolvePersistDir as I, buildFullCompactPrompt as J, buildCompactPrompt as K, resolveTasksDir as L, buildPersistedStub as M, cleanupPersistedSession as N, TOOL_USE_SKIPPED_MESSAGE as O, maybePersistToolResult as P, anchorPreviewFor as Q, buildPostCompactAttachments as R, defaultRepeatGuardTracked as S, INTERRUPT_MESSAGE_FOR_TOOL_USE as T, BASE_INSTRUCTIONS as U, selectRecentFiles as V, NO_TOOLS_PREAMBLE as W, buildUpToCompactPrompt as X, buildTailCompactPrompt as Y, ANCHOR_PREVIEW_MAX_CHARS as Z, createSkillsReadTool as _, multiEdit as a, OperationTimeoutError as at, tailTruncate as b, grep as c, OUTPUT_RESERVE_TOKENS as ct, createAgent as d, stripImagesFromTurns as et, WAIT_TASK_TIMED_OUT_PREFIX as f, createSkillsRunScriptTool as g, createSkillsUseTool as h, readFile$1 as i, CompactPromptTooLongError as it, PERSISTENCE_PREVIEW_BYTES as j, validateToolArgs as k, glob as l, effectiveContextWindow as lt, createToolSearchTool as m, createSpawnTool as n, truncateHeadForPtlRetry as nt, listFiles as o, withTimeout as ot, waitTask as p, buildFromCompactPrompt as q, shellKill as r, CompactInvalidInputError as rt, createInteractionTool as s, AUTO_COMPACT_MIN_GROWTH_FRACTION as st, writeFile$1 as t, summaryToTurn as tt, edit as u, shouldAutoCompact as ut, createShellTool as v, stableStringify as w, defaultRepeatGuardNormalize as x, shell as y, selectFilesFromReadState as z };
10127
10211
 
10128
- //# sourceMappingURL=tools-C4mCSY-v.js.map
10212
+ //# sourceMappingURL=tools-Dtv6llsJ.js.map