zidane 5.4.2 → 5.4.3

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.
Files changed (65) hide show
  1. package/README.md +15 -0
  2. package/dist/{agent-DxBoKDba.d.ts → agent-Yu8uhpy-.d.ts} +74 -3
  3. package/dist/{agent-DxBoKDba.d.ts.map → agent-Yu8uhpy-.d.ts.map} +1 -1
  4. package/dist/chat.d.ts +49 -6
  5. package/dist/chat.d.ts.map +1 -1
  6. package/dist/chat.js +2 -2
  7. package/dist/{errors-Byb0F8B9.js → errors-CDwtPIMX.js} +4 -2
  8. package/dist/{errors-Byb0F8B9.js.map → errors-CDwtPIMX.js.map} +1 -1
  9. package/dist/{index-BOtXdQkW.d.ts → index-DklfxeYy.d.ts} +8 -2
  10. package/dist/index-DklfxeYy.d.ts.map +1 -0
  11. package/dist/{index-B2VOOijU.d.ts → index-j9tY28ah.d.ts} +16 -3
  12. package/dist/index-j9tY28ah.d.ts.map +1 -0
  13. package/dist/index.d.ts +4 -4
  14. package/dist/index.js +10 -10
  15. package/dist/{interpolate-ERgZUxgg.js → interpolate-CmtjEyRJ.js} +155 -18
  16. package/dist/interpolate-CmtjEyRJ.js.map +1 -0
  17. package/dist/{login-CJbeAadS.js → login-DxyAERe1.js} +3 -3
  18. package/dist/{login-CJbeAadS.js.map → login-DxyAERe1.js.map} +1 -1
  19. package/dist/{mcp-DhmmJfxK.js → mcp-CNUbvbsy.js} +2 -2
  20. package/dist/{mcp-DhmmJfxK.js.map → mcp-CNUbvbsy.js.map} +1 -1
  21. package/dist/mcp.d.ts +1 -1
  22. package/dist/mcp.js +1 -1
  23. package/dist/{messages-D0xT979U.js → messages-fTR19Ga6.js} +2 -2
  24. package/dist/{messages-D0xT979U.js.map → messages-fTR19Ga6.js.map} +1 -1
  25. package/dist/{presets-MCcvxiNT.js → presets-D9IbaI40.js} +2 -2
  26. package/dist/{presets-MCcvxiNT.js.map → presets-D9IbaI40.js.map} +1 -1
  27. package/dist/presets.d.ts +2 -2
  28. package/dist/presets.js +1 -1
  29. package/dist/{providers-x3LZByR5.js → providers-CEzRFYtS.js} +3 -3
  30. package/dist/{providers-x3LZByR5.js.map → providers-CEzRFYtS.js.map} +1 -1
  31. package/dist/providers.d.ts +1 -1
  32. package/dist/providers.js +2 -2
  33. package/dist/session/sqlite.d.ts +1 -1
  34. package/dist/session/sqlite.js +1 -1
  35. package/dist/{session-BHZwxmfr.js → session-kwsNnOmt.js} +2 -2
  36. package/dist/{session-BHZwxmfr.js.map → session-kwsNnOmt.js.map} +1 -1
  37. package/dist/session.d.ts +1 -1
  38. package/dist/session.js +2 -2
  39. package/dist/skills.d.ts +2 -2
  40. package/dist/skills.js +1 -1
  41. package/dist/{tools-BNfyY14s.js → tools-BK2vG9UX.js} +149 -32
  42. package/dist/tools-BK2vG9UX.js.map +1 -0
  43. package/dist/tools.d.ts +2 -2
  44. package/dist/tools.js +1 -1
  45. package/dist/{transcript-anchors-DonKvoh4.d.ts → transcript-anchors-DnaBcJej.d.ts} +52 -8
  46. package/dist/transcript-anchors-DnaBcJej.d.ts.map +1 -0
  47. package/dist/tui.d.ts +4 -2
  48. package/dist/tui.d.ts.map +1 -1
  49. package/dist/tui.js +651 -42
  50. package/dist/tui.js.map +1 -1
  51. package/dist/{turn-operations-TKvy0q29.js → turn-operations-OzKEOXul.js} +240 -52
  52. package/dist/turn-operations-OzKEOXul.js.map +1 -0
  53. package/dist/types.d.ts +2 -2
  54. package/dist/types.js +1 -1
  55. package/docs/ARCHITECTURE.md +16 -3
  56. package/docs/CHAT.md +1 -1
  57. package/docs/SKILL.md +24 -14
  58. package/docs/TUI.md +24 -0
  59. package/package.json +3 -3
  60. package/dist/index-B2VOOijU.d.ts.map +0 -1
  61. package/dist/index-BOtXdQkW.d.ts.map +0 -1
  62. package/dist/interpolate-ERgZUxgg.js.map +0 -1
  63. package/dist/tools-BNfyY14s.js.map +0 -1
  64. package/dist/transcript-anchors-DonKvoh4.d.ts.map +0 -1
  65. package/dist/turn-operations-TKvy0q29.js.map +0 -1
package/dist/types.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { a as ExecutionHandle, i as ExecutionContext, n as ContextType, o as SpawnConfig, r as ExecResult, t as ContextCapabilities } from "./types-Ce78ds4h.js";
2
2
  import { t as SandboxProvider } from "./index-BiO_5Hm4.js";
3
- import { $t as ThinkingLevel, Bt as OAuthRefreshHookContext, D as SkillConfig, Dt as OpenAIParams, F as SessionRun, Ft as AgentStats, Gt as RunHookMap, Ht as PromptImagePart, I as SessionStore, It as ChildRunStats, Jt as SessionHookContext, Kt as SessionContentBlock, Lt as McpServerConfig, M as CreateSessionOptions, N as Session, Nt as AgentBehavior, P as SessionData, Pt as AgentRunOptions, Qt as StreamHookContext, Rt as McpToolHookContext, S as ReadStateMap, Ut as PromptPart, Vt as PromptDocumentPart, Wt as PromptTextPart, Xt as SessionTurn, Yt as SessionMessage, Zt as SpawnHookContext, _n as matchesContextExceeded, an as TurnUsage, b as ToolMap, cn as AgentAbortedError, ct as StreamCallbacks, dn as AgentToolNotAllowedError, dt as ToolResult, en as ToolHookContext, ft as ToolSpec, hn as ClassifiedErrorKind, i as AgentOptions, in as TurnFinishReason, j as SkillsConfig, jt as AnthropicParams, k as SkillResource, kt as CerebrasParams, ln as AgentContextExceededError, lt as StreamOptions, mn as ClassifiedError, nn as ToolResultImageContent, on as toolOutputByteLength, ot as Provider, p as McpConnection, pn as CONTEXT_EXCEEDED_MESSAGE_PATTERNS, pt as TurnResult, qt as SessionEndStatus, r as AgentHooks, rn as ToolResultTextContent, sn as toolResultToText, st as ProviderCapabilities, t as Agent, tn as ToolResultContent, un as AgentProviderError, ut as ToolCall, v as ToolContext, x as ReadStateEntry, y as ToolDef, yt as OpenRouterParams, z as RemoteStoreOptions } from "./agent-DxBoKDba.js";
4
- import { B as flattenTurns, P as InteractionToolOptions, S as SpawnToolState, V as statsByModel, b as ChildAgent, h as ValidationResult, t as Preset, x as SpawnToolOptions, z as ModelUsage } from "./index-B2VOOijU.js";
3
+ import { $t as ThinkingLevel, Bt as OAuthRefreshHookContext, D as SkillConfig, Dt as OpenAIParams, F as SessionRun, Ft as AgentStats, Gt as RunHookMap, Ht as PromptImagePart, I as SessionStore, It as ChildRunStats, Jt as SessionHookContext, Kt as SessionContentBlock, Lt as McpServerConfig, M as CreateSessionOptions, N as Session, Nt as AgentBehavior, P as SessionData, Pt as AgentRunOptions, Qt as StreamHookContext, Rt as McpToolHookContext, S as ReadStateMap, Ut as PromptPart, Vt as PromptDocumentPart, Wt as PromptTextPart, Xt as SessionTurn, Yt as SessionMessage, Zt as SpawnHookContext, _n as matchesContextExceeded, an as TurnUsage, b as ToolMap, cn as AgentAbortedError, ct as StreamCallbacks, dn as AgentToolNotAllowedError, dt as ToolResult, en as ToolHookContext, ft as ToolSpec, hn as ClassifiedErrorKind, i as AgentOptions, in as TurnFinishReason, j as SkillsConfig, jt as AnthropicParams, k as SkillResource, kt as CerebrasParams, ln as AgentContextExceededError, lt as StreamOptions, mn as ClassifiedError, nn as ToolResultImageContent, on as toolOutputByteLength, ot as Provider, p as McpConnection, pn as CONTEXT_EXCEEDED_MESSAGE_PATTERNS, pt as TurnResult, qt as SessionEndStatus, r as AgentHooks, rn as ToolResultTextContent, sn as toolResultToText, st as ProviderCapabilities, t as Agent, tn as ToolResultContent, un as AgentProviderError, ut as ToolCall, v as ToolContext, x as ReadStateEntry, y as ToolDef, yt as OpenRouterParams, z as RemoteStoreOptions } from "./agent-Yu8uhpy-.js";
4
+ import { B as flattenTurns, P as InteractionToolOptions, S as SpawnToolState, V as statsByModel, b as ChildAgent, h as ValidationResult, t as Preset, x as SpawnToolOptions, z as ModelUsage } from "./index-j9tY28ah.js";
5
5
  export { type Agent, AgentAbortedError, type AgentBehavior, AgentContextExceededError, type AgentHooks, type AgentOptions, AgentProviderError, type AgentRunOptions, type AgentStats, AgentToolNotAllowedError, type AnthropicParams, CONTEXT_EXCEEDED_MESSAGE_PATTERNS, type CerebrasParams, type ChildAgent, type ChildRunStats, type ClassifiedError, type ClassifiedErrorKind, type ContextCapabilities, type ContextType, type CreateSessionOptions, type ExecResult, type ExecutionContext, type ExecutionHandle, type InteractionToolOptions, type McpConnection, type McpServerConfig, type McpToolHookContext, type ModelUsage, type OAuthRefreshHookContext, type OpenAIParams, type OpenRouterParams, type Preset, type PromptDocumentPart, type PromptImagePart, type PromptPart, type PromptTextPart, type Provider, type ProviderCapabilities, type ReadStateEntry, type ReadStateMap, type RemoteStoreOptions, type RunHookMap, type SandboxProvider, type Session, type SessionContentBlock, type SessionData, type SessionEndStatus, type SessionHookContext, type SessionMessage, type SessionRun, type SessionStore, type SessionTurn, type SkillConfig, type SkillResource, type SkillsConfig, type SpawnConfig, type SpawnHookContext, type SpawnToolOptions, type SpawnToolState, type StreamCallbacks, type StreamHookContext, type StreamOptions, type ThinkingLevel, type ToolCall, type ToolContext, type ToolDef, type ToolHookContext, type ToolMap, type ToolResult, type ToolResultContent, type ToolResultImageContent, type ToolResultTextContent, type ToolSpec, type TurnFinishReason, type TurnResult, type TurnUsage, type ValidationResult, flattenTurns, matchesContextExceeded, statsByModel, toolOutputByteLength, toolResultToText };
package/dist/types.js CHANGED
@@ -1,4 +1,4 @@
1
- import { c as matchesContextExceeded, i as AgentToolNotAllowedError, n as AgentContextExceededError, o as CONTEXT_EXCEEDED_MESSAGE_PATTERNS, r as AgentProviderError, t as AgentAbortedError } from "./errors-Byb0F8B9.js";
1
+ import { c as matchesContextExceeded, i as AgentToolNotAllowedError, n as AgentContextExceededError, o as CONTEXT_EXCEEDED_MESSAGE_PATTERNS, r as AgentProviderError, t as AgentAbortedError } from "./errors-CDwtPIMX.js";
2
2
  import { n as toolResultToText, t as toolOutputByteLength } from "./types-IcokUOyC.js";
3
3
  import { r as statsByModel, t as flattenTurns } from "./stats-DgOvY7wd.js";
4
4
  export { AgentAbortedError, AgentContextExceededError, AgentProviderError, AgentToolNotAllowedError, CONTEXT_EXCEEDED_MESSAGE_PATTERNS, flattenTurns, matchesContextExceeded, statsByModel, toolOutputByteLength, toolResultToText };
@@ -142,7 +142,9 @@ flowchart TB
142
142
  VC -->|yes| VCH["validation:coerce hook\n(observational)"]
143
143
  VC -->|no| T7
144
144
  VCH --> T7["tool:before hook\n(ctx.coercions when present, runToolCounts)"]
145
- T7 --> T8["toolDef.execute(coercedInput, ctx)"]
145
+ T7 --> T8["toolDef.execute(coercedInput, ctx)\nracing against perCallAbort.signal"]
146
+ T8 -->|cancelled by\nagent.cancelTool| TC["tool:cancelled hook\n(reason, runToolCounts)"]
147
+ TC --> TCR["Return TOOL_USE_CANCELLED_MESSAGE\n(isError: true; skips tool:transform/after)"]
146
148
  T8 -->|error| T9["tool:error hook\n(can substitute result)"]
147
149
  T8 -->|ok| T10["tool:transform hook\n(can mutate result;\nctx.outputBytes pre-mutation)"]
148
150
  T9 --> T10
@@ -158,6 +160,8 @@ flowchart TB
158
160
 
159
161
  **`tool:gate` mutations.** Set `block` to refuse (`Blocked: reason`), `result` to substitute and skip execute, or neither to run normally. `block` wins over `result` so a policy gate always beats a consumer cache. The substitute path skips `tool:before` + validate + execute but fires `tool:transform` + `tool:after` — budgets and telemetry stay consistent with executed calls.
160
162
 
163
+ **Per-call cancellation.** Each dispatch registers an `AbortController` in `LoopContext.pendingToolCancels` keyed by `callId`; the tool body's `ctx.signal` is `AbortSignal.any([ctx.signal, perCallAbort.signal])`. `agent.cancelTool(callId, reason?)` flips the per-call signal, the body promise races against the cancellation, the loop emits `tool:cancelled`, and the wire result becomes `TOOL_USE_CANCELLED_MESSAGE` with `isError: true`. Other in-flight tools in the same batch keep running — distinct from `agent.abort()` (whole-run abort → `INTERRUPT_MESSAGE_FOR_TOOL_USE` at the batch layer) and `TOOL_USE_SKIPPED_MESSAGE` (steered out before dispatch). The map entry is removed in a `finally` so it only ever holds currently-dispatching calls; the body promise gets a no-op `.catch` so misbehaving tools that ignore the signal can't surface as unhandled rejections after the loop has moved on.
164
+
161
165
  **`runToolCounts`** is a frozen pre-call snapshot, scoped to `runId`. Includes dedup + gate-`result` substitutes; excludes blocked calls. Resumed sessions reset the counter. Concurrent fleets see the same pre-batch snapshot — built-in budget/dedup middleware uses its own gate-time reservation counter so `behavior.toolBudgets` stays atomic across the fleet.
162
166
 
163
167
  **Output shape.** `string | ToolResultContent[]`. Text tools return strings; multimodal tools (MCP browsers, screenshots) return `[{ type: 'text' }, { type: 'image', mediaType, data }]`. Providers with `capabilities.imageInToolResult: true` (Anthropic, OpenAI Codex) route arrays natively; OpenAI-compat emits a companion `user` message with `image_url` parts. Non-vision providers swap image blocks for a text marker before the hook fires.
@@ -359,15 +363,22 @@ per run():
359
363
  skills_use({ name }) → state.activate(skill, 'model')
360
364
  → skills:activate (via: 'model')
361
365
  → <skill_content> wrapper
366
+ skills_use({ name, mode: 'deactivate' }) → state.deactivate(skill)
367
+ → skills:deactivate (reason: 'model')
368
+ → "Skill X deactivated" confirmation
362
369
  skills_read / skills_run_script → gated on state.isActive + path sandbox
363
370
  run end: deactivateAllSkills() → skills:deactivate (reason: 'run-end')
364
371
 
365
372
  agent.activateSkill(name) → skills:activate (via: 'explicit')
366
373
  agent.deactivateSkill(name) → skills:deactivate (reason: 'explicit')
367
374
  agent.reset() → skills:deactivate (reason: 'reset')
375
+
376
+ session-resume rehydration:
377
+ last-mode-wins per skill across history's skills_use blocks
378
+ → trailing mode:'deactivate' STAYS deactivated; activate/deactivate/activate ends active
368
379
  ```
369
380
 
370
- **allowed-tools.** When any active skill declares `allowed-tools`, a `tool:gate` handler blocks calls outside the union (the three skills tools are always implicitly allowed).
381
+ **allowed-tools.** When any active skill declares `allowed-tools`, a `tool:gate` handler blocks calls outside the union (the three skills tools are always implicitly allowed). Block-list (`- entry`) and flow-list (`[a, b]`) authoring shapes both normalize to `string[]` via the frontmatter parser's array-aware path; `AgentToolNotAllowedError.message` carries a recovery hint pointing the model at `skills_use({ mode: 'deactivate', name })` to release the offending skill without waiting for a run boundary.
371
382
 
372
383
  **Body-only delivery.** `skills_use` returns the body (frontmatter stripped) wrapped in `<skill_content>` for host-SDK context protection. Body includes shell-interpolated instructions (`` !`cmd` ``, fresh per activation), the skill directory, the resource listing (not eagerly loaded), and compatibility + allowed-tools when present.
373
384
 
@@ -420,7 +431,7 @@ run end: uninstallLazyDisclosureGate; unlocked GC-eligible on next run()
420
431
  skills:resolve ← once per agent, after discovery (warmup / run / activateSkill — first wins)
421
432
  skills:catalog [mutable: catalog] ← once per agent, after system-prompt catalog built (same trigger)
422
433
  skills:activate ← per activation; { skill, via: 'model' | 'explicit' | 'resume' }
423
- skills:deactivate ← per deactivation; { skill, reason: 'run-end' | 'explicit' | 'reset' }
434
+ skills:deactivate ← per deactivation; { skill, reason: 'run-end' | 'explicit' | 'reset' | 'model' }
424
435
  ```
425
436
 
426
437
  Every run ends with an implicit deactivate-all pass (`reason: 'run-end'`); activation state never leaks across runs unless re-asserted via `agent.activateSkill()`.
@@ -453,6 +464,7 @@ turn:after ← always fires (incl. errors)
453
464
  tool:transform [mutable: result, isError] ← + outputBytes pre-mutation
454
465
  tool:after ← + outputBytes post-mutation
455
466
  tool:error [mutable: result?] ← on execute throw; ctx.result substitutes
467
+ tool:cancelled ← agent.cancelTool(callId); skips transform/after; wire = TOOL_USE_CANCELLED_MESSAGE
456
468
  tool-results:after ← after the tool-results user turn is pushed (persistence seam)
457
469
  usage ← running totals
458
470
  output ← when behavior.schema set
@@ -509,6 +521,7 @@ The child's lifecycle also bubbles to the parent hook surface with `childId` + `
509
521
  ```
510
522
  child:stream:text / child:stream:thinking / child:stream:end / child:stream:error
511
523
  child:tool:gate / child:mcp:tool:gate ← share the child's ctx — parent mutations propagate
524
+ child:tool:cancelled ← bubbled per-call cancel from a subagent's tool
512
525
  child:tool:transform ← share the child's ctx — parent mutations propagate
513
526
  child:tool:before / child:tool:after / child:tool:error
514
527
  child:turn:after
package/docs/CHAT.md CHANGED
@@ -419,7 +419,7 @@ type ChipColorMap = { default: ChipColor } & Partial<Record<string, ChipColor>>
419
419
 
420
420
  Per-tool approval gate with a per-project safelist. The agent emits a `tool:gate` hook; the chat layer's wired handler:
421
421
 
422
- 1. If `IMPLICITLY_SAFE_TOOLS` covers the call → allow.
422
+ 1. If `IMPLICITLY_SAFE_TOOLS` covers the call → allow. The list is `['read_file', 'list_files', 'glob', 'grep', 'ask_user', 'present_plan', 'todowrite', 'todoread', 'skills_use']` — pure reads, interaction prompts (the picker IS the gate), todo metadata, and skill activation (mutates a per-agent Map; no shell/disk/network — gating it would also break the model's recovery path when it deactivates a skill after an `AgentToolNotAllowedError`). `skills_read` (touches disk) and `skills_run_script` (executes scripts) are intentionally NOT on the list.
423
423
  2. If the project safelist (`~/.zidane/projects.json`) matches → allow.
424
424
  3. Else push an `ApprovalRequest` onto `SafeModeProvider`'s queue and await.
425
425
 
package/docs/SKILL.md CHANGED
@@ -298,7 +298,7 @@ Hooks fire at every lifecycle point via [hookable](https://github.com/unjs/hooka
298
298
  | `skills:resolve` | Once per agent, after discovery (lazy on first `warmup()` / `run()` / `activateSkill()`, eager when `eager: true`) | — | `skills` |
299
299
  | `skills:catalog` | Once per agent, after catalog build (same timing as `skills:resolve`) | **yes** (`catalog`) | `catalog, skills` |
300
300
  | `skills:activate` | Skill activated (via `skills_use` / `activateSkill` / session resume) | — | `skill, via` (`'model' \| 'explicit' \| 'resume'`) |
301
- | `skills:deactivate` | Skill deactivated | — | `skill, reason` (`'run-end' \| 'explicit' \| 'reset'`) |
301
+ | `skills:deactivate` | Skill deactivated | — | `skill, reason` (`'run-end' \| 'explicit' \| 'reset' \| 'model'`) — `'model'` fires when the model calls `skills_use({ mode: 'deactivate' })` to release an `allowed-tools` restriction it ran into |
302
302
  | `mcp:bootstrap:start` | Per MCP server, before connect + listTools | — | `name, transport` |
303
303
  | `mcp:bootstrap:end` | Per MCP server, after connect attempt (always fires) | — | `name, transport, durationMs, ok` + (`toolCount, lazy?, cached?` \| `error`) |
304
304
  | `mcp:connect` | Per MCP server after successful bootstrap (lazy-connect: after first call) | — | `name, transport, tools, lazy?` |
@@ -329,6 +329,7 @@ Hooks fire at every lifecycle point via [hookable](https://github.com/unjs/hooka
329
329
  | `tool:transform` | After tool result | **yes** (`result`, `isError`) | `+ result: string \| ToolResultContent[], isError, outputBytes: number` |
330
330
  | `tool:after` | Tool complete | — | `+ result: string \| ToolResultContent[], outputBytes: number, runToolCounts` |
331
331
  | `tool:error` | Tool error | **yes** (`result?`) | `+ error` — mutate `result` to substitute the payload sent back to the model |
332
+ | `tool:cancelled` | Per-call cancel via `agent.cancelTool(callId, reason?)` (typically a TUI "cancel this tool" affordance) | — | `+ reason: string, runToolCounts` — wire result is the canonical `TOOL_USE_CANCELLED_MESSAGE` with `isError: true`; `tool:transform` + `tool:after` do **not** fire for the cancelled call |
332
333
  | `usage` | Per-turn usage | — | `turn, turnId, usage, totalIn, totalOut` |
333
334
  | `output` | Structured output extracted | — | `output, schema` |
334
335
  | `budget:exceeded` | Per-turn tool-output bytes over `behavior.toolOutputBudget` | — | `turn, turnId, bytes, budget` |
@@ -366,7 +367,7 @@ Same three fields land on `ToolContext` (visible to the tool body via `ctx.runId
366
367
  child:stream:text / child:stream:thinking / child:stream:end
367
368
  child:tool:gate / child:mcp:tool:gate ← mutable: block/reason/result propagate to the child
368
369
  child:tool:transform ← mutable: parent can rewrite the child's tool_result
369
- child:tool:before / child:tool:after / child:tool:error
370
+ child:tool:before / child:tool:after / child:tool:error / child:tool:cancelled
370
371
  child:turn:after
371
372
  ```
372
373
 
@@ -408,17 +409,20 @@ agent.hooks.hook('context:transform', (ctx) => {
408
409
  ## Agent State and Control
409
410
 
410
411
  ```ts
411
- agent.isRunning // boolean
412
- agent.turns // SessionTurn[]
413
- agent.steer('new focus') // mid-run, between tool calls
414
- agent.followUp('next') // queue after current run
415
- agent.abort() // cancel
416
- agent.reset() // clear turns + queues
417
- await agent.warmup() // pre-connect MCP (idempotent)
412
+ agent.isRunning // boolean
413
+ agent.turns // SessionTurn[]
414
+ agent.steer('new focus') // mid-run, between tool calls
415
+ agent.followUp('next') // queue after current run
416
+ agent.abort() // cancel the whole run
417
+ agent.cancelTool(callId) // cancel a single in-flight tool; siblings keep running
418
+ agent.reset() // clear turns + queues
419
+ await agent.warmup() // pre-connect MCP (idempotent)
418
420
  await agent.waitForIdle()
419
- await agent.destroy() // clean up execution + MCP
421
+ await agent.destroy() // clean up execution + MCP
420
422
  ```
421
423
 
424
+ `cancelTool` returns `true` when a live call was flipped, `false` otherwise (idempotent). The matching call's `ctx.signal` aborts, `tool:cancelled` fires, and the wire result becomes `TOOL_USE_CANCELLED_MESSAGE` with `isError: true` — other parallel calls in the same batch keep running, and the assistant turn closes normally on the next batch boundary. Distinguished from `abort()` (whole-run abort, batch-layer `INTERRUPT_MESSAGE_FOR_TOOL_USE`) and `TOOL_USE_SKIPPED_MESSAGE` (steered out) so consumers can split the three causes by string match.
425
+
422
426
  ## Sessions
423
427
 
424
428
  ```ts
@@ -614,7 +618,7 @@ When the catalog is non-empty and `tool !== false`, three tools auto-inject:
614
618
 
615
619
  | Tool | Purpose |
616
620
  |---|---|
617
- | `skills_use` | Activate a skill by name. Idempotent. Wraps body + resources in `<skill_content spec_version="0.1">`. |
621
+ | `skills_use` | Activate or deactivate a skill by name. `mode: 'activate'` (default, spec-mandated) loads the skill body and wraps it in `<skill_content spec_version="0.1">`; `mode: 'deactivate'` (zidane extension) releases an active skill so its `allowed-tools` restrictions stop applying — fires `skills:deactivate` with `reason: 'model'`. Idempotent in both directions. |
618
622
  | `skills_read` | Read a bundled resource (`references/`, `assets/`) of an active skill. |
619
623
  | `skills_run_script` | Run `scripts/*.sh` / `*.py` with args. Returns `{ exitCode, stdout, stderr }`. |
620
624
 
@@ -632,15 +636,21 @@ await agent.deactivateSkill('pdf-processing') // skills:deactivate, reason: 'exp
632
636
 
633
637
  ### Enforcement + resume
634
638
 
635
- When any active skill declares `allowed-tools`, a `tool:gate` middleware blocks calls outside the union (the three skills tools are always implicitly allowed). Matching uses `displayName`, supports exact names (`Read`) and patterns (`Bash(git:*)`). Blocked calls throw `AgentToolNotAllowedError`.
639
+ When any active skill declares `allowed-tools`, a `tool:gate` middleware blocks calls outside the union (the three skills tools are always implicitly allowed). Matching uses `displayName`, supports exact names (`Read`) and patterns (`Bash(git:*)`). Blocked calls throw `AgentToolNotAllowedError`, whose `.message` ends with a recovery hint pointing the model at `skills_use({ mode: 'deactivate', name })` — without this the model tends to invent folk theories about "sticky restrictions" instead of releasing the skill itself.
640
+
641
+ `allowed-tools` accepts three authoring shapes (all normalize to `string[]`): spec-canonical space-separated string (`allowed-tools: Read Bash(git:*)`), YAML block list (`- Read` lines), and YAML flow list (`[Read, Bash(git:*)]`). Earlier zidane builds only handled the first; the others silently mangled the union and opened the gate. The lenient parser is in `src/skills/discovery.ts` — malformed shapes drop the field with a diagnostic instead of coercing to garbage.
642
+
643
+ The parser also tolerates **`allowedTools`** (camelCase) and **`allowed_tools`** (snake_case) as alt-spellings of the canonical `allowed-tools` key — the value is migrated to the canonical slot and a `frontmatter-key-alt-spelling` diagnostic is attached. This is a courtesy for authors used to JS / Python idioms; the spec mandates kebab-case and the diagnostic is the nudge to rename. The canonical key wins when both are present.
644
+
645
+ On session resume, `skills_use` calls in the turn history rebuild the active set with **last-mode-wins per skill**: a trailing `mode: 'deactivate'` block correctly STAYS inactive on the next run (without this, the rehydrator would silently re-activate skills the model just released, defeating the recovery path). Activations fire with `via: 'resume'`; `skills:deactivate` does NOT fire during rehydration — the state started empty so there's nothing to deactivate.
636
646
 
637
- On session resume, prior `skills_use` calls in the turn history are re-activated with `via: 'resume'` so `skills_read` / `skills_run_script` keep working.
647
+ Programmatic host-side activations (`agent.activateSkill(name)`) do NOT produce a `skills_use` block in history, so they don't survive the run-end deactivate-all pass automatically. Hosts that want persistence across runs (TUI slash-commands, for example) must re-activate before each `agent.run()`; the TUI does this via a pinned-skills set persisted in `session.metadata['zidane.activeSkills']` see `docs/TUI.md`.
638
648
 
639
649
  ### Lenient load, strict authoring
640
650
 
641
651
  Third-party skills with minor deviations load anyway via `parseSkillFile` (warnings in `SkillConfig.diagnostics`). `defineSkill` / `writeSkillToDisk` run `validateSkillForWrite` — spec-strict.
642
652
 
643
- Hooks: `skills:resolve` (`{ skills }`), `skills:catalog` (`{ catalog, skills }`), `skills:activate` (`{ skill, via: 'model'|'explicit'|'resume' }`), `skills:deactivate` (`{ skill, reason: 'run-end'|'explicit'|'reset' }`).
653
+ Hooks: `skills:resolve` (`{ skills }`), `skills:catalog` (`{ catalog, skills }`), `skills:activate` (`{ skill, via: 'model'|'explicit'|'resume' }`), `skills:deactivate` (`{ skill, reason: 'run-end'|'explicit'|'reset'|'model' }`).
644
654
 
645
655
  ## Structured Output
646
656
 
package/docs/TUI.md CHANGED
@@ -194,6 +194,7 @@ Every customizable shortcut routes through `<userDir>/keybindings.json` and is p
194
194
  | `ctrl+l` | `openEffortPicker` | chat (idle, model has reasoning) | open reasoning-effort picker |
195
195
  | `ctrl+s` | `enterSelectTurnMode` | chat (idle) | enter select-turn mode (transcript navigation) |
196
196
  | `ctrl+t` | `openTodos` | chat (session attached) | open the active run's `todowrite` checkpoints (read-only) |
197
+ | `ctrl+k` | `cancelToolCall` | chat (busy, ≥1 in-flight call) | open the cancel-tool picker — pick one call to flip via `agent.cancelTool(callId)`, or press `a` to cancel every in-flight call. Distinct from `esc abort` (whole-run abort); siblings keep running |
197
198
  | `shift+tab` | `cycleAgent` | chat (idle, ≥2 profiles) | cycle to next agent profile |
198
199
  | `ctrl+↵` | `pushQueuedMessage` | queue-selection mode | push selected queued message into the live run |
199
200
  | `backspace` | `dropQueuedMessage` | queue-selection mode | drop selected queued message |
@@ -306,6 +307,29 @@ File-edit tools (`edit` / `multi_edit` / `write_file`) get their own approval su
306
307
 
307
308
  `isFileEditTool(tool)` (exported from `file-edit-approval-modal.tsx`) is the gate routing predicate. The set is `{'edit', 'multi_edit', 'write_file'}`; everything else stays on the inline `ApprovalBlock` path. For a fully-denied file-edit call, `applyGate` skips the substitute path entirely — sets `ctx.block = true` + emits a synthetic `tool-result` event with body `[fully denied] <edit-outcomes>…</edit-outcomes>` for live display. The persisted result stays the terse `Blocked: User denied this tool call` the harness writes.
308
309
 
310
+ ### Tool-call cancellation
311
+
312
+ `CancelToolModal` (`src/tui/cancel-tool-modal.tsx`) surfaces the in-flight tool registry maintained by `App.tsx` and routes the user's pick to `agent.cancelTool(callId)`. The shortcut is `ctrl+k` (`cancelToolCall`), gated on `busy && !pendingApproval && inFlightTools.length > 0` so it never opens on a dead-empty state.
313
+
314
+ In-flight tracking is hook-driven: `App.tsx` listens on `tool:before` / `child:tool:before` to add an entry, drains on `tool:after` / `tool:error` / `tool:cancelled` (mirrored for `child:*`). The Map is keyed by `callId` and the modal opens with a snapshot of the live set — auto-dismisses 500 ms after the list empties so the user isn't left staring at "nothing in flight".
315
+
316
+ Modal row layout: `›` cursor glyph, tool name, truncated `callId`, optional `· child-N` attribution for subagent-issued calls, right-aligned elapsed time (`0.3s` / `2m12s` format). Keys: `↑` / `↓` navigate, `↵` cancels the focused row, `a` cancels every call in the snapshot, `esc` dismisses.
317
+
318
+ Distinct from the run-wide `esc abort`: the cancelled call's wire result is the canonical `TOOL_USE_CANCELLED_MESSAGE` with `isError: true`, the assistant turn closes normally on the next batch boundary, and other in-flight tools keep running. The session teardown path also clears `inFlightTools` so a switched session doesn't try to cancel calls on an agent that no longer owns them.
319
+
320
+ ### Active skills — footer chip + pinned-skills persistence
321
+
322
+ When at least one skill is active, the footer hint row gets a passive `✦ N skill(s)` chip (`COLOR.brand` accent). The chip is purely informational — no shortcut wired — but it gives the user a passive surface for "tool restrictions are in effect" without having to scroll back through the transcript looking for a `skills_use` call. Driven by `activeSkillNames: ReadonlySet<string>` in `App.tsx`, fed by the agent's `skills:activate` / `skills:deactivate` hooks.
323
+
324
+ Slash-command activations (`/skill-name`) call `agent.activateSkill()` programmatically, BEFORE `agent.run()`. The framework deactivates every active skill at run-end (`reason: 'run-end'`) and the session-resume rehydrator only scans for `skills_use` `tool_call` blocks — so a slash activation would silently lose its `allowed-tools` enforcement on the next prompt. The TUI fixes this with a **pinned-skills set persisted to session metadata** under `zidane.activeSkills`:
325
+
326
+ - The `skills:deactivate` listener filters by reason — `'run-end'` keeps the entry, `'model'` / `'explicit'` / `'reset'` drain it. So a user-driven `/skill-name` stays pinned across the framework's per-run cleanup; a model-driven `skills_use({ mode: 'deactivate' })` correctly releases the pin.
327
+ - `onSubmitPrompt` activates the union of the current prompt's `/skill` refs AND every name in the pinned set before `agent.run()`. So a `/read-only` typed once stays in force across every subsequent message in the session.
328
+ - `activateSession` seeds the React state from `session.metadata['zidane.activeSkills']` on session open — so the pin survives a TUI restart. `readPinnedSkills` is tolerant (older sessions, hand-edited metadata degrade to "no pins" rather than throwing).
329
+ - `persistPinnedSkills` mirrors every state change back into metadata via `session.setMeta(...)`, sorted for stable on-disk ordering.
330
+
331
+ The teardown path also clears the in-memory pinned set on session swap (`setActiveSkillNames(new Set())`) so the next session starts from its own persisted state, not the previous one's residue.
332
+
309
333
  ### Todos surface — indicator + modal
310
334
 
311
335
  Two thin chrome layers on top of the renderer-agnostic `useActiveTodos` hook (see [Todos in CHAT.md](./CHAT.md#todos) for the data contract — the keying rule, the auto-clear behavior, and the legacy-bag migration). Both surfaces share `TODO_STATUS_GLYPHS` so a row in the modal and the inline indicator read as the same visual language.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zidane",
3
- "version": "5.4.2",
3
+ "version": "5.4.3",
4
4
  "description": "an agent that goes straight to the goal",
5
5
  "type": "module",
6
6
  "private": false,
@@ -100,8 +100,8 @@
100
100
  "peerDependencies": {
101
101
  "@anthropic-ai/sdk": "^0.90.0",
102
102
  "@modelcontextprotocol/sdk": ">=1.11.0",
103
- "@opentui/core": "^0.2.6",
104
- "@opentui/react": "^0.2.6",
103
+ "@opentui/core": "^0.2.15",
104
+ "@opentui/react": "^0.2.15",
105
105
  "dockerode": "^4.0.0",
106
106
  "react": "^19.0.0",
107
107
  "zod": ">=4.0.0"
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-B2VOOijU.d.ts","names":[],"sources":["../src/compact/messages.ts","../src/compact/prompt.ts","../src/compact/errors.ts","../src/compact/compact.ts","../src/compact/restore.ts","../src/compact/utils.ts","../src/logger.ts","../src/loop.ts","../src/loop-persistence.ts","../src/mcp/oauth-provider.ts","../src/mcp/login.ts","../src/mcp/oauth-callback.ts","../src/metrics.ts","../src/run-summary.ts","../src/stats.ts","../src/tools/edit.ts","../src/tools/glob.ts","../src/tools/grep.ts","../src/tools/interaction.ts","../src/tools/list-files.ts","../src/tools/multi-edit.ts","../src/tools/read-file.ts","../src/tools/shell.ts","../src/tools/skills-read.ts","../src/tools/skills-run-script.ts","../src/tools/skills-use.ts","../src/tools/spawn.ts","../src/tools/tool-search.ts","../src/tools/validation.ts","../src/tools/write-file.ts","../src/tracing.ts","../src/zod.ts","../src/presets/basic.ts","../src/presets/index.ts"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-BOtXdQkW.d.ts","names":[],"sources":["../src/skills/allowed-tools.ts","../src/skills/catalog.ts","../src/skills/discovery.ts","../src/skills/interpolate.ts","../src/skills/resolve.ts","../src/skills/validate.ts","../src/skills/writer.ts","../src/skills/index.ts"],"mappings":";;;;;;cAuBa,8BAAA;;;;;;;;;;ACHb;iBDmBgB,uBAAA,CACd,KAAA,EAAO,QAAA,CAAS,UAAA,GAChB,KAAA,EAAO,oBAAA;;;UCrBQ,mBAAA;EDoBR;;;;;ECdP,oBAAA;EDe2B;;;;ECV3B,YAAA;AAAA;;;;iBAMc,YAAA,CACd,MAAA,EAAQ,WAAA,IACR,OAAA,GAAS,mBAAA;;;UCCD,eAAA;EACR,WAAA,EAAa,MAAA;EACb,IAAA;EACA,WAAA,EAAa,eAAA;AAAA;;;;;;;;;;;iBAaC,gBAAA,CAAiB,OAAA,WAAkB,eAAA;AAAA,UA0MzC,iBAAA;ED9O0B;ECgPlC,MAAA,GAAS,WAAA;AAAA;;AD/NX;;;;;;;;;;iBC6OsB,cAAA,CACpB,QAAA,UACA,OAAA,GAAS,iBAAA,GACR,OAAA,CAAQ,WAAA;;UA0MM,eAAA;EACf,IAAA;EACA,MAAA,EAAQ,WAAA;AAAA;;;;;;iBAQM,mBAAA,CAAA,GAAuB,eAAA;;;AAjbvC;;iBAkcgB,WAAA,CAAY,IAAA,WAAe,WAAA;;;AArY1C;;;;;AA6JD;;;iBA0PsB,cAAA,CACpB,KAAA,EAAO,eAAA,IACP,MAAA,GAAS,WAAA,GACR,OAAA,CAAQ,WAAA;;;;;;;;;;;;;;;iBCjfW,wBAAA,CACpB,YAAA,UACA,SAAA,EAAW,gBAAA,EACX,MAAA,EAAQ,eAAA,GACP,OAAA;;;AHXH;;;;;AAgBA;;;;AAhBA,UIGiB,oBAAA;EACf,MAAA,EAAQ,WAAA;EACR,OAAA;AAAA;;;;;;;;;;;AHRF;;;iBGwBsB,aAAA,CAAc,MAAA,EAAQ,YAAA,GAAe,OAAA,CAAQ,oBAAA;;;;;;AJLnE;;UKCiB,oBAAA;ELAC;EKEhB,IAAA;ELDO;EKGP,OAAA;ELH2B;EKK3B,KAAA;AAAA;AAAA,UAGe,qBAAA;EACf,KAAA;EACA,MAAA,EAAQ,oBAAA;AAAA;;;;;AJ/BV;;;;;AAiBA;iBI+BgB,iBAAA,CAAkB,IAAA;;;;;;iBAmBlB,qBAAA,CAAsB,KAAA,EAAO,WAAA,GAAc,qBAAA;;;;;;AH3E4B;;;;;;iBGiLvE,oBAAA,CACd,OAAA,UACA,OAAA;EACG,KAAA;EAAa,YAAA;AAAA;EAA2B,KAAA;EAAc,KAAA;AAAA;;;;AH3E1D;;;;iBG0He,uBAAA,CAAwB,KAAA;EAAkB,IAAA;EAAc,SAAA;AAAA;;;;;;;;;;;;;AHgPxE;;iBGnNgB,kBAAA,CACd,WAAA,UACA,KAAA,EAAO,MAAA,mBACP,OAAA;;;;;;iBAyBc,oBAAA,CACd,WAAA,UACA,KAAA,EAAO,MAAA,mBACP,KAAA;;;;;;ALpQF;;;;;iBM8BgB,gBAAA,CAAiB,KAAA,EAAO,WAAA,EAAa,SAAA;;;;;;iBAoCrC,iBAAA,CAAkB,MAAA,EAAQ,WAAA,IAAe,SAAA;;;;;;;;;iBCnDzC,WAAA,CAAY,MAAA,EAAQ,IAAA,CAAK,WAAA;EAA2B,MAAA,GAAS,WAAA;AAAA,IAA0B,WAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"interpolate-ERgZUxgg.js","names":[],"sources":["../src/skills/activation.ts","../src/skills/validate.ts","../src/skills/allowed-tools.ts","../src/xml.ts","../src/skills/catalog.ts","../src/skills/discovery.ts","../src/skills/writer.ts","../src/skills/resolve.ts","../src/skills/interpolate.ts"],"sourcesContent":["/**\n * Per-agent skill activation state machine.\n *\n * Tracks which skills are active across a run. The three skills tools\n * (`skills_use` / `skills_read` / `skills_run_script`) read from this state\n * for gating + listing. Allowed-tools enforcement reads from it too.\n *\n * Lifecycle:\n * - Storage lives on the agent instance (created once in `createAgent`), but\n * every `run()` ends with an implicit deactivate-all pass (reason `'run-end'`)\n * so activation does **not** persist across run boundaries. To keep a skill\n * active across successive runs, call `agent.activateSkill(name)` before each\n * run — the explicit-activation path is idempotent.\n * - `agent.reset()` clears the state with reason `'reset'`.\n * - On session-resume, carried-forward `skills_use` tool_call blocks (in prior\n * assistant turns) are replayed at run-start to rehydrate state with\n * `via: 'resume'`.\n *\n * The caps (`maxActive` from SkillsConfig) is enforced here — returning `false`\n * from `activate()` when the cap is hit lets the caller surface an actionable\n * \"max skills active\" error to the model.\n */\n\nimport type { SkillConfig } from './types'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** How a skill was activated. Surfaced in `skills:activate` hook ctx. */\nexport type ActivationVia = 'model' | 'explicit' | 'resume'\n\n/** Reason a skill was deactivated. Surfaced in `skills:deactivate` hook ctx. */\nexport type DeactivationReason = 'run-end' | 'explicit' | 'reset'\n\n/** A skill currently active in the state machine. */\nexport interface ActiveSkill {\n skill: SkillConfig\n activatedAt: number\n activatedVia: ActivationVia\n}\n\n/**\n * Per-agent skill activation state. Public read-surface is the `active()` list\n * and `isActive(name)` predicate; writes go through `activate()` / `deactivate()`.\n */\nexport interface SkillActivationState {\n /** List of currently active skills in activation order. Returns a snapshot. */\n active: () => readonly ActiveSkill[]\n /** Is the skill with this canonical name currently active? */\n isActive: (name: string) => boolean\n /** Retrieve the `ActiveSkill` record by name, or `undefined`. */\n get: (name: string) => ActiveSkill | undefined\n /**\n * Mark a skill as active.\n * - Returns `'ok'` on a fresh activation (caller should fire `skills:activate`).\n * - Returns `'already-active'` if the skill was already in the set (idempotent).\n * - Returns `'cap-reached'` if the `maxActive` cap would be exceeded. State is unchanged.\n */\n activate: (skill: SkillConfig, via: ActivationVia) => 'ok' | 'already-active' | 'cap-reached'\n /**\n * Mark a skill as inactive. Returns the removed `ActiveSkill` record or `undefined`\n * if it wasn't active. Callers fire `skills:deactivate` on removal.\n */\n deactivate: (name: string) => ActiveSkill | undefined\n /** Remove every active skill. Returns the list of removed records. */\n clear: () => readonly ActiveSkill[]\n}\n\nexport interface SkillActivationStateOptions {\n /**\n * Cap on concurrent activations. `undefined` (the default) disables the cap.\n * When set, `activate()` returns `'cap-reached'` once the set is at size `maxActive`.\n */\n maxActive?: number\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\nexport function createSkillActivationState(\n options: SkillActivationStateOptions = {},\n): SkillActivationState {\n const byName = new Map<string, ActiveSkill>()\n const maxActive = typeof options.maxActive === 'number' && options.maxActive > 0\n ? options.maxActive\n : undefined\n\n return {\n active() {\n return [...byName.values()]\n },\n\n isActive(name) {\n return byName.has(name)\n },\n\n get(name) {\n return byName.get(name)\n },\n\n activate(skill, via) {\n if (byName.has(skill.name))\n return 'already-active'\n if (maxActive !== undefined && byName.size >= maxActive)\n return 'cap-reached'\n byName.set(skill.name, {\n skill,\n activatedAt: Date.now(),\n activatedVia: via,\n })\n return 'ok'\n },\n\n deactivate(name) {\n const existing = byName.get(name)\n if (!existing)\n return undefined\n byName.delete(name)\n return existing\n },\n\n clear() {\n const snapshot = [...byName.values()]\n byName.clear()\n return snapshot\n },\n }\n}\n","/**\n * Strict validators for Agent Skills.\n *\n * Applied on the authoring path (`defineSkill`, `writeSkillToDisk`). Parser-time\n * validation is intentionally lenient — see `parseSkillFile` for diagnostic collection.\n */\n\nimport type { SkillConfig } from './types'\nimport { basename } from 'node:path'\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst NAME_MAX = 64\nconst DESCRIPTION_MAX = 1024\nconst COMPATIBILITY_MAX = 500\n\nconst SKILL_NAME_RE = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/\nconst CONSECUTIVE_HYPHENS_RE = /--/\n\n// Accepts both Claude-Code-style PascalCase (`Bash`, `Read`) AND snake_case\n// (`skills_use`, `read_file`, `mcp_fs_read`) tool names. Spec leaves the\n// naming convention to the client.\nconst ALLOWED_TOOL_PATTERN_RE = /^([\\w-]+)(?:\\(([^)]*)\\))?$/\n\n// Path-sandbox regexes (hoisted to avoid per-call recompilation).\nconst ABS_WINDOWS_PATH_RE = /^[a-z]:[\\\\/]/i\nconst PATH_SEPARATOR_RE = /[\\\\/]/\nconst TRAILING_SLASHES_RE = /\\/+$/\n\n// ---------------------------------------------------------------------------\n// Validation result\n// ---------------------------------------------------------------------------\n\n/**\n * A single issue surfaced by skill-authoring validation.\n * Distinct from `ValidationResult` in `tools/validation.ts` (tool-input JSON\n * schema validation) — different domain, different module.\n */\nexport interface SkillValidationIssue {\n /** Stable machine-readable code for consumer matching. */\n code: string\n /** Human-readable description. */\n message: string\n /** Frontmatter field name the issue relates to, when applicable. */\n field?: string\n}\n\nexport interface SkillValidationResult {\n valid: boolean\n errors: SkillValidationIssue[]\n}\n\n// ---------------------------------------------------------------------------\n// Name validation (strict — spec rules)\n// ---------------------------------------------------------------------------\n\n/**\n * Validate a skill name per the spec:\n * - 1–64 characters\n * - Lowercase alphanumeric + hyphens only\n * - Must not start or end with a hyphen\n * - Must not contain consecutive hyphens\n *\n * The parent-directory match is validated separately (it requires knowing the\n * skill's `location`, which this function does not).\n */\nexport function validateSkillName(name: string): boolean {\n if (typeof name !== 'string')\n return false\n if (name.length < 1 || name.length > NAME_MAX)\n return false\n if (CONSECUTIVE_HYPHENS_RE.test(name))\n return false\n return SKILL_NAME_RE.test(name)\n}\n\n// ---------------------------------------------------------------------------\n// Authoring-time validation (`defineSkill`, `writeSkillToDisk`)\n// ---------------------------------------------------------------------------\n\n/**\n * Strict validation for a skill that is about to be authored / written to disk.\n * Rejects anything that would violate the spec. Use the lenient parser path\n * (`parseSkillFile`) for loading third-party skills.\n */\nexport function validateSkillForWrite(skill: SkillConfig): SkillValidationResult {\n const errors: SkillValidationIssue[] = []\n\n // Name\n if (!validateSkillName(skill.name)) {\n errors.push({\n code: 'invalid-name',\n message: `Skill name \"${skill.name}\" must be 1-64 chars, lowercase alphanumeric + hyphens, no leading/trailing/consecutive hyphens.`,\n field: 'name',\n })\n }\n\n // Name must match parent directory when location is present\n if (skill.location) {\n const dirName = basename(skill.baseDir ?? '')\n if (dirName && dirName !== skill.name) {\n errors.push({\n code: 'name-mismatch-directory',\n message: `Skill name \"${skill.name}\" must match parent directory name \"${dirName}\".`,\n field: 'name',\n })\n }\n }\n\n // Description\n if (typeof skill.description !== 'string' || skill.description.length < 1) {\n errors.push({\n code: 'missing-description',\n message: 'Skill description is required (non-empty).',\n field: 'description',\n })\n }\n else if (skill.description.length > DESCRIPTION_MAX) {\n errors.push({\n code: 'description-too-long',\n message: `Skill description must be at most ${DESCRIPTION_MAX} characters (got ${skill.description.length}).`,\n field: 'description',\n })\n }\n\n // Compatibility (optional)\n if (skill.compatibility !== undefined) {\n if (typeof skill.compatibility !== 'string' || skill.compatibility.length === 0) {\n errors.push({\n code: 'invalid-compatibility',\n message: 'Compatibility must be a non-empty string when provided.',\n field: 'compatibility',\n })\n }\n else if (skill.compatibility.length > COMPATIBILITY_MAX) {\n errors.push({\n code: 'compatibility-too-long',\n message: `Compatibility must be at most ${COMPATIBILITY_MAX} characters (got ${skill.compatibility.length}).`,\n field: 'compatibility',\n })\n }\n }\n\n // Metadata values must be strings per spec\n if (skill.metadata) {\n for (const [key, value] of Object.entries(skill.metadata)) {\n if (typeof value !== 'string') {\n errors.push({\n code: 'invalid-metadata-value',\n message: `Metadata value for \"${key}\" must be a string (spec: \"A map from string keys to string values\").`,\n field: 'metadata',\n })\n }\n }\n }\n\n // Allowed-tools entries must be parseable patterns\n if (skill.allowedTools) {\n for (const pattern of skill.allowedTools) {\n if (!ALLOWED_TOOL_PATTERN_RE.test(pattern)) {\n errors.push({\n code: 'invalid-allowed-tool-pattern',\n message: `Allowed-tools entry \"${pattern}\" is not a recognized pattern (expected \"ToolName\" or \"ToolName(arg:*)\").`,\n field: 'allowed-tools',\n })\n }\n }\n }\n\n return { valid: errors.length === 0, errors }\n}\n\n// ---------------------------------------------------------------------------\n// Resource path sandbox\n// ---------------------------------------------------------------------------\n\n/**\n * Validate that `relPath` stays inside `baseDir` when resolved.\n *\n * Rejects:\n * - Absolute paths (`/etc/passwd`, `C:\\…`)\n * - Parent traversal (`..` segments that escape baseDir)\n * - Null-byte tricks\n *\n * Returns `{ valid: true, absolutePath }` on success or `{ valid: false, error }`\n * with a human-readable reason.\n */\nexport function validateResourcePath(\n relPath: string,\n baseDir: string,\n): { valid: true, absolutePath: string } | { valid: false, error: string } {\n if (typeof relPath !== 'string' || relPath.length === 0)\n return { valid: false, error: 'Resource path must be a non-empty string.' }\n\n if (relPath.includes('\\0'))\n return { valid: false, error: 'Resource path contains a null byte.' }\n\n // Reject absolute paths upfront — both POSIX and Windows forms.\n if (relPath.startsWith('/') || ABS_WINDOWS_PATH_RE.test(relPath))\n return { valid: false, error: `Absolute paths are not allowed (\"${relPath}\").` }\n\n // Normalize and ensure we stay under baseDir.\n const segments: string[] = []\n for (const segment of relPath.split(PATH_SEPARATOR_RE)) {\n if (segment === '' || segment === '.')\n continue\n if (segment === '..') {\n if (segments.length === 0) {\n return {\n valid: false,\n error: `Resource path \"${relPath}\" escapes the skill directory.`,\n }\n }\n segments.pop()\n continue\n }\n segments.push(segment)\n }\n\n if (segments.length === 0)\n return { valid: false, error: 'Resource path resolves to the skill root itself.' }\n\n const absolutePath = `${baseDir.replace(TRAILING_SLASHES_RE, '')}/${segments.join('/')}`\n return { valid: true, absolutePath }\n}\n\n// ---------------------------------------------------------------------------\n// Allowed-tools matching\n// ---------------------------------------------------------------------------\n\n/**\n * Parse a single `allowed-tools` entry into its tool name + optional argument pattern.\n *\n * Examples:\n * - `Read` → `{ tool: 'Read' }`\n * - `Bash(git:*)` → `{ tool: 'Bash', argPrefix: 'git' }`\n */\nexport function parseAllowedToolPattern(entry: string): { tool: string, argPrefix?: string } | null {\n const m = entry.trim().match(ALLOWED_TOOL_PATTERN_RE)\n if (!m)\n return null\n const tool = m[1]\n const arg = m[2]\n if (!arg)\n return { tool }\n\n // Accept `git:*` (prefix wildcard) and `git` (literal). Future: full glob.\n if (arg.endsWith(':*'))\n return { tool, argPrefix: arg.slice(0, -2) }\n return { tool, argPrefix: arg }\n}\n\n/**\n * Check whether a tool call (identified by its wire/displayName and argument input)\n * matches a skill's allow-list entry.\n *\n * Matching rules (Zidane's interpretation of the spec's unspecified syntax):\n * - Exact match: displayName === pattern (no parens).\n * - Prefix match: for `Tool(arg:*)`, displayName === 'Tool' AND **any** string\n * value in the input object starts with `arg`. This is intentionally\n * permissive: it doesn't depend on a convention about which property carries\n * the \"command\" (schemas vary across tools), and for the common\n * `shell({ command: 'git …' })` shape it behaves identically to a \"primary\n * string\" rule.\n * - For tools whose inputs carry no string values, the arg-match returns false.\n */\nexport function matchesAllowedTool(\n displayName: string,\n input: Record<string, unknown>,\n pattern: string,\n): boolean {\n const parsed = parseAllowedToolPattern(pattern)\n if (!parsed)\n return false\n if (parsed.tool !== displayName)\n return false\n if (parsed.argPrefix === undefined)\n return true\n\n // Match if any string input value starts with the arg prefix. More robust\n // than picking a single \"first\" value (object property order is a subtle\n // brittleness surface we avoid).\n for (const value of Object.values(input)) {\n if (typeof value === 'string' && value.startsWith(parsed.argPrefix))\n return true\n }\n return false\n}\n\n/**\n * Test whether a tool call is allowed by the union of `allowedTools` across a set\n * of active skills. Returns `true` when the union is empty (permissive default)\n * OR when any entry matches.\n */\nexport function isToolAllowedByUnion(\n displayName: string,\n input: Record<string, unknown>,\n union: readonly string[],\n): boolean {\n if (union.length === 0)\n return true\n return union.some(pattern => matchesAllowedTool(displayName, input, pattern))\n}\n","/**\n * `allowed-tools` enforcement middleware.\n *\n * Installed by the agent on `tool:gate` and `mcp:tool:gate`. Computes the\n * union of `allowedTools` patterns across currently-active skills; blocks any\n * tool call whose `displayName` is not in that union. The three injected\n * skills tools (`skills_use` / `skills_read` / `skills_run_script`) are\n * implicitly allowed so a skill declaring an allow-list cannot lock out the\n * scaffolding that lets it run at all.\n *\n * The match target is `displayName` (wire / LLM-facing name), not the\n * canonical name, because skill authors write allow-list entries to match\n * what the model sees.\n */\n\nimport type { Hookable } from 'hookable'\nimport type { AgentHooks } from '../agent'\nimport type { McpToolHookContext, ToolHookContext } from '../types'\nimport type { SkillActivationState } from './activation'\nimport { AgentToolNotAllowedError } from '../errors'\nimport { isToolAllowedByUnion } from './validate'\n\n/** Tools that are always allowed regardless of the active skills' allow-list. */\nexport const IMPLICITLY_ALLOWED_SKILL_TOOLS: readonly string[] = [\n 'skills_use',\n 'skills_read',\n 'skills_run_script',\n]\n\n/**\n * Register `tool:gate` / `mcp:tool:gate` handlers that enforce the union of\n * `allowedTools` across active skills.\n *\n * No-op when no active skill declares an allow-list (permissive default —\n * matches the spec's \"experimental\" note for `allowed-tools`).\n *\n * Returns an `uninstall` fn. The agent calls this at run end to detach the\n * handlers and prevent cross-run hook leaks.\n */\nexport function installAllowedToolsGate(\n hooks: Hookable<AgentHooks>,\n state: SkillActivationState,\n): () => void {\n function effectiveUnion(): { union: string[], active: string[] } {\n const active = state.active()\n const declared: string[] = []\n for (const record of active) {\n if (record.skill.allowedTools?.length)\n declared.push(...record.skill.allowedTools)\n }\n return {\n union: declared.length > 0 ? [...declared, ...IMPLICITLY_ALLOWED_SKILL_TOOLS] : [],\n active: active.map(a => a.skill.name),\n }\n }\n\n function gateHandler(ctx: ToolHookContext & { block: boolean, reason: string }) {\n // Honor a prior gate's refusal — keeps the gate stack order-independent.\n // Without this, a later-registered gate could silently overwrite an\n // earlier refusal's reason on the same call.\n if (ctx.block)\n return\n const { union, active } = effectiveUnion()\n if (union.length === 0)\n return\n if (isToolAllowedByUnion(ctx.displayName, ctx.input, union))\n return\n const err = new AgentToolNotAllowedError({\n toolName: ctx.name,\n displayName: ctx.displayName,\n allowedUnion: union,\n activeSkills: active,\n })\n ctx.block = true\n ctx.reason = err.message\n }\n\n function mcpGateHandler(ctx: McpToolHookContext & { block: boolean, reason: string }) {\n if (ctx.block)\n return\n const { union, active } = effectiveUnion()\n if (union.length === 0)\n return\n if (isToolAllowedByUnion(ctx.displayName, ctx.input, union))\n return\n const err = new AgentToolNotAllowedError({\n toolName: `mcp_${ctx.server}_${ctx.tool}`,\n displayName: ctx.displayName,\n allowedUnion: union,\n activeSkills: active,\n })\n ctx.block = true\n ctx.reason = err.message\n }\n\n const unregisterTool = hooks.hook('tool:gate', gateHandler)\n const unregisterMcp = hooks.hook('mcp:tool:gate', mcpGateHandler)\n\n return function uninstall() {\n unregisterTool()\n unregisterMcp()\n }\n}\n","/**\n * Minimal XML helpers used by catalog/result builders that emit\n * model-facing pseudo-XML (skills catalog, searchable_tools, tool_search\n * results, skill_content wrappers).\n *\n * Scope: attribute / text-node escaping only — we do NOT emit a full XML\n * document, the model sees these strings as free-form text. Centralised\n * here so the four near-identical copies in `agent.ts`, `skills/catalog.ts`,\n * `tools/skills-use.ts`, and `tools/tool-search.ts` don't drift.\n */\n\nconst RE_AMP = /&/g\nconst RE_LT = /</g\nconst RE_GT = />/g\nconst RE_QUOT = /\"/g\n\nexport function escapeXml(str: string): string {\n return str\n .replace(RE_AMP, '&amp;')\n .replace(RE_LT, '&lt;')\n .replace(RE_GT, '&gt;')\n .replace(RE_QUOT, '&quot;')\n}\n","/**\n * Skill catalog generation.\n *\n * Builds the system prompt section that discloses available skills to the\n * agent — tier 1 of progressive disclosure per the Agent Skills spec.\n *\n * The catalog's behavioral prose branches on which activation mechanism is\n * active for the run:\n *\n * - When the `skills_use` tool is auto-injected (the default for a non-empty\n * catalog), the prose tells the model to call `skills_use` with the skill's\n * name. The agent returns a structured `<skill_content>` block.\n * - When the skills tool is opted out (`SkillsConfig.tool: false`), the prose\n * falls back to the file-read pattern — the model reads `SKILL.md` itself\n * via its file-read tool.\n */\n\nimport type { SkillConfig } from './types'\nimport { escapeXml } from '../xml'\n\nexport interface BuildCatalogOptions {\n /**\n * When true (the default), the prose instructs the model to call\n * `skills_use`. Set to false when `SkillsConfig.tool === false` so the\n * system prompt matches the active activation mechanism.\n */\n skillsToolRegistered?: boolean\n /**\n * Name of the tool the model should use to read `SKILL.md` files when\n * `skillsToolRegistered` is false. Defaults to `'read_file'`.\n */\n readToolName?: string\n}\n\n/**\n * Build the skill catalog XML and behavioral instructions for the system prompt.\n */\nexport function buildCatalog(\n skills: SkillConfig[],\n options: BuildCatalogOptions = {},\n): string {\n if (skills.length === 0)\n return ''\n\n const skillsToolRegistered = options.skillsToolRegistered ?? true\n const readToolName = options.readToolName ?? 'read_file'\n\n const entries = skills.map((skill) => {\n const locationLine = skill.location\n ? `\\n <location>${escapeXml(skill.location)}</location>`\n : ''\n return ` <skill>\n <name>${escapeXml(skill.name)}</name>\n <description>${escapeXml(skill.description)}</description>${locationLine}\n </skill>`\n }).join('\\n')\n\n // Separate instructions for fs-based vs inline skills\n const hasFsSkills = skills.some(s => s.location)\n const hasInlineSkills = skills.some(s => !s.location)\n\n const behavioralParts: string[] = []\n\n behavioralParts.push(\n 'The following skills provide specialized instructions for specific tasks.',\n 'When a task matches a skill\\'s description, activate the skill to load its full instructions before proceeding.',\n )\n\n if (skillsToolRegistered) {\n behavioralParts.push(\n 'To activate a skill, call the `skills_use` tool with the skill\\'s name. '\n + 'The response contains the full instructions and any bundled resources you can then load '\n + 'via `skills_read` (reference files) or execute via `skills_run_script` (scripts/ directory).',\n 'Relative paths referenced in a skill\\'s instructions resolve against the skill directory noted in the `skills_use` response.',\n )\n }\n else if (hasFsSkills) {\n behavioralParts.push(\n `For skills with a <location>, use the ${readToolName} tool to read the SKILL.md file at that path.`,\n 'When a skill references relative paths, resolve them against the skill\\'s directory (the parent of SKILL.md) and use absolute paths in tool calls.',\n )\n }\n\n if (hasInlineSkills && !skillsToolRegistered) {\n behavioralParts.push(\n 'Skills without a <location> have their instructions included directly in <instructions> tags below.',\n )\n }\n\n // Build the full catalog block\n const parts: string[] = [\n behavioralParts.join('\\n'),\n '',\n '<available_skills>',\n entries,\n '</available_skills>',\n ]\n\n // Append inline skill instructions directly — but only when the model has no\n // other way to reach them (`skills_use` also handles inline skills when\n // registered, so we skip the duplicate copy in that case).\n if (hasInlineSkills && !skillsToolRegistered) {\n parts.push('')\n for (const skill of skills) {\n if (!skill.location && skill.instructions) {\n parts.push(`<skill_instructions name=\"${escapeXml(skill.name)}\">`)\n parts.push(skill.instructions)\n if (skill.resources && skill.resources.length > 0) {\n parts.push('')\n parts.push('<skill_resources>')\n for (const res of skill.resources) {\n parts.push(` <file type=\"${res.type}\">${escapeXml(res.path)}</file>`)\n }\n parts.push('</skill_resources>')\n }\n parts.push('</skill_instructions>')\n }\n }\n }\n\n return parts.join('\\n')\n}\n","/**\n * Skill discovery and parsing.\n *\n * Scans filesystem directories for SKILL.md files following the\n * Agent Skills specification (agentskills.io/specification).\n *\n * Parsing is intentionally **lenient** — per the spec's client-implementation\n * guide: warn, don't block. Diagnostics are attached to the returned\n * SkillConfig for host UIs to surface; only unrecoverable errors (missing\n * description, unparseable YAML) skip the skill entirely.\n */\n\nimport type { SkillConfig, SkillDiagnostic, SkillResource, SkillSource } from './types'\nimport { existsSync, readdirSync, readFileSync, statSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { basename, dirname, join, resolve } from 'node:path'\nimport { validateSkillName } from './validate'\n\n// ---------------------------------------------------------------------------\n// Regexes\n// ---------------------------------------------------------------------------\n\n// Frontmatter regex — opening ---, content, closing ---, optional body.\n// Tolerates CRLF line endings on the opening and closing fences (authoring\n// tools on Windows sometimes persist them mid-file).\nconst FRONTMATTER_RE = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?([\\s\\S]*)$/\n\nconst INDENT_RE = /^[ \\t]{2,}/\nconst KV_RE = /^([^:]+):(.*)$/\nconst DOUBLE_QUOTED_RE = /^\"((?:\\\\.|[^\"\\\\])*)\"$/\nconst SINGLE_QUOTED_RE = /^'((?:''|[^'])*)'$/\nconst DQ_ESCAPE_RE = /\\\\([\"\\\\/bfnrt])/g\nconst WHITESPACE_SPLIT_RE = /\\s+/\nconst PARAGRAPH_SPLIT_RE = /\\n\\n/\nconst COMMA_OR_SPACE_RE = /[,\\s]+/\n\n// ---------------------------------------------------------------------------\n// Frontmatter parsing\n// ---------------------------------------------------------------------------\n\ninterface ParsedSkillFile {\n frontmatter: Record<string, unknown>\n body: string\n diagnostics: SkillDiagnostic[]\n}\n\n/**\n * Parse a SKILL.md file into frontmatter + body.\n *\n * Uses a simple regex-based YAML extractor that handles:\n * - Flat key: value pairs\n * - Quoted values\n * - One-level nested maps (for `metadata:`)\n * - Lenient recovery from unquoted-colon values (e.g.\n * `description: Use when: the user asks …`) via a quote-wrap retry.\n */\nexport function parseFrontmatter(content: string): ParsedSkillFile {\n const diagnostics: SkillDiagnostic[] = []\n const match = content.match(FRONTMATTER_RE)\n if (!match) {\n return { frontmatter: {}, body: content.trim(), diagnostics }\n }\n\n const yamlBlock = match[1]\n const body = match[2].trim()\n\n // Simple YAML parser for flat and one-level nested key-value pairs\n const frontmatter: Record<string, unknown> = {}\n let currentKey: string | null = null\n let currentMap: Record<string, string> | null = null\n\n for (const line of yamlBlock.split('\\n')) {\n // Skip empty lines and comments\n if (!line.trim() || line.trim().startsWith('#'))\n continue\n\n // Nested key (indented under a map key)\n if (currentKey && currentMap && INDENT_RE.test(line)) {\n const nestedMatch = line.trim().match(KV_RE)\n if (nestedMatch) {\n const val = nestedMatch[2].trim()\n currentMap[nestedMatch[1].trim()] = unquoteYaml(val)\n }\n continue\n }\n\n // Top-level key\n if (currentKey && currentMap) {\n frontmatter[currentKey] = currentMap\n currentKey = null\n currentMap = null\n }\n\n // Split on first colon only — lenient for values containing colons.\n const kvMatch = matchFirstColon(line)\n if (!kvMatch)\n continue\n\n const key = kvMatch.key.trim()\n const rawValue = kvMatch.value.trim()\n\n if (!rawValue) {\n // Possibly a map — next lines will be indented\n currentKey = key\n currentMap = {}\n }\n else {\n frontmatter[key] = unquoteYaml(rawValue)\n }\n }\n\n // Flush any pending map\n if (currentKey && currentMap) {\n frontmatter[currentKey] = currentMap\n }\n\n return { frontmatter, body, diagnostics }\n}\n\nfunction matchFirstColon(line: string): { key: string, value: string } | null {\n const idx = line.indexOf(':')\n if (idx < 0)\n return null\n const key = line.slice(0, idx)\n const value = line.slice(idx + 1)\n // Reject accidental matches where key contains spaces before the colon wider\n // than a normal YAML key (defensive against \"some prose: foo\" in body leak).\n if (!KV_RE.test(`${key}:`))\n return null\n return { key, value }\n}\n\n/**\n * Strip outer quotes and decode YAML-style escapes.\n *\n * - Double-quoted values honor `\\\"`, `\\\\`, `\\n`, `\\r`, `\\t`, `\\b`, `\\f`, `\\/`.\n * - Single-quoted values honor `''` (the YAML single-quote escape for a literal `'`).\n * - Trailing inline comments on unquoted values (` # comment`) are dropped.\n * - Unquoted values are returned as-is (trimmed by caller).\n *\n * Skill frontmatter in the wild uses a narrow YAML subset — this is\n * sufficient for every field in the current spec and the common authoring\n * tools. Block scalars (`|`, `>`) and flow sequences are intentionally left\n * unsupported: they'd only appear in a bespoke workflow, and silently\n * half-supporting them is worse than rejecting them obviously.\n */\nfunction unquoteYaml(val: string): string {\n const dq = val.match(DOUBLE_QUOTED_RE)\n if (dq) {\n return dq[1].replace(DQ_ESCAPE_RE, (_, ch) => {\n switch (ch) {\n case '\"': return '\"'\n case '\\\\': return '\\\\'\n case '/': return '/'\n case 'b': return '\\b'\n case 'f': return '\\f'\n case 'n': return '\\n'\n case 'r': return '\\r'\n case 't': return '\\t'\n default: return ch\n }\n })\n }\n const sq = val.match(SINGLE_QUOTED_RE)\n if (sq) {\n return sq[1].replace(/''/g, '\\'')\n }\n // Strip trailing inline comment only when clearly separated (\"value # note\"\n // is a comment; \"value#tag\" is a literal). Preserves content on values that\n // legitimately contain `#` as part of text.\n const hashIdx = val.indexOf(' #')\n if (hashIdx >= 0)\n return val.slice(0, hashIdx).trimEnd()\n return val\n}\n\n/**\n * Narrow a frontmatter field to a string. Produces a diagnostic when present\n * but not a string, so malformed YAML (e.g. `name: 123`) surfaces as a\n * warning instead of silently coerced downstream via `as string`.\n */\nfunction takeString(\n frontmatter: Record<string, unknown>,\n key: string,\n diagnostics: SkillDiagnostic[],\n): string | undefined {\n const raw = frontmatter[key]\n if (raw === undefined || raw === null)\n return undefined\n if (typeof raw === 'string')\n return raw\n diagnostics.push({\n severity: 'warning',\n code: 'invalid-field-type',\n message: `Frontmatter field \"${key}\" expected string, got ${typeof raw}. Coerced.`,\n field: key,\n })\n return String(raw)\n}\n\n// ---------------------------------------------------------------------------\n// Resource enumeration\n// ---------------------------------------------------------------------------\n\nconst RESOURCE_DIRS: Record<string, SkillResource['type']> = {\n scripts: 'script',\n references: 'reference',\n assets: 'asset',\n}\n\nfunction enumerateResources(baseDir: string): SkillResource[] {\n const resources: SkillResource[] = []\n\n for (const [dir, type] of Object.entries(RESOURCE_DIRS)) {\n const dirPath = join(baseDir, dir)\n if (!existsSync(dirPath) || !statSync(dirPath).isDirectory())\n continue\n try {\n // `readdirSync` with `recursive: true` returns `string | Buffer`; we\n // opt into the `encoding: 'utf8'` overload via `withFileTypes: false`\n // default and string-encoded filenames. Guard the Buffer case in case\n // a platform quirk (non-UTF8 filenames on Linux) slips through.\n const files = readdirSync(dirPath, { recursive: true })\n for (const file of files) {\n const rel = typeof file === 'string' ? file : file.toString('utf-8')\n const fullPath = join(dirPath, rel)\n if (statSync(fullPath).isFile()) {\n resources.push({ path: join(dir, rel), type })\n }\n }\n }\n catch {\n // Skip unreadable directories\n }\n }\n\n // Also enumerate other files in the root (excluding SKILL.md)\n try {\n for (const entry of readdirSync(baseDir)) {\n if (entry === 'SKILL.md')\n continue\n const entryPath = join(baseDir, entry)\n if (statSync(entryPath).isFile()) {\n resources.push({ path: entry, type: 'other' })\n }\n }\n }\n catch {\n // Skip unreadable root\n }\n\n return resources\n}\n\n// ---------------------------------------------------------------------------\n// Parse a single SKILL.md file\n// ---------------------------------------------------------------------------\n\ninterface ParseSkillOptions {\n /** Source tag to attach to the returned SkillConfig. */\n source?: SkillSource\n}\n\n/**\n * Parse a SKILL.md file into a SkillConfig (lenient).\n *\n * Returns `null` only when the skill is fundamentally unusable:\n * - The file is missing\n * - The description is absent (required by spec for disclosure)\n *\n * All other issues are surfaced as `SkillConfig.diagnostics` with severity\n * `warning`. Deprecated top-level fields (`paths`, `model`, `thinking`) are\n * auto-migrated into `metadata['zidane.*']`.\n */\nexport async function parseSkillFile(\n filePath: string,\n options: ParseSkillOptions = {},\n): Promise<SkillConfig | null> {\n const absPath = resolve(filePath)\n if (!existsSync(absPath))\n return null\n\n const content = readFileSync(absPath, 'utf-8')\n const { frontmatter, body, diagnostics } = parseFrontmatter(content)\n\n // Description: frontmatter > first paragraph of body > skip\n let description = takeString(frontmatter, 'description', diagnostics)\n if (!description && body) {\n const firstParagraph = body.split(PARAGRAPH_SPLIT_RE)[0]?.trim()\n if (firstParagraph)\n description = firstParagraph\n }\n if (!description)\n return null\n\n if (description.length > 1024) {\n diagnostics.push({\n severity: 'warning',\n code: 'description-too-long',\n message: `Description exceeds spec limit of 1024 characters (got ${description.length}). Loading anyway.`,\n field: 'description',\n })\n }\n\n const baseDir = dirname(absPath)\n const dirName = basename(baseDir)\n const frontmatterName = takeString(frontmatter, 'name', diagnostics)\n const name = frontmatterName || dirName\n\n // Lenient name checks\n if (frontmatterName && frontmatterName !== dirName) {\n diagnostics.push({\n severity: 'warning',\n code: 'name-mismatch-directory',\n message: `Skill name \"${frontmatterName}\" does not match parent directory \"${dirName}\". Loading anyway.`,\n field: 'name',\n })\n }\n if (name.length > 64) {\n diagnostics.push({\n severity: 'warning',\n code: 'name-too-long',\n message: `Skill name \"${name}\" exceeds spec limit of 64 characters. Loading anyway.`,\n field: 'name',\n })\n }\n if (!validateSkillName(name)) {\n diagnostics.push({\n severity: 'warning',\n code: 'invalid-name-format',\n message: `Skill name \"${name}\" does not match spec format (lowercase alphanumeric + hyphens, no leading/trailing/consecutive hyphens). Loading anyway.`,\n field: 'name',\n })\n }\n\n const config: SkillConfig = {\n name,\n description,\n instructions: body,\n source: options.source ?? 'project',\n location: absPath,\n baseDir,\n resources: enumerateResources(baseDir),\n }\n\n const license = takeString(frontmatter, 'license', diagnostics)\n if (license)\n config.license = license\n\n const compatibility = takeString(frontmatter, 'compatibility', diagnostics)\n if (compatibility) {\n if (compatibility.length > 500) {\n diagnostics.push({\n severity: 'warning',\n code: 'compatibility-too-long',\n message: `Compatibility exceeds spec limit of 500 characters (got ${compatibility.length}). Loading anyway.`,\n field: 'compatibility',\n })\n }\n config.compatibility = compatibility\n }\n\n // Metadata — spec-compliant flat bag\n const metadata: Record<string, string> = {}\n const rawMetadata = frontmatter.metadata\n if (rawMetadata && typeof rawMetadata === 'object' && !Array.isArray(rawMetadata)) {\n for (const [k, v] of Object.entries(rawMetadata as Record<string, unknown>)) {\n if (typeof v !== 'string') {\n diagnostics.push({\n severity: 'warning',\n code: 'invalid-metadata-value',\n message: `Metadata value for \"${k}\" is not a string; coerced. (Spec requires string values.)`,\n field: 'metadata',\n })\n metadata[k] = String(v)\n continue\n }\n metadata[k] = v\n }\n }\n else if (rawMetadata !== undefined) {\n diagnostics.push({\n severity: 'warning',\n code: 'invalid-metadata-shape',\n message: `Frontmatter \"metadata\" expected a map, got ${Array.isArray(rawMetadata) ? 'array' : typeof rawMetadata}. Ignored.`,\n field: 'metadata',\n })\n }\n\n // Auto-migrate deprecated top-level fields into metadata.zidane.*\n const pathsField = takeString(frontmatter, 'paths', diagnostics)\n if (pathsField) {\n metadata['zidane.paths'] = pathsField.split(COMMA_OR_SPACE_RE).filter(Boolean).join(',')\n diagnostics.push({\n severity: 'warning',\n code: 'deprecated-top-level-field',\n message: '`paths` is not a spec field and is deprecated — moved to `metadata[\"zidane.paths\"]`.',\n field: 'paths',\n })\n }\n const modelField = takeString(frontmatter, 'model', diagnostics)\n if (modelField) {\n metadata['zidane.model'] = modelField\n diagnostics.push({\n severity: 'warning',\n code: 'deprecated-top-level-field',\n message: '`model` is not a spec field and is deprecated — moved to `metadata[\"zidane.model\"]`.',\n field: 'model',\n })\n }\n const thinkingField = takeString(frontmatter, 'thinking', diagnostics)\n const effortField = thinkingField ? undefined : takeString(frontmatter, 'effort', diagnostics)\n const legacyThinking = thinkingField ?? effortField\n if (legacyThinking) {\n metadata['zidane.thinking'] = legacyThinking\n diagnostics.push({\n severity: 'warning',\n code: 'deprecated-top-level-field',\n message: `\\`${thinkingField ? 'thinking' : 'effort'}\\` is not a spec field and is deprecated — moved to \\`metadata[\"zidane.thinking\"]\\`.`,\n field: thinkingField ? 'thinking' : 'effort',\n })\n }\n\n if (Object.keys(metadata).length > 0)\n config.metadata = metadata\n\n const allowedTools = takeString(frontmatter, 'allowed-tools', diagnostics)\n if (allowedTools) {\n config.allowedTools = allowedTools.split(WHITESPACE_SPLIT_RE).filter(Boolean)\n }\n\n if (diagnostics.length > 0)\n config.diagnostics = diagnostics\n\n return config\n}\n\n// ---------------------------------------------------------------------------\n// Directory scanning\n// ---------------------------------------------------------------------------\n\nconst SKIP_DIRS = new Set(['.git', 'node_modules', '.DS_Store', 'dist', 'build'])\n\nfunction findSkillDirs(root: string, maxDepth = 4, _depth = 0): string[] {\n if (_depth > maxDepth)\n return []\n if (!existsSync(root) || !statSync(root).isDirectory())\n return []\n\n const results: string[] = []\n try {\n for (const entry of readdirSync(root)) {\n if (SKIP_DIRS.has(entry))\n continue\n const entryPath = join(root, entry)\n if (!statSync(entryPath).isDirectory())\n continue\n\n const skillFile = join(entryPath, 'SKILL.md')\n if (existsSync(skillFile) && statSync(skillFile).isFile()) {\n results.push(skillFile)\n }\n else {\n // Recurse deeper\n results.push(...findSkillDirs(entryPath, maxDepth, _depth + 1))\n }\n }\n }\n catch {\n // Skip unreadable directories\n }\n return results\n}\n\n// ---------------------------------------------------------------------------\n// Default scan paths\n// ---------------------------------------------------------------------------\n\n/** A scan path paired with the source tag that should be attached to any skills found in it. */\nexport interface SourcedScanPath {\n path: string\n source: SkillSource\n}\n\n/**\n * Return the default scan paths tagged by source. Project-scope paths come\n * first; their skills therefore win on name collisions against user-scope\n * skills (first-found wins in discovery).\n */\nexport function getDefaultScanPaths(): SourcedScanPath[] {\n const home = homedir()\n const cwd = process.cwd()\n return [\n // Project-level (higher priority)\n { path: join(cwd, '.agents', 'skills'), source: 'project' },\n { path: join(cwd, '.zidane', 'skills'), source: 'project' },\n // User-level (lower priority)\n { path: join(home, '.agents', 'skills'), source: 'user' },\n { path: join(home, '.zidane', 'skills'), source: 'user' },\n ]\n}\n\n/**\n * Infer a source tag for a user-provided scan path.\n * Paths under `$HOME` are treated as 'user'; everything else as 'project'.\n */\nexport function inferSource(path: string): SkillSource {\n return path.startsWith(homedir()) ? 'user' : 'project'\n}\n\n// ---------------------------------------------------------------------------\n// Discover skills from filesystem\n// ---------------------------------------------------------------------------\n\n/**\n * Discover skills from sourced filesystem paths.\n * Each path is scanned for subdirectories containing SKILL.md.\n * Earlier paths have higher priority (first-found wins on name collision).\n *\n * `signal` is checked between each `parseSkillFile` so a rapid `cwd` switch\n * in the host (TUI / GUI) can stop a long scan without leaking I/O. Aborts\n * reject with the signal's `reason` (or a default `AbortError`) — same shape\n * `AbortSignal.throwIfAborted()` produces in modern runtimes.\n */\nexport async function discoverSkills(\n paths: SourcedScanPath[],\n signal?: AbortSignal,\n): Promise<SkillConfig[]> {\n const skillsByName = new Map<string, SkillConfig>()\n\n for (const { path: scanPath, source } of paths) {\n signal?.throwIfAborted?.()\n const skillFiles = findSkillDirs(resolve(scanPath))\n for (const file of skillFiles) {\n signal?.throwIfAborted?.()\n const skill = await parseSkillFile(file, { source })\n if (!skill)\n continue\n if (skillsByName.has(skill.name)) {\n // First-found wins — append a collision diagnostic to the winning skill.\n const existing = skillsByName.get(skill.name)!\n const diag: SkillDiagnostic = {\n severity: 'warning',\n code: 'name-collision-shadowed',\n message: `A skill with name \"${skill.name}\" was also found at ${file} (source: ${source}); shadowed by ${existing.location} (source: ${existing.source}).`,\n }\n existing.diagnostics = [...(existing.diagnostics ?? []), diag]\n continue\n }\n skillsByName.set(skill.name, skill)\n }\n }\n\n return [...skillsByName.values()]\n}\n","/**\n * Skill writer — materializes inline SkillConfig objects to disk as proper\n * SKILL.md files so they participate fully in the filesystem-based skill system.\n *\n * Strict-validates each skill before writing (see `validateSkillForWrite`).\n */\n\nimport type { SkillConfig } from './types'\nimport { mkdirSync, writeFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { validateSkillForWrite } from './validate'\n\n// ---------------------------------------------------------------------------\n// Frontmatter serialization\n// ---------------------------------------------------------------------------\n\nconst YAML_RESERVED_RE = /[:#&*!|>%@`]/\nconst YAML_EDGE_OR_QUOTE_RE = /^\\s|\\s$|[\"']/\nconst DQUOTE_RE = /\"/g\nconst LEADING_NEWLINES_RE = /^\\n+/\n\nfunction yamlEscape(value: string): string {\n // Quote values that contain YAML-reserved characters (colons, quotes, leading\n // special chars). Keeps round-trip safety for descriptions like\n // \"Use when: the user asks …\".\n if (YAML_RESERVED_RE.test(value) || YAML_EDGE_OR_QUOTE_RE.test(value) || value === '')\n return `\"${value.replace(DQUOTE_RE, '\\\\\"')}\"`\n return value\n}\n\nfunction serializeFrontmatter(skill: SkillConfig): string {\n const lines: string[] = ['---']\n\n lines.push(`name: ${yamlEscape(skill.name)}`)\n lines.push(`description: ${yamlEscape(skill.description)}`)\n\n if (skill.license)\n lines.push(`license: ${yamlEscape(skill.license)}`)\n if (skill.compatibility)\n lines.push(`compatibility: ${yamlEscape(skill.compatibility)}`)\n if (skill.allowedTools?.length)\n lines.push(`allowed-tools: ${skill.allowedTools.join(' ')}`)\n\n if (skill.metadata && Object.keys(skill.metadata).length > 0) {\n lines.push('metadata:')\n for (const [key, value] of Object.entries(skill.metadata)) {\n // Always quote metadata values — preserves string-looking numerics (\"1.0\")\n // and string-valued booleans (\"true\") from YAML's implicit type coercion.\n // Dot-keys (e.g. `zidane.paths`) are accepted verbatim by YAML.\n lines.push(` ${key}: \"${value.replace(DQUOTE_RE, '\\\\\"')}\"`)\n }\n }\n\n lines.push('---')\n return lines.join('\\n')\n}\n\n// ---------------------------------------------------------------------------\n// Write a single skill to disk\n// ---------------------------------------------------------------------------\n\n/**\n * Write a `SkillConfig` to disk as a proper skill directory with SKILL.md.\n * Returns the path to the written SKILL.md file.\n *\n * Throws if the skill fails `validateSkillForWrite` — the authoring path is\n * strict on purpose. For loading third-party skills, use `parseSkillFile`\n * directly (lenient).\n */\nexport function writeSkillToDisk(skill: SkillConfig, targetDir: string): string {\n const result = validateSkillForWrite(skill)\n if (!result.valid) {\n const summary = result.errors\n .map(e => ` - [${e.code}] ${e.message}`)\n .join('\\n')\n throw new Error(`Cannot write invalid skill \"${skill.name}\":\\n${summary}`)\n }\n\n const skillDir = join(targetDir, skill.name)\n mkdirSync(skillDir, { recursive: true })\n\n const frontmatter = serializeFrontmatter(skill)\n // Normalize: strip any leading newlines on the body so we never emit a\n // double-blank-line between the frontmatter fence and the instructions,\n // and always end the file with a single trailing newline.\n const bodyTrimmed = skill.instructions ? skill.instructions.replace(LEADING_NEWLINES_RE, '') : ''\n const content = bodyTrimmed\n ? `${frontmatter}\\n\\n${bodyTrimmed}\\n`\n : `${frontmatter}\\n`\n\n const skillPath = join(skillDir, 'SKILL.md')\n writeFileSync(skillPath, content)\n\n return skillPath\n}\n\n// ---------------------------------------------------------------------------\n// Write multiple skills to a directory\n// ---------------------------------------------------------------------------\n\n/**\n * Write multiple `SkillConfig` objects to a target directory.\n * Each skill gets its own subdirectory with a SKILL.md file.\n * Returns the target directory path (for use as a scan path).\n */\nexport function writeSkillsToDisk(skills: SkillConfig[], targetDir: string): string {\n mkdirSync(targetDir, { recursive: true })\n for (const skill of skills) {\n writeSkillToDisk(skill, targetDir)\n }\n return targetDir\n}\n","/**\n * Skill resolution — discovers filesystem skills, writes dynamic skills,\n * merges everything, and applies filtering.\n */\n\nimport type { SourcedScanPath } from './discovery'\nimport type { SkillConfig, SkillsConfig } from './types'\nimport { mkdtempSync, rmSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\nimport { discoverSkills, getDefaultScanPaths, inferSource } from './discovery'\nimport { writeSkillsToDisk } from './writer'\n\n// ---------------------------------------------------------------------------\n// Resolution\n// ---------------------------------------------------------------------------\n\n/**\n * Resolved-skills bundle: the materialized list plus a `cleanup` fn that\n * removes any temporary directory created for `config.write` skills.\n *\n * Inline skills must live on disk for the lifetime of the agent (the\n * `skills_read` / `skills_run_script` tools resolve relative paths against\n * `baseDir`), so cleanup is deferred to `agent.destroy()`. When no temp\n * directory was created, `cleanup` is a no-op.\n */\nexport interface ResolvedSkillsBundle {\n skills: SkillConfig[]\n cleanup: () => void\n}\n\n/**\n * Resolve all skills from a SkillsConfig:\n *\n * 1. Materialize `config.write` entries to a temp directory, tagged as `inline`\n * 2. Combine with default + user-provided scan paths (project-first, user-next)\n * 3. Run lenient discovery\n * 4. Apply filters: `exclude`, `enabled` allowlist, optional project-skill trust gate\n *\n * Returns `{ skills, cleanup }` — call `cleanup()` on agent destroy to remove\n * the temp directory created for inline `config.write` skills. The agent\n * factory wires this automatically; standalone callers must invoke it\n * themselves to avoid leaking OS temp.\n */\nexport async function resolveSkills(config: SkillsConfig): Promise<ResolvedSkillsBundle> {\n const sourcedPaths: SourcedScanPath[] = []\n let writeDir: string | undefined\n\n if (!config.skipDefaultPaths) {\n sourcedPaths.push(...getDefaultScanPaths())\n }\n\n // User-provided scan paths: infer source from path prefix.\n for (const p of config.scan ?? []) {\n sourcedPaths.push({ path: p, source: inferSource(p) })\n }\n\n // Inline skills materialized to a temp directory and scanned as 'inline'.\n if (config.write?.length) {\n writeDir = mkdtempSync(join(tmpdir(), 'zidane-skills-'))\n writeSkillsToDisk(config.write, writeDir)\n sourcedPaths.push({ path: writeDir, source: 'inline' })\n }\n\n // Discover all skills from filesystem (first-found-wins on name collision).\n let skills = await discoverSkills(sourcedPaths)\n\n // Optional trust gate: drop project-scoped skills when the host hasn't\n // marked the project as trusted. Undefined source is treated as `'project'`\n // (conservative default — an untrusted environment should skip unclassified\n // skills rather than silently loading them).\n if (config.trustProjectSkills === false) {\n skills = skills.filter(s => s.source !== undefined && s.source !== 'project')\n }\n\n // Filter out `exclude`\n const exclude = new Set(config.exclude ?? [])\n let filtered = skills.filter(s => !exclude.has(s.name))\n\n // Apply `enabled` allowlist when it's an array of skill names\n if (Array.isArray(config.enabled)) {\n const allowlist = new Set(config.enabled)\n filtered = filtered.filter(s => allowlist.has(s.name))\n }\n\n const cleanup = writeDir\n ? () => {\n try {\n rmSync(writeDir!, { recursive: true, force: true })\n }\n catch {\n // Best-effort — temp directory may have been removed by the OS or\n // a sibling cleanup. Don't crash agent destroy.\n }\n }\n : () => {}\n\n return { skills: filtered, cleanup }\n}\n","/**\n * Shell interpolation for skill instructions.\n *\n * The `!\\`command\\`` syntax runs shell commands as a preprocessing step\n * before skill content is sent to the agent. The command output replaces\n * the placeholder — the agent only sees the final result.\n *\n * Example:\n * - PR diff: !\\`gh pr diff\\`\n * → - PR diff: <actual diff output>\n */\n\nimport type { ExecutionContext, ExecutionHandle } from '../contexts'\nimport { errorMessage } from '../errors'\n\n/** Regex to match !`command` patterns in skill instructions */\nconst SHELL_INTERPOLATION_RE = /!`([^`]+)`/g\n\n/**\n * Interpolate shell commands in skill instructions.\n *\n * Runs each !\\`command\\` through the execution context and replaces\n * the placeholder with the command's stdout. If a command fails,\n * the placeholder is replaced with an error message.\n *\n * @param instructions - Raw skill instructions with potential !\\`command\\` patterns\n * @param execution - The execution context to run commands in\n * @param handle - The active execution handle\n * @returns Instructions with all !\\`command\\` patterns replaced by output\n */\nexport async function interpolateShellCommands(\n instructions: string,\n execution: ExecutionContext,\n handle: ExecutionHandle,\n): Promise<string> {\n const matches = [...instructions.matchAll(SHELL_INTERPOLATION_RE)]\n if (matches.length === 0)\n return instructions\n\n // Collect all commands with their positions for precise replacement\n const replacements: { index: number, length: number, output: string }[] = []\n\n for (const match of matches) {\n const command = match[1]\n const index = match.index!\n const length = match[0].length\n\n try {\n const result = await execution.exec(handle, command, { timeout: 30 })\n const output = result.exitCode === 0\n ? result.stdout.trim()\n : `[command failed (exit ${result.exitCode}): ${result.stderr.trim() || result.stdout.trim()}]`\n replacements.push({ index, length, output })\n }\n catch (err) {\n replacements.push({ index, length, output: `[command error: ${errorMessage(err)}]` })\n }\n }\n\n // Apply replacements in reverse order to preserve positions\n let result = instructions\n for (let i = replacements.length - 1; i >= 0; i--) {\n const { index, length, output } = replacements[i]\n result = result.slice(0, index) + output + result.slice(index + length)\n }\n\n return result\n}\n"],"mappings":"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"}