zidane 4.1.8 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -2
- package/dist/{index-bgh-k8Mv.d.ts → agent-JhicgLOV.d.ts} +2082 -1969
- package/dist/agent-JhicgLOV.d.ts.map +1 -0
- package/dist/chat.d.ts +340 -9
- package/dist/chat.d.ts.map +1 -1
- package/dist/chat.js +2 -2
- package/dist/contexts.d.ts +1 -1
- package/dist/{index-DRoG_udt.d.ts → index-2yLUyTbc.d.ts} +34 -4
- package/dist/{index-DRoG_udt.d.ts.map → index-2yLUyTbc.d.ts.map} +1 -1
- package/dist/{index-BB4kuRh3.d.ts → index-CXVvqTQj.d.ts} +1 -1
- package/dist/{index-BB4kuRh3.d.ts.map → index-CXVvqTQj.d.ts.map} +1 -1
- package/dist/{index-Ds5YpvfZ.d.ts → index-t_W9i7Ql.d.ts} +9 -4
- package/dist/index-t_W9i7Ql.d.ts.map +1 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.js +6 -6
- package/dist/{interpolate-CukJwP2G.js → interpolate-Ck970-61.js} +11 -2
- package/dist/interpolate-Ck970-61.js.map +1 -0
- package/dist/{mcp-8wClKY-3.js → mcp-Dw-fRPVk.js} +61 -65
- package/dist/mcp-Dw-fRPVk.js.map +1 -0
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +1 -1
- package/dist/presets-BRFH2qsQ.js +90 -0
- package/dist/presets-BRFH2qsQ.js.map +1 -0
- package/dist/presets.d.ts +3 -2
- package/dist/presets.js +2 -2
- package/dist/providers.d.ts +1 -1
- package/dist/session/sqlite.d.ts +13 -2
- package/dist/session/sqlite.d.ts.map +1 -1
- package/dist/session/sqlite.js +96 -38
- package/dist/session/sqlite.js.map +1 -1
- package/dist/{session-Cn68UASv.js → session-791hhrFa.js} +65 -30
- package/dist/session-791hhrFa.js.map +1 -0
- package/dist/session.d.ts +1 -1
- package/dist/session.js +1 -1
- package/dist/skills.d.ts +2 -2
- package/dist/skills.js +1 -1
- package/dist/{stats-BT9l57RS.js → stats-DZIsGqzu.js} +15 -5
- package/dist/stats-DZIsGqzu.js.map +1 -0
- package/dist/theme-pJv47erq.d.ts +1202 -0
- package/dist/theme-pJv47erq.d.ts.map +1 -0
- package/dist/{tools-C8kDot0H.js → tools-CLazLRb4.js} +475 -318
- package/dist/tools-CLazLRb4.js.map +1 -0
- package/dist/tools.d.ts +2 -2
- package/dist/tools.js +1 -1
- package/dist/tui.d.ts +303 -18
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +3305 -509
- package/dist/tui.js.map +1 -1
- package/dist/turn-operations-5aQu4dJg.js +3587 -0
- package/dist/turn-operations-5aQu4dJg.js.map +1 -0
- package/dist/types.d.ts +3 -3
- package/dist/types.js +1 -1
- package/package.json +6 -1
- package/dist/index-Ds5YpvfZ.d.ts.map +0 -1
- package/dist/index-bgh-k8Mv.d.ts.map +0 -1
- package/dist/interpolate-CukJwP2G.js.map +0 -1
- package/dist/mcp-8wClKY-3.js.map +0 -1
- package/dist/presets-BzkJDW1K.js +0 -39
- package/dist/presets-BzkJDW1K.js.map +0 -1
- package/dist/session-Cn68UASv.js.map +0 -1
- package/dist/stats-BT9l57RS.js.map +0 -1
- package/dist/theme-BlXO6yHe.d.ts +0 -503
- package/dist/theme-BlXO6yHe.d.ts.map +0 -1
- package/dist/theme-context-MungM3SY.js +0 -1713
- package/dist/theme-context-MungM3SY.js.map +0 -1
- package/dist/tools-C8kDot0H.js.map +0 -1
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { a as ContextCapabilities, c as ExecutionContext, l as ExecutionHandle, o as ContextType, s as ExecResult, t as SandboxProvider, u as SpawnConfig } from "./index-CXVvqTQj.js";
|
|
2
|
+
import { At as ThinkingLevel, Bt as AgentAbortedError, Ct as SessionContentBlock, D as SessionData, Dt as SessionTurn, E as Session, Et as SessionMessage, Ft as ToolResultTextContent, G as StreamCallbacks, Gt as ClassifiedError, Ht as AgentProviderError, It as TurnFinishReason, J as ToolResult, K as StreamOptions, Kt as ClassifiedErrorKind, Lt as TurnUsage, M as RemoteStoreOptions, Mt as ToolHookContext, Nt as ToolResultContent, O as SessionRun, Ot as SpawnHookContext, Pt as ToolResultImageContent, Rt as toolOutputByteLength, S as SkillResource, St as RunHookMap, T as CreateSessionOptions, Tt as SessionHookContext, U as Provider, Ut as AgentToolNotAllowedError, Vt as AgentContextExceededError, W as ProviderCapabilities, Wt as CONTEXT_EXCEEDED_MESSAGE_PATTERNS, X as TurnResult, Y as ToolSpec, Z as OpenRouterParams, _ as ToolContext, _t as OAuthRefreshHookContext, at as OpenAIParams, b as SkillConfig, bt as PromptPart, dt as AgentBehavior, f as McpConnection, ft as AgentRunOptions, gt as McpToolHookContext, ht as McpServerConfig, i as AgentOptions, jt as ToolExecutionMode, k as SessionStore, kt as StreamHookContext, lt as AnthropicParams, mt as ChildRunStats, pt as AgentStats, q as ToolCall, qt as matchesContextExceeded, r as AgentHooks, st as CerebrasParams, t as Agent, v as ToolDef, vt as PromptDocumentPart, w as SkillsConfig, wt as SessionEndStatus, xt as PromptTextPart, y as ToolMap, yt as PromptImagePart, zt as toolResultToText } from "./agent-JhicgLOV.js";
|
|
3
|
+
import { I as ModelUsage, L as flattenTurns, R as statsByModel, _ as ChildAgent, f as ValidationResult, j as InteractionToolOptions, t as Preset, v as SpawnToolOptions, y as SpawnToolState } from "./index-2yLUyTbc.js";
|
|
4
4
|
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 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 ToolExecutionMode, 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
1
|
import { a as CONTEXT_EXCEEDED_MESSAGE_PATTERNS, i as AgentToolNotAllowedError, n as AgentContextExceededError, o as matchesContextExceeded, r as AgentProviderError, t as AgentAbortedError } from "./errors-D1lhd6mX.js";
|
|
2
2
|
import { n as toolResultToText, t as toolOutputByteLength } from "./types-Bx_F8jet.js";
|
|
3
|
-
import { r as statsByModel, t as flattenTurns } from "./stats-
|
|
3
|
+
import { r as statsByModel, t as flattenTurns } from "./stats-DZIsGqzu.js";
|
|
4
4
|
export { AgentAbortedError, AgentContextExceededError, AgentProviderError, AgentToolNotAllowedError, CONTEXT_EXCEEDED_MESSAGE_PATTERNS, flattenTurns, matchesContextExceeded, statsByModel, toolOutputByteLength, toolResultToText };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zidane",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "an agent that goes straight to the goal",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"types": "./dist/index.d.ts"
|
|
21
21
|
},
|
|
22
22
|
"./types": {
|
|
23
|
+
"import": "./dist/types.js",
|
|
23
24
|
"types": "./dist/types.d.ts"
|
|
24
25
|
},
|
|
25
26
|
"./providers": {
|
|
@@ -96,6 +97,7 @@
|
|
|
96
97
|
"@modelcontextprotocol/sdk": ">=1.11.0",
|
|
97
98
|
"@opentui/core": "^0.2.6",
|
|
98
99
|
"@opentui/react": "^0.2.6",
|
|
100
|
+
"dockerode": "^4.0.0",
|
|
99
101
|
"react": "^19.0.0",
|
|
100
102
|
"zod": ">=4.0.0"
|
|
101
103
|
},
|
|
@@ -112,6 +114,9 @@
|
|
|
112
114
|
"@opentui/react": {
|
|
113
115
|
"optional": true
|
|
114
116
|
},
|
|
117
|
+
"dockerode": {
|
|
118
|
+
"optional": true
|
|
119
|
+
},
|
|
115
120
|
"react": {
|
|
116
121
|
"optional": true
|
|
117
122
|
},
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-Ds5YpvfZ.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;;;iBAkZqB,cAAA,CAAe,KAAA,EAAO,eAAA,KAAoB,OAAA,CAAQ,WAAA;;;;;;;;;;;;;;;iBC1elD,wBAAA,CACpB,YAAA,UACA,SAAA,EAAW,gBAAA,EACX,MAAA,EAAQ,eAAA,GACP,OAAA;;;AHVH;;;;;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":"index-bgh-k8Mv.d.ts","names":[],"sources":["../src/errors.ts","../src/mcp/index.ts","../src/session/file-map.ts","../src/session/memory.ts","../src/session/messages.ts","../src/session/remote.ts","../src/session/index.ts","../src/skills/types.ts","../src/skills/activation.ts","../src/agent.ts","../src/tools/types.ts","../src/types.ts","../src/providers/anthropic.ts","../src/providers/cerebras.ts","../src/providers/openai.ts","../src/providers/openai-compat.ts","../src/providers/openrouter.ts","../src/providers/index.ts"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"interpolate-CukJwP2G.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 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 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, '&')\n .replace(RE_LT, '<')\n .replace(RE_GT, '>')\n .replace(RE_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 */\nexport async function discoverSkills(paths: SourcedScanPath[]): Promise<SkillConfig[]> {\n const skillsByName = new Map<string, SkillConfig>()\n\n for (const { path: scanPath, source } of paths) {\n const skillFiles = findSkillDirs(resolve(scanPath))\n for (const file of skillFiles) {\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'\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 const message = err instanceof Error ? err.message : String(err)\n replacements.push({ index, length, output: `[command error: ${message}]` })\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":";;;;;AAiFA,SAAgB,2BACd,UAAuC,EAAE,EACnB;CACtB,MAAM,yBAAS,IAAI,KAA0B;CAC7C,MAAM,YAAY,OAAO,QAAQ,cAAc,YAAY,QAAQ,YAAY,IAC3E,QAAQ,YACR,KAAA;CAEJ,OAAO;EACL,SAAS;GACP,OAAO,CAAC,GAAG,OAAO,QAAQ,CAAC;;EAG7B,SAAS,MAAM;GACb,OAAO,OAAO,IAAI,KAAK;;EAGzB,IAAI,MAAM;GACR,OAAO,OAAO,IAAI,KAAK;;EAGzB,SAAS,OAAO,KAAK;GACnB,IAAI,OAAO,IAAI,MAAM,KAAK,EACxB,OAAO;GACT,IAAI,cAAc,KAAA,KAAa,OAAO,QAAQ,WAC5C,OAAO;GACT,OAAO,IAAI,MAAM,MAAM;IACrB;IACA,aAAa,KAAK,KAAK;IACvB,cAAc;IACf,CAAC;GACF,OAAO;;EAGT,WAAW,MAAM;GACf,MAAM,WAAW,OAAO,IAAI,KAAK;GACjC,IAAI,CAAC,UACH,OAAO,KAAA;GACT,OAAO,OAAO,KAAK;GACnB,OAAO;;EAGT,QAAQ;GACN,MAAM,WAAW,CAAC,GAAG,OAAO,QAAQ,CAAC;GACrC,OAAO,OAAO;GACd,OAAO;;EAEV;;;;AClHH,MAAM,WAAW;AACjB,MAAM,kBAAkB;AACxB,MAAM,oBAAoB;AAE1B,MAAM,gBAAgB;AACtB,MAAM,yBAAyB;AAK/B,MAAM,0BAA0B;AAGhC,MAAM,sBAAsB;AAC5B,MAAM,oBAAoB;AAC1B,MAAM,sBAAsB;;;;;;;;;;;AAuC5B,SAAgB,kBAAkB,MAAuB;CACvD,IAAI,OAAO,SAAS,UAClB,OAAO;CACT,IAAI,KAAK,SAAS,KAAK,KAAK,SAAS,UACnC,OAAO;CACT,IAAI,uBAAuB,KAAK,KAAK,EACnC,OAAO;CACT,OAAO,cAAc,KAAK,KAAK;;;;;;;AAYjC,SAAgB,sBAAsB,OAA2C;CAC/E,MAAM,SAAiC,EAAE;CAGzC,IAAI,CAAC,kBAAkB,MAAM,KAAK,EAChC,OAAO,KAAK;EACV,MAAM;EACN,SAAS,eAAe,MAAM,KAAK;EACnC,OAAO;EACR,CAAC;CAIJ,IAAI,MAAM,UAAU;EAClB,MAAM,UAAU,SAAS,MAAM,WAAW,GAAG;EAC7C,IAAI,WAAW,YAAY,MAAM,MAC/B,OAAO,KAAK;GACV,MAAM;GACN,SAAS,eAAe,MAAM,KAAK,sCAAsC,QAAQ;GACjF,OAAO;GACR,CAAC;;CAKN,IAAI,OAAO,MAAM,gBAAgB,YAAY,MAAM,YAAY,SAAS,GACtE,OAAO,KAAK;EACV,MAAM;EACN,SAAS;EACT,OAAO;EACR,CAAC;MAEC,IAAI,MAAM,YAAY,SAAS,iBAClC,OAAO,KAAK;EACV,MAAM;EACN,SAAS,qCAAqC,gBAAgB,mBAAmB,MAAM,YAAY,OAAO;EAC1G,OAAO;EACR,CAAC;CAIJ,IAAI,MAAM,kBAAkB,KAAA;MACtB,OAAO,MAAM,kBAAkB,YAAY,MAAM,cAAc,WAAW,GAC5E,OAAO,KAAK;GACV,MAAM;GACN,SAAS;GACT,OAAO;GACR,CAAC;OAEC,IAAI,MAAM,cAAc,SAAS,mBACpC,OAAO,KAAK;GACV,MAAM;GACN,SAAS,iCAAiC,kBAAkB,mBAAmB,MAAM,cAAc,OAAO;GAC1G,OAAO;GACR,CAAC;;CAKN,IAAI,MAAM;OACH,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,SAAS,EACvD,IAAI,OAAO,UAAU,UACnB,OAAO,KAAK;GACV,MAAM;GACN,SAAS,uBAAuB,IAAI;GACpC,OAAO;GACR,CAAC;;CAMR,IAAI,MAAM;OACH,MAAM,WAAW,MAAM,cAC1B,IAAI,CAAC,wBAAwB,KAAK,QAAQ,EACxC,OAAO,KAAK;GACV,MAAM;GACN,SAAS,wBAAwB,QAAQ;GACzC,OAAO;GACR,CAAC;;CAKR,OAAO;EAAE,OAAO,OAAO,WAAW;EAAG;EAAQ;;;;;;;;;;;;;AAkB/C,SAAgB,qBACd,SACA,SACyE;CACzE,IAAI,OAAO,YAAY,YAAY,QAAQ,WAAW,GACpD,OAAO;EAAE,OAAO;EAAO,OAAO;EAA6C;CAE7E,IAAI,QAAQ,SAAS,KAAK,EACxB,OAAO;EAAE,OAAO;EAAO,OAAO;EAAuC;CAGvE,IAAI,QAAQ,WAAW,IAAI,IAAI,oBAAoB,KAAK,QAAQ,EAC9D,OAAO;EAAE,OAAO;EAAO,OAAO,oCAAoC,QAAQ;EAAM;CAGlF,MAAM,WAAqB,EAAE;CAC7B,KAAK,MAAM,WAAW,QAAQ,MAAM,kBAAkB,EAAE;EACtD,IAAI,YAAY,MAAM,YAAY,KAChC;EACF,IAAI,YAAY,MAAM;GACpB,IAAI,SAAS,WAAW,GACtB,OAAO;IACL,OAAO;IACP,OAAO,kBAAkB,QAAQ;IAClC;GAEH,SAAS,KAAK;GACd;;EAEF,SAAS,KAAK,QAAQ;;CAGxB,IAAI,SAAS,WAAW,GACtB,OAAO;EAAE,OAAO;EAAO,OAAO;EAAoD;CAGpF,OAAO;EAAE,OAAO;EAAM,cAAA,GADE,QAAQ,QAAQ,qBAAqB,GAAG,CAAC,GAAG,SAAS,KAAK,IAAI;EAClD;;;;;;;;;AActC,SAAgB,wBAAwB,OAA4D;CAClG,MAAM,IAAI,MAAM,MAAM,CAAC,MAAM,wBAAwB;CACrD,IAAI,CAAC,GACH,OAAO;CACT,MAAM,OAAO,EAAE;CACf,MAAM,MAAM,EAAE;CACd,IAAI,CAAC,KACH,OAAO,EAAE,MAAM;CAGjB,IAAI,IAAI,SAAS,KAAK,EACpB,OAAO;EAAE;EAAM,WAAW,IAAI,MAAM,GAAG,GAAG;EAAE;CAC9C,OAAO;EAAE;EAAM,WAAW;EAAK;;;;;;;;;;;;;;;;AAiBjC,SAAgB,mBACd,aACA,OACA,SACS;CACT,MAAM,SAAS,wBAAwB,QAAQ;CAC/C,IAAI,CAAC,QACH,OAAO;CACT,IAAI,OAAO,SAAS,aAClB,OAAO;CACT,IAAI,OAAO,cAAc,KAAA,GACvB,OAAO;CAKT,KAAK,MAAM,SAAS,OAAO,OAAO,MAAM,EACtC,IAAI,OAAO,UAAU,YAAY,MAAM,WAAW,OAAO,UAAU,EACjE,OAAO;CAEX,OAAO;;;;;;;AAQT,SAAgB,qBACd,aACA,OACA,OACS;CACT,IAAI,MAAM,WAAW,GACnB,OAAO;CACT,OAAO,MAAM,MAAK,YAAW,mBAAmB,aAAa,OAAO,QAAQ,CAAC;;;;;ACxR/E,MAAa,iCAAoD;CAC/D;CACA;CACA;CACD;;;;;;;;;;;AAYD,SAAgB,wBACd,OACA,OACY;CACZ,SAAS,iBAAwD;EAC/D,MAAM,SAAS,MAAM,QAAQ;EAC7B,MAAM,WAAqB,EAAE;EAC7B,KAAK,MAAM,UAAU,QACnB,IAAI,OAAO,MAAM,cAAc,QAC7B,SAAS,KAAK,GAAG,OAAO,MAAM,aAAa;EAE/C,OAAO;GACL,OAAO,SAAS,SAAS,IAAI,CAAC,GAAG,UAAU,GAAG,+BAA+B,GAAG,EAAE;GAClF,QAAQ,OAAO,KAAI,MAAK,EAAE,MAAM,KAAK;GACtC;;CAGH,SAAS,YAAY,KAA2D;EAC9E,MAAM,EAAE,OAAO,WAAW,gBAAgB;EAC1C,IAAI,MAAM,WAAW,GACnB;EACF,IAAI,qBAAqB,IAAI,aAAa,IAAI,OAAO,MAAM,EACzD;EACF,MAAM,MAAM,IAAI,yBAAyB;GACvC,UAAU,IAAI;GACd,aAAa,IAAI;GACjB,cAAc;GACd,cAAc;GACf,CAAC;EACF,IAAI,QAAQ;EACZ,IAAI,SAAS,IAAI;;CAGnB,SAAS,eAAe,KAA8D;EACpF,MAAM,EAAE,OAAO,WAAW,gBAAgB;EAC1C,IAAI,MAAM,WAAW,GACnB;EACF,IAAI,qBAAqB,IAAI,aAAa,IAAI,OAAO,MAAM,EACzD;EACF,MAAM,MAAM,IAAI,yBAAyB;GACvC,UAAU,OAAO,IAAI,OAAO,GAAG,IAAI;GACnC,aAAa,IAAI;GACjB,cAAc;GACd,cAAc;GACf,CAAC;EACF,IAAI,QAAQ;EACZ,IAAI,SAAS,IAAI;;CAGnB,MAAM,iBAAiB,MAAM,KAAK,aAAa,YAAY;CAC3D,MAAM,gBAAgB,MAAM,KAAK,iBAAiB,eAAe;CAEjE,OAAO,SAAS,YAAY;EAC1B,gBAAgB;EAChB,eAAe;;;;;;;;;;;;;;;AClFnB,MAAM,SAAS;AACf,MAAM,QAAQ;AACd,MAAM,QAAQ;AACd,MAAM,UAAU;AAEhB,SAAgB,UAAU,KAAqB;CAC7C,OAAO,IACJ,QAAQ,QAAQ,QAAQ,CACxB,QAAQ,OAAO,OAAO,CACtB,QAAQ,OAAO,OAAO,CACtB,QAAQ,SAAS,SAAS;;;;;;;ACgB/B,SAAgB,aACd,QACA,UAA+B,EAAE,EACzB;CACR,IAAI,OAAO,WAAW,GACpB,OAAO;CAET,MAAM,uBAAuB,QAAQ,wBAAwB;CAC7D,MAAM,eAAe,QAAQ,gBAAgB;CAE7C,MAAM,UAAU,OAAO,KAAK,UAAU;EACpC,MAAM,eAAe,MAAM,WACvB,mBAAmB,UAAU,MAAM,SAAS,CAAC,eAC7C;EACJ,OAAO;YACC,UAAU,MAAM,KAAK,CAAC;mBACf,UAAU,MAAM,YAAY,CAAC,gBAAgB,aAAa;;GAEzE,CAAC,KAAK,KAAK;CAGb,MAAM,cAAc,OAAO,MAAK,MAAK,EAAE,SAAS;CAChD,MAAM,kBAAkB,OAAO,MAAK,MAAK,CAAC,EAAE,SAAS;CAErD,MAAM,kBAA4B,EAAE;CAEpC,gBAAgB,KACd,6EACA,iHACD;CAED,IAAI,sBACF,gBAAgB,KACd,+PAGA,8HACD;MAEE,IAAI,aACP,gBAAgB,KACd,yCAAyC,aAAa,gDACtD,oJACD;CAGH,IAAI,mBAAmB,CAAC,sBACtB,gBAAgB,KACd,sGACD;CAIH,MAAM,QAAkB;EACtB,gBAAgB,KAAK,KAAK;EAC1B;EACA;EACA;EACA;EACD;CAKD,IAAI,mBAAmB,CAAC,sBAAsB;EAC5C,MAAM,KAAK,GAAG;EACd,KAAK,MAAM,SAAS,QAClB,IAAI,CAAC,MAAM,YAAY,MAAM,cAAc;GACzC,MAAM,KAAK,6BAA6B,UAAU,MAAM,KAAK,CAAC,IAAI;GAClE,MAAM,KAAK,MAAM,aAAa;GAC9B,IAAI,MAAM,aAAa,MAAM,UAAU,SAAS,GAAG;IACjD,MAAM,KAAK,GAAG;IACd,MAAM,KAAK,oBAAoB;IAC/B,KAAK,MAAM,OAAO,MAAM,WACtB,MAAM,KAAK,iBAAiB,IAAI,KAAK,IAAI,UAAU,IAAI,KAAK,CAAC,SAAS;IAExE,MAAM,KAAK,qBAAqB;;GAElC,MAAM,KAAK,wBAAwB;;;CAKzC,OAAO,MAAM,KAAK,KAAK;;;;AC/FzB,MAAM,iBAAiB;AAEvB,MAAM,YAAY;AAClB,MAAM,QAAQ;AACd,MAAM,mBAAmB;AACzB,MAAM,mBAAmB;AACzB,MAAM,eAAe;AACrB,MAAM,sBAAsB;AAC5B,MAAM,qBAAqB;AAC3B,MAAM,oBAAoB;;;;;;;;;;;AAsB1B,SAAgB,iBAAiB,SAAkC;CACjE,MAAM,cAAiC,EAAE;CACzC,MAAM,QAAQ,QAAQ,MAAM,eAAe;CAC3C,IAAI,CAAC,OACH,OAAO;EAAE,aAAa,EAAE;EAAE,MAAM,QAAQ,MAAM;EAAE;EAAa;CAG/D,MAAM,YAAY,MAAM;CACxB,MAAM,OAAO,MAAM,GAAG,MAAM;CAG5B,MAAM,cAAuC,EAAE;CAC/C,IAAI,aAA4B;CAChC,IAAI,aAA4C;CAEhD,KAAK,MAAM,QAAQ,UAAU,MAAM,KAAK,EAAE;EAExC,IAAI,CAAC,KAAK,MAAM,IAAI,KAAK,MAAM,CAAC,WAAW,IAAI,EAC7C;EAGF,IAAI,cAAc,cAAc,UAAU,KAAK,KAAK,EAAE;GACpD,MAAM,cAAc,KAAK,MAAM,CAAC,MAAM,MAAM;GAC5C,IAAI,aAAa;IACf,MAAM,MAAM,YAAY,GAAG,MAAM;IACjC,WAAW,YAAY,GAAG,MAAM,IAAI,YAAY,IAAI;;GAEtD;;EAIF,IAAI,cAAc,YAAY;GAC5B,YAAY,cAAc;GAC1B,aAAa;GACb,aAAa;;EAIf,MAAM,UAAU,gBAAgB,KAAK;EACrC,IAAI,CAAC,SACH;EAEF,MAAM,MAAM,QAAQ,IAAI,MAAM;EAC9B,MAAM,WAAW,QAAQ,MAAM,MAAM;EAErC,IAAI,CAAC,UAAU;GAEb,aAAa;GACb,aAAa,EAAE;SAGf,YAAY,OAAO,YAAY,SAAS;;CAK5C,IAAI,cAAc,YAChB,YAAY,cAAc;CAG5B,OAAO;EAAE;EAAa;EAAM;EAAa;;AAG3C,SAAS,gBAAgB,MAAqD;CAC5E,MAAM,MAAM,KAAK,QAAQ,IAAI;CAC7B,IAAI,MAAM,GACR,OAAO;CACT,MAAM,MAAM,KAAK,MAAM,GAAG,IAAI;CAC9B,MAAM,QAAQ,KAAK,MAAM,MAAM,EAAE;CAGjC,IAAI,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,EACxB,OAAO;CACT,OAAO;EAAE;EAAK;EAAO;;;;;;;;;;;;;;;;AAiBvB,SAAS,YAAY,KAAqB;CACxC,MAAM,KAAK,IAAI,MAAM,iBAAiB;CACtC,IAAI,IACF,OAAO,GAAG,GAAG,QAAQ,eAAe,GAAG,OAAO;EAC5C,QAAQ,IAAR;GACE,KAAK,MAAK,OAAO;GACjB,KAAK,MAAM,OAAO;GAClB,KAAK,KAAK,OAAO;GACjB,KAAK,KAAK,OAAO;GACjB,KAAK,KAAK,OAAO;GACjB,KAAK,KAAK,OAAO;GACjB,KAAK,KAAK,OAAO;GACjB,KAAK,KAAK,OAAO;GACjB,SAAS,OAAO;;GAElB;CAEJ,MAAM,KAAK,IAAI,MAAM,iBAAiB;CACtC,IAAI,IACF,OAAO,GAAG,GAAG,QAAQ,OAAO,IAAK;CAKnC,MAAM,UAAU,IAAI,QAAQ,KAAK;CACjC,IAAI,WAAW,GACb,OAAO,IAAI,MAAM,GAAG,QAAQ,CAAC,SAAS;CACxC,OAAO;;;;;;;AAQT,SAAS,WACP,aACA,KACA,aACoB;CACpB,MAAM,MAAM,YAAY;CACxB,IAAI,QAAQ,KAAA,KAAa,QAAQ,MAC/B,OAAO,KAAA;CACT,IAAI,OAAO,QAAQ,UACjB,OAAO;CACT,YAAY,KAAK;EACf,UAAU;EACV,MAAM;EACN,SAAS,sBAAsB,IAAI,yBAAyB,OAAO,IAAI;EACvE,OAAO;EACR,CAAC;CACF,OAAO,OAAO,IAAI;;AAOpB,MAAM,gBAAuD;CAC3D,SAAS;CACT,YAAY;CACZ,QAAQ;CACT;AAED,SAAS,mBAAmB,SAAkC;CAC5D,MAAM,YAA6B,EAAE;CAErC,KAAK,MAAM,CAAC,KAAK,SAAS,OAAO,QAAQ,cAAc,EAAE;EACvD,MAAM,UAAU,KAAK,SAAS,IAAI;EAClC,IAAI,CAAC,WAAW,QAAQ,IAAI,CAAC,SAAS,QAAQ,CAAC,aAAa,EAC1D;EACF,IAAI;GAKF,MAAM,QAAQ,YAAY,SAAS,EAAE,WAAW,MAAM,CAAC;GACvD,KAAK,MAAM,QAAQ,OAAO;IACxB,MAAM,MAAM,OAAO,SAAS,WAAW,OAAO,KAAK,SAAS,QAAQ;IAEpE,IAAI,SADa,KAAK,SAAS,IACV,CAAC,CAAC,QAAQ,EAC7B,UAAU,KAAK;KAAE,MAAM,KAAK,KAAK,IAAI;KAAE;KAAM,CAAC;;UAI9C;;CAMR,IAAI;EACF,KAAK,MAAM,SAAS,YAAY,QAAQ,EAAE;GACxC,IAAI,UAAU,YACZ;GAEF,IAAI,SADc,KAAK,SAAS,MACV,CAAC,CAAC,QAAQ,EAC9B,UAAU,KAAK;IAAE,MAAM;IAAO,MAAM;IAAS,CAAC;;SAI9C;CAIN,OAAO;;;;;;;;;;;;;AAuBT,eAAsB,eACpB,UACA,UAA6B,EAAE,EACF;CAC7B,MAAM,UAAU,QAAQ,SAAS;CACjC,IAAI,CAAC,WAAW,QAAQ,EACtB,OAAO;CAGT,MAAM,EAAE,aAAa,MAAM,gBAAgB,iBAD3B,aAAa,SAAS,QAC6B,CAAC;CAGpE,IAAI,cAAc,WAAW,aAAa,eAAe,YAAY;CACrE,IAAI,CAAC,eAAe,MAAM;EACxB,MAAM,iBAAiB,KAAK,MAAM,mBAAmB,CAAC,IAAI,MAAM;EAChE,IAAI,gBACF,cAAc;;CAElB,IAAI,CAAC,aACH,OAAO;CAET,IAAI,YAAY,SAAS,MACvB,YAAY,KAAK;EACf,UAAU;EACV,MAAM;EACN,SAAS,0DAA0D,YAAY,OAAO;EACtF,OAAO;EACR,CAAC;CAGJ,MAAM,UAAU,QAAQ,QAAQ;CAChC,MAAM,UAAU,SAAS,QAAQ;CACjC,MAAM,kBAAkB,WAAW,aAAa,QAAQ,YAAY;CACpE,MAAM,OAAO,mBAAmB;CAGhC,IAAI,mBAAmB,oBAAoB,SACzC,YAAY,KAAK;EACf,UAAU;EACV,MAAM;EACN,SAAS,eAAe,gBAAgB,qCAAqC,QAAQ;EACrF,OAAO;EACR,CAAC;CAEJ,IAAI,KAAK,SAAS,IAChB,YAAY,KAAK;EACf,UAAU;EACV,MAAM;EACN,SAAS,eAAe,KAAK;EAC7B,OAAO;EACR,CAAC;CAEJ,IAAI,CAAC,kBAAkB,KAAK,EAC1B,YAAY,KAAK;EACf,UAAU;EACV,MAAM;EACN,SAAS,eAAe,KAAK;EAC7B,OAAO;EACR,CAAC;CAGJ,MAAM,SAAsB;EAC1B;EACA;EACA,cAAc;EACd,QAAQ,QAAQ,UAAU;EAC1B,UAAU;EACV;EACA,WAAW,mBAAmB,QAAQ;EACvC;CAED,MAAM,UAAU,WAAW,aAAa,WAAW,YAAY;CAC/D,IAAI,SACF,OAAO,UAAU;CAEnB,MAAM,gBAAgB,WAAW,aAAa,iBAAiB,YAAY;CAC3E,IAAI,eAAe;EACjB,IAAI,cAAc,SAAS,KACzB,YAAY,KAAK;GACf,UAAU;GACV,MAAM;GACN,SAAS,2DAA2D,cAAc,OAAO;GACzF,OAAO;GACR,CAAC;EAEJ,OAAO,gBAAgB;;CAIzB,MAAM,WAAmC,EAAE;CAC3C,MAAM,cAAc,YAAY;CAChC,IAAI,eAAe,OAAO,gBAAgB,YAAY,CAAC,MAAM,QAAQ,YAAY,EAC/E,KAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,YAAuC,EAAE;EAC3E,IAAI,OAAO,MAAM,UAAU;GACzB,YAAY,KAAK;IACf,UAAU;IACV,MAAM;IACN,SAAS,uBAAuB,EAAE;IAClC,OAAO;IACR,CAAC;GACF,SAAS,KAAK,OAAO,EAAE;GACvB;;EAEF,SAAS,KAAK;;MAGb,IAAI,gBAAgB,KAAA,GACvB,YAAY,KAAK;EACf,UAAU;EACV,MAAM;EACN,SAAS,8CAA8C,MAAM,QAAQ,YAAY,GAAG,UAAU,OAAO,YAAY;EACjH,OAAO;EACR,CAAC;CAIJ,MAAM,aAAa,WAAW,aAAa,SAAS,YAAY;CAChE,IAAI,YAAY;EACd,SAAS,kBAAkB,WAAW,MAAM,kBAAkB,CAAC,OAAO,QAAQ,CAAC,KAAK,IAAI;EACxF,YAAY,KAAK;GACf,UAAU;GACV,MAAM;GACN,SAAS;GACT,OAAO;GACR,CAAC;;CAEJ,MAAM,aAAa,WAAW,aAAa,SAAS,YAAY;CAChE,IAAI,YAAY;EACd,SAAS,kBAAkB;EAC3B,YAAY,KAAK;GACf,UAAU;GACV,MAAM;GACN,SAAS;GACT,OAAO;GACR,CAAC;;CAEJ,MAAM,gBAAgB,WAAW,aAAa,YAAY,YAAY;CACtE,MAAM,cAAc,gBAAgB,KAAA,IAAY,WAAW,aAAa,UAAU,YAAY;CAC9F,MAAM,iBAAiB,iBAAiB;CACxC,IAAI,gBAAgB;EAClB,SAAS,qBAAqB;EAC9B,YAAY,KAAK;GACf,UAAU;GACV,MAAM;GACN,SAAS,KAAK,gBAAgB,aAAa,SAAS;GACpD,OAAO,gBAAgB,aAAa;GACrC,CAAC;;CAGJ,IAAI,OAAO,KAAK,SAAS,CAAC,SAAS,GACjC,OAAO,WAAW;CAEpB,MAAM,eAAe,WAAW,aAAa,iBAAiB,YAAY;CAC1E,IAAI,cACF,OAAO,eAAe,aAAa,MAAM,oBAAoB,CAAC,OAAO,QAAQ;CAG/E,IAAI,YAAY,SAAS,GACvB,OAAO,cAAc;CAEvB,OAAO;;AAOT,MAAM,YAAY,IAAI,IAAI;CAAC;CAAQ;CAAgB;CAAa;CAAQ;CAAQ,CAAC;AAEjF,SAAS,cAAc,MAAc,WAAW,GAAG,SAAS,GAAa;CACvE,IAAI,SAAS,UACX,OAAO,EAAE;CACX,IAAI,CAAC,WAAW,KAAK,IAAI,CAAC,SAAS,KAAK,CAAC,aAAa,EACpD,OAAO,EAAE;CAEX,MAAM,UAAoB,EAAE;CAC5B,IAAI;EACF,KAAK,MAAM,SAAS,YAAY,KAAK,EAAE;GACrC,IAAI,UAAU,IAAI,MAAM,EACtB;GACF,MAAM,YAAY,KAAK,MAAM,MAAM;GACnC,IAAI,CAAC,SAAS,UAAU,CAAC,aAAa,EACpC;GAEF,MAAM,YAAY,KAAK,WAAW,WAAW;GAC7C,IAAI,WAAW,UAAU,IAAI,SAAS,UAAU,CAAC,QAAQ,EACvD,QAAQ,KAAK,UAAU;QAIvB,QAAQ,KAAK,GAAG,cAAc,WAAW,UAAU,SAAS,EAAE,CAAC;;SAI/D;CAGN,OAAO;;;;;;;AAkBT,SAAgB,sBAAyC;CACvD,MAAM,OAAO,SAAS;CACtB,MAAM,MAAM,QAAQ,KAAK;CACzB,OAAO;EAEL;GAAE,MAAM,KAAK,KAAK,WAAW,SAAS;GAAE,QAAQ;GAAW;EAC3D;GAAE,MAAM,KAAK,KAAK,WAAW,SAAS;GAAE,QAAQ;GAAW;EAE3D;GAAE,MAAM,KAAK,MAAM,WAAW,SAAS;GAAE,QAAQ;GAAQ;EACzD;GAAE,MAAM,KAAK,MAAM,WAAW,SAAS;GAAE,QAAQ;GAAQ;EAC1D;;;;;;AAOH,SAAgB,YAAY,MAA2B;CACrD,OAAO,KAAK,WAAW,SAAS,CAAC,GAAG,SAAS;;;;;;;AAY/C,eAAsB,eAAe,OAAkD;CACrF,MAAM,+BAAe,IAAI,KAA0B;CAEnD,KAAK,MAAM,EAAE,MAAM,UAAU,YAAY,OAAO;EAC9C,MAAM,aAAa,cAAc,QAAQ,SAAS,CAAC;EACnD,KAAK,MAAM,QAAQ,YAAY;GAC7B,MAAM,QAAQ,MAAM,eAAe,MAAM,EAAE,QAAQ,CAAC;GACpD,IAAI,CAAC,OACH;GACF,IAAI,aAAa,IAAI,MAAM,KAAK,EAAE;IAEhC,MAAM,WAAW,aAAa,IAAI,MAAM,KAAK;IAC7C,MAAM,OAAwB;KAC5B,UAAU;KACV,MAAM;KACN,SAAS,sBAAsB,MAAM,KAAK,sBAAsB,KAAK,YAAY,OAAO,iBAAiB,SAAS,SAAS,YAAY,SAAS,OAAO;KACxJ;IACD,SAAS,cAAc,CAAC,GAAI,SAAS,eAAe,EAAE,EAAG,KAAK;IAC9D;;GAEF,aAAa,IAAI,MAAM,MAAM,MAAM;;;CAIvC,OAAO,CAAC,GAAG,aAAa,QAAQ,CAAC;;;;AC/gBnC,MAAM,mBAAmB;AACzB,MAAM,wBAAwB;AAC9B,MAAM,YAAY;AAClB,MAAM,sBAAsB;AAE5B,SAAS,WAAW,OAAuB;CAIzC,IAAI,iBAAiB,KAAK,MAAM,IAAI,sBAAsB,KAAK,MAAM,IAAI,UAAU,IACjF,OAAO,IAAI,MAAM,QAAQ,WAAW,OAAM,CAAC;CAC7C,OAAO;;AAGT,SAAS,qBAAqB,OAA4B;CACxD,MAAM,QAAkB,CAAC,MAAM;CAE/B,MAAM,KAAK,SAAS,WAAW,MAAM,KAAK,GAAG;CAC7C,MAAM,KAAK,gBAAgB,WAAW,MAAM,YAAY,GAAG;CAE3D,IAAI,MAAM,SACR,MAAM,KAAK,YAAY,WAAW,MAAM,QAAQ,GAAG;CACrD,IAAI,MAAM,eACR,MAAM,KAAK,kBAAkB,WAAW,MAAM,cAAc,GAAG;CACjE,IAAI,MAAM,cAAc,QACtB,MAAM,KAAK,kBAAkB,MAAM,aAAa,KAAK,IAAI,GAAG;CAE9D,IAAI,MAAM,YAAY,OAAO,KAAK,MAAM,SAAS,CAAC,SAAS,GAAG;EAC5D,MAAM,KAAK,YAAY;EACvB,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,SAAS,EAIvD,MAAM,KAAK,KAAK,IAAI,KAAK,MAAM,QAAQ,WAAW,OAAM,CAAC,GAAG;;CAIhE,MAAM,KAAK,MAAM;CACjB,OAAO,MAAM,KAAK,KAAK;;;;;;;;;;AAezB,SAAgB,iBAAiB,OAAoB,WAA2B;CAC9E,MAAM,SAAS,sBAAsB,MAAM;CAC3C,IAAI,CAAC,OAAO,OAAO;EACjB,MAAM,UAAU,OAAO,OACpB,KAAI,MAAK,QAAQ,EAAE,KAAK,IAAI,EAAE,UAAU,CACxC,KAAK,KAAK;EACb,MAAM,IAAI,MAAM,+BAA+B,MAAM,KAAK,MAAM,UAAU;;CAG5E,MAAM,WAAW,KAAK,WAAW,MAAM,KAAK;CAC5C,UAAU,UAAU,EAAE,WAAW,MAAM,CAAC;CAExC,MAAM,cAAc,qBAAqB,MAAM;CAI/C,MAAM,cAAc,MAAM,eAAe,MAAM,aAAa,QAAQ,qBAAqB,GAAG,GAAG;CAC/F,MAAM,UAAU,cACZ,GAAG,YAAY,MAAM,YAAY,MACjC,GAAG,YAAY;CAEnB,MAAM,YAAY,KAAK,UAAU,WAAW;CAC5C,cAAc,WAAW,QAAQ;CAEjC,OAAO;;;;;;;AAYT,SAAgB,kBAAkB,QAAuB,WAA2B;CAClF,UAAU,WAAW,EAAE,WAAW,MAAM,CAAC;CACzC,KAAK,MAAM,SAAS,QAClB,iBAAiB,OAAO,UAAU;CAEpC,OAAO;;;;;;;;;;;;;;;;;AClET,eAAsB,cAAc,QAAqD;CACvF,MAAM,eAAkC,EAAE;CAC1C,IAAI;CAEJ,IAAI,CAAC,OAAO,kBACV,aAAa,KAAK,GAAG,qBAAqB,CAAC;CAI7C,KAAK,MAAM,KAAK,OAAO,QAAQ,EAAE,EAC/B,aAAa,KAAK;EAAE,MAAM;EAAG,QAAQ,YAAY,EAAE;EAAE,CAAC;CAIxD,IAAI,OAAO,OAAO,QAAQ;EACxB,WAAW,YAAY,KAAK,QAAQ,EAAE,iBAAiB,CAAC;EACxD,kBAAkB,OAAO,OAAO,SAAS;EACzC,aAAa,KAAK;GAAE,MAAM;GAAU,QAAQ;GAAU,CAAC;;CAIzD,IAAI,SAAS,MAAM,eAAe,aAAa;CAM/C,IAAI,OAAO,uBAAuB,OAChC,SAAS,OAAO,QAAO,MAAK,EAAE,WAAW,KAAA,KAAa,EAAE,WAAW,UAAU;CAI/E,MAAM,UAAU,IAAI,IAAI,OAAO,WAAW,EAAE,CAAC;CAC7C,IAAI,WAAW,OAAO,QAAO,MAAK,CAAC,QAAQ,IAAI,EAAE,KAAK,CAAC;CAGvD,IAAI,MAAM,QAAQ,OAAO,QAAQ,EAAE;EACjC,MAAM,YAAY,IAAI,IAAI,OAAO,QAAQ;EACzC,WAAW,SAAS,QAAO,MAAK,UAAU,IAAI,EAAE,KAAK,CAAC;;CAexD,OAAO;EAAE,QAAQ;EAAU,SAZX,iBACN;GACJ,IAAI;IACF,OAAO,UAAW;KAAE,WAAW;KAAM,OAAO;KAAM,CAAC;WAE/C;YAKF;EAE0B;;;;;AClFtC,MAAM,yBAAyB;;;;;;;;;;;;;AAc/B,eAAsB,yBACpB,cACA,WACA,QACiB;CACjB,MAAM,UAAU,CAAC,GAAG,aAAa,SAAS,uBAAuB,CAAC;CAClE,IAAI,QAAQ,WAAW,GACrB,OAAO;CAGT,MAAM,eAAoE,EAAE;CAE5E,KAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,UAAU,MAAM;EACtB,MAAM,QAAQ,MAAM;EACpB,MAAM,SAAS,MAAM,GAAG;EAExB,IAAI;GACF,MAAM,SAAS,MAAM,UAAU,KAAK,QAAQ,SAAS,EAAE,SAAS,IAAI,CAAC;GACrE,MAAM,SAAS,OAAO,aAAa,IAC/B,OAAO,OAAO,MAAM,GACpB,yBAAyB,OAAO,SAAS,KAAK,OAAO,OAAO,MAAM,IAAI,OAAO,OAAO,MAAM,CAAC;GAC/F,aAAa,KAAK;IAAE;IAAO;IAAQ;IAAQ,CAAC;WAEvC,KAAK;GACV,MAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;GAChE,aAAa,KAAK;IAAE;IAAO;IAAQ,QAAQ,mBAAmB,QAAQ;IAAI,CAAC;;;CAK/E,IAAI,SAAS;CACb,KAAK,IAAI,IAAI,aAAa,SAAS,GAAG,KAAK,GAAG,KAAK;EACjD,MAAM,EAAE,OAAO,QAAQ,WAAW,aAAa;EAC/C,SAAS,OAAO,MAAM,GAAG,MAAM,GAAG,SAAS,OAAO,MAAM,QAAQ,OAAO;;CAGzE,OAAO"}
|
package/dist/mcp-8wClKY-3.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-8wClKY-3.js","names":[],"sources":["../src/mcp/sse-to-json-fetch.ts","../src/mcp/tolerant-client.ts","../src/mcp/index.ts"],"sourcesContent":["/**\n * `fetch` shim that converts streamable-http POST responses with\n * `Content-Type: text/event-stream` into synthetic `application/json`\n * responses, preserving every original header (notably `mcp-session-id`).\n *\n * Why this exists\n * ----------------\n * The MCP SDK's streamable-http transport handles POST responses two ways\n * depending on `content-type`:\n *\n * - `application/json` → `await response.json()` (works on every runtime).\n * - `text/event-stream` → `body.pipeThrough(TextDecoderStream)\n * .pipeThrough(EventSourceParserStream)`\n * and forward each parsed event to `onmessage`.\n *\n * On Bun + MCP SDK 1.29.x the second pipeline silently drops the parsed\n * event: the full `event: message\\ndata: {...}\\n\\n` arrives intact, the\n * stream closes, but `onmessage` is never called. Bootstrap then waits the\n * full `bootstrapTimeout` (10s default) and the agent loses every tool the\n * server would have exposed.\n *\n * The MCP spec lets clients accept either content type\n * (`Accept: application/json, text/event-stream`), so flipping the stream\n * to JSON at the boundary is a transparent, server-agnostic workaround.\n *\n * Scope of the shim\n * -----------------\n * - POST + `text/event-stream` → drain, parse SSE message events, return\n * a synthetic `application/json` response. Single event becomes a JSON\n * object (matching the shape the SDK expects from non-streaming\n * servers); multiple events become a JSON array (the SDK already\n * iterates `Array.isArray(data)` from a JSON response).\n * - GET (long-lived `_startOrAuthSse` listener) → untouched. Per-event\n * latency matters there and the SSE pipeline isn't always broken on\n * GET in the same way (different code path inside Bun's stream impl).\n * - 202 / non-SSE / malformed SSE / no body → passthrough.\n *\n * Runtime gating\n * --------------\n * `sseToJsonFetchIfNeeded()` only returns a wrapper on Bun. Node + browser\n * runtimes get `undefined` and the SDK uses global `fetch` directly — no\n * extra buffer-and-redrain on the happy path, and no risk of collapsing a\n * future progress-streaming response into a single batched array. If you\n * need to apply the shim unconditionally (testing, custom hosts), call\n * `sseToJsonFetch()` directly.\n *\n * Cleanup\n * -------\n * Remove this file and its `fetch:` injection in `createTransport` once\n * either Bun fixes the `pipeThrough` chain or the SDK switches off the\n * streaming pipeline by default.\n */\n\n/**\n * Detect whether we're running on Bun. The `Bun` global is set by the\n * runtime itself and isn't faked by Bun's Node-compat layer.\n */\nfunction isBunRuntime(): boolean {\n return typeof (globalThis as { Bun?: unknown }).Bun !== 'undefined'\n}\n\n/**\n * Returns the `sseToJsonFetch` wrapper only on runtimes that need it\n * (currently Bun). Returns `undefined` everywhere else, which makes the\n * SDK fall back to the global `fetch` and keeps the streaming pipeline\n * intact on Node where it works correctly.\n *\n * Designed as the value to pass directly to `StreamableHTTPClientTransport`'s\n * `fetch` option:\n *\n * new StreamableHTTPClientTransport(url, {\n * fetch: sseToJsonFetchIfNeeded(),\n * })\n */\nexport function sseToJsonFetchIfNeeded(): typeof fetch | undefined {\n return isBunRuntime() ? sseToJsonFetch() : undefined\n}\n\n/**\n * Wrap a `fetch` implementation so streamable-http POST responses that come\n * back as `text/event-stream` are converted to JSON. Pass the result as\n * `opts.fetch` to `StreamableHTTPClientTransport`.\n *\n * Always-on (i.e. unconditional) — for the runtime-gated entry point,\n * use {@link sseToJsonFetchIfNeeded} instead.\n */\nexport function sseToJsonFetch(baseFetch: typeof fetch = fetch): typeof fetch {\n return async function sseToJsonWrappedFetch(input, init) {\n const response = await baseFetch(input, init)\n\n // Only intercept POSTs. The SDK's GET path opens a long-lived SSE\n // listener (`_startOrAuthSse`) that we must not buffer-drain.\n const method = (init?.method ?? 'GET').toString().toUpperCase()\n if (method !== 'POST')\n return response\n\n const contentType = response.headers.get('content-type')\n if (!contentType || !contentType.includes('text/event-stream'))\n return response\n\n if (!response.body)\n return response\n\n let raw: string\n try {\n raw = await response.text()\n }\n catch {\n // Bun edge case: if even .text() fails, surrender — the original\n // response is already drained, so we can't recover. Return it; the\n // SDK will surface the underlying read error.\n return response\n }\n\n const events = parseSseDataEvents(raw)\n // Single event → bare object; multi-event or zero → array. The SDK's\n // JSON branch handles both shapes (`Array.isArray(data) ? data.map(…) : …`).\n const payload = events.length === 1 ? events[0] : events\n return synthesizeJsonResponse(response, payload)\n } as typeof fetch\n}\n\n/**\n * Parse a buffered SSE body into the JSON payloads of its `message` events.\n *\n * Skips:\n * - SSE comments (lines starting with `:`).\n * - Non-default event types (`event: foo` ≠ `message`). The MCP server\n * only ever emits `message` events for JSON-RPC; anything else is out of\n * band and the SDK wouldn't have surfaced it to `onmessage` either.\n * - Malformed `data:` payloads (anything that fails `JSON.parse`).\n */\nfunction parseSseDataEvents(raw: string): unknown[] {\n const events: unknown[] = []\n for (const block of raw.split(/\\r?\\n\\r?\\n/)) {\n if (!block.trim())\n continue\n\n const dataLines: string[] = []\n let isMessageEvent = true\n for (const line of block.split(/\\r?\\n/)) {\n if (line.startsWith(':'))\n continue\n if (line.startsWith('event:')) {\n const eventType = line.slice('event:'.length).trim()\n if (eventType && eventType !== 'message')\n isMessageEvent = false\n }\n else if (line.startsWith('data:')) {\n // Per SSE spec: a single leading space after `data:` is part of the\n // separator, not the payload. Anything beyond it is.\n const value = line.slice('data:'.length)\n dataLines.push(value.startsWith(' ') ? value.slice(1) : value)\n }\n }\n\n if (!isMessageEvent || dataLines.length === 0)\n continue\n\n try {\n events.push(JSON.parse(dataLines.join('\\n')))\n }\n catch {\n // Drop malformed events. The SDK's broken pipe would have dropped\n // them too — staying silent here matches that baseline.\n }\n }\n return events\n}\n\n/**\n * Build a `Response` mirroring the original's status / statusText / headers\n * but with a JSON body and `content-type: application/json`. Header\n * preservation is the whole point — `mcp-session-id` is set by the server\n * on the initialize POST and must round-trip into the SDK's\n * `_sessionId` capture (`response.headers.get('mcp-session-id')`).\n */\nfunction synthesizeJsonResponse(original: Response, payload: unknown): Response {\n const headers = new Headers(original.headers)\n headers.set('content-type', 'application/json')\n return new Response(JSON.stringify(payload), {\n status: original.status,\n statusText: original.statusText,\n headers,\n })\n}\n","/**\n * Drop-in `Client` subclass whose `connect()` mirrors the upstream MCP SDK\n * sequence but treats `notifications/initialized` as best-effort.\n *\n * The MCP spec marks that notification fire-and-forget, but the SDK awaits\n * the underlying transport `send()` and rethrows on any HTTP 4xx. Several\n * real-world streamable-http servers (e.g. browser-codemode, custom MCPs\n * that gate non-initialize routes on a session id that didn't yet exist when\n * the notification posted) reject the notification with a 4xx and still\n * accept every subsequent request. The base `Client.connect()` then closes\n * the transport, the bootstrap fails, and the agent silently loses every\n * tool the server would have exposed.\n *\n * This subclass changes only that single step — log + continue if the\n * notification throws. Initialize, capability/version capture,\n * `setProtocolVersion`, listChanged handler wiring, and the close-on-failure\n * path for everything else are preserved verbatim from the SDK.\n *\n * Should be removed when the SDK lands an opt-in tolerance flag upstream.\n */\nimport { Client } from '@modelcontextprotocol/sdk/client/index.js'\nimport { Protocol } from '@modelcontextprotocol/sdk/shared/protocol.js'\nimport {\n InitializeResultSchema,\n LATEST_PROTOCOL_VERSION,\n SUPPORTED_PROTOCOL_VERSIONS,\n} from '@modelcontextprotocol/sdk/types.js'\n\n// Private fields the override needs to read/write to mirror upstream behavior.\n// Cast surface is isolated to this one type so the rest of the file stays clean.\ninterface ClientPrivates {\n _capabilities: unknown\n _clientInfo: unknown\n _serverCapabilities: unknown\n _serverVersion: unknown\n _instructions: unknown\n _pendingListChangedConfig?: unknown\n _setupListChangedHandlers: (config: unknown) => void\n}\n\ninterface MaybeSessionedTransport {\n sessionId?: unknown\n setProtocolVersion?: (v: string) => void\n}\n\nexport class TolerantMcpClient extends Client {\n async connect(\n transport: Parameters<Client['connect']>[0],\n options?: Parameters<Client['connect']>[1],\n ): Promise<void> {\n // Wire the transport (Protocol.connect — onmessage/onclose/onerror hooks\n // and transport.start) without sending any messages. We MUST NOT call\n // `super.connect()` here — that's `Client.connect`, which would\n // re-execute the very initialize+notification dance we're overriding.\n await Protocol.prototype.connect.call(this as never, transport)\n\n // Reconnect path: the upstream client short-circuits on a transport that\n // already carries a session id, so do we.\n if ((transport as MaybeSessionedTransport).sessionId !== undefined)\n return\n\n const self = this as unknown as ClientPrivates\n\n try {\n const result = await this.request(\n {\n method: 'initialize',\n params: {\n protocolVersion: LATEST_PROTOCOL_VERSION,\n capabilities: self._capabilities,\n clientInfo: self._clientInfo,\n },\n },\n InitializeResultSchema,\n options,\n )\n\n if (result === undefined)\n throw new Error(`Server sent invalid initialize result: ${result}`)\n if (!SUPPORTED_PROTOCOL_VERSIONS.includes(result.protocolVersion))\n throw new Error(`Server's protocol version is not supported: ${result.protocolVersion}`)\n\n self._serverCapabilities = result.capabilities\n self._serverVersion = result.serverInfo\n\n const setProtocolVersion = (transport as MaybeSessionedTransport).setProtocolVersion\n if (setProtocolVersion)\n setProtocolVersion.call(transport, result.protocolVersion)\n\n self._instructions = result.instructions\n\n // Best-effort. The session id (if any) is already captured by the\n // transport from the `initialize` response headers, so subsequent\n // requests like `tools/list` still authenticate. Don't bring down the\n // whole connection on a 4xx for a fire-and-forget notification.\n try {\n await this.notification({ method: 'notifications/initialized' })\n }\n catch (notifyError) {\n const msg = notifyError instanceof Error ? notifyError.message : String(notifyError)\n console.warn(`[zidane:mcp] server rejected notifications/initialized (continuing): ${msg}`)\n }\n\n if (self._pendingListChangedConfig) {\n self._setupListChangedHandlers(self._pendingListChangedConfig)\n self._pendingListChangedConfig = undefined\n }\n }\n catch (error) {\n // Same failure path as upstream Client — anything *other* than the\n // tolerated notification failure tears the transport down so the\n // bootstrap surfaces a clear error.\n void this.close()\n throw error\n }\n }\n}\n","/**\n * MCP (Model Context Protocol) server support.\n *\n * Connects to one or more MCP servers, discovers their tools,\n * and wraps them as zidane ToolDefs for use in agent loops.\n */\n\nimport type { Client } from '@modelcontextprotocol/sdk/client/index.js'\nimport type { Hookable } from 'hookable'\nimport type { AgentHooks } from '../agent'\nimport type { ToolContext, ToolDef } from '../tools/types'\nimport type { McpServerConfig, ToolResultContent } from '../types'\nimport { Buffer } from 'node:buffer'\nimport { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js'\nimport { getDefaultEnvironment, StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js'\nimport { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'\nimport { toolOutputByteLength } from '../types'\nimport { sseToJsonFetchIfNeeded } from './sse-to-json-fetch'\nimport { TolerantMcpClient } from './tolerant-client'\n\nexport type { McpServerConfig } from '../types'\n\nexport interface McpConnection {\n tools: Record<string, ToolDef>\n close: () => Promise<void>\n}\n\n// ---------------------------------------------------------------------------\n// Shape normalization\n// ---------------------------------------------------------------------------\n\ninterface RawServerShape {\n name?: string\n transport?: string\n type?: string\n command?: string\n args?: string[]\n env?: Record<string, string>\n strictEnv?: boolean\n url?: string\n httpUrl?: string\n sseUrl?: string\n headers?: Record<string, string>\n bootstrapTimeout?: number\n toolTimeout?: number\n enabledTools?: string[]\n disabledTools?: string[]\n toolFilter?: McpServerConfig['toolFilter']\n [key: string]: unknown\n}\n\nconst DEFAULT_MCP_BOOTSTRAP_TIMEOUT_MS = 10_000\n\nfunction inferTransport(raw: RawServerShape): McpServerConfig['transport'] {\n if (raw.transport === 'stdio' || raw.transport === 'sse' || raw.transport === 'streamable-http')\n return raw.transport\n if (raw.type === 'stdio' || raw.type === 'sse' || raw.type === 'streamable-http' || raw.type === 'http')\n return raw.type === 'http' ? 'streamable-http' : raw.type\n if (raw.command)\n return 'stdio'\n if (raw.httpUrl)\n return 'streamable-http'\n if (raw.sseUrl)\n return 'sse'\n if (raw.url)\n return 'streamable-http'\n throw new Error(`Cannot infer MCP transport from config: ${JSON.stringify(raw)}`)\n}\n\nfunction normalizeOne(name: string, raw: RawServerShape): McpServerConfig {\n const transport = inferTransport(raw)\n const url = raw.url ?? raw.httpUrl ?? raw.sseUrl\n\n const config: McpServerConfig = { name, transport }\n if (raw.command)\n config.command = raw.command\n if (raw.args)\n config.args = raw.args\n if (raw.env)\n config.env = raw.env\n if (raw.strictEnv === true)\n config.strictEnv = true\n if (url)\n config.url = url\n if (raw.headers)\n config.headers = raw.headers\n if (typeof raw.bootstrapTimeout === 'number')\n config.bootstrapTimeout = raw.bootstrapTimeout\n if (typeof raw.toolTimeout === 'number')\n config.toolTimeout = raw.toolTimeout\n if (Array.isArray(raw.enabledTools))\n config.enabledTools = raw.enabledTools\n if (Array.isArray(raw.disabledTools))\n config.disabledTools = raw.disabledTools\n if (typeof raw.toolFilter === 'function')\n config.toolFilter = raw.toolFilter\n\n return config\n}\n\n/**\n * True when the input looks like a single config object (flat fields like `command`,\n * `transport`, `url`) rather than a record whose values are configs.\n */\nfunction looksLikeSingleConfig(obj: Record<string, unknown>): boolean {\n const singleConfigKeys = ['transport', 'type', 'command', 'url', 'httpUrl', 'sseUrl']\n return singleConfigKeys.some(key => typeof obj[key] === 'string')\n}\n\n/**\n * Normalize MCP server configs from any common shape to `McpServerConfig[]`.\n *\n * Accepts:\n * - `McpServerConfig[]` — zidane native (pass-through).\n * - `McpServerConfig` — a single config object (wrapped to a 1-element array).\n * - `Record<string, RawShape>` — name-keyed map (common in host-SDK configs), where the key is the server name.\n * - Mixed shapes with `type` vs `transport`, `httpUrl`/`sseUrl` vs `url`.\n *\n * Returns `[]` when `input` is nullish. Throws a descriptive error when the transport\n * cannot be inferred from a given entry, or when the input shape is unsupported.\n */\nexport function normalizeMcpServers(input: unknown): McpServerConfig[] {\n if (input == null)\n return []\n\n if (Array.isArray(input)) {\n return input.map((raw, idx) => {\n const obj = raw as RawServerShape\n const name = obj.name ?? `mcp_${idx}`\n return normalizeOne(name, obj)\n })\n }\n\n if (typeof input === 'object') {\n const obj = input as Record<string, unknown>\n // Single-config heuristic: flat fields like `transport`/`command`/`url` at the top\n // level indicate a single McpServerConfig, not a record of configs.\n if (looksLikeSingleConfig(obj)) {\n const raw = obj as RawServerShape\n const name = raw.name ?? 'mcp_0'\n return [normalizeOne(name, raw)]\n }\n return Object.entries(obj as Record<string, RawServerShape>).map(\n ([name, raw]) => normalizeOne(name, raw ?? {}),\n )\n }\n\n throw new Error(`Unsupported MCP server config shape: ${typeof input}`)\n}\n\n/**\n * Lossy flattener — converts MCP `CallToolResult.content` blocks to a single\n * string. Text blocks are extracted; non-text blocks are JSON-stringified.\n *\n * Use this only at UI / log boundaries that require a string. The agent\n * loop itself routes through {@link normalizeMcpBlocks} so image blocks\n * survive into provider-native tool_result content (Anthropic blocks,\n * OpenAI companion-user-message).\n */\nexport function resultToString(content: unknown[]): string {\n if (!content || !Array.isArray(content))\n return ''\n return content\n .map((block) => {\n if (block && typeof block === 'object' && (block as { type?: unknown }).type === 'text') {\n const text = (block as { text?: unknown }).text\n if (typeof text === 'string')\n return text\n }\n return JSON.stringify(block)\n })\n .join('\\n')\n}\n\n/**\n * Normalize MCP `CallToolResult.content` to zidane's {@link ToolResultContent[]} shape.\n *\n * Handles the four MCP content block types:\n * - `text` → preserved as `{type:'text', text}`\n * - `image` → preserved as `{type:'image', mediaType, data}` (MCP uses `mimeType`)\n * - `resource` with embedded text → flattened to a text block\n * - `resource` with embedded blob whose `mimeType` is `image/*` → flattened to an image block\n * - Any unrecognized block → JSON-stringified fallback text block (lossy but safe)\n *\n * Returns `null` when the input is not an array — callers should fall back to an empty\n * result in that case.\n */\nexport function normalizeMcpBlocks(content: unknown): ToolResultContent[] | null {\n if (!Array.isArray(content))\n return null\n\n const out: ToolResultContent[] = []\n for (const raw of content) {\n if (!raw || typeof raw !== 'object')\n continue\n const block = raw as Record<string, unknown>\n\n if (block.type === 'text' && typeof block.text === 'string') {\n out.push({ type: 'text', text: block.text })\n continue\n }\n\n if (block.type === 'image' && typeof block.data === 'string') {\n const mediaType = typeof block.mimeType === 'string'\n ? block.mimeType\n : (typeof block.mediaType === 'string' ? block.mediaType : 'image/png')\n out.push({ type: 'image', mediaType, data: block.data })\n continue\n }\n\n if (block.type === 'resource' && block.resource && typeof block.resource === 'object') {\n const res = block.resource as Record<string, unknown>\n if (typeof res.text === 'string') {\n out.push({ type: 'text', text: res.text })\n continue\n }\n if (typeof res.blob === 'string' && typeof res.mimeType === 'string' && res.mimeType.startsWith('image/')) {\n out.push({ type: 'image', mediaType: res.mimeType, data: res.blob })\n continue\n }\n }\n\n // Audio, resource_link, and unknown block shapes — fall back to a JSON-stringified\n // text block. Lossy but keeps the information addressable by the model.\n out.push({ type: 'text', text: JSON.stringify(block) })\n }\n\n return out\n}\n\n/**\n * Route the MCP result content through the narrowest appropriate zidane shape:\n *\n * - All blocks are `text` → return a joined string (smaller wire payload,\n * string-friendly for hook consumers that don't need structured access).\n * - Any block is non-text → return a structured `ToolResultContent[]`.\n * - Empty / non-array input → return `''`.\n */\nfunction packMcpResult(content: unknown): string | ToolResultContent[] {\n const normalized = normalizeMcpBlocks(content)\n if (!normalized || normalized.length === 0)\n return ''\n\n // Single pass: build the joined string as we go. Bail to the structured array\n // the moment we hit a non-text block.\n const parts: string[] = []\n for (const block of normalized) {\n if (block.type !== 'text')\n return normalized\n parts.push(block.text)\n }\n return parts.join('\\n')\n}\n\n/**\n * Create the appropriate MCP transport for a server config.\n *\n * For stdio: when `config.env` is provided, it is merged on top of the MCP SDK's\n * `getDefaultEnvironment()` whitelist (`PATH`, `HOME`, `LANG`, `SHELL`, `USER` on\n * POSIX; `APPDATA`, `PATH`, ... on Win32). Without this defensive merge, older\n * MCP SDK versions strip `PATH` the moment a consumer sets any env, breaking\n * `spawn('node', ...)` with ENOENT. Pass `strictEnv: true` to opt out and send\n * `env` verbatim.\n */\nfunction createTransport(config: McpServerConfig) {\n switch (config.transport) {\n case 'stdio': {\n const mergedEnv = config.env && !config.strictEnv\n ? { ...getDefaultEnvironment(), ...config.env }\n : config.env\n return new StdioClientTransport({\n command: config.command!,\n args: config.args,\n env: mergedEnv,\n })\n }\n case 'sse':\n return new SSEClientTransport(new URL(config.url!), {\n requestInit: config.headers ? { headers: config.headers } : undefined,\n })\n case 'streamable-http':\n // `fetch: sseToJsonFetchIfNeeded()` works around a Bun + MCP SDK\n // 1.29.x bug where `text/event-stream` POST responses are buffered\n // correctly but never surface to `onmessage`, dead-locking bootstrap.\n // The helper returns the wrapper only on Bun and `undefined` on Node\n // (so the SDK's streaming pipeline stays intact where it works).\n // See ./sse-to-json-fetch.ts.\n return new StreamableHTTPClientTransport(new URL(config.url!), {\n requestInit: config.headers ? { headers: config.headers } : undefined,\n fetch: sseToJsonFetchIfNeeded(),\n })\n default:\n throw new Error(`Unknown MCP transport: ${config.transport}`)\n }\n}\n\n/**\n * Connect to MCP servers and discover their tools.\n *\n * Each tool is namespaced as `mcp_{serverName}_{toolName}` to avoid\n * collisions with agent tools or tools from other servers.\n *\n * @param configs - Array of MCP server configurations\n * @param _clientFactory - Internal: override client construction for testing\n * @param hooks - Optional agent hooks for firing mcp:connect, mcp:error, mcp:close events\n */\nexport async function connectMcpServers(\n configs: McpServerConfig[],\n _clientFactory?: () => Client,\n hooks?: Hookable<AgentHooks>,\n): Promise<McpConnection> {\n const connections: { name: string, client: Client }[] = []\n const tools: Record<string, ToolDef> = {}\n const errors: { name: string, error: Error }[] = []\n let closed = false\n\n // Bootstrap every server in parallel. Previously this was a sequential for-loop,\n // which meant a single slow server (GitHub MCP, cold streamable-http endpoints,\n // anything on a flaky network) blocked the whole first `agent.run()` for up to\n // N × bootstrapTimeout. With `Promise.all` + per-server try/catch, wall-clock\n // collapses to the slowest server, and the existing partial-failure tolerance\n // keeps the agent alive when any subset connects.\n const bootstrapResults = await Promise.all(configs.map(config => bootstrapServer(config, _clientFactory, hooks)))\n\n for (const result of bootstrapResults) {\n if (!result.ok) {\n errors.push({ name: result.name, error: result.error })\n await hooks?.callHook('mcp:error', { name: result.name, error: result.error })\n continue\n }\n\n connections.push({ name: result.name, client: result.client })\n const toolNames: string[] = []\n for (const tool of result.tools) {\n const namespacedName = `mcp_${result.config.name}_${tool.name}`\n toolNames.push(namespacedName)\n tools[namespacedName] = buildMcpToolDef(result.config, result.client, tool, namespacedName, hooks)\n }\n await hooks?.callHook('mcp:connect', {\n name: result.name,\n transport: result.config.transport,\n tools: toolNames,\n })\n }\n\n // If all servers failed, throw; partial failures are tolerated\n if (errors.length > 0 && connections.length === 0) {\n const messages = errors.map(e => `${e.name}: ${e.error.message}`).join(', ')\n throw new Error(`All MCP servers failed to connect: ${messages}`)\n }\n\n return {\n tools,\n close: async () => {\n // Idempotent — double-close on `agent.destroy()` retry should not\n // re-fire the hook or call `client.close()` twice (the stdio transport\n // treats a second close as a no-op but some transports throw).\n if (closed)\n return\n closed = true\n await Promise.allSettled(\n connections.map(async ({ name, client }) => {\n await hooks?.callHook('mcp:close', { name })\n await client.close()\n }),\n )\n },\n }\n}\n\n/**\n * Discriminated result returned by `bootstrapServer` so `connectMcpServers` can\n * aggregate successes + failures without letting a rejected promise tear down\n * the whole parallel batch.\n */\ntype BootstrapResult\n = | { ok: true, name: string, config: McpServerConfig, client: Client, tools: Array<{ name: string, description?: string | null, inputSchema?: unknown }> }\n | { ok: false, name: string, error: Error }\n\n/**\n * Connect one MCP server and list its tools, wrapped in a single race against\n * `config.bootstrapTimeout` (default 10s). Always emits `mcp:bootstrap:start`\n * before network I/O and `mcp:bootstrap:end` with `durationMs` + outcome, so a\n * host can build a timing view even when every server succeeds.\n *\n * Errors are captured into the `{ ok: false }` result rather than thrown — the\n * parent uses `Promise.all` across every server and we can't let one rejection\n * short-circuit the batch.\n */\nasync function bootstrapServer(\n config: McpServerConfig,\n _clientFactory: (() => Client) | undefined,\n hooks: Hookable<AgentHooks> | undefined,\n): Promise<BootstrapResult> {\n const start = Date.now()\n // Validate mutually-exclusive filter fields up-front so the consumer gets a\n // typed `mcp:bootstrap:end` failure rather than a silent later-stage drop.\n if (config.enabledTools && config.disabledTools) {\n const error = new Error(\n `MCP server \"${config.name}\": enabledTools and disabledTools are mutually exclusive — set one or the other, not both.`,\n )\n await hooks?.callHook('mcp:bootstrap:start', { name: config.name, transport: config.transport })\n await hooks?.callHook('mcp:bootstrap:end', {\n name: config.name,\n transport: config.transport,\n durationMs: 0,\n ok: false,\n error,\n })\n return { ok: false, name: config.name, error }\n }\n\n await hooks?.callHook('mcp:bootstrap:start', { name: config.name, transport: config.transport })\n\n let client: Client | null = null\n try {\n // TolerantMcpClient is a drop-in subclass that survives a 4xx on the\n // `notifications/initialized` post (some real-world servers reject it\n // without that breaking subsequent `tools/list` etc.). See\n // ./tolerant-client.ts for the exact semantics.\n client = _clientFactory\n ? _clientFactory()\n : new TolerantMcpClient({ name: 'zidane', version: '1.0.0' })\n const currentClient = client\n\n const transport = createTransport(config)\n const bootstrapTimeout = config.bootstrapTimeout ?? DEFAULT_MCP_BOOTSTRAP_TIMEOUT_MS\n const { tools: mcpTools } = await raceWithTimeout(\n async () => {\n await currentClient.connect(transport)\n return await currentClient.listTools()\n },\n bootstrapTimeout,\n `MCP server \"${config.name}\" bootstrap timed out after ${bootstrapTimeout}ms`,\n )\n\n // Per-tool filtering — config-side first (static host policy), then the\n // `mcp:tools:filter` hook (runtime / dynamic decisions). Both compose AND-\n // style: a tool needs to pass every stage to land in the agent registry.\n const filteredTools = await applyMcpToolFilters(config, mcpTools, hooks)\n\n const durationMs = Date.now() - start\n await hooks?.callHook('mcp:bootstrap:end', {\n name: config.name,\n transport: config.transport,\n durationMs,\n ok: true,\n toolCount: filteredTools.length,\n })\n return { ok: true, name: config.name, config, client: currentClient, tools: filteredTools }\n }\n catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n await closeClientQuietly(client)\n const durationMs = Date.now() - start\n await hooks?.callHook('mcp:bootstrap:end', {\n name: config.name,\n transport: config.transport,\n durationMs,\n ok: false,\n error,\n })\n return { ok: false, name: config.name, error }\n }\n}\n\n/**\n * Apply config-side filters (`enabledTools` / `disabledTools` / `toolFilter`)\n * and then the `mcp:tools:filter` hook to the upstream tool list.\n *\n * Composition order — narrowest-to-widest:\n * 1. Allow-list (`enabledTools`) — keep only listed tools.\n * 2. Deny-list (`disabledTools`) — drop listed tools.\n * 3. Predicate (`toolFilter`) — fine-grained metadata filtering.\n * 4. Hook (`mcp:tools:filter`) — runtime / per-host decisions.\n *\n * The mutual exclusion of `enabledTools` and `disabledTools` is checked in\n * `bootstrapServer` so this stays a pure data transform.\n */\nasync function applyMcpToolFilters(\n config: McpServerConfig,\n tools: Array<{ name: string, description?: string | null, inputSchema?: unknown }>,\n hooks: Hookable<AgentHooks> | undefined,\n): Promise<Array<{ name: string, description?: string | null, inputSchema?: unknown }>> {\n let filtered = tools\n\n if (config.enabledTools && config.enabledTools.length > 0) {\n const allow = new Set(config.enabledTools)\n filtered = filtered.filter(t => allow.has(t.name))\n }\n\n if (config.disabledTools && config.disabledTools.length > 0) {\n const deny = new Set(config.disabledTools)\n filtered = filtered.filter(t => !deny.has(t.name))\n }\n\n if (config.toolFilter) {\n const predicate = config.toolFilter\n filtered = filtered.filter(t => predicate(t))\n }\n\n if (hooks) {\n // Pass a fresh array so handlers cannot retroactively mutate the caller's\n // upstream list; mutations they make to `ctx.tools` are scoped to this turn.\n const ctx = { server: config.name, transport: config.transport, tools: [...filtered] }\n await hooks.callHook('mcp:tools:filter', ctx)\n filtered = ctx.tools\n }\n\n return filtered\n}\n\n/**\n * Build the zidane `ToolDef` that wraps a single MCP tool. Extracted so the\n * parallel bootstrap path can assemble tools from a results array without\n * inlining a 70-line closure inside the collector loop.\n *\n * The returned `execute` closes over the bootstrapped `client` — reconnects /\n * swap-outs must go through a fresh `connectMcpServers` call rather than\n * rewiring the tool in place.\n */\nfunction buildMcpToolDef(\n config: McpServerConfig,\n client: Client,\n tool: { name: string, description?: string | null, inputSchema?: unknown },\n namespacedName: string,\n hooks: Hookable<AgentHooks> | undefined,\n): ToolDef {\n return {\n spec: {\n name: namespacedName,\n description: tool.description || '',\n inputSchema: (tool.inputSchema ?? { type: 'object', properties: {} }) as Record<string, unknown>,\n },\n execute: async (input: Record<string, unknown>, ctx: ToolContext) => {\n const { turnId, callId, signal } = ctx\n const displayName = ctx.toolAliases?.[namespacedName] ?? namespacedName\n\n // Gate — block MCP tool execution or substitute a synthetic result.\n const gateCtx: {\n turnId: string\n callId: string\n server: string\n tool: string\n displayName: string\n input: Record<string, unknown>\n block: boolean\n reason: string\n result?: string | ToolResultContent[]\n } = {\n turnId,\n callId,\n server: config.name,\n tool: tool.name,\n displayName,\n input,\n block: false,\n reason: 'MCP tool execution was blocked',\n }\n await hooks?.callHook('mcp:tool:gate', gateCtx)\n\n // Conflict resolution mirrors the loop's `tool:gate`: when both `block`\n // and `result` are set (e.g. a policy gate refuses on top of a consumer\n // cache substitute), `block` wins.\n if (gateCtx.block)\n return `Blocked: ${gateCtx.reason}`\n\n const effectiveInput = gateCtx.input\n\n // MCP gate `result` substitute — skip the upstream callTool, fire the\n // transform + after hooks so consumers see the substitute consistently\n // with normally-executed calls.\n if (gateCtx.result !== undefined) {\n let substitute: string | ToolResultContent[] = gateCtx.result\n const transformCtx = {\n turnId,\n callId,\n server: config.name,\n tool: tool.name,\n displayName,\n input: effectiveInput,\n result: substitute,\n outputBytes: toolOutputByteLength(substitute),\n }\n await hooks?.callHook('mcp:tool:transform', transformCtx)\n substitute = transformCtx.result\n await hooks?.callHook('mcp:tool:after', {\n turnId,\n callId,\n server: config.name,\n tool: tool.name,\n displayName,\n input: effectiveInput,\n result: substitute,\n outputBytes: toolOutputByteLength(substitute),\n })\n return substitute\n }\n await hooks?.callHook('mcp:tool:before', {\n turnId,\n callId,\n server: config.name,\n tool: tool.name,\n displayName,\n input: effectiveInput,\n })\n const timeout = config.toolTimeout ?? 30_000\n try {\n // Race the call against the configured timeout AND the run-level\n // abort signal. Aborting the run has to propagate into MCP calls\n // — otherwise a hung stdio server keeps the tool call alive\n // until `destroy()` eventually closes the client, which can be\n // minutes if the agent is waiting on `waitForIdle()`.\n const result = await raceWithTimeoutAndSignal(\n () => client.callTool({ name: tool.name, arguments: effectiveInput }),\n timeout,\n `MCP tool \"${tool.name}\" on server \"${config.name}\" timed out after ${timeout}ms`,\n signal,\n )\n let output: string | ToolResultContent[] = packMcpResult(result.content)\n\n // Transform — mutate result before returning. `outputBytes` reflects\n // the size before any consumer mutation so a truncation hook can size-budget.\n const transformCtx = {\n turnId,\n callId,\n server: config.name,\n tool: tool.name,\n displayName,\n input: effectiveInput,\n result: output,\n outputBytes: toolOutputByteLength(output),\n }\n await hooks?.callHook('mcp:tool:transform', transformCtx)\n output = transformCtx.result\n\n await hooks?.callHook('mcp:tool:after', {\n turnId,\n callId,\n server: config.name,\n tool: tool.name,\n displayName,\n input: effectiveInput,\n result: output,\n outputBytes: toolOutputByteLength(output),\n })\n return output\n }\n catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n await hooks?.callHook('mcp:tool:error', {\n turnId,\n callId,\n server: config.name,\n tool: tool.name,\n displayName,\n input: effectiveInput,\n error,\n })\n await hooks?.callHook('mcp:tool:after', {\n turnId,\n callId,\n server: config.name,\n tool: tool.name,\n displayName,\n input: effectiveInput,\n result: error.message,\n outputBytes: Buffer.byteLength(error.message),\n })\n throw error\n }\n },\n }\n}\n\nasync function closeClientQuietly(client: Pick<Client, 'close'> | null | undefined): Promise<void> {\n if (!client)\n return\n try {\n await client.close()\n }\n catch {\n // Best-effort cleanup — original bootstrap error is more actionable.\n }\n}\n\nasync function raceWithTimeout<T>(\n task: () => Promise<T>,\n timeoutMs: number,\n timeoutMessage: string,\n): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined\n try {\n return await new Promise<T>((resolvePromise, rejectPromise) => {\n timer = setTimeout(() => rejectPromise(new Error(timeoutMessage)), timeoutMs)\n task().then(resolvePromise, rejectPromise)\n })\n }\n finally {\n if (timer)\n clearTimeout(timer)\n }\n}\n\n/**\n * Race a promise-returning task against (a) a timeout and (b) an optional\n * abort signal. Cleans up its timer and abort listener on every exit path.\n *\n * The task itself isn't cancellable (the MCP SDK doesn't take a signal), so\n * the rejection unblocks the tool call while the underlying RPC completes in\n * the background. When the agent subsequently calls `connection.close()` the\n * stdio transport kills the subprocess, which clears any stuck in-flight work.\n */\nasync function raceWithTimeoutAndSignal<T>(\n task: () => Promise<T>,\n timeoutMs: number,\n timeoutMessage: string,\n signal: AbortSignal | undefined,\n): Promise<T> {\n if (signal?.aborted)\n throw new Error('MCP tool call aborted')\n\n let timer: ReturnType<typeof setTimeout> | undefined\n let onAbort: (() => void) | undefined\n try {\n return await new Promise<T>((resolvePromise, rejectPromise) => {\n timer = setTimeout(() => rejectPromise(new Error(timeoutMessage)), timeoutMs)\n if (signal) {\n onAbort = () => rejectPromise(new Error('MCP tool call aborted'))\n signal.addEventListener('abort', onAbort, { once: true })\n }\n task().then(resolvePromise, rejectPromise)\n })\n }\n finally {\n if (timer)\n clearTimeout(timer)\n if (signal && onAbort)\n signal.removeEventListener('abort', onAbort)\n }\n}\n"],"mappings":"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"}
|
package/dist/presets-BzkJDW1K.js
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { a as multiEdit, i as readFile, n as createSpawnTool, o as listFiles, r as shell, t as writeFile, u as edit } from "./tools-C8kDot0H.js";
|
|
2
|
-
//#region src/presets/basic.ts
|
|
3
|
-
/**
|
|
4
|
-
* Core tools available in every basic preset (without spawn).
|
|
5
|
-
*
|
|
6
|
-
* `edit` and `multi_edit` ship in the basic set because surgical edits are the
|
|
7
|
-
* default modality for production agents — `write_file` is for full overwrites.
|
|
8
|
-
* `glob` and `grep` are exported but opt-in: not every agent needs codebase
|
|
9
|
-
* search, and shipping them by default would force `tool:gate` work onto
|
|
10
|
-
* consumers that prefer the model to use `shell` + classic Unix tools.
|
|
11
|
-
*/
|
|
12
|
-
const basicTools = {
|
|
13
|
-
shell,
|
|
14
|
-
readFile,
|
|
15
|
-
writeFile,
|
|
16
|
-
listFiles,
|
|
17
|
-
edit,
|
|
18
|
-
multiEdit
|
|
19
|
-
};
|
|
20
|
-
var basic_default = definePreset({
|
|
21
|
-
name: "basic",
|
|
22
|
-
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.",
|
|
23
|
-
tools: {
|
|
24
|
-
...basicTools,
|
|
25
|
-
spawn: createSpawnTool({ persist: true })
|
|
26
|
-
}
|
|
27
|
-
});
|
|
28
|
-
//#endregion
|
|
29
|
-
//#region src/presets/index.ts
|
|
30
|
-
/**
|
|
31
|
-
* Identity helper for type inference when defining a preset.
|
|
32
|
-
*/
|
|
33
|
-
function definePreset(config) {
|
|
34
|
-
return config;
|
|
35
|
-
}
|
|
36
|
-
//#endregion
|
|
37
|
-
export { basicTools as n, basic_default as r, definePreset as t };
|
|
38
|
-
|
|
39
|
-
//# sourceMappingURL=presets-BzkJDW1K.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"presets-BzkJDW1K.js","names":[],"sources":["../src/presets/basic.ts","../src/presets/index.ts"],"sourcesContent":["import { definePreset } from '.'\nimport { edit, listFiles, multiEdit, readFile, shell, 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, 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 // `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 tools: { ...basicTools, spawn: createSpawnTool({ persist: true }) },\n})\n","import type { AgentOptions } 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, and behavior defaults.\n *\n * `provider`, `execution`, `session`, and internal fields are excluded so presets\n * remain shareable and composable.\n *\n * ```ts\n * import { basic } from 'zidane/presets'\n * createAgent({ ...basic, 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\nexport { default as basic, basicTools } from './basic'\n"],"mappings":";;;;;;;;;;;AAaA,MAAa,aAAa;CAAE;CAAO;CAAU;CAAW;CAAW;CAAM;CAAW;AAEpF,IAAA,gBAAe,aAAa;CAC1B,MAAM;CACN,QAAQ;CAOR,OAAO;EAAE,GAAG;EAAY,OAAO,gBAAgB,EAAE,SAAS,MAAM,CAAC;EAAE;CACpE,CAAC;;;;;;ACNF,SAAgB,aAAa,QAAwB;CACnD,OAAO"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"session-Cn68UASv.js","names":[],"sources":["../src/session/file-map.ts","../src/session/memory.ts","../src/session/remote.ts","../src/session/index.ts"],"sourcesContent":["/**\n * File-map session store.\n *\n * Wraps a narrow 3-method adapter (`get` / `save` / `delete`) that exchanges a flat\n * map of filename → string content. Useful for embedding zidane sessions inside\n * host-provided session backends that only speak in file maps (not zidane's native\n * `SessionStore` shape).\n *\n * Serialization format:\n * - `turns.jsonl` — one `SessionTurn` per line.\n * - `meta.json` — session metadata (id, agentId, status, runs, metadata, timestamps).\n *\n * JSONL for turns keeps history inspectable with tools like `jq` and resilient to\n * partial corruption — parse up to the first bad line and you still have a valid\n * prefix. Metadata lives in its own file so large turn logs don't bloat the\n * metadata path.\n *\n * Scope: each `createFileMapStore` handles a **single session** — the adapter's\n * file map holds at most one zidane session at a time. This matches how host SDKs\n * scope their session stores per conversation.\n *\n * Divergences from the built-in memory / sqlite stores:\n * - `appendTurns` / `updateStatus` / `updateRun` auto-create a minimal `SessionData`\n * record on first write, instead of silently no-oping when the session hasn't been\n * explicitly `save()`-ed. This matches the host-SDK integration path where\n * `createSession(...)` → `agent.run(...)` directly without an explicit `save()` call.\n * - `updateRun` inserts the run if not found in the cached record (rather than\n * silently dropping). Run records therefore always reach the adapter.\n */\n\nimport type { SessionData, SessionRun, SessionStore } from '.'\nimport type { SessionTurn } from '../types'\n\n/**\n * Host-provided file-map adapter. Three methods exchanging `Record<string, string>`\n * payloads — the whole persistence surface the wrapper needs.\n */\nexport interface FileMapAdapter {\n /** Load the current file map. Returns an empty `files` record when nothing is persisted. */\n get: () => Promise<{ files: Record<string, string> }>\n /** Replace the persisted file map. Full-rewrite semantics. */\n save: (files: Record<string, string>) => Promise<void>\n /** Delete all persisted state. */\n delete: () => Promise<void>\n}\n\nexport interface FileMapStoreOptions {\n /** Filename for the JSONL turns log. Default: `turns.jsonl`. */\n turnsFile?: string\n /** Filename for the metadata JSON. Default: `meta.json`. */\n metaFile?: string\n}\n\ninterface MetaShape {\n id: string\n agentId?: string\n runs: SessionRun[]\n status: SessionData['status']\n metadata: Record<string, unknown>\n createdAt: number\n updatedAt: number\n}\n\nfunction toMeta(data: SessionData): MetaShape {\n return {\n id: data.id,\n agentId: data.agentId,\n runs: data.runs,\n status: data.status,\n metadata: data.metadata,\n createdAt: data.createdAt,\n updatedAt: data.updatedAt,\n }\n}\n\nfunction toData(meta: MetaShape, turns: SessionTurn[]): SessionData {\n return {\n id: meta.id,\n agentId: meta.agentId,\n turns,\n runs: meta.runs,\n status: meta.status,\n metadata: meta.metadata,\n createdAt: meta.createdAt,\n updatedAt: meta.updatedAt,\n }\n}\n\nfunction parseTurnsJsonl(jsonl: string): SessionTurn[] {\n if (!jsonl)\n return []\n const turns: SessionTurn[] = []\n for (const line of jsonl.split('\\n')) {\n const trimmed = line.trim()\n if (!trimmed)\n continue\n try {\n turns.push(JSON.parse(trimmed) as SessionTurn)\n }\n catch {\n // Skip malformed lines — preserves the valid prefix on partial corruption.\n }\n }\n return turns\n}\n\nfunction serializeTurnsJsonl(turns: SessionTurn[]): string {\n if (turns.length === 0)\n return ''\n return `${turns.map(t => JSON.stringify(t)).join('\\n')}\\n`\n}\n\n/**\n * Create a single-session `SessionStore` backed by a file-map adapter.\n *\n * @example\n * ```ts\n * const session = await createSession({\n * store: createFileMapStore(hostSessionStore),\n * })\n * ```\n */\nexport function createFileMapStore(\n adapter: FileMapAdapter,\n options: FileMapStoreOptions = {},\n): SessionStore {\n const turnsFile = options.turnsFile ?? 'turns.jsonl'\n const metaFile = options.metaFile ?? 'meta.json'\n\n // Cached view of the persisted session. Populated lazily on first access so the\n // factory itself doesn't do I/O.\n let cached: SessionData | null = null\n let hydrated = false\n\n async function hydrate(): Promise<void> {\n if (hydrated)\n return\n const { files } = await adapter.get()\n const metaRaw = files[metaFile]\n if (metaRaw) {\n let meta: MetaShape | null = null\n try {\n meta = JSON.parse(metaRaw) as MetaShape\n }\n catch {\n meta = null\n }\n if (meta) {\n cached = toData(meta, parseTurnsJsonl(files[turnsFile] ?? ''))\n }\n }\n hydrated = true\n }\n\n async function persist(data: SessionData): Promise<void> {\n const meta = toMeta(data)\n await adapter.save({\n [metaFile]: JSON.stringify(meta, null, 2),\n [turnsFile]: serializeTurnsJsonl(data.turns),\n })\n }\n\n // Ensure `cached` exists for `sessionId`, creating a minimal record when first written.\n // Returns false when `cached` already holds a different sessionId (request ignored).\n async function ensureCachedFor(sessionId: string): Promise<boolean> {\n await hydrate()\n if (cached) {\n return cached.id === sessionId\n }\n const now = Date.now()\n cached = {\n id: sessionId,\n turns: [],\n runs: [],\n status: 'idle',\n metadata: {},\n createdAt: now,\n updatedAt: now,\n }\n hydrated = true\n return true\n }\n\n return {\n async load(sessionId: string): Promise<SessionData | null> {\n await hydrate()\n if (!cached || cached.id !== sessionId)\n return null\n return structuredClone(cached)\n },\n\n async save(data: SessionData): Promise<void> {\n cached = structuredClone(data)\n hydrated = true\n await persist(cached)\n },\n\n async delete(sessionId: string): Promise<void> {\n await hydrate()\n if (cached && cached.id !== sessionId)\n return\n cached = null\n await adapter.delete()\n },\n\n async list(filter): Promise<string[]> {\n await hydrate()\n if (!cached)\n return []\n if (filter?.agentId && cached.agentId !== filter.agentId)\n return []\n return [cached.id]\n },\n\n async appendTurns(sessionId: string, turns: SessionTurn[]): Promise<void> {\n const ok = await ensureCachedFor(sessionId)\n if (!ok)\n return\n cached!.turns.push(...structuredClone(turns))\n cached!.updatedAt = Date.now()\n await persist(cached!)\n },\n\n async getTurns(sessionId: string, from = 0, limit?: number): Promise<SessionTurn[]> {\n await hydrate()\n if (!cached || cached.id !== sessionId)\n return []\n const slice = cached.turns.slice(from, limit !== undefined ? from + limit : undefined)\n return structuredClone(slice) as SessionTurn[]\n },\n\n async updateRun(sessionId: string, run: SessionRun): Promise<void> {\n const ok = await ensureCachedFor(sessionId)\n if (!ok)\n return\n const idx = cached!.runs.findIndex(r => r.id === run.id)\n if (idx >= 0)\n cached!.runs[idx] = structuredClone(run)\n else\n cached!.runs.push(structuredClone(run))\n cached!.updatedAt = Date.now()\n await persist(cached!)\n },\n\n async updateStatus(sessionId: string, status: SessionData['status']): Promise<void> {\n const ok = await ensureCachedFor(sessionId)\n if (!ok)\n return\n cached!.status = status\n cached!.updatedAt = Date.now()\n await persist(cached!)\n },\n }\n}\n","/**\n * In-memory session store.\n * Useful for development and testing. Data is lost when the process exits.\n */\n\nimport type { SessionData, SessionRun, SessionStore } from '.'\nimport type { SessionTurn } from '../types'\n\nexport function createMemoryStore(): SessionStore {\n const sessions = new Map<string, SessionData>()\n\n return {\n async load(sessionId: string) {\n const data = sessions.get(sessionId)\n return data ? structuredClone(data) : null\n },\n\n async save(session: SessionData) {\n sessions.set(session.id, structuredClone(session))\n },\n\n async delete(sessionId: string) {\n sessions.delete(sessionId)\n },\n\n async list(filter) {\n let ids = Array.from(sessions.keys())\n if (filter?.agentId) {\n ids = ids.filter(id => sessions.get(id)?.agentId === filter.agentId)\n }\n if (filter?.limit) {\n ids = ids.slice(0, filter.limit)\n }\n return ids\n },\n\n async appendTurns(sessionId: string, turns: SessionTurn[]) {\n const data = sessions.get(sessionId)\n if (data) {\n data.turns.push(...structuredClone(turns))\n data.updatedAt = Date.now()\n }\n },\n\n async getTurns(sessionId: string, from = 0, limit?: number) {\n const data = sessions.get(sessionId)\n if (!data)\n return []\n const sliced = data.turns.slice(from, limit !== undefined ? from + limit : undefined)\n return structuredClone(sliced) as SessionTurn[]\n },\n\n async updateRun(sessionId: string, run: SessionRun) {\n const data = sessions.get(sessionId)\n if (data) {\n const idx = data.runs.findIndex(r => r.id === run.id)\n if (idx >= 0) {\n data.runs[idx] = structuredClone(run)\n }\n data.updatedAt = Date.now()\n }\n },\n\n async updateStatus(sessionId: string, status: SessionData['status']) {\n const data = sessions.get(sessionId)\n if (data) {\n data.status = status\n data.updatedAt = Date.now()\n }\n },\n }\n}\n","/**\n * Remote session store via HTTP API.\n *\n * Expects a REST API with:\n * GET {url}/sessions/{id} -> SessionData | 404\n * PUT {url}/sessions/{id} -> save SessionData\n * DELETE {url}/sessions/{id} -> delete\n * GET {url}/sessions?agentId=&limit= -> { ids: string[] }\n * POST {url}/sessions/{id}/turns -> append turns\n * GET {url}/sessions/{id}/turns?from=&limit= -> SessionTurn[]\n * PUT {url}/sessions/{id}/runs/{runId} -> update run\n * PATCH {url}/sessions/{id} -> { status }\n */\n\nimport type { SessionData, SessionRun, SessionStore } from '.'\nimport type { SessionTurn } from '../types'\n\nexport interface RemoteStoreOptions {\n /** Base URL of the session API */\n url: string\n /** Optional headers (e.g. for authentication) */\n headers?: Record<string, string>\n}\n\nconst TRAILING_SLASH = /\\/$/\n\nexport function createRemoteStore(options: RemoteStoreOptions): SessionStore {\n const baseUrl = options.url.replace(TRAILING_SLASH, '')\n const defaultHeaders: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...options.headers,\n }\n\n async function request(path: string, init?: RequestInit): Promise<Response> {\n const url = `${baseUrl}${path}`\n const res = await fetch(url, {\n ...init,\n headers: { ...defaultHeaders, ...init?.headers },\n })\n return res\n }\n\n return {\n async load(sessionId: string) {\n const res = await request(`/sessions/${encodeURIComponent(sessionId)}`)\n if (!res.ok) {\n if (res.status === 404)\n return null\n throw new Error(`Remote session load failed: ${res.status} ${res.statusText}`)\n }\n return await res.json() as SessionData\n },\n\n async save(session: SessionData) {\n const res = await request(`/sessions/${encodeURIComponent(session.id)}`, {\n method: 'PUT',\n body: JSON.stringify(session),\n })\n if (!res.ok) {\n throw new Error(`Remote session save failed: ${res.status} ${res.statusText}`)\n }\n },\n\n async delete(sessionId: string) {\n const res = await request(`/sessions/${encodeURIComponent(sessionId)}`, {\n method: 'DELETE',\n })\n if (!res.ok && res.status !== 404) {\n throw new Error(`Remote session delete failed: ${res.status} ${res.statusText}`)\n }\n },\n\n async list(filter) {\n const params = new URLSearchParams()\n if (filter?.agentId)\n params.set('agentId', filter.agentId)\n if (filter?.limit)\n params.set('limit', String(filter.limit))\n\n const query = params.toString()\n const path = query ? `/sessions?${query}` : '/sessions'\n const res = await request(path)\n\n if (!res.ok) {\n throw new Error(`Remote session list failed: ${res.status} ${res.statusText}`)\n }\n\n const body = await res.json() as { ids: string[] }\n return body.ids\n },\n\n async appendTurns(sessionId: string, turns: SessionTurn[]) {\n const res = await request(`/sessions/${encodeURIComponent(sessionId)}/turns`, {\n method: 'POST',\n body: JSON.stringify(turns),\n })\n if (!res.ok) {\n throw new Error(`Remote appendTurns failed: ${res.status} ${res.statusText}`)\n }\n },\n\n async getTurns(sessionId: string, from = 0, limit?: number) {\n const params = new URLSearchParams()\n if (from)\n params.set('from', String(from))\n if (limit !== undefined)\n params.set('limit', String(limit))\n\n const query = params.toString()\n const path = `/sessions/${encodeURIComponent(sessionId)}/turns${query ? `?${query}` : ''}`\n const res = await request(path)\n\n if (!res.ok) {\n throw new Error(`Remote getTurns failed: ${res.status} ${res.statusText}`)\n }\n\n return await res.json() as SessionTurn[]\n },\n\n async updateRun(sessionId: string, run: SessionRun) {\n const res = await request(\n `/sessions/${encodeURIComponent(sessionId)}/runs/${encodeURIComponent(run.id)}`,\n {\n method: 'PUT',\n body: JSON.stringify(run),\n },\n )\n if (!res.ok) {\n throw new Error(`Remote updateRun failed: ${res.status} ${res.statusText}`)\n }\n },\n\n async updateStatus(sessionId: string, status: SessionData['status']) {\n const res = await request(`/sessions/${encodeURIComponent(sessionId)}`, {\n method: 'PATCH',\n body: JSON.stringify({ status }),\n })\n if (!res.ok) {\n throw new Error(`Remote updateStatus failed: ${res.status} ${res.statusText}`)\n }\n },\n }\n}\n","/**\n * Session management for agents.\n *\n * A session tracks identity, turn history, and run metadata.\n * Plug in any storage backend by implementing the SessionStore interface,\n * or use one of the built-in stores: memory, sqlite, remote.\n */\n\nimport type { SessionTurn, TurnUsage } from '../types'\n\nexport type { SessionContentBlock, SessionMessage, SessionTurn } from '../types'\nexport { createFileMapStore } from './file-map'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface SessionRun {\n id: string\n startedAt: number\n endedAt?: number\n prompt: string\n status: 'running' | 'completed' | 'aborted' | 'error'\n turns?: number\n tokensIn?: number\n tokensOut?: number\n error?: string\n /** Per-turn usage breakdown */\n turnUsage?: TurnUsage[]\n /** Total usage across all turns */\n totalUsage?: TurnUsage\n /** Estimated cost in USD */\n cost?: number\n /**\n * The run that spawned this one, when the agent is a subagent sharing its\n * parent's session. Undefined on top-level `agent.run()`. Consumers can walk\n * `runs` by `parentRunId` to reconstruct the subagent tree.\n */\n parentRunId?: string\n /**\n * Zero-based subagent depth. 0 = top-level run, 1 = direct child, …\n * Recorded here so hosts can query/filter by level without walking the tree.\n */\n depth?: number\n}\n\nexport interface SessionData {\n id: string\n agentId?: string\n turns: SessionTurn[]\n runs: SessionRun[]\n status: 'idle' | 'running' | 'completed' | 'error'\n metadata: Record<string, unknown>\n createdAt: number\n updatedAt: number\n}\n\n// ---------------------------------------------------------------------------\n// SessionStore interface (pluggable backend)\n// ---------------------------------------------------------------------------\n\nexport interface SessionStore {\n /** Optional: generate a session ID server-side (e.g. Supabase UUID). */\n generateSessionId?: () => string | Promise<string>\n\n /** Optional: generate a turn ID server-side. */\n generateTurnId?: () => string | Promise<string>\n\n /** Load a session by ID. Returns null if not found. */\n load: (sessionId: string) => Promise<SessionData | null>\n\n /** Save a session (create or update, full document). */\n save: (session: SessionData) => Promise<void>\n\n /** Delete a session. */\n delete: (sessionId: string) => Promise<void>\n\n /** List session IDs, optionally filtered. */\n list: (filter?: { agentId?: string, limit?: number }) => Promise<string[]>\n\n /** Append new turns to a session (incremental, avoids full re-save). */\n appendTurns: (sessionId: string, turns: SessionTurn[]) => Promise<void>\n\n /** Return a slice of turns for a session. */\n getTurns: (sessionId: string, from?: number, limit?: number) => Promise<SessionTurn[]>\n\n /** Persist an updated run record (called after completeRun / abortRun / errorRun). */\n updateRun: (sessionId: string, run: SessionRun) => Promise<void>\n\n /** Update the top-level status of a session. */\n updateStatus: (sessionId: string, status: SessionData['status']) => Promise<void>\n}\n\n// ---------------------------------------------------------------------------\n// Session (live instance wrapping a SessionData)\n// ---------------------------------------------------------------------------\n\nexport interface Session {\n /** Session ID */\n readonly id: string\n\n /** Agent ID (optional label) */\n readonly agentId?: string\n\n /** Current turn history */\n readonly turns: SessionTurn[]\n\n /**\n * True when this session has no turns yet.\n *\n * Use this as a first-prompt signal when setting up a run — e.g. writing initial\n * configuration only on fresh sessions. Equivalent to `turns.length === 0`.\n */\n readonly isEmpty: boolean\n\n /** Top-level session status */\n readonly status: SessionData['status']\n\n /** All runs in this session */\n readonly runs: SessionRun[]\n\n /** Arbitrary metadata */\n readonly metadata: Record<string, unknown>\n\n /**\n * Start tracking a new run. `extras.parentRunId` + `extras.depth` are\n * populated by the spawn tool when a child agent shares its parent's\n * session; regular top-level `agent.run()` calls omit them.\n */\n startRun: (runId: string, prompt?: string, extras?: { parentRunId?: string, depth?: number }) => void\n\n /** Mark a run as completed */\n completeRun: (runId: string, stats: { turns: number, tokensIn: number, tokensOut: number, turnUsage?: TurnUsage[], cost?: number }) => void\n\n /** Mark a run as aborted */\n abortRun: (runId: string) => void\n\n /** Mark a run as errored */\n errorRun: (runId: string, error: string) => void\n\n /** Append turns to in-memory history AND persist via store.appendTurns (if store present) */\n appendTurns: (turns: SessionTurn[]) => Promise<void>\n\n /** Replace all turns in-memory (does not persist — use save() for that) */\n setTurns: (turns: SessionTurn[]) => void\n\n /** Update the session status in memory AND via store.updateStatus (if store present) */\n updateStatus: (status: SessionData['status']) => Promise<void>\n\n /** Persist an updated run record via store.updateRun (if store present) */\n updateRun: (run: SessionRun) => Promise<void>\n\n /** Generate a turn ID using store.generateTurnId if available, else crypto.randomUUID() */\n generateTurnId: () => string | Promise<string>\n\n /** Set metadata key */\n setMeta: (key: string, value: unknown) => void\n\n /** Persist the full session document to the store */\n save: () => Promise<void>\n\n /** Serialize to SessionData */\n toJSON: () => SessionData\n}\n\n// ---------------------------------------------------------------------------\n// createSession\n// ---------------------------------------------------------------------------\n\nexport interface CreateSessionOptions {\n /** Session ID. If omitted and store provides generateSessionId, that is used. */\n id?: string\n /** Agent ID label */\n agentId?: string\n /** Initial metadata */\n metadata?: Record<string, unknown>\n /** Storage backend (optional, enables save/load) */\n store?: SessionStore\n // @internal: restore from existing data (bypasses id/agentId/metadata options)\n _data?: SessionData\n}\n\n/**\n * Create a new session.\n * Async so stores that generate IDs server-side (e.g. Supabase) can be supported.\n */\nexport async function createSession(options: CreateSessionOptions = {}): Promise<Session> {\n const store = options.store\n const now = Date.now()\n\n let sessionId = options.id\n if (!sessionId && store?.generateSessionId) {\n sessionId = await store.generateSessionId()\n }\n if (!sessionId) {\n sessionId = generateId()\n }\n\n const data: SessionData = options._data ?? {\n id: sessionId,\n agentId: options.agentId,\n turns: [],\n runs: [],\n status: 'idle',\n metadata: options.metadata ?? {},\n createdAt: now,\n updatedAt: now,\n }\n\n function touch() {\n data.updatedAt = Date.now()\n }\n\n function findRun(runId: string): SessionRun | undefined {\n return data.runs.find(r => r.id === runId)\n }\n\n const session: Session = {\n get id() { return data.id },\n get agentId() { return data.agentId },\n get turns() { return data.turns },\n get isEmpty() { return data.turns.length === 0 },\n get status() { return data.status },\n get runs() { return data.runs },\n get metadata() { return data.metadata },\n\n startRun(runId: string, prompt?: string, extras?: { parentRunId?: string, depth?: number }) {\n data.runs.push({\n id: runId,\n startedAt: Date.now(),\n prompt: prompt ?? '',\n status: 'running',\n ...(extras?.parentRunId ? { parentRunId: extras.parentRunId } : {}),\n ...(typeof extras?.depth === 'number' ? { depth: extras.depth } : {}),\n })\n touch()\n },\n\n completeRun(runId: string, stats: { turns: number, tokensIn: number, tokensOut: number, turnUsage?: TurnUsage[], cost?: number }) {\n const run = findRun(runId)\n if (run) {\n run.status = 'completed'\n run.endedAt = Date.now()\n run.turns = stats.turns\n run.tokensIn = stats.tokensIn\n run.tokensOut = stats.tokensOut\n if (stats.turnUsage) {\n run.turnUsage = stats.turnUsage\n const total = stats.turnUsage.reduce((acc, t) => ({\n input: acc.input + t.input,\n output: acc.output + t.output,\n cacheCreation: (acc.cacheCreation ?? 0) + (t.cacheCreation ?? 0),\n cacheRead: (acc.cacheRead ?? 0) + (t.cacheRead ?? 0),\n thinking: (acc.thinking ?? 0) + (t.thinking ?? 0),\n }), { input: 0, output: 0, cacheCreation: 0, cacheRead: 0, thinking: 0 })\n run.totalUsage = {\n input: total.input,\n output: total.output,\n ...(total.cacheCreation ? { cacheCreation: total.cacheCreation } : {}),\n ...(total.cacheRead ? { cacheRead: total.cacheRead } : {}),\n ...(total.thinking ? { thinking: total.thinking } : {}),\n }\n }\n if (stats.cost !== undefined)\n run.cost = stats.cost\n }\n touch()\n },\n\n abortRun(runId: string) {\n const run = findRun(runId)\n if (run) {\n run.status = 'aborted'\n run.endedAt = Date.now()\n }\n touch()\n },\n\n errorRun(runId: string, error: string) {\n const run = findRun(runId)\n if (run) {\n run.status = 'error'\n run.endedAt = Date.now()\n run.error = error\n }\n touch()\n },\n\n async appendTurns(turns: SessionTurn[]) {\n data.turns.push(...turns)\n touch()\n if (store) {\n await store.appendTurns(data.id, turns)\n }\n },\n\n setTurns(turns: SessionTurn[]) {\n data.turns = turns\n touch()\n },\n\n async updateStatus(status: SessionData['status']) {\n data.status = status\n touch()\n if (store) {\n await store.updateStatus(data.id, status)\n }\n },\n\n async updateRun(run: SessionRun) {\n if (store) {\n await store.updateRun(data.id, run)\n }\n },\n\n generateTurnId() {\n if (store?.generateTurnId) {\n return store.generateTurnId()\n }\n return crypto.randomUUID()\n },\n\n setMeta(key: string, value: unknown) {\n data.metadata[key] = value\n touch()\n },\n\n async save() {\n if (!store) {\n throw new Error('No SessionStore configured. Pass a store to createSession() to enable persistence.')\n }\n await store.save(data)\n },\n\n toJSON() {\n return structuredClone(data)\n },\n }\n\n return session\n}\n\n/**\n * Load an existing session from a store.\n */\nexport async function loadSession(store: SessionStore, sessionId: string): Promise<Session | null> {\n const loaded = await store.load(sessionId)\n if (!loaded)\n return null\n\n return createSession({ store, _data: loaded })\n}\n\n// ---------------------------------------------------------------------------\n// Re-export stores\n// ---------------------------------------------------------------------------\n\nexport type { FileMapAdapter, FileMapStoreOptions } from './file-map'\nexport { createMemoryStore } from './memory'\nexport { autoDetectAndConvert, fromAnthropic, fromOpenAI, toAnthropic, toOpenAI } from './messages'\nexport { createRemoteStore } from './remote'\nexport type { RemoteStoreOptions } from './remote'\n\n// NOTE: `createSqliteStore` is intentionally NOT re-exported here. It lives behind\n// the dedicated `zidane/session/sqlite` subpath so that non-Bun consumers don't\n// transitively evaluate `bun:sqlite` when they import from `zidane/session`.\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction generateId(): string {\n return `ses_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"stats-BT9l57RS.js","names":[],"sources":["../src/stats.ts"],"sourcesContent":["/**\n * Pure derivations over `AgentStats`.\n *\n * Both helpers are tree-shakeable — import only what you need. They never\n * touch agent state, never do I/O, and always operate on the recursive\n * `AgentStats` tree returned by `agent.run()`.\n */\n\nimport type { AgentStats, TurnUsage } from './types'\n\n/**\n * Per-model usage rollup produced by {@link statsByModel}.\n *\n * `turns` counts the number of `TurnUsage` entries attributed to the model\n * across the whole tree (parent loop + every recursively-spawned child).\n * Cache and cost numbers are summed from the same set of turns.\n */\nexport interface ModelUsage {\n input: number\n output: number\n cost: number\n cacheRead: number\n cacheCreation: number\n turns: number\n}\n\n/**\n * Common shape for token-usage helpers. Mirrors `AgentStats`'s cumulative\n * fields. Callers working with `TurnUsage` / `SessionRun.totalUsage`\n * (`input` / `output` / `cacheRead` / `cacheCreation`) map their fields in\n * at the call site — we don't accept both shapes here because\n * `AgentStats.output` is a structured-output payload (`Record<string,\n * unknown>`), not a token count, so the field name `output` is ambiguous.\n */\nexport interface TokenUsageLike {\n totalIn?: number\n totalOut?: number\n totalCacheRead?: number\n totalCacheCreation?: number\n}\n\nfunction normalize(stats: TokenUsageLike): {\n input: number\n output: number\n cacheRead: number\n cacheCreation: number\n} {\n return {\n input: stats.totalIn ?? 0,\n output: stats.totalOut ?? 0,\n cacheRead: stats.totalCacheRead ?? 0,\n cacheCreation: stats.totalCacheCreation ?? 0,\n }\n}\n\n/**\n * Sum of `input + cacheRead + cacheCreation` — i.e. the number of tokens the\n * model actually saw, regardless of how they were billed.\n *\n * With provider prompt caching (Anthropic, OpenRouter→Anthropic, Gemini),\n * `AgentStats.totalIn` only counts **new uncached** tokens per turn; the\n * bulk of an N-turn run's context lives in `totalCacheRead`, plus a smaller\n * `totalCacheCreation` chunk for whichever turns added new breakpoints.\n * Showing only `totalIn` in a per-run summary makes long subagent runs look\n * suspiciously cheap (e.g. \"13 in\" for 8 turns over a large repo).\n *\n * `TurnUsage` / `SessionRun.totalUsage` callers map their fields to the\n * `total*` names at the call site (see {@link TokenUsageLike}).\n */\nexport function effectiveInputTokens(stats: TokenUsageLike): number {\n const { input, cacheRead, cacheCreation } = normalize(stats)\n return input + cacheRead + cacheCreation\n}\n\n/**\n * Render a one-line token summary suitable for spawn-end markers, child\n * tool-result text, and any other per-run \"what did this cost?\" surface.\n *\n * `in 52413 (cache 50000) / 4075 out`\n *\n * The `in` total includes cached reads and cache-creation tokens (see\n * {@link effectiveInputTokens}); the `(cache N)` parenthetical breaks out\n * the cached portion so the user can tell at a glance how much was reused\n * vs new. The parenthetical is omitted when its value is zero, so\n * non-caching providers and brand-new runs read simply as `in N / M out`.\n *\n * Output-side caching is not a concept any current provider exposes —\n * Anthropic's `cacheRead` / `cacheCreation` are both input-billed. If a\n * future provider ships an output cache, extend `TokenUsageLike` with\n * output-cache fields and add a parallel `(cache N)` slot on the `out`\n * side here; today the right side is always plain `${N} out`.\n */\nexport function formatTokenUsage(stats: TokenUsageLike): string {\n const { input, output, cacheRead, cacheCreation } = normalize(stats)\n const inputTotal = input + cacheRead + cacheCreation\n const inputCache = cacheRead + cacheCreation\n const inPart = inputCache > 0\n ? `in ${inputTotal} (cache ${inputCache})`\n : `in ${inputTotal}`\n return `${inPart} / ${output} out`\n}\n\n/**\n * Depth-first walk over the stats tree, returning every `TurnUsage` entry\n * — parent loop first, then each child subtree in completion order.\n *\n * Closes the cache-token aggregation gap: `TurnUsage.cacheRead` /\n * `cacheCreation` live only on per-turn entries, and the top-level\n * `AgentStats` deliberately doesn't carry cumulative forms (one source of\n * truth, no risk of drift). Anything that needs a tree-wide sum walks\n * through this.\n */\nexport function flattenTurns(stats: AgentStats): TurnUsage[] {\n const out: TurnUsage[] = []\n collectTurns(stats, out)\n return out\n}\n\nfunction collectTurns(stats: AgentStats, out: TurnUsage[]): void {\n if (stats.turnUsage)\n out.push(...stats.turnUsage)\n if (stats.children) {\n for (const child of stats.children)\n collectTurns(child.stats, out)\n }\n}\n\n/**\n * Group cumulative usage by `TurnUsage.modelId`. Each entry sums the input,\n * output, cache, cost, and turn-count across every turn the tree attributed\n * to that model — naturally handling cross-model runs (vision-fallback,\n * model-shifted subagents, mixed-provider workflows).\n *\n * Turns missing `modelId` (mock providers, providers that don't echo a model\n * id) are bucketed under the literal string `'(unknown)'`.\n */\nexport function statsByModel(stats: AgentStats): Map<string, ModelUsage> {\n const out = new Map<string, ModelUsage>()\n for (const turn of flattenTurns(stats)) {\n const key = turn.modelId ?? '(unknown)'\n let entry = out.get(key)\n if (!entry) {\n entry = { input: 0, output: 0, cost: 0, cacheRead: 0, cacheCreation: 0, turns: 0 }\n out.set(key, entry)\n }\n entry.input += turn.input\n entry.output += turn.output\n entry.cost += turn.cost ?? 0\n entry.cacheRead += turn.cacheRead ?? 0\n entry.cacheCreation += turn.cacheCreation ?? 0\n entry.turns += 1\n }\n return out\n}\n"],"mappings":";AAyCA,SAAS,UAAU,OAKjB;CACA,OAAO;EACL,OAAO,MAAM,WAAW;EACxB,QAAQ,MAAM,YAAY;EAC1B,WAAW,MAAM,kBAAkB;EACnC,eAAe,MAAM,sBAAsB;EAC5C;;;;;;;;;;;;;;;;;;;;AAwCH,SAAgB,iBAAiB,OAA+B;CAC9D,MAAM,EAAE,OAAO,QAAQ,WAAW,kBAAkB,UAAU,MAAM;CACpE,MAAM,aAAa,QAAQ,YAAY;CACvC,MAAM,aAAa,YAAY;CAI/B,OAAO,GAHQ,aAAa,IACxB,MAAM,WAAW,UAAU,WAAW,KACtC,MAAM,aACO,KAAK,OAAO;;;;;;;;;;;;AAa/B,SAAgB,aAAa,OAAgC;CAC3D,MAAM,MAAmB,EAAE;CAC3B,aAAa,OAAO,IAAI;CACxB,OAAO;;AAGT,SAAS,aAAa,OAAmB,KAAwB;CAC/D,IAAI,MAAM,WACR,IAAI,KAAK,GAAG,MAAM,UAAU;CAC9B,IAAI,MAAM,UACR,KAAK,MAAM,SAAS,MAAM,UACxB,aAAa,MAAM,OAAO,IAAI;;;;;;;;;;;AAapC,SAAgB,aAAa,OAA4C;CACvE,MAAM,sBAAM,IAAI,KAAyB;CACzC,KAAK,MAAM,QAAQ,aAAa,MAAM,EAAE;EACtC,MAAM,MAAM,KAAK,WAAW;EAC5B,IAAI,QAAQ,IAAI,IAAI,IAAI;EACxB,IAAI,CAAC,OAAO;GACV,QAAQ;IAAE,OAAO;IAAG,QAAQ;IAAG,MAAM;IAAG,WAAW;IAAG,eAAe;IAAG,OAAO;IAAG;GAClF,IAAI,IAAI,KAAK,MAAM;;EAErB,MAAM,SAAS,KAAK;EACpB,MAAM,UAAU,KAAK;EACrB,MAAM,QAAQ,KAAK,QAAQ;EAC3B,MAAM,aAAa,KAAK,aAAa;EACrC,MAAM,iBAAiB,KAAK,iBAAiB;EAC7C,MAAM,SAAS;;CAEjB,OAAO"}
|