@dot-agent/compiler 0.10.2 → 0.12.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["bpInit","bpParseBehavior","bpParseDescription"],"sources":["../src/parser.ts","../src/linter.ts","../src/zip.ts","../src/schema.ts","../src/pack.ts","../src/bundle.ts"],"sourcesContent":["// Copyright 2026 Danilo Borges\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n\nimport { createRequire } from 'module'\nimport { Parser, Language } from 'web-tree-sitter'\nimport type { Node, Tree } from 'web-tree-sitter'\nimport type { LangId, BehaviorFile, DescriptionFile, ParseDiagnostic } from './types.js'\nimport { init as bpInit, parse_behavior as bpParseBehavior, parse_description as bpParseDescription, get_graph } from '@dot-agent/parser-dsl'\n\nconst require = createRequire(import.meta.url)\nconst { descriptionWasmPath, behaviorWasmPath } = require('@dot-agent/tree-sitter') as {\n descriptionWasmPath: string\n behaviorWasmPath: string\n}\n\nlet _initialized = false\nlet _descriptionParser: Parser\nlet _behaviorParser: Parser\nlet _bpInitialized = false\n\nexport async function initBehaviorParser(): Promise<void> {\n if (_bpInitialized) return\n await bpInit()\n _bpInitialized = true\n}\n\nexport interface ParseResult<T> {\n ok: T | null\n diagnostics: ParseDiagnostic[]\n}\n\nexport function parseBehaviorFile(text: string): ParseResult<BehaviorFile> {\n return JSON.parse(bpParseBehavior(text)) as ParseResult<BehaviorFile>\n}\n\nexport function parseDescriptionFile(text: string): ParseResult<DescriptionFile> {\n return JSON.parse(bpParseDescription(text)) as ParseResult<DescriptionFile>\n}\n\nexport function getBehaviorScxml(text: string): string {\n return get_graph(text)\n}\n\nexport async function initParsers(): Promise<void> {\n if (_initialized) return\n await Parser.init()\n const descriptionLang = await Language.load(descriptionWasmPath)\n const behaviorLang = await Language.load(behaviorWasmPath)\n _descriptionParser = new Parser()\n _descriptionParser.setLanguage(descriptionLang)\n _behaviorParser = new Parser()\n _behaviorParser.setLanguage(behaviorLang)\n _initialized = true\n}\n\n/**\n * Parse source text and return a tree-sitter Tree.\n *\n * @param langId - 'description' or 'behavior'\n * @param text - source text to parse\n * @param previousTree - optional previous tree for incremental parsing (LSP use)\n */\nexport async function parse(\n langId: LangId,\n text: string,\n previousTree?: Tree\n): Promise<Tree> {\n await initParsers()\n const parser = langId === 'behavior' ? _behaviorParser : _descriptionParser\n return parser.parse(text, previousTree)!\n}\n\n/** Parse without initializing if parsers are already ready. Returns null if not initialized. */\nexport function parseSync(langId: LangId, text: string, previousTree?: Tree): Tree | null {\n if (!_initialized) return null\n const parser = langId === 'behavior' ? _behaviorParser : _descriptionParser\n return parser.parse(text, previousTree)\n}\n\n// ── AST helpers ──────────────────────────────────────────────────────────────\n\nexport function nodesOfType(tree: Tree, type: string): Node[] {\n if (!tree) return []\n return tree.rootNode.descendantsOfType(type).filter((n): n is Node => n !== null)\n}\n\nexport function nodeAtOffset(tree: Tree, offset: number): Node | null {\n if (!tree) return null\n return tree.rootNode.descendantForIndex(offset)\n}\n\nexport function nodeToRange(node: Node): {\n start: { line: number; character: number }\n end: { line: number; character: number }\n} {\n return {\n start: { line: node.startPosition.row, character: node.startPosition.column },\n end: { line: node.endPosition.row, character: node.endPosition.column },\n }\n}\n\nexport function positionToOffset(text: string, line: number, character: number): number {\n let offset = 0\n for (let i = 0; i < line; i++) {\n const nl = text.indexOf('\\n', offset)\n offset = nl === -1 ? text.length : nl + 1\n }\n return offset + character\n}\n\nexport function getContextNode(tree: Tree, offset: number): Node {\n let node = nodeAtOffset(tree, offset)\n while (node && (node.isError || node.isMissing)) {\n node = node.parent\n }\n if (!node || node.type === 'ERROR') {\n const raw = nodeAtOffset(tree, offset)\n const parent = raw?.parent\n if (parent) {\n const siblings = parent.children\n const idx = siblings.findIndex((c: Node | null) => c !== null && c.startIndex > offset)\n const prev = idx > 0 ? siblings[idx - 1] : siblings[siblings.length - 1]\n if (prev && !prev.isError) node = prev\n }\n }\n return node ?? tree.rootNode\n}\n","// Copyright 2026 Danilo Borges\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { readFileSync } from 'fs'\nimport { resolve, dirname } from 'path'\nimport { parse, nodesOfType, parseSync, initBehaviorParser, parseBehaviorFile } from './parser.js'\nimport type { LintMessage } from './types.js'\nimport type { Node, Tree } from 'web-tree-sitter'\n\nfunction nodePosition(node: Node): { line: number; col: number } {\n return { line: node.startPosition.row + 1, col: node.startPosition.column + 1 }\n}\n\n// ── Syntax error collection (reports deepest ERROR node per branch) ──────────\n\nconst MISSING_HINTS: Record<string, string> = {\n interact_stmt: \"Missing 'interact' — oriented states require 'goal … interact … on intent … on offtopic'.\",\n offtopic_handler: \"Missing 'on offtopic' handler — every state with 'interact' must handle the offtopic case.\",\n intent_handler: \"Missing at least one 'on intent' handler after 'interact'.\",\n goal_stmt: \"Missing 'goal' — every state with 'interact' must declare a goal.\",\n state_name: \"Missing state name after 'state' keyword.\",\n quoted_string: \"Missing quoted string — expected a value in double quotes.\",\n}\n\nfunction collectSyntaxErrors(root: Node, messages: LintMessage[], file: string): void {\n const seen = new Set<string>()\n\n function push(node: Node, message: string, code: string, severity: 'error' | 'warning' = 'error') {\n const key = `${node.startIndex}:${node.endIndex}:${message}`\n if (seen.has(key)) return\n seen.add(key)\n const { line, col } = nodePosition(node)\n messages.push({ file, line, col, severity, code, message })\n }\n\n function walk(node: Node) {\n if (node.isMissing) {\n const hint = MISSING_HINTS[node.type]\n push(node, hint ?? `Syntax error: missing '${node.type}'.`, 'E004')\n return\n }\n if (node.type === 'ERROR') {\n const hasNestedError = node.descendantsOfType('ERROR').some((e: Node | null) => e !== null && e.id !== node.id)\n if (!hasNestedError) {\n const snippet = node.text.replace(/\\s+/g, ' ').trim().slice(0, 40)\n push(node, snippet ? `Syntax error near '${snippet}'.` : 'Syntax error.', 'E004')\n return\n }\n }\n for (const child of node.children) {\n if (child) walk(child)\n }\n }\n\n walk(root)\n}\n\n// ── Description linting ──────────────────────────────────────────────────────\n\nconst STRICT_BLOCK_TYPES: Record<string, string> = {\n input_block: 'input',\n output_block: 'output',\n requires_block: 'requires',\n capabilities_block: 'capabilities',\n}\n\nexport async function lintDescription(text: string, file = 'agent.description'): Promise<LintMessage[]> {\n const tree = await parse('description', text)\n const messages: LintMessage[] = []\n\n collectSyntaxErrors(tree.rootNode, messages, file)\n\n // W003: default domain value\n // The grammar uses `agent_meta` nodes with key/value fields (not `domain_declaration`)\n for (const metaNode of nodesOfType(tree, 'agent_meta')) {\n const keyNode = metaNode.childForFieldName('key')\n if (keyNode?.text !== 'domain') continue\n const valueNode = metaNode.childForFieldName('value')\n if (valueNode?.text === 'example.com') {\n const { line, col } = nodePosition(valueNode)\n messages.push({\n file,\n line,\n col,\n severity: 'warning',\n code: 'W003',\n message: 'domain still has default value \"example.com\"',\n })\n }\n }\n\n // W007: no domain declared → agent will be packaged as unknown/name\n const hasDomain = nodesOfType(tree, 'agent_meta').some(\n n => n.childForFieldName('key')?.text === 'domain' && n.childForFieldName('value')?.text?.trim(),\n )\n if (!hasDomain) {\n messages.push({\n file,\n line: 1,\n col: 1,\n severity: 'warning',\n code: 'W007',\n message:\n 'No domain declared — agent will be packaged as unknown/name. Interoperability between runtimes is not guaranteed.',\n })\n }\n\n // E017: multiple behavior declarations\n const behaviorBlocks = nodesOfType(tree, 'behavior_block')\n if (behaviorBlocks.length > 1) {\n const { line, col } = nodePosition(behaviorBlocks[1])\n messages.push({\n file, line, col, severity: 'error', code: 'E017',\n message: \"Multiple 'behavior' declarations — only one is allowed. To combine multiple files, use 'merge' in your .behavior file.\",\n })\n }\n\n // W004: undeclared type references in input/output/requires/capabilities blocks\n const declaredTypes = new Set(\n nodesOfType(tree, 'type_decl')\n .map(n => n.childForFieldName('name')?.text)\n .filter(Boolean) as string[]\n )\n\n if (declaredTypes.size > 0) {\n for (const blockType of Object.keys(STRICT_BLOCK_TYPES)) {\n for (const blockNode of nodesOfType(tree, blockType)) {\n for (const typeRefNode of blockNode.descendantsOfType('type_reference').filter((n): n is Node => n !== null)) {\n const idNode = typeRefNode.firstNamedChild\n if (!idNode) continue\n const typeName = idNode.text\n if (!declaredTypes.has(typeName)) {\n const { line, col } = nodePosition(idNode)\n messages.push({\n file,\n line,\n col,\n severity: 'warning',\n code: 'W004',\n message: `Type '${typeName}' is not declared in this file (assuming native or external).`,\n })\n }\n }\n }\n }\n }\n\n return messages\n}\n\n// ── Behavior linting ─────────────────────────────────────────────────────────\n\nfunction levenshtein(a: string, b: string): number {\n const la = a.length, lb = b.length\n const dp: number[][] = Array.from({ length: la + 1 }, (_, i) =>\n Array.from({ length: lb + 1 }, (_, j) => (i === 0 ? j : j === 0 ? i : 0))\n )\n for (let i = 1; i <= la; i++) {\n for (let j = 1; j <= lb; j++) {\n dp[i][j] = a[i - 1] === b[j - 1]\n ? dp[i - 1][j - 1]\n : 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1])\n }\n }\n return dp[la][lb]\n}\n\nfunction closestName(token: string, candidates: string[]): string | undefined {\n let best: string | undefined\n let bestDist = Infinity\n for (const name of candidates) {\n const d = levenshtein(token.toLowerCase(), name.toLowerCase())\n if (d > 0 && d <= 2 && d < bestDist) { bestDist = d; best = name }\n }\n return best\n}\n\nconst KERNEL_LIFECYCLE_NAMES = ['init', 'welcome', 'end', 'online', 'offline']\n\nfunction collectTransitionTargets(stmts: Array<{ type: string; [k: string]: unknown }>): string[] {\n const targets: string[] = []\n for (const stmt of stmts) {\n if (!stmt || typeof stmt !== 'object') continue\n if (stmt.type === 'transition_stmt' && typeof stmt['state'] === 'string') {\n targets.push(stmt['state'])\n }\n if (stmt.type === 'intent_handler' && typeof stmt['body'] === 'string') {\n targets.push(stmt['body'])\n }\n const recurse = (v: unknown) => {\n if (Array.isArray(v)) targets.push(...collectTransitionTargets(v as Array<{ type: string }>))\n }\n if (stmt.type !== 'intent_handler') recurse(stmt['body'])\n recurse(stmt['handlers'])\n recurse(stmt['then'])\n recurse(stmt['else'])\n recurse(stmt['on_complete'])\n recurse(stmt['on_failure'])\n }\n return targets\n}\n\nfunction collectMergedStates(\n tree: Tree,\n docDir: string,\n states: Set<string>,\n visited = new Set<string>()\n): void {\n for (const mergeNode of nodesOfType(tree, 'merge_decl')) {\n const pathNode = mergeNode.childForFieldName('path')\n if (!pathNode) continue\n const filename = pathNode.text.replace(/^\"|\"$/g, '')\n const absPath = resolve(docDir, filename)\n if (visited.has(absPath)) continue\n visited.add(absPath)\n let mergedText: string\n try {\n mergedText = readFileSync(absPath, 'utf-8')\n } catch {\n continue\n }\n const mergedTree = parseSync('behavior', mergedText)\n if (!mergedTree) continue\n nodesOfType(mergedTree, 'state_decl').forEach(n => {\n const name = n.childForFieldName('name')?.text\n if (name) states.add(name)\n })\n collectMergedStates(mergedTree, dirname(absPath), states, visited)\n }\n}\n\nexport async function lintBehavior(\n text: string,\n file = 'agent.behavior',\n docPath?: string,\n consolidated = false,\n externalStates?: Set<string>,\n mergedText?: string,\n): Promise<LintMessage[]> {\n await initBehaviorParser()\n if (!text.endsWith('\\n')) text = text + '\\n'\n const tree = await parse('behavior', text)\n const messages: LintMessage[] = []\n\n // Rule 0: syntax errors\n collectSyntaxErrors(tree.rootNode, messages, file)\n\n for (const stateNode of nodesOfType(tree, 'state_decl')) {\n if (stateNode.hasError) continue\n const nameNode = stateNode.childForFieldName('name')\n const stateName = nameNode?.text ?? '?'\n const hasInteract = stateNode.descendantsOfType('interact_stmt').length > 0\n const hasGoal = stateNode.descendantsOfType('goal_stmt').length > 0\n const intentHandlers = stateNode.descendantsOfType('intent_handler')\n\n // W013: interact without goal (supersedes E008 — downgraded to warning)\n if (hasInteract && !hasGoal) {\n const { line, col } = nodePosition(nameNode ?? stateNode)\n messages.push({\n file, line, col, severity: 'warning', code: 'W013',\n message: `'interact' without 'goal'. Add 'goal \"...\"' before 'interact'.`,\n })\n }\n\n // W012: goal without interact\n if (hasGoal && !hasInteract) {\n const { line, col } = nodePosition(nameNode ?? stateNode)\n messages.push({\n file, line, col, severity: 'warning', code: 'W012',\n message: `'goal' is only valid in an oriented state. Add 'interact' or remove 'goal'.`,\n })\n }\n\n // E009: oriented state with no on intent handlers\n if (hasInteract && intentHandlers.length === 0) {\n const { line, col } = nodePosition(nameNode ?? stateNode)\n messages.push({\n file, line, col, severity: 'error', code: 'E009',\n message: `Oriented state '${stateName}' has no 'on intent' handlers. At least one is required.`,\n })\n }\n\n // W008: duplicate on intent label in same state (Error-level per spec)\n const seenIntents = new Map<string, true>()\n for (const handler of intentHandlers) {\n const intentNode = handler.childForFieldName('intent')\n if (!intentNode) continue\n const label = intentNode.text.replace(/^\"|\"$/g, '')\n if (seenIntents.has(label)) {\n const { line, col } = nodePosition(handler)\n messages.push({\n file, line, col, severity: 'error', code: 'W008',\n message: `Duplicate 'on intent \"${label}\"' in state '${stateName}'. The FSM cannot route ambiguous intents — use a unique label for each handler.`,\n })\n } else {\n seenIntents.set(label, true)\n }\n }\n\n // W011: on intent handler transitions to its own enclosing state\n for (const handler of intentHandlers) {\n for (const t of handler.descendantsOfType('transition_stmt')) {\n const targetNode = t.childForFieldName('state')\n if (targetNode?.text === stateName) {\n const { line, col } = nodePosition(handler)\n messages.push({\n file, line, col, severity: 'warning', code: 'W011',\n message: `'on intent' handler in state '${stateName}' transitions back to itself. The user expressed an intent but receives no progress — did you mean a different target state?`,\n })\n }\n }\n }\n\n // I001/I002: state overrides kernel lifecycle\n if (stateName === 'init' || stateName === 'end') {\n const { line, col } = nodePosition(nameNode ?? stateNode)\n if (stateName === 'init') {\n messages.push({\n file, line, col, severity: 'info', code: 'I001',\n message: `State 'init' overrides the kernel's default entry lifecycle. The kernel will use this definition instead of its built-in init sequence.`,\n })\n } else {\n messages.push({\n file, line, col, severity: 'info', code: 'I002',\n message: `State 'end' overrides the kernel's default terminal lifecycle. The kernel will treat this state as the canonical exit point.`,\n })\n }\n }\n\n // H001: state name close to (but not exact match of) kernel lifecycle names\n if (!KERNEL_LIFECYCLE_NAMES.includes(stateName)) {\n const closest = closestName(stateName, KERNEL_LIFECYCLE_NAMES)\n if (closest) {\n const { line, col } = nodePosition(nameNode ?? stateNode)\n messages.push({\n file, line, col, severity: 'hint', code: 'H001',\n message: `State name '${stateName}' resembles the kernel lifecycle name '${closest}'. If this is intentional, ignore this hint.`,\n })\n }\n }\n }\n\n // E010: parallel block with no run statements\n for (const parallelNode of nodesOfType(tree, 'parallel_stmt')) {\n if (parallelNode.hasError) continue\n if (parallelNode.descendantsOfType('run_stmt').length === 0) {\n const { line, col } = nodePosition(parallelNode)\n let stateName = '?'\n let ancestor = parallelNode.parent\n while (ancestor && ancestor.type !== 'state_decl') ancestor = ancestor.parent\n if (ancestor) stateName = ancestor.childForFieldName('name')?.text ?? '?'\n messages.push({\n file, line, col, severity: 'warning', code: 'E010',\n message: `'parallel' block in state '${stateName}' has no 'run' statements and does nothing.`,\n })\n }\n }\n\n // E011: after statement with prompts: 0\n for (const afterNode of nodesOfType(tree, 'after_stmt')) {\n if (afterNode.hasError) continue\n const countNode = afterNode.childForFieldName('count')\n if (countNode?.text === '0') {\n const { line, col } = nodePosition(countNode)\n messages.push({\n file, line, col, severity: 'error', code: 'E011',\n message: `'after 0' is invalid — prompts must be ≥ 1. Use 'after 1' for the next prompt.`,\n })\n }\n }\n\n // W002: goal_stmt text > 280 chars\n for (const stmtNode of nodesOfType(tree, 'goal_stmt')) {\n const strNode = stmtNode.descendantsOfType('quoted_string').find((n): n is Node => n !== null)\n if (!strNode) continue\n const content = strNode.text.replace(/^\"|\"$/g, '')\n if (content.length > 280) {\n const { line, col } = nodePosition(strNode)\n messages.push({\n file, line, col, severity: 'warning', code: 'W002',\n message: `Text block exceeds 280 characters (${content.length}). Consider using 'guide' to load long orientation text from an external text file.`,\n })\n }\n }\n\n // W010: guide_stmt text > 280 chars\n for (const stmtNode of nodesOfType(tree, 'guide_stmt')) {\n const strNode = stmtNode.descendantsOfType('quoted_string').find((n): n is Node => n !== null)\n if (!strNode) continue\n const content = strNode.text.replace(/^\"|\"$/g, '')\n if (content.length > 280) {\n const { line, col } = nodePosition(strNode)\n let p = stmtNode.parent\n while (p && p.type !== 'state_decl') p = p.parent\n const stateName = p?.childForFieldName('name')?.text ?? '?'\n messages.push({\n file, line, col, severity: 'warning', code: 'W010',\n message: `'guide' text in state '${stateName}' is ${content.length} characters. Consider using an external file.`,\n })\n }\n }\n\n // E005/W005: dangling transitions — state not defined (H002: hint with closest name)\n const definedStates = new Set(\n nodesOfType(tree, 'state_decl')\n .map(n => n.childForFieldName('name')?.text)\n .filter(Boolean) as string[]\n )\n\n if (docPath) {\n try {\n collectMergedStates(tree, dirname(docPath), definedStates)\n } catch {\n // path resolution failed — continue with local states only\n }\n }\n\n // Fragment files (merged INTO another file, with no merge of their own)\n // don't see the parent's states via collectMergedStates, which only walks\n // forward. Callers that resolve the merge root can pass its consolidated\n // state set here so dangling-transition checks see the whole tree.\n if (externalStates) {\n for (const name of externalStates) definedStates.add(name)\n }\n\n const stateNameList = Array.from(definedStates)\n for (const transitionNode of nodesOfType(tree, 'transition_stmt')) {\n const stateNode = transitionNode.childForFieldName('state')\n if (!stateNode) continue\n const target = stateNode.text\n if (!definedStates.has(target)) {\n const { line, col } = nodePosition(stateNode)\n const isExternal = target.includes('.')\n // H002: enrich E005 with closest state name suggestion\n const hint = !isExternal ? closestName(target, stateNameList) : undefined\n messages.push({\n file, line, col,\n severity: isExternal ? 'warning' : 'error',\n code: isExternal ? 'W005' : 'E005',\n message: isExternal\n ? `State '${target}' is not defined locally (assuming external flow reference).`\n : `State '${target}' is not defined in this file.`,\n ...(hint ? { hint: `did you mean '${hint}'?` } : {}),\n })\n }\n }\n\n // W006: dead-end interact (no handlers at all)\n for (const interactNode of nodesOfType(tree, 'interact_stmt')) {\n let ancestor = interactNode.parent\n while (ancestor && ancestor.type !== 'state_decl') ancestor = ancestor.parent\n if (!ancestor) continue\n const hasHandlers =\n ancestor.descendantsOfType('intent_handler').length +\n ancestor.descendantsOfType('offtopic_handler').length > 0\n if (!hasHandlers) {\n const { line, col } = nodePosition(interactNode)\n messages.push({\n file, line, col, severity: 'warning', code: 'W006',\n message: 'This state calls interact but has no handlers (on intent/offtopic). This will trap the agent.',\n })\n }\n }\n\n // Semantic FSM validation via behavior-parser WASM. This always parses the\n // file's own `text` — never `mergedText` — so E006 and node positions below\n // (W009) stay anchored to real locations in the file the editor has open.\n const fsmResult = parseBehaviorFile(text)\n if (fsmResult.ok === null) {\n const firstMsg = fsmResult.diagnostics[0]?.message ?? 'Parse error'\n messages.push({\n file, line: 1, col: 1, severity: 'error', code: 'E006',\n message: `Parse error: ${firstMsg}`,\n })\n return messages\n }\n\n const fsm = fsmResult.ok\n\n // Reachability (used by W001/W009) should see the whole merge component\n // when it's known, so a state only ever reached from a merged sibling file\n // isn't wrongly flagged — but we still only *report* on states declared in\n // this file, at positions from this file's own tree.\n const wholeFsm = mergedText !== undefined ? parseBehaviorFile(mergedText).ok : null\n const reachabilityStates = wholeFsm?.states ?? fsm.states\n const allTargets = new Set(collectTransitionTargets(reachabilityStates.flatMap(s => s.body)))\n\n // W001: isolated state (no incoming and no outgoing transitions)\n for (const state of fsm.states) {\n const hasOutgoing = collectTransitionTargets(state.body).length > 0\n const hasIncoming = allTargets.has(state.name)\n if (!hasIncoming && !hasOutgoing) {\n messages.push({\n file, line: 1, col: 1, severity: 'warning', code: 'W001',\n message: `State \"${state.name}\" has no transitions`,\n })\n }\n }\n\n // W009: unreachable state (no incoming transitions, not the first state)\n for (let i = 1; i < fsm.states.length; i++) {\n const state = fsm.states[i]\n if (!allTargets.has(state.name)) {\n const stateNode = nodesOfType(tree, 'state_decl')\n .find(n => n.childForFieldName('name')?.text === state.name)\n const pos = stateNode ? nodePosition(stateNode) : { line: 1, col: 1 }\n messages.push({\n file, line: pos.line, col: pos.col, severity: 'warning', code: 'W009',\n message: `State '${state.name}' is unreachable — no other state transitions to it.`,\n })\n }\n }\n\n if (consolidated) {\n // E015/E016/W014 are whole-tree facts. When `mergedText` is given, derive\n // them from it instead of the local `fsm` — this is the only place a\n // merged-text FSM should be consulted, and it never affects positions\n // (all three report at a synthetic line 1 col 1, never a node position).\n const wholeTreeFsm = wholeFsm ?? fsm\n\n // E015: duplicate state name across merged files\n const seenStates = new Set<string>()\n for (const state of wholeTreeFsm.states) {\n if (seenStates.has(state.name)) {\n messages.push({\n file, line: 1, col: 1, severity: 'error', code: 'E015',\n message: `Duplicate state '${state.name}' across merged files — each state name must be unique in the consolidated FSM.`,\n })\n } else {\n seenStates.add(state.name)\n }\n }\n\n // E016: init state missing\n if (!wholeTreeFsm.states.some(s => s.name === 'init')) {\n messages.push({\n file, line: 1, col: 1, severity: 'error', code: 'E016',\n message: `Required 'init' state is missing. Add a state named 'init' as the entry point of your behavior.`,\n })\n }\n\n // W014: duplicate global trigger event across merged files\n const seenTriggers = new Set<string>()\n for (const trigger of wholeTreeFsm.global_triggers) {\n if (seenTriggers.has(trigger.event)) {\n messages.push({\n file, line: 1, col: 1, severity: 'warning', code: 'W014',\n message: `Duplicate global trigger '${trigger.event}' across merged files — only the last definition takes effect.`,\n })\n } else {\n seenTriggers.add(trigger.event)\n }\n }\n }\n\n return messages\n}\n\nexport async function createLinter() {\n return { lintDescription, lintBehavior }\n}\n","// Copyright 2026 Danilo Borges\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport JSZip from 'jszip'\nimport { readFile, writeFile } from 'fs/promises'\nexport { createZip, extractFiles } from './zip-core.js'\nimport {\n validateMagicBytes as validateMagicBytesCore,\n validateZipBomb as validateZipBombCore,\n} from './zip-core.js'\n\nexport async function readZip(filePath: string): Promise<JSZip> {\n const data = await readFile(filePath)\n return JSZip.loadAsync(data)\n}\n\nexport async function validateZipBomb(filePath: string): Promise<boolean> {\n const data = await readFile(filePath)\n const zip = await JSZip.loadAsync(data)\n validateZipBombCore(zip, data.length)\n return true\n}\n\nexport async function validateMagicBytes(filePath: string): Promise<boolean> {\n const data = await readFile(filePath)\n validateMagicBytesCore(data)\n return true\n}\n\nexport async function writeZip(zip: JSZip, outPath: string): Promise<void> {\n const data = await zip.generateAsync({ type: 'arraybuffer' })\n await writeFile(outPath, Buffer.from(data))\n}\n","// Copyright 2026 Danilo Borges\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n\nimport type { DescriptionFile, TypeDefinition, PropertyType, AnnotatedRef } from './types.js'\n\nconst STD_BASE = 'https://dot-agent.dev/schema/std/v1/'\n\nfunction propertyTypeToSchema(pt: PropertyType): object {\n switch (pt.kind) {\n case 'primitive':\n return { type: pt.value }\n case 'reference':\n return pt.value.startsWith('std.')\n ? { $ref: `${STD_BASE}${pt.value.slice(4)}.json` }\n : { $ref: `#/$defs/${pt.value}` }\n case 'array':\n return { type: 'array', items: propertyTypeToSchema(pt.value) }\n case 'enum':\n return { type: 'string', enum: pt.value }\n }\n}\n\nfunction typeDefinitionToSchema(td: TypeDefinition): object {\n const required = td.properties.filter(p => !p.is_optional).map(p => p.name)\n const properties: Record<string, object> = {}\n for (const p of td.properties) {\n properties[p.name] = {\n ...propertyTypeToSchema(p.type),\n ...(p.description ? { description: p.description } : {}),\n }\n }\n return {\n $schema: 'https://json-schema.org/draft/2020-12/schema',\n 'x-category': td.category.uri,\n ...(td.category.label ? { 'x-category-label': td.category.label } : {}),\n ...(td.concept ? { 'x-concept': td.concept.uri } : {}),\n ...(td.concept?.label ? { 'x-concept-label': td.concept.label } : {}),\n type: 'object',\n properties,\n ...(required.length ? { required } : {}),\n }\n}\n\nfunction refFromAnnotatedRef(ref: AnnotatedRef): object {\n return ref.name.startsWith('std.')\n ? { $ref: `${STD_BASE}${ref.name.slice(4)}.json` }\n : { $ref: `#/$defs/${ref.name}` }\n}\n\n/** Returns JSON Schema 2020-12 string for types.json, or null if nothing to write. */\nexport function buildTypesJson(df: DescriptionFile): string | null {\n if (df.types.length === 0 && df.input.length === 0 && df.output.length === 0) return null\n\n const defs: Record<string, object> = {}\n for (const td of df.types) {\n defs[td.name] = typeDefinitionToSchema(td)\n }\n\n return JSON.stringify(\n {\n ...(df.input.length ? { input: df.input.map(refFromAnnotatedRef) } : {}),\n ...(df.output.length ? { output: df.output.map(refFromAnnotatedRef) } : {}),\n ...(Object.keys(defs).length ? { $defs: defs } : {}),\n },\n null,\n 2\n )\n}\n","// Copyright 2026 Danilo Borges\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n\nimport { readFile, stat, readdir } from 'fs/promises'\nimport { join, basename, resolve, relative, isAbsolute, normalize, dirname } from 'path'\nimport { execSync } from 'child_process'\nimport { createHash } from 'crypto'\nimport JSZip from 'jszip'\nimport type { LintMessage, PackOptions, PackResult, Statement } from './types.js'\nimport { lintDescription, lintBehavior } from './linter.js'\nimport { buildId, slugify, isValidVersion } from './id.js'\nimport { buildAboutme, aboutmeToJson } from './manifest.js'\nimport { initBehaviorParser, parseDescriptionFile, parseBehaviorFile } from './parser.js'\nimport { buildTypesJson } from './schema.js'\nimport { writeZip } from './zip.js'\nimport { COMPILER_VERSION } from './generated-version.js'\nimport { isInContentNamespace, classifyContentPath } from './namespace.js'\n\nfunction gitRevParseShort(): string | null {\n try {\n return execSync('git rev-parse --short HEAD', { stdio: 'pipe', encoding: 'utf-8' }).trim()\n } catch {\n return null\n }\n}\n\nasync function resolveCommit(explicit?: string): Promise<string | undefined> {\n if (explicit) return explicit\n return gitRevParseShort() ?? undefined\n}\n\n// ── Version resolution ────────────────────────────────────────────────────────\n\ninterface VersionCandidate {\n version: string\n label: string\n}\n\n// The repo's tags are all monorepo-style `<pkg>@<version>` (there is no plain\n// vX.Y.Z release tag convention here). Rather than guess which tag belongs to\n// the directory being packed, list the most recent tags with their package\n// context and let a human pick — precision comes from judgment, not a\n// heuristic that can silently attribute the wrong package's version.\nfunction recentTagCandidates(limit = 5): VersionCandidate[] {\n let tags: string[]\n try {\n tags = execSync('git tag --sort=-creatordate', { stdio: 'pipe', encoding: 'utf-8' })\n .trim()\n .split('\\n')\n .filter(Boolean)\n } catch {\n return []\n }\n return tags\n .slice(0, limit)\n .map((tag): VersionCandidate => {\n const atIdx = tag.lastIndexOf('@')\n const version = atIdx === -1 ? tag : tag.slice(atIdx + 1)\n const label = atIdx === -1 ? tag : `${version} (tag: ${tag})`\n return { version, label }\n })\n .filter(c => isValidVersion(c.version))\n}\n\n// String sentinels (not symbols) — @clack/prompts' select() types `value` as\n// `string`, and these are extremely unlikely to collide with a real tag-derived version.\nconst CUSTOM_VERSION = '__dot-agent-custom-version__'\nconst BARE_VERSION = '__dot-agent-bare-version__'\n\n// No hardcoded version default — an unresolved version produces a form A\n// (bare) id per docs/reference/agent-id.md, rather than fabricating one.\nasync function resolveVersionInteractive(explicit?: string): Promise<string | undefined> {\n if (explicit) {\n if (!isValidVersion(explicit)) {\n throw new Error(`E019: Invalid version format '${explicit}' — expected vX.Y[.Z][-prerelease] or X.Y[.Z][-prerelease]`)\n }\n return explicit\n }\n\n if (!process.stdin.isTTY || !process.stdout.isTTY) {\n process.stderr.write('[dot-agent] no TTY and no --version — packing without a version\\n')\n return undefined\n }\n\n const candidates = recentTagCandidates()\n\n // @clack/prompts is ESM-only — dynamic import() resolves it correctly\n // regardless of whether this package itself is consumed as ESM or CJS\n // (a static import would break `require()` callers), and it also means the\n // non-interactive paths above never pay to load it at all.\n const clack = await import('@clack/prompts')\n\n const choice = await clack.select({\n message: 'Choose a version for this package',\n options: [\n ...candidates.map(c => ({ value: c.version, label: c.label })),\n { value: CUSTOM_VERSION, label: 'Type a custom version…' },\n { value: BARE_VERSION, label: 'None (bare — no version)' },\n ],\n })\n\n if (clack.isCancel(choice)) {\n clack.cancel('Pack cancelled.')\n process.exit(1)\n }\n\n if (choice === BARE_VERSION) return undefined\n\n if (choice === CUSTOM_VERSION) {\n const typed = await clack.text({\n message: 'Version',\n validate: v => (v && isValidVersion(v) ? undefined : 'Invalid version format — expected vX.Y[.Z][-prerelease] or X.Y[.Z][-prerelease]'),\n })\n if (clack.isCancel(typed)) {\n clack.cancel('Pack cancelled.')\n process.exit(1)\n }\n return typed\n }\n\n return choice as string\n}\n\n// ── Path safety ──────────────────────────────────────────────────────────────\n\nfunction isExternalPath(agentRoot: string, declaredPath: string): boolean {\n if (isAbsolute(declaredPath)) return true\n const normRoot = normalize(resolve(agentRoot))\n const resolved = resolve(normRoot, declaredPath)\n return relative(normRoot, resolved).startsWith('..')\n}\n\n// ── Description file discovery ────────────────────────────────────────────────\n\nexport async function discoverDescriptionFile(dir: string, explicit?: string): Promise<string> {\n if (explicit) {\n try {\n await stat(join(dir, explicit))\n return explicit\n } catch {\n throw new Error(`E003: Description file '${explicit}' not found in ${dir}`)\n }\n }\n const entries = await readdir(dir)\n const descFiles = entries.filter(f => f.endsWith('.description'))\n if (descFiles.length === 0) {\n throw new Error(`E003: No .description file found in ${dir}`)\n }\n if (descFiles.length > 1) {\n throw new Error(`E003: Multiple .description files found: ${descFiles.join(', ')} — use PackOptions.description to specify one`)\n }\n const name = descFiles[0]\n if (name !== 'agent.description') {\n console.info(`[dot-agent] using description file: ${name}`)\n }\n return name\n}\n\n// ── Merge graph consolidation ─────────────────────────────────────────────────\n\ninterface ConsolidateResult {\n mergedText: string\n mergeSources: string[] // relative paths within agent root, e.g. [\"main.behavior\"]\n}\n\nexport async function consolidate(agentRoot: string, entryFile: string): Promise<ConsolidateResult> {\n await initBehaviorParser()\n const normRoot = normalize(resolve(agentRoot))\n const visiting = new Set<string>()\n const visited = new Set<string>()\n const order: string[] = []\n const textCache = new Map<string, string>()\n\n async function dfs(relPath: string): Promise<void> {\n const absPath = resolve(normRoot, relPath)\n\n if (visiting.has(absPath)) {\n throw new Error(`E013: Circular merge dependency involving '${relPath}'`)\n }\n if (visited.has(absPath)) return\n\n visiting.add(absPath)\n\n let fileText: string\n try {\n fileText = await readFile(absPath, 'utf-8')\n } catch {\n throw new Error(`E012: Merge target not found: '${relPath}'`)\n }\n textCache.set(absPath, fileText)\n\n const result = parseBehaviorFile(fileText)\n const merges = result.ok?.merges ?? []\n\n for (const mergePath of merges) {\n if (isAbsolute(mergePath)) {\n throw new Error(`E014: Merge path '${mergePath}' in '${relPath}' is absolute — only paths within the agent root are allowed`)\n }\n const mergeAbs = resolve(dirname(absPath), mergePath)\n const mergeRel = relative(normRoot, mergeAbs)\n if (mergeRel.startsWith('..')) {\n throw new Error(`E014: Merge path '${mergePath}' in '${relPath}' escapes the agent root`)\n }\n await dfs(mergeRel)\n }\n\n visiting.delete(absPath)\n visited.add(absPath)\n order.push(relPath)\n }\n\n await dfs(entryFile)\n\n const texts = order.map(relPath => textCache.get(resolve(normRoot, relPath))!)\n return {\n mergedText: texts.join('\\n'),\n mergeSources: order,\n }\n}\n\n// ── guide/teach file references ───────────────────────────────────────────────\n\n// `guide \"...\"` / `teach \"...\"` text is either inline orientation prose or a\n// filename to bundle alongside the agent (e.g. `teach \"recipes.txt\"`). A\n// trailing .txt/.md is the only signal we have to tell them apart — anything\n// else stays literal, embedded verbatim in the flattened agent.behavior.\nconst FILE_REF_RE = /\\.(txt|md)$/i\n\ninterface FileRef {\n kind: 'guide' | 'teach'\n text: string\n}\n\nfunction collectFileRefs(stmts: Statement[], out: Map<string, FileRef>): void {\n for (const s of stmts) {\n switch (s.type) {\n case 'guide_stmt':\n if (FILE_REF_RE.test(s.text)) out.set(`guide:${s.text}`, { kind: 'guide', text: s.text })\n break\n case 'teach_stmt':\n if (FILE_REF_RE.test(s.text)) out.set(`teach:${s.text}`, { kind: 'teach', text: s.text })\n break\n case 'interact_stmt':\n collectFileRefs(s.handlers, out)\n break\n case 'intent_handler':\n if (Array.isArray(s.body)) collectFileRefs(s.body, out)\n break\n case 'offtopic_handler':\n case 'after_stmt':\n case 'parallel_stmt':\n collectFileRefs(s.body, out)\n break\n case 'conditional_stmt':\n collectFileRefs(s.then, out)\n if (s.else) collectFileRefs(s.else, out)\n break\n }\n }\n}\n\n// ── File collection ───────────────────────────────────────────────────────────\n\n// A `guide`/`teach` reference is a path relative to the agent root, bundled\n// verbatim at that path — the namespace is whatever the path itself declares\n// (`knowledge/x.md`, `guides/x.md`), not something derived from the keyword.\n// This keeps the reference, the on-disk location, and the bundle key a single\n// value, so nothing can drift into a doubled `knowledge/knowledge/x.md`. Only\n// light normalization: forward slashes and a stripped leading `./`.\nfunction normalizeRefPath(text: string): string {\n return text.replace(/\\\\/g, '/').replace(/^\\.\\//, '')\n}\n\nasync function collectBehaviorFileRefs(mergedBehaviorText: string): Promise<Map<string, FileRef>> {\n await initBehaviorParser()\n const refs = new Map<string, FileRef>()\n const behaviorAst = parseBehaviorFile(mergedBehaviorText).ok\n if (!behaviorAst) return refs\n for (const state of behaviorAst.states) collectFileRefs(state.body, refs)\n for (const trigger of behaviorAst.global_triggers) collectFileRefs(trigger.body, refs)\n return refs\n}\n\n// Every file under guides/ or knowledge/, keyed by the bundle path it *would*\n// occupy. Nothing here reaches the bundle on its own — only a guide/teach\n// reference pulls a file in (see collectFiles) — so this exists solely to let\n// findOrphanContentFiles report the files that never make it.\nasync function listContentFiles(dir: string, ns: 'guides' | 'knowledge'): Promise<string[]> {\n const found: string[] = []\n\n async function walk(subdir: string, prefix: string) {\n let entries: string[]\n try {\n entries = await readdir(subdir)\n } catch {\n return // directory doesn't exist or can't be read\n }\n for (const entry of entries) {\n if (entry.startsWith('.')) continue\n const fullPath = join(subdir, entry)\n const relativePath = `${prefix}/${entry}`\n if ((await stat(fullPath)).isDirectory()) {\n await walk(fullPath, relativePath)\n } else {\n found.push(relativePath)\n }\n }\n }\n\n await walk(join(dir, ns), ns)\n return found\n}\n\n// A file in guides/ or knowledge/ that no guide/teach statement names is absent\n// from the bundle under the linked-only rule — and would be unreachable at runtime\n// even if it were bundled, since the kernel hands the LLM a bare filename via the\n// teach effect and the MCP server exposes no listing endpoint. W015 is what keeps\n// that from being a silent drop, including for something like knowledge/data.csv\n// that FILE_REF_RE never recognises as a file reference to begin with.\nexport async function findOrphanContentFiles(\n dir: string,\n mergedBehaviorText: string,\n): Promise<LintMessage[]> {\n const refs = await collectBehaviorFileRefs(mergedBehaviorText)\n const referenced = new Set<string>()\n const messages: LintMessage[] = []\n\n // Single pass: every ref's bundlePath is normalized once and reused for both\n // checks below, instead of recomputing it in two separate loops.\n for (const { kind, text } of refs.values()) {\n const bundlePath = normalizeRefPath(text)\n referenced.add(bundlePath)\n\n // W016: a reference that resolves outside guides/ or knowledge/. It is\n // bundled at its literal path, but bundle.ts/sdk-load.ts only expose files\n // under those two prefixes, so the runtime can never hand its content to\n // the host — the teach/guide effect would surface a path nothing serves.\n // Flags the old \"loose file next to agent.behavior\" convention, now\n // unreachable. Only fires when the file actually exists and will actually\n // be bundled — a reference to a nonexistent file gets E018 from\n // collectFiles() instead, and this warning would otherwise falsely claim\n // it \"will be bundled\".\n if (isExternalPath(dir, bundlePath) || isInContentNamespace(bundlePath)) continue\n try {\n await stat(join(dir, bundlePath))\n } catch {\n continue\n }\n messages.push({\n file: bundlePath,\n line: 1,\n col: 1,\n severity: 'warning',\n code: 'W016',\n message: `'${kind}' reference '${text}' resolves outside guides/ or knowledge/ — it will be bundled but is unreachable at runtime; move it under knowledge/ (or guides/) and reference it there`,\n })\n }\n\n const onDisk = [\n ...(await listContentFiles(dir, 'guides')),\n ...(await listContentFiles(dir, 'knowledge')),\n ]\n\n const orphanMessages: LintMessage[] = onDisk\n .filter(path => !referenced.has(path))\n .map((path): LintMessage => ({\n file: path,\n line: 1,\n col: 1,\n severity: 'warning',\n code: 'W015',\n message: `'${path}' is not referenced by any guide or teach statement — it will not be included in the bundle`,\n }))\n\n return [...orphanMessages, ...messages]\n}\n\nexport async function collectFiles(\n dir: string,\n descriptionFile: string,\n mergedBehaviorText: string,\n mergeSources: string[],\n personaFile?: string,\n): Promise<Map<string, string>> {\n const files = new Map<string, string>()\n\n files.set(descriptionFile, await readFile(join(dir, descriptionFile), 'utf-8'))\n // mergedBehaviorText is a literal concatenation of every merged file's raw\n // source (see consolidate() above), so a `merge \"...\"` line from the entry\n // file survives verbatim even though every state it would pull in is\n // already inlined by the concatenation. Left in, a runtime that re-parses\n // this flat file (e.g. AgentSession.start() in @dot-agent/sdk) treats it as\n // a live merge directive and tries to re-resolve it against a differently\n // keyed bundle, failing with \"files not found\". It's dead once flattened —\n // strip it. Safe to do after linting (above), which already ran on the\n // unstripped text.\n const flatBehaviorText = mergedBehaviorText.replace(/^\\s*merge\\s+\"[^\"]*\"\\s*$/gm, '')\n files.set('agent.behavior', flatBehaviorText)\n\n for (const relPath of mergeSources) {\n files.set(`behaviors/${relPath}`, await readFile(join(dir, relPath), 'utf-8'))\n }\n\n if (personaFile) {\n if (isExternalPath(dir, personaFile)) {\n throw new Error(`E014: persona path '${personaFile}' in '${descriptionFile}' is absolute or escapes the agent root`)\n }\n let personaText: string\n try {\n personaText = await readFile(join(dir, personaFile), 'utf-8')\n } catch {\n throw new Error(`E_DESC: persona file '${personaFile}' declared in '${descriptionFile}' not found`)\n }\n files.set(personaFile, personaText)\n }\n\n // A `guide \"guides/intro.md\"` / `teach \"knowledge/recipes.md\"` reference is the\n // only thing that pulls a content file into the bundle — guides/ and knowledge/\n // are not swept wholesale, so the bundle is a function of the behavior graph\n // rather than of whatever happens to sit in the directory. The reference is a\n // path relative to the agent root, resolved literally and bundled verbatim at\n // that same path — no namespace guessing, no doubled `knowledge/knowledge/…`.\n // findOrphanContentFiles() reports what this loop leaves behind (W015) and any\n // reference that lands outside guides/ or knowledge/ (W016).\n const refs = await collectBehaviorFileRefs(mergedBehaviorText)\n for (const { kind, text } of refs.values()) {\n const bundlePath = normalizeRefPath(text)\n if (isExternalPath(dir, bundlePath)) {\n throw new Error(`E014: '${kind}' path '${text}' is absolute or escapes the agent root`)\n }\n\n let content: string\n try {\n content = await readFile(join(dir, bundlePath), 'utf-8')\n } catch {\n throw new Error(\n `E018: '${kind}' file '${text}' referenced in agent.behavior not found in ${dir} — looked for '${bundlePath}' relative to the agent root`\n )\n }\n\n // Nothing constrains bundlePath to guides/ or knowledge/ (see comment\n // above), so it can collide with a reserved key already set above — the\n // description file, the flattened agent.behavior, a merge source under\n // behaviors/, or the persona. Silently overwriting one of those would\n // corrupt content the kernel or SDK depends on (e.g. a behaviors/ entry\n // resolved at runtime for `merge \"...\"`), so refuse instead.\n if (files.has(bundlePath)) {\n throw new Error(\n `E020: '${kind}' reference '${text}' resolves to '${bundlePath}', which collides with a reserved bundle path (the description file, agent.behavior, a merged behaviors/ file, or the persona) — reference a different path`\n )\n }\n\n files.set(bundlePath, content)\n }\n\n return files\n}\n\n// The bundle extension is always .agent — append it when the caller left it off\n// rather than requiring `--out foo.agent` to be typed out every time.\nfunction withAgentExtension(path: string): string {\n return path.endsWith('.agent') ? path : `${path}.agent`\n}\n\nexport async function pack(options: PackOptions = {}): Promise<PackResult> {\n const dir = options.dir ?? process.cwd()\n const outPath = withAgentExtension(options.out ?? join(dir, basename(dir)))\n\n // 1. Discover and read description file\n const descriptionFileName = await discoverDescriptionFile(dir, options.description)\n const descriptionText = await readFile(join(dir, descriptionFileName), 'utf-8')\n\n // 2. Lint description — fail fast on errors (E017, E004, etc.)\n const descriptionMessages = await lintDescription(descriptionText, descriptionFileName)\n const descErrors = descriptionMessages.filter(m => m.severity === 'error')\n if (descErrors.length > 0) {\n throw new Error(\n `Lint failed:\\n${descErrors.map(e => ` ${e.file}:${e.line}:${e.col} ${e.code} ${e.message}`).join('\\n')}`\n )\n }\n\n // 3. Init WASM parser (needed for parseDescriptionFile and consolidate)\n await initBehaviorParser()\n\n // 4. Parse description to get df.behavior\n const descResult = parseDescriptionFile(descriptionText)\n if (descResult.ok === null) {\n const firstError = descResult.diagnostics.find(d => d.severity === 'error')\n throw new Error(`E_DESC: ${firstError?.message ?? 'parse failed'}`)\n }\n const df = descResult.ok\n\n // 5. Validate df.behavior\n if (!df.behavior) {\n throw new Error(`E_DESC: '${descriptionFileName}' must declare a behavior file — add 'behavior \"agent.behavior\"' (or the name of your entry .behavior file)`)\n }\n if (isExternalPath(dir, df.behavior)) {\n throw new Error(`E014: behavior path '${df.behavior}' in '${descriptionFileName}' is absolute or escapes the agent root`)\n }\n\n // 6. Consolidate merge graph → single merged text\n const { mergedText, mergeSources } = await consolidate(dir, df.behavior)\n\n // 7. Lint consolidated behavior (E015, E016, W014 only fire when consolidated=true)\n const behaviorMessages = await lintBehavior(mergedText, 'agent.behavior', undefined, true)\n const allMessages = [...descriptionMessages, ...behaviorMessages]\n const errors = allMessages.filter(m => m.severity === 'error')\n const lintWarnings = allMessages.filter(m => m.severity === 'warning')\n\n if (errors.length > 0) {\n throw new Error(\n `Lint failed:\\n${errors.map(e => ` ${e.file}:${e.line}:${e.col} ${e.code} ${e.message}`).join('\\n')}`\n )\n }\n\n // 8. Collect all files for the bundle\n const version = await resolveVersionInteractive(options.version)\n const commit = await resolveCommit(options.commit)\n const allFiles = await collectFiles(dir, descriptionFileName, mergedText, mergeSources, df.persona ?? undefined)\n const warnings = [...lintWarnings, ...(await findOrphanContentFiles(dir, mergedText))]\n\n const contentForHash = Array.from(allFiles.values()).join('')\n const sha256 = createHash('sha256').update(contentForHash).digest('hex')\n\n const namespace = df.agent.domain ?? 'unknown'\n // digest requires version (buildId's own invariant) — a bare (versionless)\n // id never carries a digest either, even if a commit sha is available.\n const id = buildId({ namespace, name: slugify(df.agent.name), version, digest: version ? commit : undefined })\n\n const typesJson = buildTypesJson(df)\n const integrity = {\n sha256,\n ...(typesJson ? { types: '.agent/types.json' } : {}),\n files: '.agent/files.json',\n }\n\n const aboutme = buildAboutme({\n id,\n name: df.agent.name,\n description: df.description ?? '',\n version: version ?? '',\n domain: df.agent.domain ?? '',\n license: df.agent.license ?? '',\n persona: df.persona ?? undefined,\n purpose: 'unknown',\n compiler: `dot-agent/${COMPILER_VERSION}`,\n commit,\n capabilities: df.capabilities.map(c => ({ id: c.name, description: c.description ?? '' })),\n requires: df.requires,\n integrity,\n })\n\n const zip = new JSZip()\n const agentFolder = zip.folder('.agent')!\n agentFolder.file('aboutme.json', aboutmeToJson(aboutme))\n\n if (typesJson) {\n agentFolder.file('types.json', typesJson)\n }\n\n const filesJson = {\n description: descriptionFileName,\n behavior: 'agent.behavior',\n ...(df.persona ? { persona: df.persona } : {}),\n behaviors: Array.from(allFiles.keys()).filter(f => f.startsWith('behaviors/')),\n guides: Array.from(allFiles.keys()).filter(f => classifyContentPath(f) === 'guides'),\n knowledge: Array.from(allFiles.keys()).filter(f => classifyContentPath(f) === 'knowledge'),\n }\n agentFolder.file('files.json', JSON.stringify(filesJson, null, 2))\n\n for (const [path, content] of allFiles) {\n zip.file(path, content)\n }\n\n await writeZip(zip, outPath)\n\n return { path: outPath, id, warnings }\n}\n","// Copyright 2026 Danilo Borges\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n\nimport { readFile } from 'fs/promises'\nimport { join } from 'path'\nimport { createHash } from 'crypto'\nimport type { AgentBundle, AgentFiles } from './types.js'\nimport { discoverDescriptionFile, consolidate, collectFiles, findOrphanContentFiles } from './pack.js'\nimport { lintDescription, lintBehavior } from './linter.js'\nimport { buildId, slugify } from './id.js'\nimport { buildAboutme } from './manifest.js'\nimport { initBehaviorParser, parseDescriptionFile } from './parser.js'\nimport { COMPILER_VERSION } from './generated-version.js'\nimport { classifyContentPath } from './namespace.js'\n\nexport async function bundleFromDir(dir: string): Promise<AgentBundle> {\n const descriptionFileName = await discoverDescriptionFile(dir)\n const descriptionText = await readFile(join(dir, descriptionFileName), 'utf-8')\n\n const descMessages = await lintDescription(descriptionText, descriptionFileName)\n const descErrors = descMessages.filter(m => m.severity === 'error')\n if (descErrors.length > 0) {\n throw new Error(\n `Lint failed:\\n${descErrors.map(e => ` ${e.file}:${e.line}:${e.col} ${e.code} ${e.message}`).join('\\n')}`\n )\n }\n\n await initBehaviorParser()\n const descResult = parseDescriptionFile(descriptionText)\n if (descResult.ok === null) {\n const firstError = descResult.diagnostics.find(d => d.severity === 'error')\n throw new Error(`E_DESC: ${firstError?.message ?? 'parse failed'}`)\n }\n const df = descResult.ok\n\n if (!df.behavior) {\n throw new Error(`E_DESC: '${descriptionFileName}' must declare a behavior file`)\n }\n\n const { mergedText, mergeSources } = await consolidate(dir, df.behavior)\n\n const behaviorMessages = await lintBehavior(mergedText, 'agent.behavior', undefined, true)\n const orphanMessages = await findOrphanContentFiles(dir, mergedText)\n const allMessages = [...descMessages, ...behaviorMessages, ...orphanMessages]\n const errors = allMessages.filter(m => m.severity === 'error')\n const warnings = allMessages.filter(m => m.severity === 'warning')\n\n if (errors.length > 0) {\n throw new Error(\n `Lint failed:\\n${errors.map(e => ` ${e.file}:${e.line}:${e.col} ${e.code} ${e.message}`).join('\\n')}`\n )\n }\n\n for (const w of warnings) {\n process.stderr.write(`\\x1b[33m⚠\\x1b[0m ${w.file}:${w.line}:${w.col} ${w.code} ${w.message}\\n`)\n }\n\n const allFiles = await collectFiles(dir, descriptionFileName, mergedText, mergeSources, df.persona ?? undefined)\n\n const sha256 = createHash('sha256')\n .update(Array.from(allFiles.values()).join(''))\n .digest('hex')\n\n const id = buildId({ namespace: df.agent.domain ?? 'unknown', name: slugify(df.agent.name), version: 'dev' })\n\n const aboutme = buildAboutme({\n id,\n name: df.agent.name,\n description: df.description ?? '',\n version: 'dev',\n domain: df.agent.domain ?? '',\n license: df.agent.license ?? '',\n persona: df.persona ?? undefined,\n purpose: 'development',\n compiler: `dot-agent/${COMPILER_VERSION}`,\n capabilities: df.capabilities.map(c => ({ id: c.name, description: c.description ?? '' })),\n requires: df.requires,\n integrity: { sha256, files: '.agent/files.json' },\n })\n\n const files: AgentFiles = {\n description: descriptionText,\n // Reuse collectFiles()'s 'agent.behavior' entry rather than the raw\n // mergedText — it has redundant `merge \"...\"` lines stripped (see\n // collectFiles() for why they're dead weight once flattened).\n behavior: allFiles.get('agent.behavior') ?? mergedText,\n persona: df.persona ? allFiles.get(df.persona) : undefined,\n guides: Array.from(allFiles.entries())\n .filter(([p]) => classifyContentPath(p) === 'guides')\n .map(([path, content]) => ({ path, content })),\n knowledge: Array.from(allFiles.entries())\n .filter(([p]) => classifyContentPath(p) === 'knowledge')\n .map(([path, content]) => ({ path, content })),\n behaviors: Array.from(allFiles.entries())\n .filter(([p]) => p.startsWith('behaviors/'))\n .map(([path, content]) => ({ path, content })),\n }\n\n return { id, aboutme, files }\n}\n"],"mappings":";;;;;;;;;;;AAeA,MAAM,EAAE,qBAAqB,qBADb,cAAc,OAAO,KAAK,GACc,CAAC,CAAC,wBAAwB;AAKlF,IAAI,eAAe;AACnB,IAAI;AACJ,IAAI;AACJ,IAAI,iBAAiB;AAErB,eAAsB,qBAAoC;CACxD,IAAI,gBAAgB;CACpB,MAAMA,KAAO;CACb,iBAAiB;AACnB;AAOA,SAAgB,kBAAkB,MAAyC;CACzE,OAAO,KAAK,MAAMC,eAAgB,IAAI,CAAC;AACzC;AAEA,SAAgB,qBAAqB,MAA4C;CAC/E,OAAO,KAAK,MAAMC,kBAAmB,IAAI,CAAC;AAC5C;AAEA,SAAgB,iBAAiB,MAAsB;CACrD,OAAO,UAAU,IAAI;AACvB;AAEA,eAAsB,cAA6B;CACjD,IAAI,cAAc;CAClB,MAAM,OAAO,KAAK;CAClB,MAAM,kBAAkB,MAAM,SAAS,KAAK,mBAAmB;CAC/D,MAAM,eAAe,MAAM,SAAS,KAAK,gBAAgB;CACzD,qBAAqB,IAAI,OAAO;CAChC,mBAAmB,YAAY,eAAe;CAC9C,kBAAkB,IAAI,OAAO;CAC7B,gBAAgB,YAAY,YAAY;CACxC,eAAe;AACjB;;;;;;;;AASA,eAAsB,MACpB,QACA,MACA,cACe;CACf,MAAM,YAAY;CAElB,QADe,WAAW,aAAa,kBAAkB,mBAAA,CAC3C,MAAM,MAAM,YAAY;AACxC;;AAGA,SAAgB,UAAU,QAAgB,MAAc,cAAkC;CACxF,IAAI,CAAC,cAAc,OAAO;CAE1B,QADe,WAAW,aAAa,kBAAkB,mBAAA,CAC3C,MAAM,MAAM,YAAY;AACxC;AAIA,SAAgB,YAAY,MAAY,MAAsB;CAC5D,IAAI,CAAC,MAAM,OAAO,CAAC;CACnB,OAAO,KAAK,SAAS,kBAAkB,IAAI,CAAC,CAAC,QAAQ,MAAiB,MAAM,IAAI;AAClF;AAEA,SAAgB,aAAa,MAAY,QAA6B;CACpE,IAAI,CAAC,MAAM,OAAO;CAClB,OAAO,KAAK,SAAS,mBAAmB,MAAM;AAChD;AAEA,SAAgB,YAAY,MAG1B;CACA,OAAO;EACL,OAAO;GAAE,MAAM,KAAK,cAAc;GAAK,WAAW,KAAK,cAAc;EAAO;EAC5E,KAAK;GAAE,MAAM,KAAK,YAAY;GAAK,WAAW,KAAK,YAAY;EAAO;CACxE;AACF;AAEA,SAAgB,iBAAiB,MAAc,MAAc,WAA2B;CACtF,IAAI,SAAS;CACb,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,KAAK;EAC7B,MAAM,KAAK,KAAK,QAAQ,MAAM,MAAM;EACpC,SAAS,OAAO,KAAK,KAAK,SAAS,KAAK;CAC1C;CACA,OAAO,SAAS;AAClB;AAEA,SAAgB,eAAe,MAAY,QAAsB;CAC/D,IAAI,OAAO,aAAa,MAAM,MAAM;CACpC,OAAO,SAAS,KAAK,WAAW,KAAK,YACnC,OAAO,KAAK;CAEd,IAAI,CAAC,QAAQ,KAAK,SAAS,SAAS;EAElC,MAAM,SADM,aAAa,MAAM,MACd,CAAC,EAAE;EACpB,IAAI,QAAQ;GACV,MAAM,WAAW,OAAO;GACxB,MAAM,MAAM,SAAS,WAAW,MAAmB,MAAM,QAAQ,EAAE,aAAa,MAAM;GACtF,MAAM,OAAO,MAAM,IAAI,SAAS,MAAM,KAAK,SAAS,SAAS,SAAS;GACtE,IAAI,QAAQ,CAAC,KAAK,SAAS,OAAO;EACpC;CACF;CACA,OAAO,QAAQ,KAAK;AACtB;;;AC/GA,SAAS,aAAa,MAA2C;CAC/D,OAAO;EAAE,MAAM,KAAK,cAAc,MAAM;EAAG,KAAK,KAAK,cAAc,SAAS;CAAE;AAChF;AAIA,MAAM,gBAAwC;CAC5C,eAAe;CACf,kBAAkB;CAClB,gBAAgB;CAChB,WAAW;CACX,YAAY;CACZ,eAAe;AACjB;AAEA,SAAS,oBAAoB,MAAY,UAAyB,MAAoB;CACpF,MAAM,uBAAO,IAAI,IAAY;CAE7B,SAAS,KAAK,MAAY,SAAiB,MAAc,WAAgC,SAAS;EAChG,MAAM,MAAM,GAAG,KAAK,WAAW,GAAG,KAAK,SAAS,GAAG;EACnD,IAAI,KAAK,IAAI,GAAG,GAAG;EACnB,KAAK,IAAI,GAAG;EACZ,MAAM,EAAE,MAAM,QAAQ,aAAa,IAAI;EACvC,SAAS,KAAK;GAAE;GAAM;GAAM;GAAK;GAAU;GAAM;EAAQ,CAAC;CAC5D;CAEA,SAAS,KAAK,MAAY;EACxB,IAAI,KAAK,WAAW;GAClB,MAAM,OAAO,cAAc,KAAK;GAChC,KAAK,MAAM,QAAQ,0BAA0B,KAAK,KAAK,KAAK,MAAM;GAClE;EACF;EACA,IAAI,KAAK,SAAS;OAEZ,CADmB,KAAK,kBAAkB,OAAO,CAAC,CAAC,MAAM,MAAmB,MAAM,QAAQ,EAAE,OAAO,KAAK,EAC1F,GAAG;IACnB,MAAM,UAAU,KAAK,KAAK,QAAQ,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,EAAE;IACjE,KAAK,MAAM,UAAU,sBAAsB,QAAQ,MAAM,iBAAiB,MAAM;IAChF;GACF;;EAEF,KAAK,MAAM,SAAS,KAAK,UACvB,IAAI,OAAO,KAAK,KAAK;CAEzB;CAEA,KAAK,IAAI;AACX;AAIA,MAAM,qBAA6C;CACjD,aAAa;CACb,cAAc;CACd,gBAAgB;CAChB,oBAAoB;AACtB;AAEA,eAAsB,gBAAgB,MAAc,OAAO,qBAA6C;CACtG,MAAM,OAAO,MAAM,MAAM,eAAe,IAAI;CAC5C,MAAM,WAA0B,CAAC;CAEjC,oBAAoB,KAAK,UAAU,UAAU,IAAI;CAIjD,KAAK,MAAM,YAAY,YAAY,MAAM,YAAY,GAAG;EAEtD,IADgB,SAAS,kBAAkB,KACjC,CAAC,EAAE,SAAS,UAAU;EAChC,MAAM,YAAY,SAAS,kBAAkB,OAAO;EACpD,IAAI,WAAW,SAAS,eAAe;GACrC,MAAM,EAAE,MAAM,QAAQ,aAAa,SAAS;GAC5C,SAAS,KAAK;IACZ;IACA;IACA;IACA,UAAU;IACV,MAAM;IACN,SAAS;GACX,CAAC;EACH;CACF;CAMA,IAAI,CAHc,YAAY,MAAM,YAAY,CAAC,CAAC,MAChD,MAAK,EAAE,kBAAkB,KAAK,CAAC,EAAE,SAAS,YAAY,EAAE,kBAAkB,OAAO,CAAC,EAAE,MAAM,KAAK,CAEpF,GACX,SAAS,KAAK;EACZ;EACA,MAAM;EACN,KAAK;EACL,UAAU;EACV,MAAM;EACN,SACE;CACJ,CAAC;CAIH,MAAM,iBAAiB,YAAY,MAAM,gBAAgB;CACzD,IAAI,eAAe,SAAS,GAAG;EAC7B,MAAM,EAAE,MAAM,QAAQ,aAAa,eAAe,EAAE;EACpD,SAAS,KAAK;GACZ;GAAM;GAAM;GAAK,UAAU;GAAS,MAAM;GAC1C,SAAS;EACX,CAAC;CACH;CAGA,MAAM,gBAAgB,IAAI,IACxB,YAAY,MAAM,WAAW,CAAC,CAC3B,KAAI,MAAK,EAAE,kBAAkB,MAAM,CAAC,EAAE,IAAI,CAAC,CAC3C,OAAO,OAAO,CACnB;CAEA,IAAI,cAAc,OAAO,GACvB,KAAK,MAAM,aAAa,OAAO,KAAK,kBAAkB,GACpD,KAAK,MAAM,aAAa,YAAY,MAAM,SAAS,GACjD,KAAK,MAAM,eAAe,UAAU,kBAAkB,gBAAgB,CAAC,CAAC,QAAQ,MAAiB,MAAM,IAAI,GAAG;EAC5G,MAAM,SAAS,YAAY;EAC3B,IAAI,CAAC,QAAQ;EACb,MAAM,WAAW,OAAO;EACxB,IAAI,CAAC,cAAc,IAAI,QAAQ,GAAG;GAChC,MAAM,EAAE,MAAM,QAAQ,aAAa,MAAM;GACzC,SAAS,KAAK;IACZ;IACA;IACA;IACA,UAAU;IACV,MAAM;IACN,SAAS,SAAS,SAAS;GAC7B,CAAC;EACH;CACF;CAKN,OAAO;AACT;AAIA,SAAS,YAAY,GAAW,GAAmB;CACjD,MAAM,KAAK,EAAE,QAAQ,KAAK,EAAE;CAC5B,MAAM,KAAiB,MAAM,KAAK,EAAE,QAAQ,KAAK,EAAE,IAAI,GAAG,MACxD,MAAM,KAAK,EAAE,QAAQ,KAAK,EAAE,IAAI,GAAG,MAAO,MAAM,IAAI,IAAI,MAAM,IAAI,IAAI,CAAE,CAC1E;CACA,KAAK,IAAI,IAAI,GAAG,KAAK,IAAI,KACvB,KAAK,IAAI,IAAI,GAAG,KAAK,IAAI,KACvB,GAAG,EAAE,CAAC,KAAK,EAAE,IAAI,OAAO,EAAE,IAAI,KAC1B,GAAG,IAAI,EAAE,CAAC,IAAI,KACd,IAAI,KAAK,IAAI,GAAG,IAAI,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,IAAI,IAAI,GAAG,IAAI,EAAE,CAAC,IAAI,EAAE;CAGjE,OAAO,GAAG,GAAG,CAAC;AAChB;AAEA,SAAS,YAAY,OAAe,YAA0C;CAC5E,IAAI;CACJ,IAAI,WAAW;CACf,KAAK,MAAM,QAAQ,YAAY;EAC7B,MAAM,IAAI,YAAY,MAAM,YAAY,GAAG,KAAK,YAAY,CAAC;EAC7D,IAAI,IAAI,KAAK,KAAK,KAAK,IAAI,UAAU;GAAE,WAAW;GAAG,OAAO;EAAK;CACnE;CACA,OAAO;AACT;AAEA,MAAM,yBAAyB;CAAC;CAAQ;CAAW;CAAO;CAAU;AAAS;AAE7E,SAAS,yBAAyB,OAAgE;CAChG,MAAM,UAAoB,CAAC;CAC3B,KAAK,MAAM,QAAQ,OAAO;EACxB,IAAI,CAAC,QAAQ,OAAO,SAAS,UAAU;EACvC,IAAI,KAAK,SAAS,qBAAqB,OAAO,KAAK,aAAa,UAC9D,QAAQ,KAAK,KAAK,QAAQ;EAE5B,IAAI,KAAK,SAAS,oBAAoB,OAAO,KAAK,YAAY,UAC5D,QAAQ,KAAK,KAAK,OAAO;EAE3B,MAAM,WAAW,MAAe;GAC9B,IAAI,MAAM,QAAQ,CAAC,GAAG,QAAQ,KAAK,GAAG,yBAAyB,CAA4B,CAAC;EAC9F;EACA,IAAI,KAAK,SAAS,kBAAkB,QAAQ,KAAK,OAAO;EACxD,QAAQ,KAAK,WAAW;EACxB,QAAQ,KAAK,OAAO;EACpB,QAAQ,KAAK,OAAO;EACpB,QAAQ,KAAK,cAAc;EAC3B,QAAQ,KAAK,aAAa;CAC5B;CACA,OAAO;AACT;AAEA,SAAS,oBACP,MACA,QACA,QACA,0BAAU,IAAI,IAAY,GACpB;CACN,KAAK,MAAM,aAAa,YAAY,MAAM,YAAY,GAAG;EACvD,MAAM,WAAW,UAAU,kBAAkB,MAAM;EACnD,IAAI,CAAC,UAAU;EAEf,MAAM,UAAU,QAAQ,QADP,SAAS,KAAK,QAAQ,UAAU,EACV,CAAC;EACxC,IAAI,QAAQ,IAAI,OAAO,GAAG;EAC1B,QAAQ,IAAI,OAAO;EACnB,IAAI;EACJ,IAAI;GACF,aAAa,aAAa,SAAS,OAAO;EAC5C,QAAQ;GACN;EACF;EACA,MAAM,aAAa,UAAU,YAAY,UAAU;EACnD,IAAI,CAAC,YAAY;EACjB,YAAY,YAAY,YAAY,CAAC,CAAC,SAAQ,MAAK;GACjD,MAAM,OAAO,EAAE,kBAAkB,MAAM,CAAC,EAAE;GAC1C,IAAI,MAAM,OAAO,IAAI,IAAI;EAC3B,CAAC;EACD,oBAAoB,YAAY,QAAQ,OAAO,GAAG,QAAQ,OAAO;CACnE;AACF;AAEA,eAAsB,aACpB,MACA,OAAO,kBACP,SACA,eAAe,OACf,gBACA,YACwB;CACxB,MAAM,mBAAmB;CACzB,IAAI,CAAC,KAAK,SAAS,IAAI,GAAG,OAAO,OAAO;CACxC,MAAM,OAAO,MAAM,MAAM,YAAY,IAAI;CACzC,MAAM,WAA0B,CAAC;CAGjC,oBAAoB,KAAK,UAAU,UAAU,IAAI;CAEjD,KAAK,MAAM,aAAa,YAAY,MAAM,YAAY,GAAG;EACvD,IAAI,UAAU,UAAU;EACxB,MAAM,WAAW,UAAU,kBAAkB,MAAM;EACnD,MAAM,YAAY,UAAU,QAAQ;EACpC,MAAM,cAAc,UAAU,kBAAkB,eAAe,CAAC,CAAC,SAAS;EAC1E,MAAM,UAAU,UAAU,kBAAkB,WAAW,CAAC,CAAC,SAAS;EAClE,MAAM,iBAAiB,UAAU,kBAAkB,gBAAgB;EAGnE,IAAI,eAAe,CAAC,SAAS;GAC3B,MAAM,EAAE,MAAM,QAAQ,aAAa,YAAY,SAAS;GACxD,SAAS,KAAK;IACZ;IAAM;IAAM;IAAK,UAAU;IAAW,MAAM;IAC5C,SAAS;GACX,CAAC;EACH;EAGA,IAAI,WAAW,CAAC,aAAa;GAC3B,MAAM,EAAE,MAAM,QAAQ,aAAa,YAAY,SAAS;GACxD,SAAS,KAAK;IACZ;IAAM;IAAM;IAAK,UAAU;IAAW,MAAM;IAC5C,SAAS;GACX,CAAC;EACH;EAGA,IAAI,eAAe,eAAe,WAAW,GAAG;GAC9C,MAAM,EAAE,MAAM,QAAQ,aAAa,YAAY,SAAS;GACxD,SAAS,KAAK;IACZ;IAAM;IAAM;IAAK,UAAU;IAAS,MAAM;IAC1C,SAAS,mBAAmB,UAAU;GACxC,CAAC;EACH;EAGA,MAAM,8BAAc,IAAI,IAAkB;EAC1C,KAAK,MAAM,WAAW,gBAAgB;GACpC,MAAM,aAAa,QAAQ,kBAAkB,QAAQ;GACrD,IAAI,CAAC,YAAY;GACjB,MAAM,QAAQ,WAAW,KAAK,QAAQ,UAAU,EAAE;GAClD,IAAI,YAAY,IAAI,KAAK,GAAG;IAC1B,MAAM,EAAE,MAAM,QAAQ,aAAa,OAAO;IAC1C,SAAS,KAAK;KACZ;KAAM;KAAM;KAAK,UAAU;KAAS,MAAM;KAC1C,SAAS,yBAAyB,MAAM,eAAe,UAAU;IACnE,CAAC;GACH,OACE,YAAY,IAAI,OAAO,IAAI;EAE/B;EAGA,KAAK,MAAM,WAAW,gBACpB,KAAK,MAAM,KAAK,QAAQ,kBAAkB,iBAAiB,GAEzD,IADmB,EAAE,kBAAkB,OAC1B,CAAC,EAAE,SAAS,WAAW;GAClC,MAAM,EAAE,MAAM,QAAQ,aAAa,OAAO;GAC1C,SAAS,KAAK;IACZ;IAAM;IAAM;IAAK,UAAU;IAAW,MAAM;IAC5C,SAAS,iCAAiC,UAAU;GACtD,CAAC;EACH;EAKJ,IAAI,cAAc,UAAU,cAAc,OAAO;GAC/C,MAAM,EAAE,MAAM,QAAQ,aAAa,YAAY,SAAS;GACxD,IAAI,cAAc,QAChB,SAAS,KAAK;IACZ;IAAM;IAAM;IAAK,UAAU;IAAQ,MAAM;IACzC,SAAS;GACX,CAAC;QAED,SAAS,KAAK;IACZ;IAAM;IAAM;IAAK,UAAU;IAAQ,MAAM;IACzC,SAAS;GACX,CAAC;EAEL;EAGA,IAAI,CAAC,uBAAuB,SAAS,SAAS,GAAG;GAC/C,MAAM,UAAU,YAAY,WAAW,sBAAsB;GAC7D,IAAI,SAAS;IACX,MAAM,EAAE,MAAM,QAAQ,aAAa,YAAY,SAAS;IACxD,SAAS,KAAK;KACZ;KAAM;KAAM;KAAK,UAAU;KAAQ,MAAM;KACzC,SAAS,eAAe,UAAU,yCAAyC,QAAQ;IACrF,CAAC;GACH;EACF;CACF;CAGA,KAAK,MAAM,gBAAgB,YAAY,MAAM,eAAe,GAAG;EAC7D,IAAI,aAAa,UAAU;EAC3B,IAAI,aAAa,kBAAkB,UAAU,CAAC,CAAC,WAAW,GAAG;GAC3D,MAAM,EAAE,MAAM,QAAQ,aAAa,YAAY;GAC/C,IAAI,YAAY;GAChB,IAAI,WAAW,aAAa;GAC5B,OAAO,YAAY,SAAS,SAAS,cAAc,WAAW,SAAS;GACvE,IAAI,UAAU,YAAY,SAAS,kBAAkB,MAAM,CAAC,EAAE,QAAQ;GACtE,SAAS,KAAK;IACZ;IAAM;IAAM;IAAK,UAAU;IAAW,MAAM;IAC5C,SAAS,8BAA8B,UAAU;GACnD,CAAC;EACH;CACF;CAGA,KAAK,MAAM,aAAa,YAAY,MAAM,YAAY,GAAG;EACvD,IAAI,UAAU,UAAU;EACxB,MAAM,YAAY,UAAU,kBAAkB,OAAO;EACrD,IAAI,WAAW,SAAS,KAAK;GAC3B,MAAM,EAAE,MAAM,QAAQ,aAAa,SAAS;GAC5C,SAAS,KAAK;IACZ;IAAM;IAAM;IAAK,UAAU;IAAS,MAAM;IAC1C,SAAS;GACX,CAAC;EACH;CACF;CAGA,KAAK,MAAM,YAAY,YAAY,MAAM,WAAW,GAAG;EACrD,MAAM,UAAU,SAAS,kBAAkB,eAAe,CAAC,CAAC,MAAM,MAAiB,MAAM,IAAI;EAC7F,IAAI,CAAC,SAAS;EACd,MAAM,UAAU,QAAQ,KAAK,QAAQ,UAAU,EAAE;EACjD,IAAI,QAAQ,SAAS,KAAK;GACxB,MAAM,EAAE,MAAM,QAAQ,aAAa,OAAO;GAC1C,SAAS,KAAK;IACZ;IAAM;IAAM;IAAK,UAAU;IAAW,MAAM;IAC5C,SAAS,sCAAsC,QAAQ,OAAO;GAChE,CAAC;EACH;CACF;CAGA,KAAK,MAAM,YAAY,YAAY,MAAM,YAAY,GAAG;EACtD,MAAM,UAAU,SAAS,kBAAkB,eAAe,CAAC,CAAC,MAAM,MAAiB,MAAM,IAAI;EAC7F,IAAI,CAAC,SAAS;EACd,MAAM,UAAU,QAAQ,KAAK,QAAQ,UAAU,EAAE;EACjD,IAAI,QAAQ,SAAS,KAAK;GACxB,MAAM,EAAE,MAAM,QAAQ,aAAa,OAAO;GAC1C,IAAI,IAAI,SAAS;GACjB,OAAO,KAAK,EAAE,SAAS,cAAc,IAAI,EAAE;GAC3C,MAAM,YAAY,GAAG,kBAAkB,MAAM,CAAC,EAAE,QAAQ;GACxD,SAAS,KAAK;IACZ;IAAM;IAAM;IAAK,UAAU;IAAW,MAAM;IAC5C,SAAS,0BAA0B,UAAU,OAAO,QAAQ,OAAO;GACrE,CAAC;EACH;CACF;CAGA,MAAM,gBAAgB,IAAI,IACxB,YAAY,MAAM,YAAY,CAAC,CAC5B,KAAI,MAAK,EAAE,kBAAkB,MAAM,CAAC,EAAE,IAAI,CAAC,CAC3C,OAAO,OAAO,CACnB;CAEA,IAAI,SACF,IAAI;EACF,oBAAoB,MAAM,QAAQ,OAAO,GAAG,aAAa;CAC3D,QAAQ,CAER;CAOF,IAAI,gBACF,KAAK,MAAM,QAAQ,gBAAgB,cAAc,IAAI,IAAI;CAG3D,MAAM,gBAAgB,MAAM,KAAK,aAAa;CAC9C,KAAK,MAAM,kBAAkB,YAAY,MAAM,iBAAiB,GAAG;EACjE,MAAM,YAAY,eAAe,kBAAkB,OAAO;EAC1D,IAAI,CAAC,WAAW;EAChB,MAAM,SAAS,UAAU;EACzB,IAAI,CAAC,cAAc,IAAI,MAAM,GAAG;GAC9B,MAAM,EAAE,MAAM,QAAQ,aAAa,SAAS;GAC5C,MAAM,aAAa,OAAO,SAAS,GAAG;GAEtC,MAAM,OAAO,CAAC,aAAa,YAAY,QAAQ,aAAa,IAAI,KAAA;GAChE,SAAS,KAAK;IACZ;IAAM;IAAM;IACZ,UAAU,aAAa,YAAY;IACnC,MAAM,aAAa,SAAS;IAC5B,SAAS,aACL,UAAU,OAAO,gEACjB,UAAU,OAAO;IACrB,GAAI,OAAO,EAAE,MAAM,iBAAiB,KAAK,IAAI,IAAI,CAAC;GACpD,CAAC;EACH;CACF;CAGA,KAAK,MAAM,gBAAgB,YAAY,MAAM,eAAe,GAAG;EAC7D,IAAI,WAAW,aAAa;EAC5B,OAAO,YAAY,SAAS,SAAS,cAAc,WAAW,SAAS;EACvE,IAAI,CAAC,UAAU;EAIf,IAAI,EAFF,SAAS,kBAAkB,gBAAgB,CAAC,CAAC,SAC3C,SAAS,kBAAkB,kBAAkB,CAAC,CAAC,SAAS,IAC1C;GAChB,MAAM,EAAE,MAAM,QAAQ,aAAa,YAAY;GAC/C,SAAS,KAAK;IACZ;IAAM;IAAM;IAAK,UAAU;IAAW,MAAM;IAC5C,SAAS;GACX,CAAC;EACH;CACF;CAKA,MAAM,YAAY,kBAAkB,IAAI;CACxC,IAAI,UAAU,OAAO,MAAM;EACzB,MAAM,WAAW,UAAU,YAAY,EAAE,EAAE,WAAW;EACtD,SAAS,KAAK;GACZ;GAAM,MAAM;GAAG,KAAK;GAAG,UAAU;GAAS,MAAM;GAChD,SAAS,gBAAgB;EAC3B,CAAC;EACD,OAAO;CACT;CAEA,MAAM,MAAM,UAAU;CAMtB,MAAM,WAAW,eAAe,KAAA,IAAY,kBAAkB,UAAU,CAAC,CAAC,KAAK;CAC/E,MAAM,qBAAqB,UAAU,UAAU,IAAI;CACnD,MAAM,aAAa,IAAI,IAAI,yBAAyB,mBAAmB,SAAQ,MAAK,EAAE,IAAI,CAAC,CAAC;CAG5F,KAAK,MAAM,SAAS,IAAI,QAAQ;EAC9B,MAAM,cAAc,yBAAyB,MAAM,IAAI,CAAC,CAAC,SAAS;EAElE,IAAI,CADgB,WAAW,IAAI,MAAM,IAC1B,KAAK,CAAC,aACnB,SAAS,KAAK;GACZ;GAAM,MAAM;GAAG,KAAK;GAAG,UAAU;GAAW,MAAM;GAClD,SAAS,UAAU,MAAM,KAAK;EAChC,CAAC;CAEL;CAGA,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,OAAO,QAAQ,KAAK;EAC1C,MAAM,QAAQ,IAAI,OAAO;EACzB,IAAI,CAAC,WAAW,IAAI,MAAM,IAAI,GAAG;GAC/B,MAAM,YAAY,YAAY,MAAM,YAAY,CAAC,CAC9C,MAAK,MAAK,EAAE,kBAAkB,MAAM,CAAC,EAAE,SAAS,MAAM,IAAI;GAC7D,MAAM,MAAM,YAAY,aAAa,SAAS,IAAI;IAAE,MAAM;IAAG,KAAK;GAAE;GACpE,SAAS,KAAK;IACZ;IAAM,MAAM,IAAI;IAAM,KAAK,IAAI;IAAK,UAAU;IAAW,MAAM;IAC/D,SAAS,UAAU,MAAM,KAAK;GAChC,CAAC;EACH;CACF;CAEA,IAAI,cAAc;EAKhB,MAAM,eAAe,YAAY;EAGjC,MAAM,6BAAa,IAAI,IAAY;EACnC,KAAK,MAAM,SAAS,aAAa,QAC/B,IAAI,WAAW,IAAI,MAAM,IAAI,GAC3B,SAAS,KAAK;GACZ;GAAM,MAAM;GAAG,KAAK;GAAG,UAAU;GAAS,MAAM;GAChD,SAAS,oBAAoB,MAAM,KAAK;EAC1C,CAAC;OAED,WAAW,IAAI,MAAM,IAAI;EAK7B,IAAI,CAAC,aAAa,OAAO,MAAK,MAAK,EAAE,SAAS,MAAM,GAClD,SAAS,KAAK;GACZ;GAAM,MAAM;GAAG,KAAK;GAAG,UAAU;GAAS,MAAM;GAChD,SAAS;EACX,CAAC;EAIH,MAAM,+BAAe,IAAI,IAAY;EACrC,KAAK,MAAM,WAAW,aAAa,iBACjC,IAAI,aAAa,IAAI,QAAQ,KAAK,GAChC,SAAS,KAAK;GACZ;GAAM,MAAM;GAAG,KAAK;GAAG,UAAU;GAAW,MAAM;GAClD,SAAS,6BAA6B,QAAQ,MAAM;EACtD,CAAC;OAED,aAAa,IAAI,QAAQ,KAAK;CAGpC;CAEA,OAAO;AACT;AAEA,eAAsB,eAAe;CACnC,OAAO;EAAE;EAAiB;CAAa;AACzC;;;ACriBA,eAAsB,QAAQ,UAAkC;CAC9D,MAAM,OAAO,MAAM,SAAS,QAAQ;CACpC,OAAO,MAAM,UAAU,IAAI;AAC7B;AAEA,eAAsB,gBAAgB,UAAoC;CACxE,MAAM,OAAO,MAAM,SAAS,QAAQ;CAEpC,kBAAoB,MADF,MAAM,UAAU,IAAI,GACb,KAAK,MAAM;CACpC,OAAO;AACT;AAEA,eAAsB,mBAAmB,UAAoC;CAE3E,qBAAuB,MADJ,SAAS,QAAQ,CACT;CAC3B,OAAO;AACT;AAEA,eAAsB,SAAS,KAAY,SAAgC;CACzE,MAAM,OAAO,MAAM,IAAI,cAAc,EAAE,MAAM,cAAc,CAAC;CAC5D,MAAM,UAAU,SAAS,OAAO,KAAK,IAAI,CAAC;AAC5C;;;ACjCA,MAAM,WAAW;AAEjB,SAAS,qBAAqB,IAA0B;CACtD,QAAQ,GAAG,MAAX;EACE,KAAK,aACH,OAAO,EAAE,MAAM,GAAG,MAAM;EAC1B,KAAK,aACH,OAAO,GAAG,MAAM,WAAW,MAAM,IAC7B,EAAE,MAAM,GAAG,WAAW,GAAG,MAAM,MAAM,CAAC,EAAE,OAAO,IAC/C,EAAE,MAAM,WAAW,GAAG,QAAQ;EACpC,KAAK,SACH,OAAO;GAAE,MAAM;GAAS,OAAO,qBAAqB,GAAG,KAAK;EAAE;EAChE,KAAK,QACH,OAAO;GAAE,MAAM;GAAU,MAAM,GAAG;EAAM;CAC5C;AACF;AAEA,SAAS,uBAAuB,IAA4B;CAC1D,MAAM,WAAW,GAAG,WAAW,QAAO,MAAK,CAAC,EAAE,WAAW,CAAC,CAAC,KAAI,MAAK,EAAE,IAAI;CAC1E,MAAM,aAAqC,CAAC;CAC5C,KAAK,MAAM,KAAK,GAAG,YACjB,WAAW,EAAE,QAAQ;EACnB,GAAG,qBAAqB,EAAE,IAAI;EAC9B,GAAI,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,IAAI,CAAC;CACxD;CAEF,OAAO;EACL,SAAS;EACT,cAAc,GAAG,SAAS;EAC1B,GAAI,GAAG,SAAS,QAAQ,EAAE,oBAAoB,GAAG,SAAS,MAAM,IAAI,CAAC;EACrE,GAAI,GAAG,UAAU,EAAE,aAAa,GAAG,QAAQ,IAAI,IAAI,CAAC;EACpD,GAAI,GAAG,SAAS,QAAQ,EAAE,mBAAmB,GAAG,QAAQ,MAAM,IAAI,CAAC;EACnE,MAAM;EACN;EACA,GAAI,SAAS,SAAS,EAAE,SAAS,IAAI,CAAC;CACxC;AACF;AAEA,SAAS,oBAAoB,KAA2B;CACtD,OAAO,IAAI,KAAK,WAAW,MAAM,IAC7B,EAAE,MAAM,GAAG,WAAW,IAAI,KAAK,MAAM,CAAC,EAAE,OAAO,IAC/C,EAAE,MAAM,WAAW,IAAI,OAAO;AACpC;;AAGA,SAAgB,eAAe,IAAoC;CACjE,IAAI,GAAG,MAAM,WAAW,KAAK,GAAG,MAAM,WAAW,KAAK,GAAG,OAAO,WAAW,GAAG,OAAO;CAErF,MAAM,OAA+B,CAAC;CACtC,KAAK,MAAM,MAAM,GAAG,OAClB,KAAK,GAAG,QAAQ,uBAAuB,EAAE;CAG3C,OAAO,KAAK,UACV;EACE,GAAI,GAAG,MAAM,SAAS,EAAE,OAAO,GAAG,MAAM,IAAI,mBAAmB,EAAE,IAAI,CAAC;EACtE,GAAI,GAAG,OAAO,SAAS,EAAE,QAAQ,GAAG,OAAO,IAAI,mBAAmB,EAAE,IAAI,CAAC;EACzE,GAAI,OAAO,KAAK,IAAI,CAAC,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;CACpD,GACA,MACA,CACF;AACF;;;ACjDA,SAAS,mBAAkC;CACzC,IAAI;EACF,OAAO,SAAS,8BAA8B;GAAE,OAAO;GAAQ,UAAU;EAAQ,CAAC,CAAC,CAAC,KAAK;CAC3F,QAAQ;EACN,OAAO;CACT;AACF;AAEA,eAAe,cAAc,UAAgD;CAC3E,IAAI,UAAU,OAAO;CACrB,OAAO,iBAAiB,KAAK,KAAA;AAC/B;AAcA,SAAS,oBAAoB,QAAQ,GAAuB;CAC1D,IAAI;CACJ,IAAI;EACF,OAAO,SAAS,+BAA+B;GAAE,OAAO;GAAQ,UAAU;EAAQ,CAAC,CAAC,CACjF,KAAK,CAAC,CACN,MAAM,IAAI,CAAC,CACX,OAAO,OAAO;CACnB,QAAQ;EACN,OAAO,CAAC;CACV;CACA,OAAO,KACJ,MAAM,GAAG,KAAK,CAAC,CACf,KAAK,QAA0B;EAC9B,MAAM,QAAQ,IAAI,YAAY,GAAG;EACjC,MAAM,UAAU,UAAU,KAAK,MAAM,IAAI,MAAM,QAAQ,CAAC;EAExD,OAAO;GAAE;GAAS,OADJ,UAAU,KAAK,MAAM,GAAG,QAAQ,WAAW,IAAI;EACrC;CAC1B,CAAC,CAAC,CACD,QAAO,MAAK,eAAe,EAAE,OAAO,CAAC;AAC1C;AAIA,MAAM,iBAAiB;AACvB,MAAM,eAAe;AAIrB,eAAe,0BAA0B,UAAgD;CACvF,IAAI,UAAU;EACZ,IAAI,CAAC,eAAe,QAAQ,GAC1B,MAAM,IAAI,MAAM,iCAAiC,SAAS,2DAA2D;EAEvH,OAAO;CACT;CAEA,IAAI,CAAC,QAAQ,MAAM,SAAS,CAAC,QAAQ,OAAO,OAAO;EACjD,QAAQ,OAAO,MAAM,mEAAmE;EACxF;CACF;CAEA,MAAM,aAAa,oBAAoB;CAMvC,MAAM,QAAQ,MAAM,OAAO;CAE3B,MAAM,SAAS,MAAM,MAAM,OAAO;EAChC,SAAS;EACT,SAAS;GACP,GAAG,WAAW,KAAI,OAAM;IAAE,OAAO,EAAE;IAAS,OAAO,EAAE;GAAM,EAAE;GAC7D;IAAE,OAAO;IAAgB,OAAO;GAAyB;GACzD;IAAE,OAAO;IAAc,OAAO;GAA2B;EAC3D;CACF,CAAC;CAED,IAAI,MAAM,SAAS,MAAM,GAAG;EAC1B,MAAM,OAAO,iBAAiB;EAC9B,QAAQ,KAAK,CAAC;CAChB;CAEA,IAAI,WAAW,cAAc,OAAO,KAAA;CAEpC,IAAI,WAAW,gBAAgB;EAC7B,MAAM,QAAQ,MAAM,MAAM,KAAK;GAC7B,SAAS;GACT,WAAU,MAAM,KAAK,eAAe,CAAC,IAAI,KAAA,IAAY;EACvD,CAAC;EACD,IAAI,MAAM,SAAS,KAAK,GAAG;GACzB,MAAM,OAAO,iBAAiB;GAC9B,QAAQ,KAAK,CAAC;EAChB;EACA,OAAO;CACT;CAEA,OAAO;AACT;AAIA,SAAS,eAAe,WAAmB,cAA+B;CACxE,IAAI,WAAW,YAAY,GAAG,OAAO;CACrC,MAAM,WAAW,UAAU,QAAQ,SAAS,CAAC;CAE7C,OAAO,SAAS,UADC,QAAQ,UAAU,YACF,CAAC,CAAC,CAAC,WAAW,IAAI;AACrD;AAIA,eAAsB,wBAAwB,KAAa,UAAoC;CAC7F,IAAI,UACF,IAAI;EACF,MAAM,KAAK,KAAK,KAAK,QAAQ,CAAC;EAC9B,OAAO;CACT,QAAQ;EACN,MAAM,IAAI,MAAM,2BAA2B,SAAS,iBAAiB,KAAK;CAC5E;CAGF,MAAM,aAAY,MADI,QAAQ,GAAG,EAAA,CACP,QAAO,MAAK,EAAE,SAAS,cAAc,CAAC;CAChE,IAAI,UAAU,WAAW,GACvB,MAAM,IAAI,MAAM,uCAAuC,KAAK;CAE9D,IAAI,UAAU,SAAS,GACrB,MAAM,IAAI,MAAM,4CAA4C,UAAU,KAAK,IAAI,EAAE,8CAA8C;CAEjI,MAAM,OAAO,UAAU;CACvB,IAAI,SAAS,qBACX,QAAQ,KAAK,uCAAuC,MAAM;CAE5D,OAAO;AACT;AASA,eAAsB,YAAY,WAAmB,WAA+C;CAClG,MAAM,mBAAmB;CACzB,MAAM,WAAW,UAAU,QAAQ,SAAS,CAAC;CAC7C,MAAM,2BAAW,IAAI,IAAY;CACjC,MAAM,0BAAU,IAAI,IAAY;CAChC,MAAM,QAAkB,CAAC;CACzB,MAAM,4BAAY,IAAI,IAAoB;CAE1C,eAAe,IAAI,SAAgC;EACjD,MAAM,UAAU,QAAQ,UAAU,OAAO;EAEzC,IAAI,SAAS,IAAI,OAAO,GACtB,MAAM,IAAI,MAAM,8CAA8C,QAAQ,EAAE;EAE1E,IAAI,QAAQ,IAAI,OAAO,GAAG;EAE1B,SAAS,IAAI,OAAO;EAEpB,IAAI;EACJ,IAAI;GACF,WAAW,MAAM,SAAS,SAAS,OAAO;EAC5C,QAAQ;GACN,MAAM,IAAI,MAAM,kCAAkC,QAAQ,EAAE;EAC9D;EACA,UAAU,IAAI,SAAS,QAAQ;EAG/B,MAAM,SADS,kBAAkB,QACb,CAAC,CAAC,IAAI,UAAU,CAAC;EAErC,KAAK,MAAM,aAAa,QAAQ;GAC9B,IAAI,WAAW,SAAS,GACtB,MAAM,IAAI,MAAM,qBAAqB,UAAU,QAAQ,QAAQ,6DAA6D;GAE9H,MAAM,WAAW,QAAQ,QAAQ,OAAO,GAAG,SAAS;GACpD,MAAM,WAAW,SAAS,UAAU,QAAQ;GAC5C,IAAI,SAAS,WAAW,IAAI,GAC1B,MAAM,IAAI,MAAM,qBAAqB,UAAU,QAAQ,QAAQ,yBAAyB;GAE1F,MAAM,IAAI,QAAQ;EACpB;EAEA,SAAS,OAAO,OAAO;EACvB,QAAQ,IAAI,OAAO;EACnB,MAAM,KAAK,OAAO;CACpB;CAEA,MAAM,IAAI,SAAS;CAGnB,OAAO;EACL,YAFY,MAAM,KAAI,YAAW,UAAU,IAAI,QAAQ,UAAU,OAAO,CAAC,CAEzD,CAAC,CAAC,KAAK,IAAI;EAC3B,cAAc;CAChB;AACF;AAQA,MAAM,cAAc;AAOpB,SAAS,gBAAgB,OAAoB,KAAiC;CAC5E,KAAK,MAAM,KAAK,OACd,QAAQ,EAAE,MAAV;EACE,KAAK;GACH,IAAI,YAAY,KAAK,EAAE,IAAI,GAAG,IAAI,IAAI,SAAS,EAAE,QAAQ;IAAE,MAAM;IAAS,MAAM,EAAE;GAAK,CAAC;GACxF;EACF,KAAK;GACH,IAAI,YAAY,KAAK,EAAE,IAAI,GAAG,IAAI,IAAI,SAAS,EAAE,QAAQ;IAAE,MAAM;IAAS,MAAM,EAAE;GAAK,CAAC;GACxF;EACF,KAAK;GACH,gBAAgB,EAAE,UAAU,GAAG;GAC/B;EACF,KAAK;GACH,IAAI,MAAM,QAAQ,EAAE,IAAI,GAAG,gBAAgB,EAAE,MAAM,GAAG;GACtD;EACF,KAAK;EACL,KAAK;EACL,KAAK;GACH,gBAAgB,EAAE,MAAM,GAAG;GAC3B;EACF,KAAK;GACH,gBAAgB,EAAE,MAAM,GAAG;GAC3B,IAAI,EAAE,MAAM,gBAAgB,EAAE,MAAM,GAAG;GACvC;CACJ;AAEJ;AAUA,SAAS,iBAAiB,MAAsB;CAC9C,OAAO,KAAK,QAAQ,OAAO,GAAG,CAAC,CAAC,QAAQ,SAAS,EAAE;AACrD;AAEA,eAAe,wBAAwB,oBAA2D;CAChG,MAAM,mBAAmB;CACzB,MAAM,uBAAO,IAAI,IAAqB;CACtC,MAAM,cAAc,kBAAkB,kBAAkB,CAAC,CAAC;CAC1D,IAAI,CAAC,aAAa,OAAO;CACzB,KAAK,MAAM,SAAS,YAAY,QAAQ,gBAAgB,MAAM,MAAM,IAAI;CACxE,KAAK,MAAM,WAAW,YAAY,iBAAiB,gBAAgB,QAAQ,MAAM,IAAI;CACrF,OAAO;AACT;AAMA,eAAe,iBAAiB,KAAa,IAA+C;CAC1F,MAAM,QAAkB,CAAC;CAEzB,eAAe,KAAK,QAAgB,QAAgB;EAClD,IAAI;EACJ,IAAI;GACF,UAAU,MAAM,QAAQ,MAAM;EAChC,QAAQ;GACN;EACF;EACA,KAAK,MAAM,SAAS,SAAS;GAC3B,IAAI,MAAM,WAAW,GAAG,GAAG;GAC3B,MAAM,WAAW,KAAK,QAAQ,KAAK;GACnC,MAAM,eAAe,GAAG,OAAO,GAAG;GAClC,KAAK,MAAM,KAAK,QAAQ,EAAA,CAAG,YAAY,GACrC,MAAM,KAAK,UAAU,YAAY;QAEjC,MAAM,KAAK,YAAY;EAE3B;CACF;CAEA,MAAM,KAAK,KAAK,KAAK,EAAE,GAAG,EAAE;CAC5B,OAAO;AACT;AAQA,eAAsB,uBACpB,KACA,oBACwB;CACxB,MAAM,OAAO,MAAM,wBAAwB,kBAAkB;CAC7D,MAAM,6BAAa,IAAI,IAAY;CACnC,MAAM,WAA0B,CAAC;CAIjC,KAAK,MAAM,EAAE,MAAM,UAAU,KAAK,OAAO,GAAG;EAC1C,MAAM,aAAa,iBAAiB,IAAI;EACxC,WAAW,IAAI,UAAU;EAWzB,IAAI,eAAe,KAAK,UAAU,KAAK,qBAAqB,UAAU,GAAG;EACzE,IAAI;GACF,MAAM,KAAK,KAAK,KAAK,UAAU,CAAC;EAClC,QAAQ;GACN;EACF;EACA,SAAS,KAAK;GACZ,MAAM;GACN,MAAM;GACN,KAAK;GACL,UAAU;GACV,MAAM;GACN,SAAS,IAAI,KAAK,eAAe,KAAK;EACxC,CAAC;CACH;CAkBA,OAAO,CAAC,GAX8B,CAJpC,GAAI,MAAM,iBAAiB,KAAK,QAAQ,GACxC,GAAI,MAAM,iBAAiB,KAAK,WAAW,CAGF,CAAC,CACzC,QAAO,SAAQ,CAAC,WAAW,IAAI,IAAI,CAAC,CAAC,CACrC,KAAK,UAAuB;EAC3B,MAAM;EACN,MAAM;EACN,KAAK;EACL,UAAU;EACV,MAAM;EACN,SAAS,IAAI,KAAK;CACpB,EAEsB,GAAG,GAAG,QAAQ;AACxC;AAEA,eAAsB,aACpB,KACA,iBACA,oBACA,cACA,aAC8B;CAC9B,MAAM,wBAAQ,IAAI,IAAoB;CAEtC,MAAM,IAAI,iBAAiB,MAAM,SAAS,KAAK,KAAK,eAAe,GAAG,OAAO,CAAC;CAU9E,MAAM,mBAAmB,mBAAmB,QAAQ,6BAA6B,EAAE;CACnF,MAAM,IAAI,kBAAkB,gBAAgB;CAE5C,KAAK,MAAM,WAAW,cACpB,MAAM,IAAI,aAAa,WAAW,MAAM,SAAS,KAAK,KAAK,OAAO,GAAG,OAAO,CAAC;CAG/E,IAAI,aAAa;EACf,IAAI,eAAe,KAAK,WAAW,GACjC,MAAM,IAAI,MAAM,uBAAuB,YAAY,QAAQ,gBAAgB,wCAAwC;EAErH,IAAI;EACJ,IAAI;GACF,cAAc,MAAM,SAAS,KAAK,KAAK,WAAW,GAAG,OAAO;EAC9D,QAAQ;GACN,MAAM,IAAI,MAAM,yBAAyB,YAAY,iBAAiB,gBAAgB,YAAY;EACpG;EACA,MAAM,IAAI,aAAa,WAAW;CACpC;CAUA,MAAM,OAAO,MAAM,wBAAwB,kBAAkB;CAC7D,KAAK,MAAM,EAAE,MAAM,UAAU,KAAK,OAAO,GAAG;EAC1C,MAAM,aAAa,iBAAiB,IAAI;EACxC,IAAI,eAAe,KAAK,UAAU,GAChC,MAAM,IAAI,MAAM,UAAU,KAAK,UAAU,KAAK,wCAAwC;EAGxF,IAAI;EACJ,IAAI;GACF,UAAU,MAAM,SAAS,KAAK,KAAK,UAAU,GAAG,OAAO;EACzD,QAAQ;GACN,MAAM,IAAI,MACR,UAAU,KAAK,UAAU,KAAK,8CAA8C,IAAI,iBAAiB,WAAW,6BAC9G;EACF;EAQA,IAAI,MAAM,IAAI,UAAU,GACtB,MAAM,IAAI,MACR,UAAU,KAAK,eAAe,KAAK,iBAAiB,WAAW,4JACjE;EAGF,MAAM,IAAI,YAAY,OAAO;CAC/B;CAEA,OAAO;AACT;AAIA,SAAS,mBAAmB,MAAsB;CAChD,OAAO,KAAK,SAAS,QAAQ,IAAI,OAAO,GAAG,KAAK;AAClD;AAEA,eAAsB,KAAK,UAAuB,CAAC,GAAwB;CACzE,MAAM,MAAM,QAAQ,OAAO,QAAQ,IAAI;CACvC,MAAM,UAAU,mBAAmB,QAAQ,OAAO,KAAK,KAAK,SAAS,GAAG,CAAC,CAAC;CAG1E,MAAM,sBAAsB,MAAM,wBAAwB,KAAK,QAAQ,WAAW;CAClF,MAAM,kBAAkB,MAAM,SAAS,KAAK,KAAK,mBAAmB,GAAG,OAAO;CAG9E,MAAM,sBAAsB,MAAM,gBAAgB,iBAAiB,mBAAmB;CACtF,MAAM,aAAa,oBAAoB,QAAO,MAAK,EAAE,aAAa,OAAO;CACzE,IAAI,WAAW,SAAS,GACtB,MAAM,IAAI,MACR,iBAAiB,WAAW,KAAI,MAAK,KAAK,EAAE,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,IAAI,GAAG,EAAE,KAAK,GAAG,EAAE,SAAS,CAAC,CAAC,KAAK,IAAI,GACzG;CAIF,MAAM,mBAAmB;CAGzB,MAAM,aAAa,qBAAqB,eAAe;CACvD,IAAI,WAAW,OAAO,MAAM;EAC1B,MAAM,aAAa,WAAW,YAAY,MAAK,MAAK,EAAE,aAAa,OAAO;EAC1E,MAAM,IAAI,MAAM,WAAW,YAAY,WAAW,gBAAgB;CACpE;CACA,MAAM,KAAK,WAAW;CAGtB,IAAI,CAAC,GAAG,UACN,MAAM,IAAI,MAAM,YAAY,oBAAoB,4GAA4G;CAE9J,IAAI,eAAe,KAAK,GAAG,QAAQ,GACjC,MAAM,IAAI,MAAM,wBAAwB,GAAG,SAAS,QAAQ,oBAAoB,wCAAwC;CAI1H,MAAM,EAAE,YAAY,iBAAiB,MAAM,YAAY,KAAK,GAAG,QAAQ;CAGvE,MAAM,mBAAmB,MAAM,aAAa,YAAY,kBAAkB,KAAA,GAAW,IAAI;CACzF,MAAM,cAAc,CAAC,GAAG,qBAAqB,GAAG,gBAAgB;CAChE,MAAM,SAAS,YAAY,QAAO,MAAK,EAAE,aAAa,OAAO;CAC7D,MAAM,eAAe,YAAY,QAAO,MAAK,EAAE,aAAa,SAAS;CAErE,IAAI,OAAO,SAAS,GAClB,MAAM,IAAI,MACR,iBAAiB,OAAO,KAAI,MAAK,KAAK,EAAE,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,IAAI,GAAG,EAAE,KAAK,GAAG,EAAE,SAAS,CAAC,CAAC,KAAK,IAAI,GACrG;CAIF,MAAM,UAAU,MAAM,0BAA0B,QAAQ,OAAO;CAC/D,MAAM,SAAS,MAAM,cAAc,QAAQ,MAAM;CACjD,MAAM,WAAW,MAAM,aAAa,KAAK,qBAAqB,YAAY,cAAc,GAAG,WAAW,KAAA,CAAS;CAC/G,MAAM,WAAW,CAAC,GAAG,cAAc,GAAI,MAAM,uBAAuB,KAAK,UAAU,CAAE;CAErF,MAAM,iBAAiB,MAAM,KAAK,SAAS,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE;CAC5D,MAAM,SAAS,WAAW,QAAQ,CAAC,CAAC,OAAO,cAAc,CAAC,CAAC,OAAO,KAAK;CAKvE,MAAM,KAAK,QAAQ;EAAE,WAHH,GAAG,MAAM,UAAU;EAGL,MAAM,QAAQ,GAAG,MAAM,IAAI;EAAG;EAAS,QAAQ,UAAU,SAAS,KAAA;CAAU,CAAC;CAE7G,MAAM,YAAY,eAAe,EAAE;CACnC,MAAM,YAAY;EAChB;EACA,GAAI,YAAY,EAAE,OAAO,oBAAoB,IAAI,CAAC;EAClD,OAAO;CACT;CAEA,MAAM,UAAU,aAAa;EAC3B;EACA,MAAM,GAAG,MAAM;EACf,aAAa,GAAG,eAAe;EAC/B,SAAS,WAAW;EACpB,QAAQ,GAAG,MAAM,UAAU;EAC3B,SAAS,GAAG,MAAM,WAAW;EAC7B,SAAS,GAAG,WAAW,KAAA;EACvB,SAAS;EACT,UAAU,aAAa;EACvB;EACA,cAAc,GAAG,aAAa,KAAI,OAAM;GAAE,IAAI,EAAE;GAAM,aAAa,EAAE,eAAe;EAAG,EAAE;EACzF,UAAU,GAAG;EACb;CACF,CAAC;CAED,MAAM,MAAM,IAAI,MAAM;CACtB,MAAM,cAAc,IAAI,OAAO,QAAQ;CACvC,YAAY,KAAK,gBAAgB,cAAc,OAAO,CAAC;CAEvD,IAAI,WACF,YAAY,KAAK,cAAc,SAAS;CAG1C,MAAM,YAAY;EAChB,aAAa;EACb,UAAU;EACV,GAAI,GAAG,UAAU,EAAE,SAAS,GAAG,QAAQ,IAAI,CAAC;EAC5C,WAAW,MAAM,KAAK,SAAS,KAAK,CAAC,CAAC,CAAC,QAAO,MAAK,EAAE,WAAW,YAAY,CAAC;EAC7E,QAAQ,MAAM,KAAK,SAAS,KAAK,CAAC,CAAC,CAAC,QAAO,MAAK,oBAAoB,CAAC,MAAM,QAAQ;EACnF,WAAW,MAAM,KAAK,SAAS,KAAK,CAAC,CAAC,CAAC,QAAO,MAAK,oBAAoB,CAAC,MAAM,WAAW;CAC3F;CACA,YAAY,KAAK,cAAc,KAAK,UAAU,WAAW,MAAM,CAAC,CAAC;CAEjE,KAAK,MAAM,CAAC,MAAM,YAAY,UAC5B,IAAI,KAAK,MAAM,OAAO;CAGxB,MAAM,SAAS,KAAK,OAAO;CAE3B,OAAO;EAAE,MAAM;EAAS;EAAI;CAAS;AACvC;;;ACljBA,eAAsB,cAAc,KAAmC;CACrE,MAAM,sBAAsB,MAAM,wBAAwB,GAAG;CAC7D,MAAM,kBAAkB,MAAM,SAAS,KAAK,KAAK,mBAAmB,GAAG,OAAO;CAE9E,MAAM,eAAe,MAAM,gBAAgB,iBAAiB,mBAAmB;CAC/E,MAAM,aAAa,aAAa,QAAO,MAAK,EAAE,aAAa,OAAO;CAClE,IAAI,WAAW,SAAS,GACtB,MAAM,IAAI,MACR,iBAAiB,WAAW,KAAI,MAAK,KAAK,EAAE,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,IAAI,GAAG,EAAE,KAAK,GAAG,EAAE,SAAS,CAAC,CAAC,KAAK,IAAI,GACzG;CAGF,MAAM,mBAAmB;CACzB,MAAM,aAAa,qBAAqB,eAAe;CACvD,IAAI,WAAW,OAAO,MAAM;EAC1B,MAAM,aAAa,WAAW,YAAY,MAAK,MAAK,EAAE,aAAa,OAAO;EAC1E,MAAM,IAAI,MAAM,WAAW,YAAY,WAAW,gBAAgB;CACpE;CACA,MAAM,KAAK,WAAW;CAEtB,IAAI,CAAC,GAAG,UACN,MAAM,IAAI,MAAM,YAAY,oBAAoB,+BAA+B;CAGjF,MAAM,EAAE,YAAY,iBAAiB,MAAM,YAAY,KAAK,GAAG,QAAQ;CAEvE,MAAM,mBAAmB,MAAM,aAAa,YAAY,kBAAkB,KAAA,GAAW,IAAI;CACzF,MAAM,iBAAiB,MAAM,uBAAuB,KAAK,UAAU;CACnE,MAAM,cAAc;EAAC,GAAG;EAAc,GAAG;EAAkB,GAAG;CAAc;CAC5E,MAAM,SAAS,YAAY,QAAO,MAAK,EAAE,aAAa,OAAO;CAC7D,MAAM,WAAW,YAAY,QAAO,MAAK,EAAE,aAAa,SAAS;CAEjE,IAAI,OAAO,SAAS,GAClB,MAAM,IAAI,MACR,iBAAiB,OAAO,KAAI,MAAK,KAAK,EAAE,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,IAAI,GAAG,EAAE,KAAK,GAAG,EAAE,SAAS,CAAC,CAAC,KAAK,IAAI,GACrG;CAGF,KAAK,MAAM,KAAK,UACd,QAAQ,OAAO,MAAM,oBAAoB,EAAE,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,IAAI,GAAG,EAAE,KAAK,GAAG,EAAE,QAAQ,GAAG;CAG/F,MAAM,WAAW,MAAM,aAAa,KAAK,qBAAqB,YAAY,cAAc,GAAG,WAAW,KAAA,CAAS;CAE/G,MAAM,SAAS,WAAW,QAAQ,CAAC,CAChC,OAAO,MAAM,KAAK,SAAS,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAC9C,OAAO,KAAK;CAEf,MAAM,KAAK,QAAQ;EAAE,WAAW,GAAG,MAAM,UAAU;EAAW,MAAM,QAAQ,GAAG,MAAM,IAAI;EAAG,SAAS;CAAM,CAAC;CAmC5G,OAAO;EAAE;EAAI,SAjCG,aAAa;GAC3B;GACA,MAAM,GAAG,MAAM;GACf,aAAa,GAAG,eAAe;GAC/B,SAAS;GACT,QAAQ,GAAG,MAAM,UAAU;GAC3B,SAAS,GAAG,MAAM,WAAW;GAC7B,SAAS,GAAG,WAAW,KAAA;GACvB,SAAS;GACT,UAAU,aAAa;GACvB,cAAc,GAAG,aAAa,KAAI,OAAM;IAAE,IAAI,EAAE;IAAM,aAAa,EAAE,eAAe;GAAG,EAAE;GACzF,UAAU,GAAG;GACb,WAAW;IAAE;IAAQ,OAAO;GAAoB;EAClD,CAoBmB;EAAG,OAAA;GAjBpB,aAAa;GAIb,UAAU,SAAS,IAAI,gBAAgB,KAAK;GAC5C,SAAS,GAAG,UAAU,SAAS,IAAI,GAAG,OAAO,IAAI,KAAA;GACjD,QAAQ,MAAM,KAAK,SAAS,QAAQ,CAAC,CAAC,CACnC,QAAQ,CAAC,OAAO,oBAAoB,CAAC,MAAM,QAAQ,CAAC,CACpD,KAAK,CAAC,MAAM,cAAc;IAAE;IAAM;GAAQ,EAAE;GAC/C,WAAW,MAAM,KAAK,SAAS,QAAQ,CAAC,CAAC,CACtC,QAAQ,CAAC,OAAO,oBAAoB,CAAC,MAAM,WAAW,CAAC,CACvD,KAAK,CAAC,MAAM,cAAc;IAAE;IAAM;GAAQ,EAAE;GAC/C,WAAW,MAAM,KAAK,SAAS,QAAQ,CAAC,CAAC,CACtC,QAAQ,CAAC,OAAO,EAAE,WAAW,YAAY,CAAC,CAAC,CAC3C,KAAK,CAAC,MAAM,cAAc;IAAE;IAAM;GAAQ,EAAE;EAGvB;CAAE;AAC9B"}
1
+ {"version":3,"file":"index.mjs","names":["bpInit","bpParseBehavior","bpParseDescription"],"sources":["../src/parser.ts","../src/linter.ts","../src/zip.ts","../src/schema.ts","../src/pack.ts","../src/bundle.ts"],"sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\nimport { createRequire } from 'module'\nimport { Parser, Language } from 'web-tree-sitter'\nimport type { Node, Tree } from 'web-tree-sitter'\nimport type { LangId, BehaviorFile, DescriptionFile, ParseDiagnostic } from './types.js'\nimport { init as bpInit, parse_behavior as bpParseBehavior, parse_description as bpParseDescription, get_graph } from '@dot-agent/parser-dsl'\n\nconst require = createRequire(import.meta.url)\nconst { descriptionWasmPath, behaviorWasmPath } = require('@dot-agent/tree-sitter') as {\n descriptionWasmPath: string\n behaviorWasmPath: string\n}\n\nlet _initialized = false\nlet _descriptionParser: Parser\nlet _behaviorParser: Parser\nlet _bpInitialized = false\n\nexport async function initBehaviorParser(): Promise<void> {\n if (_bpInitialized) return\n await bpInit()\n _bpInitialized = true\n}\n\nexport interface ParseResult<T> {\n ok: T | null\n diagnostics: ParseDiagnostic[]\n}\n\nexport function parseBehaviorFile(text: string): ParseResult<BehaviorFile> {\n return JSON.parse(bpParseBehavior(text)) as ParseResult<BehaviorFile>\n}\n\nexport function parseDescriptionFile(text: string): ParseResult<DescriptionFile> {\n return JSON.parse(bpParseDescription(text)) as ParseResult<DescriptionFile>\n}\n\nexport function getBehaviorScxml(text: string): string {\n return get_graph(text)\n}\n\nexport async function initParsers(): Promise<void> {\n if (_initialized) return\n await Parser.init()\n const descriptionLang = await Language.load(descriptionWasmPath)\n const behaviorLang = await Language.load(behaviorWasmPath)\n _descriptionParser = new Parser()\n _descriptionParser.setLanguage(descriptionLang)\n _behaviorParser = new Parser()\n _behaviorParser.setLanguage(behaviorLang)\n _initialized = true\n}\n\n/**\n * Parse source text and return a tree-sitter Tree.\n *\n * @param langId - 'description' or 'behavior'\n * @param text - source text to parse\n * @param previousTree - optional previous tree for incremental parsing (LSP use)\n */\nexport async function parse(\n langId: LangId,\n text: string,\n previousTree?: Tree\n): Promise<Tree> {\n await initParsers()\n const parser = langId === 'behavior' ? _behaviorParser : _descriptionParser\n return parser.parse(text, previousTree)!\n}\n\n/** Parse without initializing if parsers are already ready. Returns null if not initialized. */\nexport function parseSync(langId: LangId, text: string, previousTree?: Tree): Tree | null {\n if (!_initialized) return null\n const parser = langId === 'behavior' ? _behaviorParser : _descriptionParser\n return parser.parse(text, previousTree)\n}\n\n// ── AST helpers ──────────────────────────────────────────────────────────────\n\nexport function nodesOfType(tree: Tree, type: string): Node[] {\n if (!tree) return []\n return tree.rootNode.descendantsOfType(type).filter((n): n is Node => n !== null)\n}\n\nexport function nodeAtOffset(tree: Tree, offset: number): Node | null {\n if (!tree) return null\n return tree.rootNode.descendantForIndex(offset)\n}\n\nexport function nodeToRange(node: Node): {\n start: { line: number; character: number }\n end: { line: number; character: number }\n} {\n return {\n start: { line: node.startPosition.row, character: node.startPosition.column },\n end: { line: node.endPosition.row, character: node.endPosition.column },\n }\n}\n\nexport function positionToOffset(text: string, line: number, character: number): number {\n let offset = 0\n for (let i = 0; i < line; i++) {\n const nl = text.indexOf('\\n', offset)\n offset = nl === -1 ? text.length : nl + 1\n }\n return offset + character\n}\n\nexport function getContextNode(tree: Tree, offset: number): Node {\n let node = nodeAtOffset(tree, offset)\n while (node && (node.isError || node.isMissing)) {\n node = node.parent\n }\n if (!node || node.type === 'ERROR') {\n const raw = nodeAtOffset(tree, offset)\n const parent = raw?.parent\n if (parent) {\n const siblings = parent.children\n const idx = siblings.findIndex((c: Node | null) => c !== null && c.startIndex > offset)\n const prev = idx > 0 ? siblings[idx - 1] : siblings[siblings.length - 1]\n if (prev && !prev.isError) node = prev\n }\n }\n return node ?? tree.rootNode\n}\n","// SPDX-License-Identifier: Apache-2.0\n\nimport { readFileSync } from 'fs'\nimport { resolve, dirname } from 'path'\nimport { parse, nodesOfType, parseSync, initBehaviorParser, parseBehaviorFile } from './parser.js'\nimport type { LintMessage } from './types.js'\nimport type { Node, Tree } from 'web-tree-sitter'\n\nfunction nodePosition(node: Node): { line: number; col: number } {\n return { line: node.startPosition.row + 1, col: node.startPosition.column + 1 }\n}\n\n// ── Syntax error collection (reports deepest ERROR node per branch) ──────────\n\nconst MISSING_HINTS: Record<string, string> = {\n interact_stmt: \"Missing 'interact' — oriented states require 'goal … interact … on intent … on offtopic'.\",\n offtopic_handler: \"Missing 'on offtopic' handler — every state with 'interact' must handle the offtopic case.\",\n intent_handler: \"Missing at least one 'on intent' handler after 'interact'.\",\n goal_stmt: \"Missing 'goal' — every state with 'interact' must declare a goal.\",\n state_name: \"Missing state name after 'state' keyword.\",\n quoted_string: \"Missing quoted string — expected a value in double quotes.\",\n}\n\nfunction collectSyntaxErrors(\n root: Node,\n messages: LintMessage[],\n file: string,\n): void {\n const seen = new Set<string>()\n\n function push(node: Node, message: string, code: string, severity: 'error' | 'warning' = 'error') {\n const key = `${node.startIndex}:${node.endIndex}:${message}`\n if (seen.has(key)) return\n seen.add(key)\n const { line, col } = nodePosition(node)\n messages.push({ file, line, col, severity, code, message })\n }\n\n function walk(node: Node) {\n if (node.isMissing) {\n const hint = MISSING_HINTS[node.type]\n push(node, hint ?? `Syntax error: missing '${node.type}'.`, 'E004')\n return\n }\n if (node.type === 'ERROR') {\n const hasNestedError = node.descendantsOfType('ERROR').some((e: Node | null) => e !== null && e.id !== node.id)\n if (!hasNestedError) {\n const snippet = node.text.replace(/\\s+/g, ' ').trim().slice(0, 40)\n push(node, snippet ? `Syntax error near '${snippet}'.` : 'Syntax error.', 'E004')\n return\n }\n }\n for (const child of node.children) {\n if (child) walk(child)\n }\n }\n\n walk(root)\n}\n\n// ── Description linting ──────────────────────────────────────────────────────\n\nconst STRICT_BLOCK_TYPES: Record<string, string> = {\n input_block: 'input',\n output_block: 'output',\n requires_block: 'requires',\n capabilities_block: 'capabilities',\n}\n\nexport async function lintDescription(text: string, file = 'agent.description'): Promise<LintMessage[]> {\n const tree = await parse('description', text)\n const messages: LintMessage[] = []\n\n collectSyntaxErrors(tree.rootNode, messages, file)\n\n // W003: default domain value\n // The grammar uses `agent_meta` nodes with key/value fields (not `domain_declaration`)\n for (const metaNode of nodesOfType(tree, 'agent_meta')) {\n const keyNode = metaNode.childForFieldName('key')\n if (keyNode?.text !== 'domain') continue\n const valueNode = metaNode.childForFieldName('value')\n if (valueNode?.text === 'example.com') {\n const { line, col } = nodePosition(valueNode)\n messages.push({\n file,\n line,\n col,\n severity: 'warning',\n code: 'W003',\n message: 'domain still has default value \"example.com\"',\n })\n }\n }\n\n // W007: no domain declared → agent will be packaged as unknown/name\n const hasDomain = nodesOfType(tree, 'agent_meta').some(\n n => n.childForFieldName('key')?.text === 'domain' && n.childForFieldName('value')?.text?.trim(),\n )\n if (!hasDomain) {\n messages.push({\n file,\n line: 1,\n col: 1,\n severity: 'warning',\n code: 'W007',\n message:\n 'No domain declared — agent will be packaged as unknown/name. Interoperability between runtimes is not guaranteed.',\n })\n }\n\n // E017: multiple behavior declarations\n const behaviorBlocks = nodesOfType(tree, 'behavior_block')\n if (behaviorBlocks.length > 1) {\n const { line, col } = nodePosition(behaviorBlocks[1])\n messages.push({\n file, line, col, severity: 'error', code: 'E017',\n message: \"Multiple 'behavior' declarations — only one is allowed. To combine multiple files, use 'merge' in your .behavior file.\",\n })\n }\n\n // W004: undeclared type references in input/output/requires/capabilities blocks\n const declaredTypes = new Set(\n nodesOfType(tree, 'type_decl')\n .map(n => n.childForFieldName('name')?.text)\n .filter(Boolean) as string[]\n )\n\n if (declaredTypes.size > 0) {\n for (const blockType of Object.keys(STRICT_BLOCK_TYPES)) {\n for (const blockNode of nodesOfType(tree, blockType)) {\n for (const typeRefNode of blockNode.descendantsOfType('type_reference').filter((n): n is Node => n !== null)) {\n const idNode = typeRefNode.firstNamedChild\n if (!idNode) continue\n const typeName = idNode.text\n if (!declaredTypes.has(typeName)) {\n const { line, col } = nodePosition(idNode)\n messages.push({\n file,\n line,\n col,\n severity: 'warning',\n code: 'W004',\n message: `Type '${typeName}' is not declared in this file (assuming native or external).`,\n })\n }\n }\n }\n }\n }\n\n return messages\n}\n\n// ── Behavior linting ─────────────────────────────────────────────────────────\n\nfunction levenshtein(a: string, b: string): number {\n const la = a.length, lb = b.length\n const dp: number[][] = Array.from({ length: la + 1 }, (_, i) =>\n Array.from({ length: lb + 1 }, (_, j) => (i === 0 ? j : j === 0 ? i : 0))\n )\n for (let i = 1; i <= la; i++) {\n for (let j = 1; j <= lb; j++) {\n dp[i][j] = a[i - 1] === b[j - 1]\n ? dp[i - 1][j - 1]\n : 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1])\n }\n }\n return dp[la][lb]\n}\n\nfunction closestName(token: string, candidates: string[]): string | undefined {\n let best: string | undefined\n let bestDist = Infinity\n for (const name of candidates) {\n const d = levenshtein(token.toLowerCase(), name.toLowerCase())\n if (d > 0 && d <= 2 && d < bestDist) { bestDist = d; best = name }\n }\n return best\n}\n\nconst KERNEL_LIFECYCLE_NAMES = ['init', 'welcome', 'end', 'online', 'offline']\n\nfunction collectTransitionTargets(stmts: Array<{ type: string; [k: string]: unknown }>): string[] {\n const targets: string[] = []\n for (const stmt of stmts) {\n if (!stmt || typeof stmt !== 'object') continue\n if (stmt.type === 'transition_stmt' && typeof stmt['state'] === 'string') {\n targets.push(stmt['state'])\n }\n if (stmt.type === 'intent_handler' && typeof stmt['body'] === 'string') {\n targets.push(stmt['body'])\n }\n const recurse = (v: unknown) => {\n if (Array.isArray(v)) targets.push(...collectTransitionTargets(v as Array<{ type: string }>))\n }\n if (stmt.type !== 'intent_handler') recurse(stmt['body'])\n recurse(stmt['handlers'])\n recurse(stmt['then'])\n recurse(stmt['else'])\n recurse(stmt['on_complete'])\n recurse(stmt['on_failure'])\n }\n return targets\n}\n\nfunction collectMergedStates(\n tree: Tree,\n docDir: string,\n states: Set<string>,\n visited = new Set<string>()\n): void {\n for (const mergeNode of nodesOfType(tree, 'merge_decl')) {\n const pathNode = mergeNode.childForFieldName('path')\n if (!pathNode) continue\n const filename = pathNode.text.replace(/^\"|\"$/g, '')\n const absPath = resolve(docDir, filename)\n if (visited.has(absPath)) continue\n visited.add(absPath)\n let mergedText: string\n try {\n mergedText = readFileSync(absPath, 'utf-8')\n } catch {\n continue\n }\n const mergedTree = parseSync('behavior', mergedText)\n if (!mergedTree) continue\n nodesOfType(mergedTree, 'state_decl').forEach(n => {\n const name = n.childForFieldName('name')?.text\n if (name) states.add(name)\n })\n collectMergedStates(mergedTree, dirname(absPath), states, visited)\n }\n}\n\nexport async function lintBehavior(\n text: string,\n file = 'agent.behavior',\n docPath?: string,\n consolidated = false,\n externalStates?: Set<string>,\n mergedText?: string,\n): Promise<LintMessage[]> {\n await initBehaviorParser()\n if (!text.endsWith('\\n')) text = text + '\\n'\n const tree = await parse('behavior', text)\n const messages: LintMessage[] = []\n\n // Rule 0: syntax errors\n collectSyntaxErrors(tree.rootNode, messages, file)\n\n for (const stateNode of nodesOfType(tree, 'state_decl')) {\n if (stateNode.hasError) continue\n const nameNode = stateNode.childForFieldName('name')\n const stateName = nameNode?.text ?? '?'\n const interactStmts = stateNode.descendantsOfType('interact_stmt')\n const hasInteract = interactStmts.length > 0\n const hasGoal = stateNode.descendantsOfType('goal_stmt').length > 0\n const hasGuide = stateNode.descendantsOfType('guide_stmt').length > 0\n const hasTeach = stateNode.descendantsOfType('teach_stmt').length > 0\n const intentHandlers = stateNode.descendantsOfType('intent_handler')\n\n // W013: interact without goal (supersedes E008 — downgraded to warning)\n if (hasInteract && !hasGoal) {\n const { line, col } = nodePosition(nameNode ?? stateNode)\n messages.push({\n file, line, col, severity: 'warning', code: 'W013',\n message: `'interact' without 'goal'. Add 'goal \"...\"' before 'interact'.`,\n })\n }\n\n // W012: goal/guide/teach without interact (ADR DA00-09: an Oriented\n // State carries goal/guide/teach only alongside 'interact'; a state with\n // none of these three is a Setup State and this rule doesn't apply to it).\n const presentOrientationNames = (\n [hasGoal && 'goal', hasGuide && 'guide', hasTeach && 'teach'] as const\n ).filter((n): n is 'goal' | 'guide' | 'teach' => n !== false)\n if (presentOrientationNames.length > 0 && !hasInteract) {\n const { line, col } = nodePosition(nameNode ?? stateNode)\n const list = presentOrientationNames.map(n => `'${n}'`).join(', ')\n const isPlural = presentOrientationNames.length > 1\n messages.push({\n file, line, col, severity: 'warning', code: 'W012',\n message: `${list} ${isPlural ? 'are' : 'is'} only valid in an oriented state. Add 'interact' or remove ${isPlural ? 'them' : 'it'}.`,\n })\n }\n\n // W017: duplicate 'interact' in the same state, before the first\n // state-level 'transition to'. The kernel's exec_entry_statements\n // (fsm.rs) executes a state's entry statements in order and stops as\n // soon as current_state changes — so an 'interact' that comes after a\n // state-level transition never runs in that entry batch; only the ones\n // preceding the first transition can both fire and emit a second\n // 'request_interact' effect, which is what this rule flags (ADR\n // DA00-09).\n const bodyStmts = (stateNode.childForFieldName('body')?.children ?? []).filter(\n (n): n is Node => n !== null,\n )\n const firstTransitionIndex = bodyStmts.findIndex(n => n.type === 'transition_stmt')\n const interactsBeforeFirstTransition = bodyStmts.filter(\n (n, i) => n.type === 'interact_stmt' && (firstTransitionIndex === -1 || i < firstTransitionIndex),\n )\n if (interactsBeforeFirstTransition.length > 1) {\n for (const dup of interactsBeforeFirstTransition.slice(1)) {\n const { line, col } = nodePosition(dup)\n messages.push({\n file, line, col, severity: 'warning', code: 'W017',\n message: `Duplicate 'interact' in state '${stateName}' before any transition. Only one 'interact' is allowed per state before a 'transition to' — a second one, still reachable in the same entry batch, emits a second 'request_interact' effect with no dedupe at the host layer.`,\n })\n }\n }\n\n // W018: an entry statement after a state-level 'transition to' another state never runs —\n // exec_entry_statements (fsm.rs) stops the entry batch as soon as current_state changes, the\n // way code after a `return` never runs. A transition to the state itself does not change\n // current_state, so it cuts nothing; a transition inside `if` is conditional, so it cuts\n // nothing either; handlers are not entry statements and stay reachable declarations.\n const leavingIndex = bodyStmts.findIndex(\n n => n.type === 'transition_stmt' && n.childForFieldName('state')?.text !== stateName,\n )\n if (leavingIndex !== -1) {\n const target = bodyStmts[leavingIndex].childForFieldName('state')?.text ?? '?'\n for (const stmt of bodyStmts.slice(leavingIndex + 1)) {\n if (stmt.type === 'intent_handler' || stmt.type === 'offtopic_handler' || stmt.type === 'comment') continue\n const { line, col } = nodePosition(stmt)\n messages.push({\n file, line, col, severity: 'warning', code: 'W018',\n message: `Unreachable: state '${stateName}' leaves for '${target}' on entry before this statement runs. Everything after a state-level 'transition to' is skipped, like code after a return — move it before the transition or remove it.`,\n })\n }\n }\n\n // E009: oriented state with no on intent handlers\n if (hasInteract && intentHandlers.length === 0) {\n const { line, col } = nodePosition(nameNode ?? stateNode)\n messages.push({\n file, line, col, severity: 'error', code: 'E009',\n message: `Oriented state '${stateName}' has no 'on intent' handlers. At least one is required.`,\n })\n }\n\n // W008: duplicate on intent label in same state (Error-level per spec)\n const seenIntents = new Map<string, true>()\n for (const handler of intentHandlers) {\n const intentNode = handler.childForFieldName('intent')\n if (!intentNode) continue\n const label = intentNode.text.replace(/^\"|\"$/g, '')\n if (seenIntents.has(label)) {\n const { line, col } = nodePosition(handler)\n messages.push({\n file, line, col, severity: 'error', code: 'W008',\n message: `Duplicate 'on intent \"${label}\"' in state '${stateName}'. The FSM cannot route ambiguous intents — use a unique label for each handler.`,\n })\n } else {\n seenIntents.set(label, true)\n }\n }\n\n // W011: on intent handler transitions to its own enclosing state\n for (const handler of intentHandlers) {\n for (const t of handler.descendantsOfType('transition_stmt')) {\n const targetNode = t.childForFieldName('state')\n if (targetNode?.text === stateName) {\n const { line, col } = nodePosition(handler)\n messages.push({\n file, line, col, severity: 'warning', code: 'W011',\n message: `'on intent' handler in state '${stateName}' transitions back to itself. The user expressed an intent but receives no progress — did you mean a different target state?`,\n })\n }\n }\n }\n\n // I001/I002: state overrides kernel lifecycle\n if (stateName === 'init' || stateName === 'end') {\n const { line, col } = nodePosition(nameNode ?? stateNode)\n if (stateName === 'init') {\n messages.push({\n file, line, col, severity: 'info', code: 'I001',\n message: `State 'init' overrides the kernel's default entry lifecycle. The kernel will use this definition instead of its built-in init sequence.`,\n })\n } else {\n messages.push({\n file, line, col, severity: 'info', code: 'I002',\n message: `State 'end' overrides the kernel's default terminal lifecycle. The kernel will treat this state as the canonical exit point.`,\n })\n }\n }\n\n // H001: state name close to (but not exact match of) kernel lifecycle names\n if (!KERNEL_LIFECYCLE_NAMES.includes(stateName)) {\n const closest = closestName(stateName, KERNEL_LIFECYCLE_NAMES)\n if (closest) {\n const { line, col } = nodePosition(nameNode ?? stateNode)\n messages.push({\n file, line, col, severity: 'hint', code: 'H001',\n message: `State name '${stateName}' resembles the kernel lifecycle name '${closest}'. If this is intentional, ignore this hint.`,\n })\n }\n }\n }\n\n // E010: parallel block with no run statements\n for (const parallelNode of nodesOfType(tree, 'parallel_stmt')) {\n if (parallelNode.hasError) continue\n if (parallelNode.descendantsOfType('run_stmt').length === 0) {\n const { line, col } = nodePosition(parallelNode)\n let stateName = '?'\n let ancestor = parallelNode.parent\n while (ancestor && ancestor.type !== 'state_decl') ancestor = ancestor.parent\n if (ancestor) stateName = ancestor.childForFieldName('name')?.text ?? '?'\n messages.push({\n file, line, col, severity: 'warning', code: 'E010',\n message: `'parallel' block in state '${stateName}' has no 'run' statements and does nothing.`,\n })\n }\n }\n\n // E011: after statement with prompts: 0\n for (const afterNode of nodesOfType(tree, 'after_stmt')) {\n if (afterNode.hasError) continue\n const countNode = afterNode.childForFieldName('count')\n if (countNode?.text === '0') {\n const { line, col } = nodePosition(countNode)\n messages.push({\n file, line, col, severity: 'error', code: 'E011',\n message: `'after 0' is invalid — prompts must be ≥ 1. Use 'after 1' for the next prompt.`,\n })\n }\n }\n\n // W002: goal_stmt text > 280 chars\n for (const stmtNode of nodesOfType(tree, 'goal_stmt')) {\n const strNode = stmtNode.descendantsOfType('quoted_string').find((n): n is Node => n !== null)\n if (!strNode) continue\n const content = strNode.text.replace(/^\"|\"$/g, '')\n if (content.length > 280) {\n const { line, col } = nodePosition(strNode)\n messages.push({\n file, line, col, severity: 'warning', code: 'W002',\n message: `Text block exceeds 280 characters (${content.length}). Consider using 'guide' to load long orientation text from an external text file.`,\n })\n }\n }\n\n // W010: guide_stmt text > 280 chars\n for (const stmtNode of nodesOfType(tree, 'guide_stmt')) {\n const strNode = stmtNode.descendantsOfType('quoted_string').find((n): n is Node => n !== null)\n if (!strNode) continue\n const content = strNode.text.replace(/^\"|\"$/g, '')\n if (content.length > 280) {\n const { line, col } = nodePosition(strNode)\n let p = stmtNode.parent\n while (p && p.type !== 'state_decl') p = p.parent\n const stateName = p?.childForFieldName('name')?.text ?? '?'\n messages.push({\n file, line, col, severity: 'warning', code: 'W010',\n message: `'guide' text in state '${stateName}' is ${content.length} characters. Consider using an external file.`,\n })\n }\n }\n\n // E005/W005: dangling transitions — state not defined (H002: hint with closest name)\n const definedStates = new Set(\n nodesOfType(tree, 'state_decl')\n .map(n => n.childForFieldName('name')?.text)\n .filter(Boolean) as string[]\n )\n\n if (docPath) {\n try {\n collectMergedStates(tree, dirname(docPath), definedStates)\n } catch {\n // path resolution failed — continue with local states only\n }\n }\n\n // Fragment files (merged INTO another file, with no merge of their own)\n // don't see the parent's states via collectMergedStates, which only walks\n // forward. Callers that resolve the merge root can pass its consolidated\n // state set here so dangling-transition checks see the whole tree.\n if (externalStates) {\n for (const name of externalStates) definedStates.add(name)\n }\n\n const stateNameList = Array.from(definedStates)\n for (const transitionNode of nodesOfType(tree, 'transition_stmt')) {\n const stateNode = transitionNode.childForFieldName('state')\n if (!stateNode) continue\n const target = stateNode.text\n if (!definedStates.has(target)) {\n const { line, col } = nodePosition(stateNode)\n const isExternal = target.includes('.')\n // H002: enrich E005 with closest state name suggestion\n const hint = !isExternal ? closestName(target, stateNameList) : undefined\n messages.push({\n file, line, col,\n severity: isExternal ? 'warning' : 'error',\n code: isExternal ? 'W005' : 'E005',\n message: isExternal\n ? `State '${target}' is not defined locally (assuming external flow reference).`\n : `State '${target}' is not defined in this file.`,\n ...(hint ? { hint: `did you mean '${hint}'?` } : {}),\n })\n }\n }\n\n // W006: dead-end interact (no handlers at all)\n for (const interactNode of nodesOfType(tree, 'interact_stmt')) {\n let ancestor = interactNode.parent\n while (ancestor && ancestor.type !== 'state_decl') ancestor = ancestor.parent\n if (!ancestor) continue\n const hasHandlers =\n ancestor.descendantsOfType('intent_handler').length +\n ancestor.descendantsOfType('offtopic_handler').length > 0\n if (!hasHandlers) {\n const { line, col } = nodePosition(interactNode)\n messages.push({\n file, line, col, severity: 'warning', code: 'W006',\n message: 'This state calls interact but has no handlers (on intent/offtopic). This will trap the agent.',\n })\n }\n }\n\n // Semantic FSM validation via behavior-parser WASM. This always parses the\n // file's own `text` — never `mergedText` — so E006 and node positions below\n // (W009) stay anchored to real locations in the file the editor has open.\n const fsmResult = parseBehaviorFile(text)\n if (fsmResult.ok === null) {\n const firstMsg = fsmResult.diagnostics[0]?.message ?? 'Parse error'\n messages.push({\n file, line: 1, col: 1, severity: 'error', code: 'E006',\n message: `Parse error: ${firstMsg}`,\n })\n return messages\n }\n\n const fsm = fsmResult.ok\n\n // Reachability (used by W001/W009) should see the whole merge component\n // when it's known, so a state only ever reached from a merged sibling file\n // isn't wrongly flagged — but we still only *report* on states declared in\n // this file, at positions from this file's own tree.\n const wholeFsm = mergedText !== undefined ? parseBehaviorFile(mergedText).ok : null\n const reachabilityStates = wholeFsm?.states ?? fsm.states\n const allTargets = new Set(collectTransitionTargets(reachabilityStates.flatMap(s => s.body)))\n\n // W001: isolated state (no incoming and no outgoing transitions)\n for (const state of fsm.states) {\n const hasOutgoing = collectTransitionTargets(state.body).length > 0\n const hasIncoming = allTargets.has(state.name)\n if (!hasIncoming && !hasOutgoing) {\n messages.push({\n file, line: 1, col: 1, severity: 'warning', code: 'W001',\n message: `State \"${state.name}\" has no transitions`,\n })\n }\n }\n\n // W009: unreachable state (no incoming transitions, not the first state)\n for (let i = 1; i < fsm.states.length; i++) {\n const state = fsm.states[i]\n if (!allTargets.has(state.name)) {\n const stateNode = nodesOfType(tree, 'state_decl')\n .find(n => n.childForFieldName('name')?.text === state.name)\n const pos = stateNode ? nodePosition(stateNode) : { line: 1, col: 1 }\n messages.push({\n file, line: pos.line, col: pos.col, severity: 'warning', code: 'W009',\n message: `State '${state.name}' is unreachable — no other state transitions to it.`,\n })\n }\n }\n\n if (consolidated) {\n // E015/E016/W014 are whole-tree facts. When `mergedText` is given, derive\n // them from it instead of the local `fsm` — this is the only place a\n // merged-text FSM should be consulted, and it never affects positions\n // (all three report at a synthetic line 1 col 1, never a node position).\n const wholeTreeFsm = wholeFsm ?? fsm\n\n // E015: duplicate state name across merged files\n const seenStates = new Set<string>()\n for (const state of wholeTreeFsm.states) {\n if (seenStates.has(state.name)) {\n messages.push({\n file, line: 1, col: 1, severity: 'error', code: 'E015',\n message: `Duplicate state '${state.name}' across merged files — each state name must be unique in the consolidated FSM.`,\n })\n } else {\n seenStates.add(state.name)\n }\n }\n\n // E016: init state missing\n if (!wholeTreeFsm.states.some(s => s.name === 'init')) {\n messages.push({\n file, line: 1, col: 1, severity: 'error', code: 'E016',\n message: `Required 'init' state is missing. Add a state named 'init' as the entry point of your behavior.`,\n })\n }\n\n // W014: duplicate global trigger event across merged files\n const seenTriggers = new Set<string>()\n for (const trigger of wholeTreeFsm.global_triggers) {\n if (seenTriggers.has(trigger.event)) {\n messages.push({\n file, line: 1, col: 1, severity: 'warning', code: 'W014',\n message: `Duplicate global trigger '${trigger.event}' across merged files — only the last definition takes effect.`,\n })\n } else {\n seenTriggers.add(trigger.event)\n }\n }\n }\n\n return messages\n}\n\nexport async function createLinter() {\n return { lintDescription, lintBehavior }\n}\n","// SPDX-License-Identifier: Apache-2.0\n\nimport JSZip from 'jszip'\nimport { readFile, writeFile } from 'fs/promises'\nexport { createZip, extractFiles } from './zip-core.js'\nimport {\n validateMagicBytes as validateMagicBytesCore,\n validateZipBomb as validateZipBombCore,\n} from './zip-core.js'\n\nexport async function readZip(filePath: string): Promise<JSZip> {\n const data = await readFile(filePath)\n return JSZip.loadAsync(data)\n}\n\nexport async function validateZipBomb(filePath: string): Promise<boolean> {\n const data = await readFile(filePath)\n const zip = await JSZip.loadAsync(data)\n validateZipBombCore(zip, data.length)\n return true\n}\n\nexport async function validateMagicBytes(filePath: string): Promise<boolean> {\n const data = await readFile(filePath)\n validateMagicBytesCore(data)\n return true\n}\n\nexport async function writeZip(zip: JSZip, outPath: string): Promise<void> {\n const data = await zip.generateAsync({ type: 'arraybuffer' })\n await writeFile(outPath, Buffer.from(data))\n}\n","// SPDX-License-Identifier: Apache-2.0\n\nimport type { DescriptionFile, TypeDefinition, PropertyType, AnnotatedRef } from './types.js'\n\nconst STD_BASE = 'https://dot-agent.dev/schema/std/v1/'\n\nfunction propertyTypeToSchema(pt: PropertyType): object {\n switch (pt.kind) {\n case 'primitive':\n return { type: pt.value }\n case 'reference':\n return pt.value.startsWith('std.')\n ? { $ref: `${STD_BASE}${pt.value.slice(4)}.json` }\n : { $ref: `#/$defs/${pt.value}` }\n case 'array':\n return { type: 'array', items: propertyTypeToSchema(pt.value) }\n case 'enum':\n return { type: 'string', enum: pt.value }\n }\n}\n\nfunction typeDefinitionToSchema(td: TypeDefinition): object {\n const required = td.properties.filter(p => !p.is_optional).map(p => p.name)\n const properties: Record<string, object> = {}\n for (const p of td.properties) {\n properties[p.name] = {\n ...propertyTypeToSchema(p.type),\n ...(p.description ? { description: p.description } : {}),\n }\n }\n return {\n $schema: 'https://json-schema.org/draft/2020-12/schema',\n 'x-category': td.category.uri,\n ...(td.category.label ? { 'x-category-label': td.category.label } : {}),\n ...(td.concept ? { 'x-concept': td.concept.uri } : {}),\n ...(td.concept?.label ? { 'x-concept-label': td.concept.label } : {}),\n type: 'object',\n properties,\n ...(required.length ? { required } : {}),\n }\n}\n\nfunction refFromAnnotatedRef(ref: AnnotatedRef): object {\n return ref.name.startsWith('std.')\n ? { $ref: `${STD_BASE}${ref.name.slice(4)}.json` }\n : { $ref: `#/$defs/${ref.name}` }\n}\n\n/** Returns JSON Schema 2020-12 string for types.json, or null if nothing to write. */\nexport function buildTypesJson(df: DescriptionFile): string | null {\n if (df.types.length === 0 && df.input.length === 0 && df.output.length === 0) return null\n\n const defs: Record<string, object> = {}\n for (const td of df.types) {\n defs[td.name] = typeDefinitionToSchema(td)\n }\n\n return JSON.stringify(\n {\n ...(df.input.length ? { input: df.input.map(refFromAnnotatedRef) } : {}),\n ...(df.output.length ? { output: df.output.map(refFromAnnotatedRef) } : {}),\n ...(Object.keys(defs).length ? { $defs: defs } : {}),\n },\n null,\n 2\n )\n}\n","// SPDX-License-Identifier: Apache-2.0\n\nimport { readFile, stat, readdir } from 'fs/promises'\nimport { join, basename, resolve, relative, isAbsolute, normalize, dirname } from 'path'\nimport { execSync } from 'child_process'\nimport { createHash } from 'crypto'\nimport JSZip from 'jszip'\nimport type { LintMessage, PackOptions, PackResult, Statement } from './types.js'\nimport { lintDescription, lintBehavior } from './linter.js'\nimport { buildId, slugify, isValidVersion } from './id.js'\nimport { buildAboutme, aboutmeToJson } from './manifest.js'\nimport { initBehaviorParser, parseDescriptionFile, parseBehaviorFile } from './parser.js'\nimport { buildTypesJson } from './schema.js'\nimport { writeZip } from './zip.js'\nimport { COMPILER_VERSION } from './generated-version.js'\nimport { isInContentNamespace, classifyContentPath } from './namespace.js'\n\nfunction gitRevParseShort(): string | null {\n try {\n return execSync('git rev-parse --short HEAD', { stdio: 'pipe', encoding: 'utf-8' }).trim()\n } catch {\n return null\n }\n}\n\nasync function resolveCommit(explicit?: string): Promise<string | undefined> {\n if (explicit) return explicit\n return gitRevParseShort() ?? undefined\n}\n\n// ── Version resolution ────────────────────────────────────────────────────────\n\ninterface VersionCandidate {\n version: string\n label: string\n}\n\n// The repo's tags are all monorepo-style `<pkg>@<version>` (there is no plain\n// vX.Y.Z release tag convention here). Rather than guess which tag belongs to\n// the directory being packed, list the most recent tags with their package\n// context and let a human pick — precision comes from judgment, not a\n// heuristic that can silently attribute the wrong package's version.\nfunction recentTagCandidates(limit = 5): VersionCandidate[] {\n let tags: string[]\n try {\n tags = execSync('git tag --sort=-creatordate', { stdio: 'pipe', encoding: 'utf-8' })\n .trim()\n .split('\\n')\n .filter(Boolean)\n } catch {\n return []\n }\n return tags\n .slice(0, limit)\n .map((tag): VersionCandidate => {\n const atIdx = tag.lastIndexOf('@')\n const version = atIdx === -1 ? tag : tag.slice(atIdx + 1)\n const label = atIdx === -1 ? tag : `${version} (tag: ${tag})`\n return { version, label }\n })\n .filter(c => isValidVersion(c.version))\n}\n\n// String sentinels (not symbols) — @clack/prompts' select() types `value` as\n// `string`, and these are extremely unlikely to collide with a real tag-derived version.\nconst CUSTOM_VERSION = '__dot-agent-custom-version__'\nconst BARE_VERSION = '__dot-agent-bare-version__'\n\n// No hardcoded version default — an unresolved version produces a form A\n// (bare) id per docs/reference/agent-id.md, rather than fabricating one.\nasync function resolveVersionInteractive(explicit?: string): Promise<string | undefined> {\n if (explicit) {\n if (!isValidVersion(explicit)) {\n throw new Error(`E019: Invalid version format '${explicit}' — expected vX.Y[.Z][-prerelease] or X.Y[.Z][-prerelease]`)\n }\n return explicit\n }\n\n if (!process.stdin.isTTY || !process.stdout.isTTY) {\n process.stderr.write('[dot-agent] no TTY and no --version — packing without a version\\n')\n return undefined\n }\n\n const candidates = recentTagCandidates()\n\n // @clack/prompts is ESM-only — dynamic import() resolves it correctly\n // regardless of whether this package itself is consumed as ESM or CJS\n // (a static import would break `require()` callers), and it also means the\n // non-interactive paths above never pay to load it at all.\n const clack = await import('@clack/prompts')\n\n const choice = await clack.select({\n message: 'Choose a version for this package',\n options: [\n ...candidates.map(c => ({ value: c.version, label: c.label })),\n { value: CUSTOM_VERSION, label: 'Type a custom version…' },\n { value: BARE_VERSION, label: 'None (bare — no version)' },\n ],\n })\n\n if (clack.isCancel(choice)) {\n clack.cancel('Pack cancelled.')\n process.exit(1)\n }\n\n if (choice === BARE_VERSION) return undefined\n\n if (choice === CUSTOM_VERSION) {\n const typed = await clack.text({\n message: 'Version',\n validate: v => (v && isValidVersion(v) ? undefined : 'Invalid version format — expected vX.Y[.Z][-prerelease] or X.Y[.Z][-prerelease]'),\n })\n if (clack.isCancel(typed)) {\n clack.cancel('Pack cancelled.')\n process.exit(1)\n }\n return typed\n }\n\n return choice as string\n}\n\n// ── Path safety ──────────────────────────────────────────────────────────────\n\nfunction isExternalPath(agentRoot: string, declaredPath: string): boolean {\n if (isAbsolute(declaredPath)) return true\n const normRoot = normalize(resolve(agentRoot))\n const resolved = resolve(normRoot, declaredPath)\n return relative(normRoot, resolved).startsWith('..')\n}\n\n// ── Description file discovery ────────────────────────────────────────────────\n\nexport async function discoverDescriptionFile(dir: string, explicit?: string): Promise<string> {\n if (explicit) {\n try {\n await stat(join(dir, explicit))\n return explicit\n } catch {\n throw new Error(`E003: Description file '${explicit}' not found in ${dir}`)\n }\n }\n const entries = await readdir(dir)\n const descFiles = entries.filter(f => f.endsWith('.description'))\n if (descFiles.length === 0) {\n throw new Error(`E003: No .description file found in ${dir}`)\n }\n if (descFiles.length > 1) {\n throw new Error(`E003: Multiple .description files found: ${descFiles.join(', ')} — use PackOptions.description to specify one`)\n }\n const name = descFiles[0]\n if (name !== 'agent.description') {\n console.info(`[dot-agent] using description file: ${name}`)\n }\n return name\n}\n\n// ── Merge graph consolidation ─────────────────────────────────────────────────\n\ninterface ConsolidateResult {\n mergedText: string\n mergeSources: string[] // relative paths within agent root, e.g. [\"main.behavior\"]\n}\n\nexport async function consolidate(agentRoot: string, entryFile: string): Promise<ConsolidateResult> {\n await initBehaviorParser()\n const normRoot = normalize(resolve(agentRoot))\n const visiting = new Set<string>()\n const visited = new Set<string>()\n const order: string[] = []\n const textCache = new Map<string, string>()\n\n async function dfs(relPath: string): Promise<void> {\n const absPath = resolve(normRoot, relPath)\n\n if (visiting.has(absPath)) {\n throw new Error(`E013: Circular merge dependency involving '${relPath}'`)\n }\n if (visited.has(absPath)) return\n\n visiting.add(absPath)\n\n let fileText: string\n try {\n fileText = await readFile(absPath, 'utf-8')\n } catch {\n throw new Error(`E012: Merge target not found: '${relPath}'`)\n }\n textCache.set(absPath, fileText)\n\n const result = parseBehaviorFile(fileText)\n const merges = result.ok?.merges ?? []\n\n for (const mergePath of merges) {\n if (isAbsolute(mergePath)) {\n throw new Error(`E014: Merge path '${mergePath}' in '${relPath}' is absolute — only paths within the agent root are allowed`)\n }\n const mergeAbs = resolve(dirname(absPath), mergePath)\n const mergeRel = relative(normRoot, mergeAbs)\n if (mergeRel.startsWith('..')) {\n throw new Error(`E014: Merge path '${mergePath}' in '${relPath}' escapes the agent root`)\n }\n await dfs(mergeRel)\n }\n\n visiting.delete(absPath)\n visited.add(absPath)\n order.push(relPath)\n }\n\n await dfs(entryFile)\n\n const texts = order.map(relPath => textCache.get(resolve(normRoot, relPath))!)\n return {\n mergedText: texts.join('\\n'),\n mergeSources: order,\n }\n}\n\n// ── guide/teach file references ───────────────────────────────────────────────\n\n// `guide \"...\"` / `teach \"...\"` text is either inline orientation prose or a\n// filename to bundle alongside the agent (e.g. `teach \"recipes.txt\"`). A\n// trailing .txt/.md is the only signal we have to tell them apart — anything\n// else stays literal, embedded verbatim in the flattened agent.behavior.\nconst FILE_REF_RE = /\\.(txt|md)$/i\n\ninterface FileRef {\n kind: 'guide' | 'teach'\n text: string\n}\n\nfunction collectFileRefs(stmts: Statement[], out: Map<string, FileRef>): void {\n for (const s of stmts) {\n switch (s.type) {\n case 'guide_stmt':\n if (FILE_REF_RE.test(s.text)) out.set(`guide:${s.text}`, { kind: 'guide', text: s.text })\n break\n case 'teach_stmt':\n if (FILE_REF_RE.test(s.text)) out.set(`teach:${s.text}`, { kind: 'teach', text: s.text })\n break\n case 'interact_stmt':\n collectFileRefs(s.handlers, out)\n break\n case 'intent_handler':\n if (Array.isArray(s.body)) collectFileRefs(s.body, out)\n break\n case 'offtopic_handler':\n case 'after_stmt':\n case 'parallel_stmt':\n collectFileRefs(s.body, out)\n break\n case 'conditional_stmt':\n collectFileRefs(s.then, out)\n if (s.else) collectFileRefs(s.else, out)\n break\n }\n }\n}\n\n// ── File collection ───────────────────────────────────────────────────────────\n\n// A `guide`/`teach` reference is a path relative to the agent root, bundled\n// verbatim at that path — the namespace is whatever the path itself declares\n// (`knowledge/x.md`, `guides/x.md`), not something derived from the keyword.\n// This keeps the reference, the on-disk location, and the bundle key a single\n// value, so nothing can drift into a doubled `knowledge/knowledge/x.md`. Only\n// light normalization: forward slashes and a stripped leading `./`.\nfunction normalizeRefPath(text: string): string {\n return text.replace(/\\\\/g, '/').replace(/^\\.\\//, '')\n}\n\nasync function collectBehaviorFileRefs(mergedBehaviorText: string): Promise<Map<string, FileRef>> {\n await initBehaviorParser()\n const refs = new Map<string, FileRef>()\n const behaviorAst = parseBehaviorFile(mergedBehaviorText).ok\n if (!behaviorAst) return refs\n for (const state of behaviorAst.states) collectFileRefs(state.body, refs)\n for (const trigger of behaviorAst.global_triggers) collectFileRefs(trigger.body, refs)\n return refs\n}\n\n// Every file under guides/ or knowledge/, keyed by the bundle path it *would*\n// occupy. Nothing here reaches the bundle on its own — only a guide/teach\n// reference pulls a file in (see collectFiles) — so this exists solely to let\n// findOrphanContentFiles report the files that never make it.\nasync function listContentFiles(dir: string, ns: 'guides' | 'knowledge'): Promise<string[]> {\n const found: string[] = []\n\n async function walk(subdir: string, prefix: string) {\n let entries: string[]\n try {\n entries = await readdir(subdir)\n } catch {\n return // directory doesn't exist or can't be read\n }\n for (const entry of entries) {\n if (entry.startsWith('.')) continue\n const fullPath = join(subdir, entry)\n const relativePath = `${prefix}/${entry}`\n if ((await stat(fullPath)).isDirectory()) {\n await walk(fullPath, relativePath)\n } else {\n found.push(relativePath)\n }\n }\n }\n\n await walk(join(dir, ns), ns)\n return found\n}\n\n// A file in guides/ or knowledge/ that no guide/teach statement names is absent\n// from the bundle under the linked-only rule — and would be unreachable at runtime\n// even if it were bundled, since the kernel hands the LLM a bare filename via the\n// teach effect and the MCP server exposes no listing endpoint. W015 is what keeps\n// that from being a silent drop, including for something like knowledge/data.csv\n// that FILE_REF_RE never recognises as a file reference to begin with.\nexport async function findOrphanContentFiles(\n dir: string,\n mergedBehaviorText: string,\n): Promise<LintMessage[]> {\n const refs = await collectBehaviorFileRefs(mergedBehaviorText)\n const referenced = new Set<string>()\n const messages: LintMessage[] = []\n\n // Single pass: every ref's bundlePath is normalized once and reused for both\n // checks below, instead of recomputing it in two separate loops.\n for (const { kind, text } of refs.values()) {\n const bundlePath = normalizeRefPath(text)\n referenced.add(bundlePath)\n\n // E022 (platform#9): a reference that resolves outside guides/ or\n // knowledge/. bundle.ts/sdk-load.ts only expose files under those two\n // prefixes, so the runtime can never hand its content to the host — the\n // teach/guide effect would surface a path nothing serves. Formerly a\n // warning (a warning, so pack still wrote an archive with unreachable\n // content); it is an error now, so pack() refuses before writing the\n // archive rather than shipping a bundle nothing can serve. Flags the old\n // \"loose file next to agent.behavior\" convention. Only fires when the\n // file actually exists and would otherwise be bundled — a reference to a\n // nonexistent file gets E018 from collectFiles() instead.\n if (isExternalPath(dir, bundlePath) || isInContentNamespace(bundlePath)) continue\n try {\n await stat(join(dir, bundlePath))\n } catch {\n continue\n }\n messages.push({\n file: bundlePath,\n line: 1,\n col: 1,\n severity: 'error',\n code: 'E022',\n message: `'${kind}' reference '${text}' resolves to '${bundlePath}', which is outside guides/ and knowledge/ — those are the only two directories the runtime can serve content from; move '${bundlePath}' under guides/ or knowledge/ and update the '${kind}' statement to reference it there`,\n })\n }\n\n const onDisk = [\n ...(await listContentFiles(dir, 'guides')),\n ...(await listContentFiles(dir, 'knowledge')),\n ]\n\n const orphanMessages: LintMessage[] = onDisk\n .filter(path => !referenced.has(path))\n .map((path): LintMessage => ({\n file: path,\n line: 1,\n col: 1,\n severity: 'warning',\n code: 'W015',\n message: `'${path}' is not referenced by any guide or teach statement — it will not be included in the bundle`,\n }))\n\n return [...orphanMessages, ...messages]\n}\n\nexport async function collectFiles(\n dir: string,\n descriptionFile: string,\n mergedBehaviorText: string,\n mergeSources: string[],\n personaFile?: string,\n): Promise<Map<string, string>> {\n const files = new Map<string, string>()\n\n files.set(descriptionFile, await readFile(join(dir, descriptionFile), 'utf-8'))\n // mergedBehaviorText is a literal concatenation of every merged file's raw\n // source (see consolidate() above), so a `merge \"...\"` line from the entry\n // file survives verbatim even though every state it would pull in is\n // already inlined by the concatenation. Left in, a runtime that re-parses\n // this flat file (e.g. AgentSession.start() in @dot-agent/sdk) treats it as\n // a live merge directive and tries to re-resolve it against a differently\n // keyed bundle, failing with \"files not found\". It's dead once flattened —\n // strip it. Safe to do after linting (above), which already ran on the\n // unstripped text.\n const flatBehaviorText = mergedBehaviorText.replace(/^\\s*merge\\s+\"[^\"]*\"\\s*$/gm, '')\n files.set('agent.behavior', flatBehaviorText)\n\n for (const relPath of mergeSources) {\n files.set(`behaviors/${relPath}`, await readFile(join(dir, relPath), 'utf-8'))\n }\n\n if (personaFile) {\n if (isExternalPath(dir, personaFile)) {\n throw new Error(`E014: persona path '${personaFile}' in '${descriptionFile}' is absolute or escapes the agent root`)\n }\n let personaText: string\n try {\n personaText = await readFile(join(dir, personaFile), 'utf-8')\n } catch {\n throw new Error(`E_DESC: persona file '${personaFile}' declared in '${descriptionFile}' not found`)\n }\n files.set(personaFile, personaText)\n }\n\n // A `guide \"guides/intro.md\"` / `teach \"knowledge/recipes.md\"` reference is the\n // only thing that pulls a content file into the bundle — guides/ and knowledge/\n // are not swept wholesale, so the bundle is a function of the behavior graph\n // rather than of whatever happens to sit in the directory. The reference is a\n // path relative to the agent root, resolved literally and bundled verbatim at\n // that same path — no namespace guessing, no doubled `knowledge/knowledge/…`.\n // findOrphanContentFiles() reports what this loop leaves behind (W015) and any\n // reference that lands outside guides/ or knowledge/ (E022, checked by pack()\n // before it writes the archive).\n const refs = await collectBehaviorFileRefs(mergedBehaviorText)\n for (const { kind, text } of refs.values()) {\n const bundlePath = normalizeRefPath(text)\n if (isExternalPath(dir, bundlePath)) {\n throw new Error(`E014: '${kind}' path '${text}' is absolute or escapes the agent root`)\n }\n\n let content: string\n try {\n content = await readFile(join(dir, bundlePath), 'utf-8')\n } catch {\n throw new Error(\n `E018: '${kind}' file '${text}' referenced in agent.behavior not found in ${dir} — looked for '${bundlePath}' relative to the agent root`\n )\n }\n\n // Nothing constrains bundlePath to guides/ or knowledge/ (see comment\n // above), so it can collide with a reserved key already set above — the\n // description file, the flattened agent.behavior, a merge source under\n // behaviors/, or the persona. Silently overwriting one of those would\n // corrupt content the kernel or SDK depends on (e.g. a behaviors/ entry\n // resolved at runtime for `merge \"...\"`), so refuse instead.\n if (files.has(bundlePath)) {\n throw new Error(\n `E020: '${kind}' reference '${text}' resolves to '${bundlePath}', which collides with a reserved bundle path (the description file, agent.behavior, a merged behaviors/ file, or the persona) — reference a different path`\n )\n }\n\n files.set(bundlePath, content)\n }\n\n return files\n}\n\n// The bundle extension is always .agent — append it when the caller left it off\n// rather than requiring `--out foo.agent` to be typed out every time.\nfunction withAgentExtension(path: string): string {\n return path.endsWith('.agent') ? path : `${path}.agent`\n}\n\nexport async function pack(options: PackOptions = {}): Promise<PackResult> {\n const dir = options.dir ?? process.cwd()\n const outPath = withAgentExtension(options.out ?? join(dir, basename(dir)))\n\n // 1. Discover and read description file\n const descriptionFileName = await discoverDescriptionFile(dir, options.description)\n const descriptionText = await readFile(join(dir, descriptionFileName), 'utf-8')\n\n // 2. Lint description — fail fast on errors (E017, E004, etc.)\n const descriptionMessages = await lintDescription(descriptionText, descriptionFileName)\n const descErrors = descriptionMessages.filter(m => m.severity === 'error')\n if (descErrors.length > 0) {\n throw new Error(\n `Lint failed:\\n${descErrors.map(e => ` ${e.file}:${e.line}:${e.col} ${e.code} ${e.message}`).join('\\n')}`\n )\n }\n\n // 3. Init WASM parser (needed for parseDescriptionFile and consolidate)\n await initBehaviorParser()\n\n // 4. Parse description to get df.behavior\n const descResult = parseDescriptionFile(descriptionText)\n if (descResult.ok === null) {\n const firstError = descResult.diagnostics.find(d => d.severity === 'error')\n throw new Error(`E_DESC: ${firstError?.message ?? 'parse failed'}`)\n }\n const df = descResult.ok\n\n // 5. Validate df.behavior\n if (!df.behavior) {\n throw new Error(`E_DESC: '${descriptionFileName}' must declare a behavior file — add 'behavior \"agent.behavior\"' (or the name of your entry .behavior file)`)\n }\n if (isExternalPath(dir, df.behavior)) {\n throw new Error(`E014: behavior path '${df.behavior}' in '${descriptionFileName}' is absolute or escapes the agent root`)\n }\n\n // 6. Consolidate merge graph → single merged text\n const { mergedText, mergeSources } = await consolidate(dir, df.behavior)\n\n // 7. Lint consolidated behavior (E015, E016, W014 only fire when consolidated=true)\n const behaviorMessages = await lintBehavior(mergedText, 'agent.behavior', undefined, true)\n const allMessages = [...descriptionMessages, ...behaviorMessages]\n const errors = allMessages.filter(m => m.severity === 'error')\n const lintWarnings = allMessages.filter(m => m.severity === 'warning')\n\n if (errors.length > 0) {\n throw new Error(\n `Lint failed:\\n${errors.map(e => ` ${e.file}:${e.line}:${e.col} ${e.code} ${e.message}`).join('\\n')}`\n )\n }\n\n // 8. Collect all files for the bundle\n const version = await resolveVersionInteractive(options.version)\n const commit = await resolveCommit(options.commit)\n const allFiles = await collectFiles(dir, descriptionFileName, mergedText, mergeSources, df.persona ?? undefined)\n const contentMessages = await findOrphanContentFiles(dir, mergedText)\n\n // E022 (platform#9): a guide/teach reference resolving outside guides/ or\n // knowledge/ is bundled but unreachable at runtime — refuse before writing\n // the archive rather than shipping a bundle nothing can serve.\n const contentErrors = contentMessages.filter(m => m.severity === 'error')\n if (contentErrors.length > 0) {\n throw new Error(\n `Lint failed:\\n${contentErrors.map(e => ` ${e.file}:${e.line}:${e.col} ${e.code} ${e.message}`).join('\\n')}`\n )\n }\n\n const warnings = [...lintWarnings, ...contentMessages.filter(m => m.severity === 'warning')]\n\n const contentForHash = Array.from(allFiles.values()).join('')\n const sha256 = createHash('sha256').update(contentForHash).digest('hex')\n\n const namespace = df.agent.domain ?? 'unknown'\n // digest requires version (buildId's own invariant) — a bare (versionless)\n // id never carries a digest either, even if a commit sha is available.\n const id = buildId({ namespace, name: slugify(df.agent.name), version, digest: version ? commit : undefined })\n\n const typesJson = buildTypesJson(df)\n const integrity = {\n sha256,\n ...(typesJson ? { types: '.agent/types.json' } : {}),\n files: '.agent/files.json',\n }\n\n const aboutme = buildAboutme({\n id,\n name: df.agent.name,\n description: df.description ?? '',\n version: version ?? '',\n domain: df.agent.domain ?? '',\n license: df.agent.license ?? '',\n persona: df.persona ?? undefined,\n purpose: 'unknown',\n compiler: `dot-agent/${COMPILER_VERSION}`,\n commit,\n capabilities: df.capabilities.map(c => ({ id: c.name, description: c.description ?? '' })),\n requires: df.requires,\n integrity,\n })\n\n const zip = new JSZip()\n const agentFolder = zip.folder('.agent')!\n agentFolder.file('aboutme.json', aboutmeToJson(aboutme))\n\n if (typesJson) {\n agentFolder.file('types.json', typesJson)\n }\n\n const filesJson = {\n description: descriptionFileName,\n behavior: 'agent.behavior',\n ...(df.persona ? { persona: df.persona } : {}),\n behaviors: Array.from(allFiles.keys()).filter(f => f.startsWith('behaviors/')),\n guides: Array.from(allFiles.keys()).filter(f => classifyContentPath(f) === 'guides'),\n knowledge: Array.from(allFiles.keys()).filter(f => classifyContentPath(f) === 'knowledge'),\n }\n agentFolder.file('files.json', JSON.stringify(filesJson, null, 2))\n\n for (const [path, content] of allFiles) {\n zip.file(path, content)\n }\n\n await writeZip(zip, outPath)\n\n return { path: outPath, id, warnings }\n}\n","// SPDX-License-Identifier: Apache-2.0\n\nimport { readFile } from 'fs/promises'\nimport { join } from 'path'\nimport { createHash } from 'crypto'\nimport type { AgentBundle, AgentFiles } from './types.js'\nimport { discoverDescriptionFile, consolidate, collectFiles, findOrphanContentFiles } from './pack.js'\nimport { lintDescription, lintBehavior } from './linter.js'\nimport { buildId, slugify } from './id.js'\nimport { buildAboutme } from './manifest.js'\nimport { initBehaviorParser, parseDescriptionFile } from './parser.js'\nimport { COMPILER_VERSION } from './generated-version.js'\nimport { classifyContentPath } from './namespace.js'\n\nexport async function bundleFromDir(dir: string): Promise<AgentBundle> {\n const descriptionFileName = await discoverDescriptionFile(dir)\n const descriptionText = await readFile(join(dir, descriptionFileName), 'utf-8')\n\n const descMessages = await lintDescription(descriptionText, descriptionFileName)\n const descErrors = descMessages.filter(m => m.severity === 'error')\n if (descErrors.length > 0) {\n throw new Error(\n `Lint failed:\\n${descErrors.map(e => ` ${e.file}:${e.line}:${e.col} ${e.code} ${e.message}`).join('\\n')}`\n )\n }\n\n await initBehaviorParser()\n const descResult = parseDescriptionFile(descriptionText)\n if (descResult.ok === null) {\n const firstError = descResult.diagnostics.find(d => d.severity === 'error')\n throw new Error(`E_DESC: ${firstError?.message ?? 'parse failed'}`)\n }\n const df = descResult.ok\n\n if (!df.behavior) {\n throw new Error(`E_DESC: '${descriptionFileName}' must declare a behavior file`)\n }\n\n const { mergedText, mergeSources } = await consolidate(dir, df.behavior)\n\n const behaviorMessages = await lintBehavior(mergedText, 'agent.behavior', undefined, true)\n const orphanMessages = await findOrphanContentFiles(dir, mergedText)\n const allMessages = [...descMessages, ...behaviorMessages, ...orphanMessages]\n const errors = allMessages.filter(m => m.severity === 'error')\n const warnings = allMessages.filter(m => m.severity === 'warning')\n\n if (errors.length > 0) {\n throw new Error(\n `Lint failed:\\n${errors.map(e => ` ${e.file}:${e.line}:${e.col} ${e.code} ${e.message}`).join('\\n')}`\n )\n }\n\n for (const w of warnings) {\n process.stderr.write(`\\x1b[33m⚠\\x1b[0m ${w.file}:${w.line}:${w.col} ${w.code} ${w.message}\\n`)\n }\n\n const allFiles = await collectFiles(dir, descriptionFileName, mergedText, mergeSources, df.persona ?? undefined)\n\n const sha256 = createHash('sha256')\n .update(Array.from(allFiles.values()).join(''))\n .digest('hex')\n\n const id = buildId({ namespace: df.agent.domain ?? 'unknown', name: slugify(df.agent.name), version: 'dev' })\n\n const aboutme = buildAboutme({\n id,\n name: df.agent.name,\n description: df.description ?? '',\n version: 'dev',\n domain: df.agent.domain ?? '',\n license: df.agent.license ?? '',\n persona: df.persona ?? undefined,\n purpose: 'development',\n compiler: `dot-agent/${COMPILER_VERSION}`,\n capabilities: df.capabilities.map(c => ({ id: c.name, description: c.description ?? '' })),\n requires: df.requires,\n integrity: { sha256, files: '.agent/files.json' },\n })\n\n const files: AgentFiles = {\n description: descriptionText,\n // Reuse collectFiles()'s 'agent.behavior' entry rather than the raw\n // mergedText — it has redundant `merge \"...\"` lines stripped (see\n // collectFiles() for why they're dead weight once flattened).\n behavior: allFiles.get('agent.behavior') ?? mergedText,\n persona: df.persona ? allFiles.get(df.persona) : undefined,\n guides: Array.from(allFiles.entries())\n .filter(([p]) => classifyContentPath(p) === 'guides')\n .map(([path, content]) => ({ path, content })),\n knowledge: Array.from(allFiles.entries())\n .filter(([p]) => classifyContentPath(p) === 'knowledge')\n .map(([path, content]) => ({ path, content })),\n behaviors: Array.from(allFiles.entries())\n .filter(([p]) => p.startsWith('behaviors/'))\n .map(([path, content]) => ({ path, content })),\n }\n\n return { id, aboutme, files }\n}\n"],"mappings":"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"}
@@ -15,7 +15,7 @@ var __copyProps = (to, from, except, desc) => {
15
15
  }
16
16
  return to;
17
17
  };
18
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
19
19
  value: mod,
20
20
  enumerable: true
21
21
  }) : target, mod));
@@ -23,7 +23,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
23
  let jszip = require("jszip");
24
24
  jszip = __toESM(jszip, 1);
25
25
  //#region src/generated-version.ts
26
- const COMPILER_VERSION = "0.10.2";
26
+ const COMPILER_VERSION = "0.12.0-beta.1";
27
27
  //#endregion
28
28
  //#region src/manifest.ts
29
29
  function parseAboutme(json) {
@@ -316,4 +316,4 @@ Object.defineProperty(exports, "validateZipBomb", {
316
316
  }
317
317
  });
318
318
 
319
- //# sourceMappingURL=namespace-0cuKn3-s.cjs.map
319
+ //# sourceMappingURL=namespace-CLx06F20.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"namespace-CLx06F20.cjs","names":["JSZip"],"sources":["../src/generated-version.ts","../src/manifest.ts","../src/id.ts","../src/zip-core.ts","../src/namespace.ts"],"sourcesContent":["// Generated by scripts/embed-version.mjs from dsl/VERSION and package.json — do not edit by hand.\nexport const DSL_VERSION = '0.1'\nexport const COMPILER_VERSION = '0.12.0-beta.1'\n","// SPDX-License-Identifier: Apache-2.0\n\nimport type { AboutMe, BuildAboutmeOptions } from './types.js'\nimport { DSL_VERSION } from './generated-version.js'\n\nexport function parseAboutme(json: any): AboutMe {\n if (!json.dslVersion) throw new Error('Missing dslVersion in aboutme.json')\n if (!json.id) throw new Error('Missing id in aboutme.json')\n if (!json.name) throw new Error('Missing name in aboutme.json')\n if (!json.description) throw new Error('Missing description in aboutme.json')\n if (!json.domain) throw new Error('Missing domain in aboutme.json')\n if (!json.compiler) throw new Error('Missing compiler in aboutme.json')\n if (!Array.isArray(json.capabilities)) throw new Error('Missing capabilities array in aboutme.json')\n if (!Array.isArray(json.requires)) throw new Error('Missing requires array in aboutme.json')\n if (!json.integrity) throw new Error('Missing integrity in aboutme.json')\n\n return {\n dslVersion: json.dslVersion,\n id: json.id,\n name: json.name,\n description: json.description,\n version: json.version ?? '',\n domain: json.domain,\n license: json.license ?? '',\n persona: json.persona,\n purpose: json.purpose ?? 'unknown',\n compiler: json.compiler,\n commit: json.commit,\n capabilities: json.capabilities,\n requires: json.requires,\n integrity: json.integrity,\n }\n}\n\nexport function buildAboutme(opts: BuildAboutmeOptions): AboutMe {\n return {\n dslVersion: `dot-agent/${DSL_VERSION}`,\n id: opts.id,\n name: opts.name,\n description: opts.description,\n version: opts.version,\n domain: opts.domain,\n license: opts.license ?? '',\n persona: opts.persona,\n purpose: opts.purpose ?? 'unknown',\n compiler: opts.compiler,\n commit: opts.commit,\n capabilities: opts.capabilities ?? [],\n requires: opts.requires ?? [],\n integrity: opts.integrity,\n }\n}\n\nexport function aboutmeToJson(aboutme: AboutMe): string {\n return JSON.stringify(aboutme, null, 2)\n}\n","// SPDX-License-Identifier: Apache-2.0\n\nimport type { IdParts } from './types.js'\n\n// Code hosting platforms whose namespace format is platform/user rather than plain domain.\n// The list is maintained by the compiler and updated via CLI releases.\nexport const KNOWN_PLATFORMS = ['github.com', 'gitlab.com', 'codeberg.org', 'sr.ht'] as const\n\nfunction parseNamespaceName(identifier: string): { namespace: string; name: string } {\n // Email namespace: @ appears before any /\n const atIdx = identifier.indexOf('@')\n if (atIdx !== -1 && (identifier.indexOf('/') === -1 || atIdx < identifier.indexOf('/'))) {\n const slashIdx = identifier.indexOf('/')\n if (slashIdx === -1) {\n throw new Error(`Invalid agent ID: email namespace requires a name after '/' (got '${identifier}')`)\n }\n return {\n namespace: identifier.slice(0, slashIdx),\n name: identifier.slice(slashIdx + 1),\n }\n }\n\n // Known code-hosting platforms: namespace is platform/user, name is the next segment.\n for (const platform of KNOWN_PLATFORMS) {\n if (identifier.startsWith(platform + '/')) {\n const afterPlatform = identifier.slice(platform.length + 1)\n const slashIdx = afterPlatform.indexOf('/')\n if (slashIdx === -1) {\n throw new Error(\n `Invalid agent ID: '${platform}' namespace requires a user segment and a name (got '${identifier}')`,\n )\n }\n return {\n namespace: platform + '/' + afterPlatform.slice(0, slashIdx),\n name: afterPlatform.slice(slashIdx + 1),\n }\n }\n }\n\n // Domain or reserved keyword (e.g. 'unknown'): last '/' separates namespace from name.\n const lastSlash = identifier.lastIndexOf('/')\n if (lastSlash === -1) {\n throw new Error(`Invalid agent ID: missing '/' separator in '${identifier}'`)\n }\n return {\n namespace: identifier.slice(0, lastSlash),\n name: identifier.slice(lastSlash + 1),\n }\n}\n\nexport function parseId(id: string): IdParts {\n if (!id) throw new Error('Invalid agent ID: empty string')\n\n // Phase 1: split on the first ':' to isolate the identifier from version~digest.\n const colonIdx = id.indexOf(':')\n\n let identifier: string\n let version: string | undefined\n let digest: string | undefined\n\n if (colonIdx === -1) {\n // Form A: namespace/name\n identifier = id\n } else {\n identifier = id.slice(0, colonIdx)\n const rest = id.slice(colonIdx + 1)\n if (!rest) throw new Error(`Invalid agent ID: empty version after ':' in '${id}'`)\n\n // Phase 2: split version~digest\n const tildeIdx = rest.indexOf('~')\n if (tildeIdx === -1) {\n // Form B: namespace/name:version\n version = rest\n } else {\n // Form D: namespace/name:version~digest\n version = rest.slice(0, tildeIdx)\n digest = rest.slice(tildeIdx + 1)\n if (!version) throw new Error(`Invalid agent ID: empty version before '~' in '${id}'`)\n if (!digest) throw new Error(`Invalid agent ID: empty digest after '~' in '${id}'`)\n }\n }\n\n // Phase 3: extract namespace and name from the identifier\n const { namespace, name } = parseNamespaceName(identifier)\n\n if (!namespace) throw new Error(`Invalid agent ID: empty namespace in '${id}'`)\n if (!name) throw new Error(`Invalid agent ID: empty name in '${id}'`)\n\n return { namespace, name, version, digest }\n}\n\nexport function buildId(parts: IdParts): string {\n const { namespace, name, version, digest } = parts\n if (!namespace || !name) {\n throw new Error('Missing required ID parts: namespace and name')\n }\n if (digest && !version) {\n throw new Error('Invalid ID parts: digest requires version')\n }\n let result = `${namespace}/${name}`\n if (version) {\n result += `:${version}`\n if (digest) result += `~${digest}`\n }\n // Ids are always lowercase — domains, platform usernames (GitHub/GitLab/\n // Codeberg/Sourcehut) and email local-parts are all case-insensitive in\n // practice, so normalizing here is safe and gives every id a single shape.\n return result.toLowerCase()\n}\n\n// Turns a human display name (e.g. \"Fridge Assistant\", from `agent Fridge\n// Assistant` in the DSL — spaces/capitalization are deliberate there) into\n// the kebab-case slug used for an id's name segment.\nexport function slugify(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n}\n\n// Accepts optional leading 'v' (id spec examples use it; monorepo tags after\n// their '@' split don't), 1-3 dot-separated numeric groups, and optional\n// -prerelease / +build suffixes — e.g. v1.0, 2.3.1, v1.0.0-alpha.1, 1.0+build.\nconst VERSION_RE = /^v?\\d+(\\.\\d+){0,2}(-[0-9A-Za-z.]+)?(\\+[0-9A-Za-z.]+)?$/i\n\nexport function isValidVersion(version: string): boolean {\n return VERSION_RE.test(version)\n}\n\nexport function extractDigest(id: string): string {\n try {\n return parseId(id).digest ?? ''\n } catch {\n return ''\n }\n}\n\nexport function extractName(id: string): string {\n try {\n return parseId(id).name\n } catch {\n return ''\n }\n}\n","// SPDX-License-Identifier: Apache-2.0\n\nimport JSZip from 'jszip'\n\nexport const MAX_ZIP_SIZE = 500 * 1024 * 1024\nexport const MAX_COMPRESSION_RATIO = 100\n\nexport function validateMagicBytes(bytes: Uint8Array): void {\n if (!(bytes[0] === 0x50 && bytes[1] === 0x4b && bytes[2] === 0x03 && bytes[3] === 0x04)) {\n throw new Error('Not a valid .agent file (invalid magic bytes)')\n }\n}\n\nexport function validateZipBomb(zip: JSZip, compressedSize: number): void {\n let totalUncompressed = 0\n zip.forEach((_path, file) => {\n if (!file.dir) totalUncompressed += (file as any)._data?.uncompressedSize || 0\n })\n if (totalUncompressed > MAX_ZIP_SIZE) {\n throw new Error(`Bundle exceeds 500MB uncompressed: ${totalUncompressed}`)\n }\n if (totalUncompressed / compressedSize > MAX_COMPRESSION_RATIO) {\n throw new Error(`Compression ratio exceeds 100x: ${(totalUncompressed / compressedSize).toFixed(1)}x`)\n }\n}\n\nexport function createZip(): JSZip {\n return new JSZip()\n}\n\nexport async function extractFiles(zip: JSZip, filter?: string[]): Promise<Map<string, string>> {\n const files = new Map<string, string>()\n const promises: Promise<void>[] = []\n\n zip.forEach((relativePath, file) => {\n if (file.dir) return\n if (filter && !filter.some(f => relativePath.startsWith(f))) return\n promises.push(\n file.async('text').then(content => {\n files.set(relativePath, content)\n })\n )\n })\n\n await Promise.all(promises)\n return files\n}\n","// SPDX-License-Identifier: Apache-2.0\n\n// The two directories the runtime can actually serve content from: pack.ts's\n// collectFiles() bundles a guide/teach reference at its literal path, but\n// bundle.ts, sdk/load.ts, and the CLI's MCP resource handlers each classify a\n// bundled file into guides/knowledge purely by this prefix — a reference\n// resolving outside them is refused at pack time (see pack.ts's E022) rather\n// than bundled unreachable.\n// Single source of truth so the three sites can't drift on the prefix list.\nexport const CONTENT_NAMESPACES = ['guides', 'knowledge'] as const\nexport type ContentNamespace = (typeof CONTENT_NAMESPACES)[number]\n\nexport function isInContentNamespace(bundlePath: string): boolean {\n return classifyContentPath(bundlePath) !== null\n}\n\nexport function classifyContentPath(bundlePath: string): ContentNamespace | null {\n return CONTENT_NAMESPACES.find(ns => bundlePath.startsWith(`${ns}/`)) ?? null\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"namespace-DsoVSANe.d.cts","names":[],"sources":["../src/types.ts","../src/manifest.ts","../src/id.ts","../src/zip-core.ts","../src/namespace.ts"],"mappings":";;;KAQY;;UAiCK;EACf;EACA;EACA;EACA;;EAEA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;;UAGe;EACf;EACA;;UAGe;EACf;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,cAAc;EACd,UAAU;EACV,WAAW;;UAGI;EACf;EACA;EACA;EACA,QAAQ;IAAQ;IAAc;;EAC9B,WAAW;IAAQ;IAAc;;EACjC,WAAW;IAAQ;IAAc;;;UAGlB;EACf;EACA,SAAS;EACT,OAAO;;UAGQ;EACf;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA,UAAU;;UAGK;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,eAAe;EACf,WAAW;EACX,WAAW;;;;iBC/HG,aAAa,YAAY;iBA6BzB,aAAa,MAAM,sBAAsB;iBAmBzC,cAAc,SAAS;;;iBCGvB,QAAQ,aAAa;iBAyCrB,QAAQ,OAAO;iBAsCf,cAAc;iBAQd,YAAY;;;iBClIZ,mBAAmB,OAAO;iBAM1B,gBAAgB,KAAK,OAAO;iBAa5B,aAAa;iBAIP,aAAa,KAAK,OAAO,oBAAoB,QAAQ;;;cC5B9D;KACD,2BAA2B;iBAEvB,qBAAqB;iBAIrB,oBAAoB,qBAAqB"}
1
+ {"version":3,"file":"namespace-DsoVSANe.d.cts","names":[],"sources":["../src/types.ts","../src/manifest.ts","../src/id.ts","../src/zip-core.ts","../src/namespace.ts"],"mappings":";;;KAEY;;UAiCK;EACf;EACA;EACA;EACA;;EAEA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;;UAGe;EACf;EACA;;UAGe;EACf;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,cAAc;EACd,UAAU;EACV,WAAW;;UAGI;EACf;EACA;EACA;EACA,QAAQ;IAAQ;IAAc;;EAC9B,WAAW;IAAQ;IAAc;;EACjC,WAAW;IAAQ;IAAc;;;UAGlB;EACf;EACA,SAAS;EACT,OAAO;;UAGQ;EACf;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA,UAAU;;UAGK;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,eAAe;EACf,WAAW;EACX,WAAW;;;;iBC/HG,aAAa,YAAY;iBA6BzB,aAAa,MAAM,sBAAsB;iBAmBzC,cAAc,SAAS;;;iBCHvB,QAAQ,aAAa;iBAyCrB,QAAQ,OAAO;iBAsCf,cAAc;iBAQd,YAAY;;;iBClIZ,mBAAmB,OAAO;iBAM1B,gBAAgB,KAAK,OAAO;iBAa5B,aAAa;iBAIP,aAAa,KAAK,OAAO,oBAAoB,QAAQ;;;cCrB9D;KACD,2BAA2B;iBAEvB,qBAAqB;iBAIrB,oBAAoB,qBAAqB"}
@@ -1 +1 @@
1
- {"version":3,"file":"namespace-DsoVSANe.d.mts","names":[],"sources":["../src/types.ts","../src/manifest.ts","../src/id.ts","../src/zip-core.ts","../src/namespace.ts"],"mappings":";;;KAQY;;UAiCK;EACf;EACA;EACA;EACA;;EAEA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;;UAGe;EACf;EACA;;UAGe;EACf;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,cAAc;EACd,UAAU;EACV,WAAW;;UAGI;EACf;EACA;EACA;EACA,QAAQ;IAAQ;IAAc;;EAC9B,WAAW;IAAQ;IAAc;;EACjC,WAAW;IAAQ;IAAc;;;UAGlB;EACf;EACA,SAAS;EACT,OAAO;;UAGQ;EACf;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA,UAAU;;UAGK;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,eAAe;EACf,WAAW;EACX,WAAW;;;;iBC/HG,aAAa,YAAY;iBA6BzB,aAAa,MAAM,sBAAsB;iBAmBzC,cAAc,SAAS;;;iBCGvB,QAAQ,aAAa;iBAyCrB,QAAQ,OAAO;iBAsCf,cAAc;iBAQd,YAAY;;;iBClIZ,mBAAmB,OAAO;iBAM1B,gBAAgB,KAAK,OAAO;iBAa5B,aAAa;iBAIP,aAAa,KAAK,OAAO,oBAAoB,QAAQ;;;cC5B9D;KACD,2BAA2B;iBAEvB,qBAAqB;iBAIrB,oBAAoB,qBAAqB"}
1
+ {"version":3,"file":"namespace-DsoVSANe.d.mts","names":[],"sources":["../src/types.ts","../src/manifest.ts","../src/id.ts","../src/zip-core.ts","../src/namespace.ts"],"mappings":";;;KAEY;;UAiCK;EACf;EACA;EACA;EACA;;EAEA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;;UAGe;EACf;EACA;;UAGe;EACf;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,cAAc;EACd,UAAU;EACV,WAAW;;UAGI;EACf;EACA;EACA;EACA,QAAQ;IAAQ;IAAc;;EAC9B,WAAW;IAAQ;IAAc;;EACjC,WAAW;IAAQ;IAAc;;;UAGlB;EACf;EACA,SAAS;EACT,OAAO;;UAGQ;EACf;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA,UAAU;;UAGK;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,eAAe;EACf,WAAW;EACX,WAAW;;;;iBC/HG,aAAa,YAAY;iBA6BzB,aAAa,MAAM,sBAAsB;iBAmBzC,cAAc,SAAS;;;iBCHvB,QAAQ,aAAa;iBAyCrB,QAAQ,OAAO;iBAsCf,cAAc;iBAQd,YAAY;;;iBClIZ,mBAAmB,OAAO;iBAM1B,gBAAgB,KAAK,OAAO;iBAa5B,aAAa;iBAIP,aAAa,KAAK,OAAO,oBAAoB,QAAQ;;;cCrB9D;KACD,2BAA2B;iBAEvB,qBAAqB;iBAIrB,oBAAoB,qBAAqB"}
@@ -1,6 +1,6 @@
1
1
  import JSZip from "jszip";
2
2
  //#region src/generated-version.ts
3
- const COMPILER_VERSION = "0.10.2";
3
+ const COMPILER_VERSION = "0.12.0-beta.1";
4
4
  //#endregion
5
5
  //#region src/manifest.ts
6
6
  function parseAboutme(json) {
@@ -186,4 +186,4 @@ function classifyContentPath(bundlePath) {
186
186
  //#endregion
187
187
  export { COMPILER_VERSION as _, extractFiles as a, buildId as c, isValidVersion as d, parseId as f, parseAboutme as g, buildAboutme as h, createZip as i, extractDigest as l, aboutmeToJson as m, classifyContentPath as n, validateMagicBytes as o, slugify as p, isInContentNamespace as r, validateZipBomb as s, CONTENT_NAMESPACES as t, extractName as u };
188
188
 
189
- //# sourceMappingURL=namespace-CjeG5-7u.mjs.map
189
+ //# sourceMappingURL=namespace-oeoFrzmu.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"namespace-oeoFrzmu.mjs","names":[],"sources":["../src/generated-version.ts","../src/manifest.ts","../src/id.ts","../src/zip-core.ts","../src/namespace.ts"],"sourcesContent":["// Generated by scripts/embed-version.mjs from dsl/VERSION and package.json — do not edit by hand.\nexport const DSL_VERSION = '0.1'\nexport const COMPILER_VERSION = '0.12.0-beta.1'\n","// SPDX-License-Identifier: Apache-2.0\n\nimport type { AboutMe, BuildAboutmeOptions } from './types.js'\nimport { DSL_VERSION } from './generated-version.js'\n\nexport function parseAboutme(json: any): AboutMe {\n if (!json.dslVersion) throw new Error('Missing dslVersion in aboutme.json')\n if (!json.id) throw new Error('Missing id in aboutme.json')\n if (!json.name) throw new Error('Missing name in aboutme.json')\n if (!json.description) throw new Error('Missing description in aboutme.json')\n if (!json.domain) throw new Error('Missing domain in aboutme.json')\n if (!json.compiler) throw new Error('Missing compiler in aboutme.json')\n if (!Array.isArray(json.capabilities)) throw new Error('Missing capabilities array in aboutme.json')\n if (!Array.isArray(json.requires)) throw new Error('Missing requires array in aboutme.json')\n if (!json.integrity) throw new Error('Missing integrity in aboutme.json')\n\n return {\n dslVersion: json.dslVersion,\n id: json.id,\n name: json.name,\n description: json.description,\n version: json.version ?? '',\n domain: json.domain,\n license: json.license ?? '',\n persona: json.persona,\n purpose: json.purpose ?? 'unknown',\n compiler: json.compiler,\n commit: json.commit,\n capabilities: json.capabilities,\n requires: json.requires,\n integrity: json.integrity,\n }\n}\n\nexport function buildAboutme(opts: BuildAboutmeOptions): AboutMe {\n return {\n dslVersion: `dot-agent/${DSL_VERSION}`,\n id: opts.id,\n name: opts.name,\n description: opts.description,\n version: opts.version,\n domain: opts.domain,\n license: opts.license ?? '',\n persona: opts.persona,\n purpose: opts.purpose ?? 'unknown',\n compiler: opts.compiler,\n commit: opts.commit,\n capabilities: opts.capabilities ?? [],\n requires: opts.requires ?? [],\n integrity: opts.integrity,\n }\n}\n\nexport function aboutmeToJson(aboutme: AboutMe): string {\n return JSON.stringify(aboutme, null, 2)\n}\n","// SPDX-License-Identifier: Apache-2.0\n\nimport type { IdParts } from './types.js'\n\n// Code hosting platforms whose namespace format is platform/user rather than plain domain.\n// The list is maintained by the compiler and updated via CLI releases.\nexport const KNOWN_PLATFORMS = ['github.com', 'gitlab.com', 'codeberg.org', 'sr.ht'] as const\n\nfunction parseNamespaceName(identifier: string): { namespace: string; name: string } {\n // Email namespace: @ appears before any /\n const atIdx = identifier.indexOf('@')\n if (atIdx !== -1 && (identifier.indexOf('/') === -1 || atIdx < identifier.indexOf('/'))) {\n const slashIdx = identifier.indexOf('/')\n if (slashIdx === -1) {\n throw new Error(`Invalid agent ID: email namespace requires a name after '/' (got '${identifier}')`)\n }\n return {\n namespace: identifier.slice(0, slashIdx),\n name: identifier.slice(slashIdx + 1),\n }\n }\n\n // Known code-hosting platforms: namespace is platform/user, name is the next segment.\n for (const platform of KNOWN_PLATFORMS) {\n if (identifier.startsWith(platform + '/')) {\n const afterPlatform = identifier.slice(platform.length + 1)\n const slashIdx = afterPlatform.indexOf('/')\n if (slashIdx === -1) {\n throw new Error(\n `Invalid agent ID: '${platform}' namespace requires a user segment and a name (got '${identifier}')`,\n )\n }\n return {\n namespace: platform + '/' + afterPlatform.slice(0, slashIdx),\n name: afterPlatform.slice(slashIdx + 1),\n }\n }\n }\n\n // Domain or reserved keyword (e.g. 'unknown'): last '/' separates namespace from name.\n const lastSlash = identifier.lastIndexOf('/')\n if (lastSlash === -1) {\n throw new Error(`Invalid agent ID: missing '/' separator in '${identifier}'`)\n }\n return {\n namespace: identifier.slice(0, lastSlash),\n name: identifier.slice(lastSlash + 1),\n }\n}\n\nexport function parseId(id: string): IdParts {\n if (!id) throw new Error('Invalid agent ID: empty string')\n\n // Phase 1: split on the first ':' to isolate the identifier from version~digest.\n const colonIdx = id.indexOf(':')\n\n let identifier: string\n let version: string | undefined\n let digest: string | undefined\n\n if (colonIdx === -1) {\n // Form A: namespace/name\n identifier = id\n } else {\n identifier = id.slice(0, colonIdx)\n const rest = id.slice(colonIdx + 1)\n if (!rest) throw new Error(`Invalid agent ID: empty version after ':' in '${id}'`)\n\n // Phase 2: split version~digest\n const tildeIdx = rest.indexOf('~')\n if (tildeIdx === -1) {\n // Form B: namespace/name:version\n version = rest\n } else {\n // Form D: namespace/name:version~digest\n version = rest.slice(0, tildeIdx)\n digest = rest.slice(tildeIdx + 1)\n if (!version) throw new Error(`Invalid agent ID: empty version before '~' in '${id}'`)\n if (!digest) throw new Error(`Invalid agent ID: empty digest after '~' in '${id}'`)\n }\n }\n\n // Phase 3: extract namespace and name from the identifier\n const { namespace, name } = parseNamespaceName(identifier)\n\n if (!namespace) throw new Error(`Invalid agent ID: empty namespace in '${id}'`)\n if (!name) throw new Error(`Invalid agent ID: empty name in '${id}'`)\n\n return { namespace, name, version, digest }\n}\n\nexport function buildId(parts: IdParts): string {\n const { namespace, name, version, digest } = parts\n if (!namespace || !name) {\n throw new Error('Missing required ID parts: namespace and name')\n }\n if (digest && !version) {\n throw new Error('Invalid ID parts: digest requires version')\n }\n let result = `${namespace}/${name}`\n if (version) {\n result += `:${version}`\n if (digest) result += `~${digest}`\n }\n // Ids are always lowercase — domains, platform usernames (GitHub/GitLab/\n // Codeberg/Sourcehut) and email local-parts are all case-insensitive in\n // practice, so normalizing here is safe and gives every id a single shape.\n return result.toLowerCase()\n}\n\n// Turns a human display name (e.g. \"Fridge Assistant\", from `agent Fridge\n// Assistant` in the DSL — spaces/capitalization are deliberate there) into\n// the kebab-case slug used for an id's name segment.\nexport function slugify(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n}\n\n// Accepts optional leading 'v' (id spec examples use it; monorepo tags after\n// their '@' split don't), 1-3 dot-separated numeric groups, and optional\n// -prerelease / +build suffixes — e.g. v1.0, 2.3.1, v1.0.0-alpha.1, 1.0+build.\nconst VERSION_RE = /^v?\\d+(\\.\\d+){0,2}(-[0-9A-Za-z.]+)?(\\+[0-9A-Za-z.]+)?$/i\n\nexport function isValidVersion(version: string): boolean {\n return VERSION_RE.test(version)\n}\n\nexport function extractDigest(id: string): string {\n try {\n return parseId(id).digest ?? ''\n } catch {\n return ''\n }\n}\n\nexport function extractName(id: string): string {\n try {\n return parseId(id).name\n } catch {\n return ''\n }\n}\n","// SPDX-License-Identifier: Apache-2.0\n\nimport JSZip from 'jszip'\n\nexport const MAX_ZIP_SIZE = 500 * 1024 * 1024\nexport const MAX_COMPRESSION_RATIO = 100\n\nexport function validateMagicBytes(bytes: Uint8Array): void {\n if (!(bytes[0] === 0x50 && bytes[1] === 0x4b && bytes[2] === 0x03 && bytes[3] === 0x04)) {\n throw new Error('Not a valid .agent file (invalid magic bytes)')\n }\n}\n\nexport function validateZipBomb(zip: JSZip, compressedSize: number): void {\n let totalUncompressed = 0\n zip.forEach((_path, file) => {\n if (!file.dir) totalUncompressed += (file as any)._data?.uncompressedSize || 0\n })\n if (totalUncompressed > MAX_ZIP_SIZE) {\n throw new Error(`Bundle exceeds 500MB uncompressed: ${totalUncompressed}`)\n }\n if (totalUncompressed / compressedSize > MAX_COMPRESSION_RATIO) {\n throw new Error(`Compression ratio exceeds 100x: ${(totalUncompressed / compressedSize).toFixed(1)}x`)\n }\n}\n\nexport function createZip(): JSZip {\n return new JSZip()\n}\n\nexport async function extractFiles(zip: JSZip, filter?: string[]): Promise<Map<string, string>> {\n const files = new Map<string, string>()\n const promises: Promise<void>[] = []\n\n zip.forEach((relativePath, file) => {\n if (file.dir) return\n if (filter && !filter.some(f => relativePath.startsWith(f))) return\n promises.push(\n file.async('text').then(content => {\n files.set(relativePath, content)\n })\n )\n })\n\n await Promise.all(promises)\n return files\n}\n","// SPDX-License-Identifier: Apache-2.0\n\n// The two directories the runtime can actually serve content from: pack.ts's\n// collectFiles() bundles a guide/teach reference at its literal path, but\n// bundle.ts, sdk/load.ts, and the CLI's MCP resource handlers each classify a\n// bundled file into guides/knowledge purely by this prefix — a reference\n// resolving outside them is refused at pack time (see pack.ts's E022) rather\n// than bundled unreachable.\n// Single source of truth so the three sites can't drift on the prefix list.\nexport const CONTENT_NAMESPACES = ['guides', 'knowledge'] as const\nexport type ContentNamespace = (typeof CONTENT_NAMESPACES)[number]\n\nexport function isInContentNamespace(bundlePath: string): boolean {\n return classifyContentPath(bundlePath) !== null\n}\n\nexport function classifyContentPath(bundlePath: string): ContentNamespace | null {\n return CONTENT_NAMESPACES.find(ns => bundlePath.startsWith(`${ns}/`)) ?? null\n}\n"],"mappings":";;AAEA,MAAa,mBAAmB;;;ACGhC,SAAgB,aAAa,MAAoB;CAC/C,IAAI,CAAC,KAAK,YAAY,MAAM,IAAI,MAAM,oCAAoC;CAC1E,IAAI,CAAC,KAAK,IAAI,MAAM,IAAI,MAAM,4BAA4B;CAC1D,IAAI,CAAC,KAAK,MAAM,MAAM,IAAI,MAAM,8BAA8B;CAC9D,IAAI,CAAC,KAAK,aAAa,MAAM,IAAI,MAAM,qCAAqC;CAC5E,IAAI,CAAC,KAAK,QAAQ,MAAM,IAAI,MAAM,gCAAgC;CAClE,IAAI,CAAC,KAAK,UAAU,MAAM,IAAI,MAAM,kCAAkC;CACtE,IAAI,CAAC,MAAM,QAAQ,KAAK,YAAY,GAAG,MAAM,IAAI,MAAM,4CAA4C;CACnG,IAAI,CAAC,MAAM,QAAQ,KAAK,QAAQ,GAAG,MAAM,IAAI,MAAM,wCAAwC;CAC3F,IAAI,CAAC,KAAK,WAAW,MAAM,IAAI,MAAM,mCAAmC;CAExE,OAAO;EACL,YAAY,KAAK;EACjB,IAAI,KAAK;EACT,MAAM,KAAK;EACX,aAAa,KAAK;EAClB,SAAS,KAAK,WAAW;EACzB,QAAQ,KAAK;EACb,SAAS,KAAK,WAAW;EACzB,SAAS,KAAK;EACd,SAAS,KAAK,WAAW;EACzB,UAAU,KAAK;EACf,QAAQ,KAAK;EACb,cAAc,KAAK;EACnB,UAAU,KAAK;EACf,WAAW,KAAK;CAClB;AACF;AAEA,SAAgB,aAAa,MAAoC;CAC/D,OAAO;EACL,YAAY;EACZ,IAAI,KAAK;EACT,MAAM,KAAK;EACX,aAAa,KAAK;EAClB,SAAS,KAAK;EACd,QAAQ,KAAK;EACb,SAAS,KAAK,WAAW;EACzB,SAAS,KAAK;EACd,SAAS,KAAK,WAAW;EACzB,UAAU,KAAK;EACf,QAAQ,KAAK;EACb,cAAc,KAAK,gBAAgB,CAAC;EACpC,UAAU,KAAK,YAAY,CAAC;EAC5B,WAAW,KAAK;CAClB;AACF;AAEA,SAAgB,cAAc,SAA0B;CACtD,OAAO,KAAK,UAAU,SAAS,MAAM,CAAC;AACxC;;;ACjDA,MAAa,kBAAkB;CAAC;CAAc;CAAc;CAAgB;AAAO;AAEnF,SAAS,mBAAmB,YAAyD;CAEnF,MAAM,QAAQ,WAAW,QAAQ,GAAG;CACpC,IAAI,UAAU,OAAO,WAAW,QAAQ,GAAG,MAAM,MAAM,QAAQ,WAAW,QAAQ,GAAG,IAAI;EACvF,MAAM,WAAW,WAAW,QAAQ,GAAG;EACvC,IAAI,aAAa,IACf,MAAM,IAAI,MAAM,qEAAqE,WAAW,GAAG;EAErG,OAAO;GACL,WAAW,WAAW,MAAM,GAAG,QAAQ;GACvC,MAAM,WAAW,MAAM,WAAW,CAAC;EACrC;CACF;CAGA,KAAK,MAAM,YAAY,iBACrB,IAAI,WAAW,WAAW,WAAW,GAAG,GAAG;EACzC,MAAM,gBAAgB,WAAW,MAAM,SAAS,SAAS,CAAC;EAC1D,MAAM,WAAW,cAAc,QAAQ,GAAG;EAC1C,IAAI,aAAa,IACf,MAAM,IAAI,MACR,sBAAsB,SAAS,uDAAuD,WAAW,GACnG;EAEF,OAAO;GACL,WAAW,WAAW,MAAM,cAAc,MAAM,GAAG,QAAQ;GAC3D,MAAM,cAAc,MAAM,WAAW,CAAC;EACxC;CACF;CAIF,MAAM,YAAY,WAAW,YAAY,GAAG;CAC5C,IAAI,cAAc,IAChB,MAAM,IAAI,MAAM,+CAA+C,WAAW,EAAE;CAE9E,OAAO;EACL,WAAW,WAAW,MAAM,GAAG,SAAS;EACxC,MAAM,WAAW,MAAM,YAAY,CAAC;CACtC;AACF;AAEA,SAAgB,QAAQ,IAAqB;CAC3C,IAAI,CAAC,IAAI,MAAM,IAAI,MAAM,gCAAgC;CAGzD,MAAM,WAAW,GAAG,QAAQ,GAAG;CAE/B,IAAI;CACJ,IAAI;CACJ,IAAI;CAEJ,IAAI,aAAa,IAEf,aAAa;MACR;EACL,aAAa,GAAG,MAAM,GAAG,QAAQ;EACjC,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC;EAClC,IAAI,CAAC,MAAM,MAAM,IAAI,MAAM,iDAAiD,GAAG,EAAE;EAGjF,MAAM,WAAW,KAAK,QAAQ,GAAG;EACjC,IAAI,aAAa,IAEf,UAAU;OACL;GAEL,UAAU,KAAK,MAAM,GAAG,QAAQ;GAChC,SAAS,KAAK,MAAM,WAAW,CAAC;GAChC,IAAI,CAAC,SAAS,MAAM,IAAI,MAAM,kDAAkD,GAAG,EAAE;GACrF,IAAI,CAAC,QAAQ,MAAM,IAAI,MAAM,gDAAgD,GAAG,EAAE;EACpF;CACF;CAGA,MAAM,EAAE,WAAW,SAAS,mBAAmB,UAAU;CAEzD,IAAI,CAAC,WAAW,MAAM,IAAI,MAAM,yCAAyC,GAAG,EAAE;CAC9E,IAAI,CAAC,MAAM,MAAM,IAAI,MAAM,oCAAoC,GAAG,EAAE;CAEpE,OAAO;EAAE;EAAW;EAAM;EAAS;CAAO;AAC5C;AAEA,SAAgB,QAAQ,OAAwB;CAC9C,MAAM,EAAE,WAAW,MAAM,SAAS,WAAW;CAC7C,IAAI,CAAC,aAAa,CAAC,MACjB,MAAM,IAAI,MAAM,+CAA+C;CAEjE,IAAI,UAAU,CAAC,SACb,MAAM,IAAI,MAAM,2CAA2C;CAE7D,IAAI,SAAS,GAAG,UAAU,GAAG;CAC7B,IAAI,SAAS;EACX,UAAU,IAAI;EACd,IAAI,QAAQ,UAAU,IAAI;CAC5B;CAIA,OAAO,OAAO,YAAY;AAC5B;AAKA,SAAgB,QAAQ,MAAsB;CAC5C,OAAO,KACJ,YAAY,CAAC,CACb,QAAQ,eAAe,GAAG,CAAC,CAC3B,QAAQ,YAAY,EAAE;AAC3B;AAKA,MAAM,aAAa;AAEnB,SAAgB,eAAe,SAA0B;CACvD,OAAO,WAAW,KAAK,OAAO;AAChC;AAEA,SAAgB,cAAc,IAAoB;CAChD,IAAI;EACF,OAAO,QAAQ,EAAE,CAAC,CAAC,UAAU;CAC/B,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAgB,YAAY,IAAoB;CAC9C,IAAI;EACF,OAAO,QAAQ,EAAE,CAAC,CAAC;CACrB,QAAQ;EACN,OAAO;CACT;AACF;ACxIA,SAAgB,mBAAmB,OAAyB;CAC1D,IAAI,EAAE,MAAM,OAAO,MAAQ,MAAM,OAAO,MAAQ,MAAM,OAAO,KAAQ,MAAM,OAAO,IAChF,MAAM,IAAI,MAAM,+CAA+C;AAEnE;AAEA,SAAgB,gBAAgB,KAAY,gBAA8B;CACxE,IAAI,oBAAoB;CACxB,IAAI,SAAS,OAAO,SAAS;EAC3B,IAAI,CAAC,KAAK,KAAK,qBAAsB,KAAa,OAAO,oBAAoB;CAC/E,CAAC;CACD,IAAI,oBAAA,UACF,MAAM,IAAI,MAAM,sCAAsC,mBAAmB;CAE3E,IAAI,oBAAoB,iBAAA,KACtB,MAAM,IAAI,MAAM,oCAAoC,oBAAoB,eAAA,CAAgB,QAAQ,CAAC,EAAE,EAAE;AAEzG;AAEA,SAAgB,YAAmB;CACjC,OAAO,IAAI,MAAM;AACnB;AAEA,eAAsB,aAAa,KAAY,QAAiD;CAC9F,MAAM,wBAAQ,IAAI,IAAoB;CACtC,MAAM,WAA4B,CAAC;CAEnC,IAAI,SAAS,cAAc,SAAS;EAClC,IAAI,KAAK,KAAK;EACd,IAAI,UAAU,CAAC,OAAO,MAAK,MAAK,aAAa,WAAW,CAAC,CAAC,GAAG;EAC7D,SAAS,KACP,KAAK,MAAM,MAAM,CAAC,CAAC,MAAK,YAAW;GACjC,MAAM,IAAI,cAAc,OAAO;EACjC,CAAC,CACH;CACF,CAAC;CAED,MAAM,QAAQ,IAAI,QAAQ;CAC1B,OAAO;AACT;;;ACrCA,MAAa,qBAAqB,CAAC,UAAU,WAAW;AAGxD,SAAgB,qBAAqB,YAA6B;CAChE,OAAO,oBAAoB,UAAU,MAAM;AAC7C;AAEA,SAAgB,oBAAoB,YAA6C;CAC/E,OAAO,mBAAmB,MAAK,OAAM,WAAW,WAAW,GAAG,GAAG,EAAE,CAAC,KAAK;AAC3E"}