@agimon-ai/doompi-domain 0.0.1-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +73 -0
  3. package/dist/_virtual/_rolldown/runtime.cjs +1 -0
  4. package/dist/adapters/applyDomains.cjs +2 -0
  5. package/dist/adapters/applyDomains.cjs.map +1 -0
  6. package/dist/adapters/applyDomains.d.cts +24 -0
  7. package/dist/adapters/applyDomains.d.cts.map +1 -0
  8. package/dist/adapters/applyDomains.d.mts +24 -0
  9. package/dist/adapters/applyDomains.d.mts.map +1 -0
  10. package/dist/adapters/applyDomains.mjs +2 -0
  11. package/dist/adapters/applyDomains.mjs.map +1 -0
  12. package/dist/adapters/domainCatalog.cjs +2 -0
  13. package/dist/adapters/domainCatalog.cjs.map +1 -0
  14. package/dist/adapters/domainCatalog.d.cts +20 -0
  15. package/dist/adapters/domainCatalog.d.cts.map +1 -0
  16. package/dist/adapters/domainCatalog.d.mts +20 -0
  17. package/dist/adapters/domainCatalog.d.mts.map +1 -0
  18. package/dist/adapters/domainCatalog.mjs +2 -0
  19. package/dist/adapters/domainCatalog.mjs.map +1 -0
  20. package/dist/adapters/domainSwitchHandoff.cjs +2 -0
  21. package/dist/adapters/domainSwitchHandoff.cjs.map +1 -0
  22. package/dist/adapters/domainSwitchHandoff.d.cts +10 -0
  23. package/dist/adapters/domainSwitchHandoff.d.cts.map +1 -0
  24. package/dist/adapters/domainSwitchHandoff.d.mts +10 -0
  25. package/dist/adapters/domainSwitchHandoff.d.mts.map +1 -0
  26. package/dist/adapters/domainSwitchHandoff.mjs +2 -0
  27. package/dist/adapters/domainSwitchHandoff.mjs.map +1 -0
  28. package/dist/adapters/mcpFilter.cjs +3 -0
  29. package/dist/adapters/mcpFilter.cjs.map +1 -0
  30. package/dist/adapters/mcpFilter.d.cts +39 -0
  31. package/dist/adapters/mcpFilter.d.cts.map +1 -0
  32. package/dist/adapters/mcpFilter.d.mts +39 -0
  33. package/dist/adapters/mcpFilter.d.mts.map +1 -0
  34. package/dist/adapters/mcpFilter.mjs +3 -0
  35. package/dist/adapters/mcpFilter.mjs.map +1 -0
  36. package/dist/adapters/mcpSessionEnvironment.cjs +2 -0
  37. package/dist/adapters/mcpSessionEnvironment.cjs.map +1 -0
  38. package/dist/adapters/mcpSessionEnvironment.d.cts +14 -0
  39. package/dist/adapters/mcpSessionEnvironment.d.cts.map +1 -0
  40. package/dist/adapters/mcpSessionEnvironment.d.mts +14 -0
  41. package/dist/adapters/mcpSessionEnvironment.d.mts.map +1 -0
  42. package/dist/adapters/mcpSessionEnvironment.mjs +2 -0
  43. package/dist/adapters/mcpSessionEnvironment.mjs.map +1 -0
  44. package/dist/adapters/pi/extension.cjs +2 -0
  45. package/dist/adapters/pi/extension.cjs.map +1 -0
  46. package/dist/adapters/pi/extension.d.cts +13 -0
  47. package/dist/adapters/pi/extension.d.cts.map +1 -0
  48. package/dist/adapters/pi/extension.d.mts +13 -0
  49. package/dist/adapters/pi/extension.d.mts.map +1 -0
  50. package/dist/adapters/pi/extension.mjs +2 -0
  51. package/dist/adapters/pi/extension.mjs.map +1 -0
  52. package/dist/adapters/pi/voiceTool.cjs +2 -0
  53. package/dist/adapters/pi/voiceTool.cjs.map +1 -0
  54. package/dist/adapters/pi/voiceTool.d.cts +16 -0
  55. package/dist/adapters/pi/voiceTool.d.cts.map +1 -0
  56. package/dist/adapters/pi/voiceTool.d.mts +16 -0
  57. package/dist/adapters/pi/voiceTool.d.mts.map +1 -0
  58. package/dist/adapters/pi/voiceTool.mjs +2 -0
  59. package/dist/adapters/pi/voiceTool.mjs.map +1 -0
  60. package/dist/adapters/pluginMaterializer.cjs +2 -0
  61. package/dist/adapters/pluginMaterializer.cjs.map +1 -0
  62. package/dist/adapters/pluginMaterializer.d.cts +14 -0
  63. package/dist/adapters/pluginMaterializer.d.cts.map +1 -0
  64. package/dist/adapters/pluginMaterializer.d.mts +14 -0
  65. package/dist/adapters/pluginMaterializer.d.mts.map +1 -0
  66. package/dist/adapters/pluginMaterializer.mjs +2 -0
  67. package/dist/adapters/pluginMaterializer.mjs.map +1 -0
  68. package/dist/adapters/resourceCollector.cjs +3 -0
  69. package/dist/adapters/resourceCollector.cjs.map +1 -0
  70. package/dist/adapters/resourceCollector.d.cts +25 -0
  71. package/dist/adapters/resourceCollector.d.cts.map +1 -0
  72. package/dist/adapters/resourceCollector.d.mts +25 -0
  73. package/dist/adapters/resourceCollector.d.mts.map +1 -0
  74. package/dist/adapters/resourceCollector.mjs +3 -0
  75. package/dist/adapters/resourceCollector.mjs.map +1 -0
  76. package/dist/adapters/skillCacheLocation.cjs +2 -0
  77. package/dist/adapters/skillCacheLocation.cjs.map +1 -0
  78. package/dist/adapters/skillCacheLocation.d.cts +16 -0
  79. package/dist/adapters/skillCacheLocation.d.cts.map +1 -0
  80. package/dist/adapters/skillCacheLocation.d.mts +16 -0
  81. package/dist/adapters/skillCacheLocation.d.mts.map +1 -0
  82. package/dist/adapters/skillCacheLocation.mjs +2 -0
  83. package/dist/adapters/skillCacheLocation.mjs.map +1 -0
  84. package/dist/adapters/telemetry/logSinkTelemetry.cjs +2 -0
  85. package/dist/adapters/telemetry/logSinkTelemetry.cjs.map +1 -0
  86. package/dist/adapters/telemetry/logSinkTelemetry.d.cts +14 -0
  87. package/dist/adapters/telemetry/logSinkTelemetry.d.cts.map +1 -0
  88. package/dist/adapters/telemetry/logSinkTelemetry.d.mts +14 -0
  89. package/dist/adapters/telemetry/logSinkTelemetry.d.mts.map +1 -0
  90. package/dist/adapters/telemetry/logSinkTelemetry.mjs +2 -0
  91. package/dist/adapters/telemetry/logSinkTelemetry.mjs.map +1 -0
  92. package/dist/apply.cjs +1 -0
  93. package/dist/apply.d.cts +2 -0
  94. package/dist/apply.d.mts +2 -0
  95. package/dist/apply.mjs +1 -0
  96. package/dist/commands/domainsCommand.cjs +2 -0
  97. package/dist/commands/domainsCommand.cjs.map +1 -0
  98. package/dist/commands/domainsCommand.d.cts +24 -0
  99. package/dist/commands/domainsCommand.d.cts.map +1 -0
  100. package/dist/commands/domainsCommand.d.mts +24 -0
  101. package/dist/commands/domainsCommand.d.mts.map +1 -0
  102. package/dist/commands/domainsCommand.mjs +2 -0
  103. package/dist/commands/domainsCommand.mjs.map +1 -0
  104. package/dist/extensions/pi.cjs +1 -0
  105. package/dist/extensions/pi.d.cts +2 -0
  106. package/dist/extensions/pi.d.mts +2 -0
  107. package/dist/extensions/pi.mjs +1 -0
  108. package/dist/index.cjs +1 -0
  109. package/dist/index.d.cts +13 -0
  110. package/dist/index.d.mts +13 -0
  111. package/dist/index.mjs +1 -0
  112. package/dist/mcp.cjs +1 -0
  113. package/dist/mcp.d.cts +3 -0
  114. package/dist/mcp.d.mts +3 -0
  115. package/dist/mcp.mjs +1 -0
  116. package/dist/plugins.cjs +1 -0
  117. package/dist/plugins.d.cts +2 -0
  118. package/dist/plugins.d.mts +2 -0
  119. package/dist/plugins.mjs +1 -0
  120. package/dist/resources.cjs +1 -0
  121. package/dist/resources.d.cts +4 -0
  122. package/dist/resources.d.mts +4 -0
  123. package/dist/resources.mjs +1 -0
  124. package/dist/schemas/domainVoiceTools.cjs +2 -0
  125. package/dist/schemas/domainVoiceTools.cjs.map +1 -0
  126. package/dist/schemas/domainVoiceTools.d.cts +22 -0
  127. package/dist/schemas/domainVoiceTools.d.cts.map +1 -0
  128. package/dist/schemas/domainVoiceTools.d.mts +22 -0
  129. package/dist/schemas/domainVoiceTools.d.mts.map +1 -0
  130. package/dist/schemas/domainVoiceTools.mjs +2 -0
  131. package/dist/schemas/domainVoiceTools.mjs.map +1 -0
  132. package/dist/services/domainText.cjs +2 -0
  133. package/dist/services/domainText.cjs.map +1 -0
  134. package/dist/services/domainText.d.cts +30 -0
  135. package/dist/services/domainText.d.cts.map +1 -0
  136. package/dist/services/domainText.d.mts +30 -0
  137. package/dist/services/domainText.d.mts.map +1 -0
  138. package/dist/services/domainText.mjs +2 -0
  139. package/dist/services/domainText.mjs.map +1 -0
  140. package/dist/services/toolNames.cjs +2 -0
  141. package/dist/services/toolNames.cjs.map +1 -0
  142. package/dist/services/toolNames.d.cts +21 -0
  143. package/dist/services/toolNames.d.cts.map +1 -0
  144. package/dist/services/toolNames.d.mts +21 -0
  145. package/dist/services/toolNames.d.mts.map +1 -0
  146. package/dist/services/toolNames.mjs +2 -0
  147. package/dist/services/toolNames.mjs.map +1 -0
  148. package/dist/types/domains.cjs +2 -0
  149. package/dist/types/domains.cjs.map +1 -0
  150. package/dist/types/domains.d.cts +33 -0
  151. package/dist/types/domains.d.cts.map +1 -0
  152. package/dist/types/domains.d.mts +33 -0
  153. package/dist/types/domains.d.mts.map +1 -0
  154. package/dist/types/domains.mjs +2 -0
  155. package/dist/types/domains.mjs.map +1 -0
  156. package/dist/types/handoff.d.cts +35 -0
  157. package/dist/types/handoff.d.cts.map +1 -0
  158. package/dist/types/handoff.d.mts +35 -0
  159. package/dist/types/handoff.d.mts.map +1 -0
  160. package/dist/types/resources.d.cts +46 -0
  161. package/dist/types/resources.d.cts.map +1 -0
  162. package/dist/types/resources.d.mts +46 -0
  163. package/dist/types/resources.d.mts.map +1 -0
  164. package/dist/types/telemetry.cjs +2 -0
  165. package/dist/types/telemetry.cjs.map +1 -0
  166. package/dist/types/telemetry.d.cts +15 -0
  167. package/dist/types/telemetry.d.cts.map +1 -0
  168. package/dist/types/telemetry.d.mts +15 -0
  169. package/dist/types/telemetry.d.mts.map +1 -0
  170. package/dist/types/telemetry.mjs +2 -0
  171. package/dist/types/telemetry.mjs.map +1 -0
  172. package/llms.txt +7 -0
  173. package/package.json +117 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resourceCollector.mjs","names":[],"sources":["../../src/adapters/resourceCollector.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport type { PluginEntry, PluginSkillDiscovery } from '@agimon-ai/doompi-config/domains';\nimport { parse, stringify } from 'yaml';\nimport { toPiToolName } from '../services/toolNames.ts';\nimport type { HarnessResourceOptions, HarnessResources, JsonObject, NamedResource } from '../types/resources.ts';\nimport type { PluginHookSource } from '@agimon-ai/doompi-config/types';\nimport { applyMcpAllowlist } from './mcpFilter.ts';\nimport { resolveSkillCacheDirectory } from './skillCacheLocation.ts';\n\nexport const DISPATCHER_AGENT_NAME = 'agiflow-dispatcher';\nconst DISPATCHER_TOOLS = ['read', 'grep', 'find', 'ls', 'bash', 'launch_workflow', 'list_workflows'];\nconst SKILL_MANIFEST_VERSION = 2;\nconst SKILL_MANIFEST_HASH_LENGTH = 16;\n\ninterface SkillManifestFile {\n path: string;\n name: string;\n digest: string;\n size: number;\n mtimeMs: number;\n ctimeMs: number;\n}\n\ninterface SkillManifestDirectory {\n path: string;\n mtimeMs: number;\n ctimeMs: number;\n}\n\ninterface SkillManifest {\n version: number;\n root: string;\n discovery: PluginSkillDiscovery;\n files: SkillManifestFile[];\n directories: SkillManifestDirectory[];\n}\n\nfunction splitFrontmatter(content: string): { attributes: JsonObject; body: string } {\n const match = content.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?([\\s\\S]*)$/);\n if (!match) throw new Error('Resource is missing YAML frontmatter');\n return { attributes: parse(match[1]!) as JsonObject, body: match[2] ?? '' };\n}\n\nconst CLAUDE_MODEL_ALIASES: Record<string, string> = {\n sonnet: 'anthropic/claude-sonnet-4-6',\n opus: 'anthropic/claude-opus-4-6',\n haiku: 'anthropic/claude-haiku-4-5',\n};\n\nfunction assertSafeAgentName(name: string): string {\n const trimmed = name.trim();\n if (\n !trimmed ||\n trimmed !== name ||\n trimmed === '.' ||\n trimmed === '..' ||\n trimmed.includes('\\0') ||\n /[\\\\/]/.test(trimmed)\n ) {\n throw new Error(`Unsafe agent name: ${JSON.stringify(name)}`);\n }\n return trimmed;\n}\n\nfunction normalizeClaudeModel(value: unknown): unknown {\n if (typeof value === 'string') return CLAUDE_MODEL_ALIASES[value.toLowerCase()] ?? value;\n if (Array.isArray(value)) return value.map((entry) => normalizeClaudeModel(entry));\n return value;\n}\n\n/** Rewrites a Claude-authored agent definition into the form Pi loads. */\nexport function adaptAgentDefinition(content: string): { name: string; content: string } {\n const { attributes, body } = splitFrontmatter(content);\n const rawName = typeof attributes.name === 'string' ? attributes.name : undefined;\n if (!rawName) throw new Error('Agent definition requires a name');\n const name = assertSafeAgentName(rawName);\n const hasTools = Object.hasOwn(attributes, 'tools');\n const rawTools = Array.isArray(attributes.tools)\n ? attributes.tools.map(String)\n : typeof attributes.tools === 'string'\n ? attributes.tools\n .split(',')\n .map((tool) => tool.trim())\n .filter(Boolean)\n : [];\n const mappedTools = [...new Set(rawTools.map(toPiToolName).filter((tool): tool is string => Boolean(tool)))];\n const converted: JsonObject = {\n ...attributes,\n inheritProjectContext: true,\n inheritSkills: true,\n systemPromptMode: attributes.systemPromptMode ?? 'replace',\n };\n if (hasTools) converted.tools = Array.isArray(attributes.tools) ? mappedTools : mappedTools.join(', ');\n else delete converted.tools;\n if (converted.model !== undefined) converted.model = normalizeClaudeModel(converted.model);\n if (converted.fallbackModels !== undefined) converted.fallbackModels = normalizeClaudeModel(converted.fallbackModels);\n if (converted.memory === 'project' || converted.memory === 'user')\n converted.memory = { scope: converted.memory, path: name };\n else if (\n converted.memory !== undefined &&\n (typeof converted.memory !== 'object' || converted.memory === null || Array.isArray(converted.memory))\n )\n throw new Error('Unsupported memory declaration');\n delete converted.permissionMode;\n return { name, content: `---\\n${stringify(converted).trim()}\\n---\\n\\n${body.trimStart()}` };\n}\n\nfunction skillManifestPath(\n repoRoot: string,\n skillRoot: string,\n discovery: PluginSkillDiscovery,\n cacheDirectory?: string,\n): string {\n const key = createHash('sha256')\n .update(`${path.resolve(skillRoot)}\\0${discovery}`)\n .digest('hex')\n .slice(0, SKILL_MANIFEST_HASH_LENGTH);\n return path.join(cacheDirectory ?? resolveSkillCacheDirectory(repoRoot), `${key}.json`);\n}\n\nfunction fileMatches(previous: SkillManifestFile): boolean {\n try {\n const stat = fs.statSync(previous.path);\n return (\n stat.isFile() &&\n stat.size === previous.size &&\n stat.mtimeMs === previous.mtimeMs &&\n stat.ctimeMs === previous.ctimeMs\n );\n } catch {\n return false;\n }\n}\n\nfunction directoryMatches(previous: SkillManifestDirectory): boolean {\n try {\n const stat = fs.statSync(previous.path);\n return stat.isDirectory() && stat.mtimeMs === previous.mtimeMs && stat.ctimeMs === previous.ctimeMs;\n } catch {\n return false;\n }\n}\n\nfunction readSkillManifest(\n manifestPath: string,\n root: string,\n discovery: PluginSkillDiscovery,\n): SkillManifest | undefined {\n try {\n const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as SkillManifest;\n if (\n manifest.version !== SKILL_MANIFEST_VERSION ||\n manifest.root !== path.resolve(root) ||\n manifest.discovery !== discovery ||\n !Array.isArray(manifest.files) ||\n !Array.isArray(manifest.directories) ||\n !manifest.files.every(fileMatches) ||\n !manifest.directories.every(directoryMatches)\n ) {\n return undefined;\n }\n return manifest;\n } catch {\n return undefined;\n }\n}\n\nfunction writeSkillManifest(manifestPath: string, manifest: SkillManifest): void {\n fs.mkdirSync(path.dirname(manifestPath), { recursive: true, mode: 0o700 });\n const temporary = `${manifestPath}.${process.pid}.${Date.now()}.tmp`;\n fs.writeFileSync(temporary, `${JSON.stringify(manifest, null, 2)}\\n`, { mode: 0o600 });\n try {\n fs.renameSync(temporary, manifestPath);\n } catch (error) {\n fs.rmSync(temporary, { force: true });\n if (!fs.existsSync(manifestPath)) throw error;\n }\n}\n\nasync function pathExists(target: string): Promise<boolean> {\n try {\n await fs.promises.access(target);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function readSkillManifestAsync(\n manifestPath: string,\n root: string,\n discovery: PluginSkillDiscovery,\n): Promise<SkillManifest | undefined> {\n try {\n const manifest = JSON.parse(await fs.promises.readFile(manifestPath, 'utf8')) as SkillManifest;\n if (\n manifest.version !== SKILL_MANIFEST_VERSION ||\n manifest.root !== path.resolve(root) ||\n manifest.discovery !== discovery ||\n !Array.isArray(manifest.files) ||\n !Array.isArray(manifest.directories)\n ) {\n return undefined;\n }\n for (const previous of manifest.files) {\n const stat = await fs.promises.stat(previous.path);\n if (\n !stat.isFile() ||\n stat.size !== previous.size ||\n stat.mtimeMs !== previous.mtimeMs ||\n stat.ctimeMs !== previous.ctimeMs\n ) {\n return undefined;\n }\n }\n for (const previous of manifest.directories) {\n const stat = await fs.promises.stat(previous.path);\n if (!stat.isDirectory() || stat.mtimeMs !== previous.mtimeMs || stat.ctimeMs !== previous.ctimeMs) {\n return undefined;\n }\n }\n return manifest;\n } catch {\n return undefined;\n }\n}\n\nasync function writeSkillManifestAsync(manifestPath: string, manifest: SkillManifest): Promise<void> {\n await fs.promises.mkdir(path.dirname(manifestPath), { recursive: true, mode: 0o700 });\n const temporary = `${manifestPath}.${process.pid}.${Date.now()}.tmp`;\n await fs.promises.writeFile(temporary, `${JSON.stringify(manifest, null, 2)}\\n`, { mode: 0o600 });\n try {\n await fs.promises.rename(temporary, manifestPath);\n } catch (error) {\n await fs.promises.rm(temporary, { force: true });\n if (!(await pathExists(manifestPath))) throw error;\n }\n}\n\nfunction scanSkillManifest(root: string, discovery: PluginSkillDiscovery): SkillManifest {\n const directories: SkillManifestDirectory[] = [];\n const files: SkillManifestFile[] = [];\n const walk = (directory: string, depth: number): void => {\n if (!fs.existsSync(directory)) return;\n const directoryStat = fs.statSync(directory);\n directories.push({ path: directory, mtimeMs: directoryStat.mtimeMs, ctimeMs: directoryStat.ctimeMs });\n for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {\n const candidate = path.join(directory, entry.name);\n if (entry.isDirectory()) {\n if (discovery === 'recursive' || depth === 0) walk(candidate, depth + 1);\n continue;\n }\n if (!entry.isFile() || entry.name !== 'SKILL.md' || (discovery === 'direct-children' && depth !== 1)) {\n continue;\n }\n const content = fs.readFileSync(candidate, 'utf8');\n const { attributes } = splitFrontmatter(content);\n if (typeof attributes.name !== 'string') throw new Error(`Resource requires a name: ${candidate}`);\n const stat = fs.statSync(candidate);\n files.push({\n path: candidate,\n name: attributes.name,\n digest: createHash('sha256').update(content).digest('hex'),\n size: stat.size,\n mtimeMs: stat.mtimeMs,\n ctimeMs: stat.ctimeMs,\n });\n }\n };\n const resolvedRoot = path.resolve(root);\n walk(resolvedRoot, 0);\n files.sort((left, right) => left.path.localeCompare(right.path));\n directories.sort((left, right) => left.path.localeCompare(right.path));\n return { version: SKILL_MANIFEST_VERSION, root: resolvedRoot, discovery, files, directories };\n}\n\n/** Cached skill metadata and exact files, ready for Pi without a second tree walk. */\nexport function discoverSkills(\n repoRoot: string,\n root: string,\n discovery: PluginSkillDiscovery = 'recursive',\n cacheDirectory?: string,\n): NamedResource[] {\n if (!fs.existsSync(root)) return [];\n const manifestPath = skillManifestPath(repoRoot, root, discovery, cacheDirectory);\n const cached = readSkillManifest(manifestPath, root, discovery);\n const manifest = cached ?? scanSkillManifest(root, discovery);\n if (!cached) writeSkillManifest(manifestPath, manifest);\n return manifest.files.map(({ name, path: filePath, digest }) => ({ name, path: filePath, digest }));\n}\n\nasync function scanSkillManifestAsync(root: string, discovery: PluginSkillDiscovery): Promise<SkillManifest> {\n const directories: SkillManifestDirectory[] = [];\n const files: SkillManifestFile[] = [];\n const walk = async (directory: string, depth: number): Promise<void> => {\n let entries: fs.Dirent[];\n try {\n const directoryStat = await fs.promises.stat(directory);\n directories.push({ path: directory, mtimeMs: directoryStat.mtimeMs, ctimeMs: directoryStat.ctimeMs });\n entries = await fs.promises.readdir(directory, { withFileTypes: true });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return;\n throw error;\n }\n for (const entry of entries) {\n const candidate = path.join(directory, entry.name);\n if (entry.isDirectory()) {\n if (discovery === 'recursive' || depth === 0) await walk(candidate, depth + 1);\n continue;\n }\n if (!entry.isFile() || entry.name !== 'SKILL.md' || (discovery === 'direct-children' && depth !== 1)) {\n continue;\n }\n const content = await fs.promises.readFile(candidate, 'utf8');\n const { attributes } = splitFrontmatter(content);\n if (typeof attributes.name !== 'string') throw new Error(`Resource requires a name: ${candidate}`);\n const stat = await fs.promises.stat(candidate);\n files.push({\n path: candidate,\n name: attributes.name,\n digest: createHash('sha256').update(content).digest('hex'),\n size: stat.size,\n mtimeMs: stat.mtimeMs,\n ctimeMs: stat.ctimeMs,\n });\n }\n };\n const resolvedRoot = path.resolve(root);\n await walk(resolvedRoot, 0);\n files.sort((left, right) => left.path.localeCompare(right.path));\n directories.sort((left, right) => left.path.localeCompare(right.path));\n return { version: SKILL_MANIFEST_VERSION, root: resolvedRoot, discovery, files, directories };\n}\n\nexport async function discoverSkillsAsync(\n repoRoot: string,\n root: string,\n discovery: PluginSkillDiscovery = 'recursive',\n cacheDirectory?: string,\n): Promise<NamedResource[]> {\n if (!(await pathExists(root))) return [];\n const manifestPath = skillManifestPath(repoRoot, root, discovery, cacheDirectory);\n const cached = await readSkillManifestAsync(manifestPath, root, discovery);\n const manifest = cached ?? (await scanSkillManifestAsync(root, discovery));\n if (!cached) await writeSkillManifestAsync(manifestPath, manifest);\n return manifest.files.map(({ name, path: filePath, digest }) => ({ name, path: filePath, digest }));\n}\n\nasync function markdownFilesAsync(directory: string): Promise<string[]> {\n let entries: fs.Dirent[];\n try {\n entries = await fs.promises.readdir(directory, { withFileTypes: true });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return [];\n throw error;\n }\n const results: string[] = [];\n for (const entry of entries) {\n const candidate = path.join(directory, entry.name);\n if (entry.isDirectory()) results.push(...(await markdownFilesAsync(candidate)));\n if (entry.isFile() && entry.name.endsWith('.md')) results.push(candidate);\n }\n return results;\n}\n\nasync function frontmatterNameAsync(filePath: string): Promise<string> {\n const { attributes } = splitFrontmatter(await fs.promises.readFile(filePath, 'utf8'));\n if (typeof attributes.name !== 'string') throw new Error(`Resource requires a name: ${filePath}`);\n return attributes.name;\n}\n\nasync function assertUniqueAsync(resources: NamedResource[], kind: string): Promise<void> {\n const seen = new Map<string, string>();\n const digestByName = new Map<string, string>();\n for (const resource of resources) {\n const previous = seen.get(resource.name);\n const digest =\n resource.digest ??\n createHash('sha256')\n .update(await fs.promises.readFile(resource.path))\n .digest('hex');\n if (previous && digestByName.get(resource.name) !== digest) {\n throw new Error(`Conflicting ${kind} \"${resource.name}\": ${previous} and ${resource.path}`);\n }\n seen.set(resource.name, resource.path);\n digestByName.set(resource.name, digest);\n }\n}\n\nfunction dispatcherAgentSource(): string {\n const attributes: JsonObject = {\n name: DISPATCHER_AGENT_NAME,\n description: 'Selects and launches Agiflow workflows for one loop pass without implementing the work.',\n thinking: 'high',\n systemPromptMode: 'replace',\n inheritProjectContext: true,\n inheritSkills: true,\n tools: DISPATCHER_TOOLS.join(', '),\n // No feature extension is named here. Team inherits the ordered child\n // composition projected from the selected layers for every helper process.\n defaultContext: 'fresh',\n defaultProgress: false,\n };\n const body = [\n 'You are the Agiflow workflow dispatcher.',\n 'Reason about the supplied dispatch context and launch eligible workflows.',\n 'Launch workflows without monitoring them. After dispatching, report and exit.',\n 'Follow the task restrictions exactly. Do not implement jobs or edit repository files.',\n ].join('\\n');\n return `---\\n${stringify(attributes).trim()}\\n---\\n\\n${body}\\n`;\n}\n\nexport function mergeMcpConfigs(configPaths: string[]): JsonObject {\n const merged: JsonObject = { mcpServers: {} };\n const servers = merged.mcpServers as Record<string, unknown>;\n const sources = new Map<string, string>();\n for (const configPath of configPaths) {\n if (!fs.existsSync(configPath)) continue;\n const config = JSON.parse(fs.readFileSync(configPath, 'utf8')) as JsonObject;\n const incoming = (config.mcpServers ?? {}) as Record<string, unknown>;\n for (const [name, definition] of Object.entries(incoming)) {\n const previous = servers[name];\n if (previous && JSON.stringify(previous) !== JSON.stringify(definition)) {\n throw new Error(`Conflicting MCP server \"${name}\": ${sources.get(name)} and ${configPath}`);\n }\n servers[name] = definition;\n sources.set(name, configPath);\n }\n }\n return merged;\n}\n\nexport async function mergeMcpConfigsAsync(configPaths: string[]): Promise<JsonObject> {\n const merged: JsonObject = { mcpServers: {} };\n const servers = merged.mcpServers as Record<string, unknown>;\n const sources = new Map<string, string>();\n for (const configPath of configPaths) {\n let content: string;\n try {\n content = await fs.promises.readFile(configPath, 'utf8');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') continue;\n throw error;\n }\n const config = JSON.parse(content) as JsonObject;\n const incoming = (config.mcpServers ?? {}) as Record<string, unknown>;\n for (const [name, definition] of Object.entries(incoming)) {\n const previous = servers[name];\n if (previous && JSON.stringify(previous) !== JSON.stringify(definition)) {\n throw new Error(`Conflicting MCP server \"${name}\": ${sources.get(name)} and ${configPath}`);\n }\n servers[name] = definition;\n sources.set(name, configPath);\n }\n }\n return merged;\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/** Matches a resource name against a subset filter. Undefined keeps everything. */\nfunction keepsName(allowed: string[] | undefined, name: string): boolean {\n if (!allowed) return true;\n return allowed.some((pattern) =>\n pattern.includes('*')\n ? new RegExp(`^${pattern.split('*').map(escapeRegExp).join('.*')}$`).test(name)\n : pattern === name,\n );\n}\n\n/**\n * Stages every resource the selected domains contribute, ready for one Pi session.\n *\n * The caller owns the returned cleanup(): the temporary directory holding agents\n * and the generated MCP config has to outlive this function and be removed once\n * the session that reads it is done.\n */\nexport async function collectResources(\n repoRoot: string,\n plugins: Array<string | PluginEntry>,\n options: HarnessResourceOptions,\n): Promise<HarnessResources> {\n const pluginEntries: PluginEntry[] = plugins.map((plugin) =>\n typeof plugin === 'string' ? { directory: plugin } : plugin,\n );\n // A caller-supplied directory is owned by the caller: it is either a live\n // session's directory or the synced one, and removing it here would delete\n // resources that outlive this collection.\n const ownsDirectory = options.temporaryDirectory === undefined;\n const temporaryDirectory =\n options.temporaryDirectory ?? (await fs.promises.mkdtemp(path.join(os.tmpdir(), 'doom-pi-')));\n await fs.promises.mkdir(temporaryDirectory, { mode: 0o700, recursive: true });\n await fs.promises.chmod(temporaryDirectory, 0o700);\n const sharedSkills = path.join(repoRoot, '.claude', 'skills');\n // A domain can opt out of the always-on shared skills to keep its context small.\n const sharedSkillSources =\n options.sharedSkills === false\n ? []\n : await discoverSkillsAsync(repoRoot, sharedSkills, 'recursive', options.skillCacheDirectory);\n const skillDirectories: string[] = [];\n const skillSources: NamedResource[] = [];\n const agentSources: Array<{ name: string; path: string }> = [];\n const pluginHooks: PluginHookSource[] = [];\n const pluginMcpConfigPaths: string[] = [];\n const mcpPaths = [path.join(repoRoot, '.mcp.json')];\n\n for (const entry of pluginEntries) {\n const pluginDirectory = entry.directory;\n const skills = path.join(pluginDirectory, 'skills');\n if (await pathExists(skills)) {\n const found = (\n await discoverSkillsAsync(repoRoot, skills, entry.skillDiscovery ?? 'recursive', options.skillCacheDirectory)\n ).filter((skill) => keepsName(entry.skills, skill.name));\n // Exact files let Pi skip another recursive traversal and make a plugin\n // subset unambiguous without staging copies of the skill bodies.\n skillDirectories.push(...found.map((skill) => skill.path));\n skillSources.push(...found);\n }\n const agents = path.join(pluginDirectory, 'agents');\n const agentFiles = await markdownFilesAsync(agents);\n const agentNames = await Promise.all(agentFiles.map((filePath) => frontmatterNameAsync(filePath)));\n agentSources.push(\n ...agentFiles\n .map((filePath, index) => ({ name: agentNames[index] ?? '', path: filePath }))\n .filter((agent) => keepsName(entry.agents, agent.name)),\n );\n const hookConfig = path.join(pluginDirectory, 'hooks', 'hooks.json');\n if (entry.hooks !== false && (await pathExists(hookConfig))) {\n pluginHooks.push({ pluginRoot: pluginDirectory, configPath: hookConfig });\n }\n const mcpConfig = path.join(pluginDirectory, '.mcp.json');\n if (entry.mcp !== false && (await pathExists(mcpConfig))) {\n mcpPaths.push(mcpConfig);\n pluginMcpConfigPaths.push(mcpConfig);\n }\n }\n\n await assertUniqueAsync(skillSources, 'skill');\n await assertUniqueAsync(sharedSkillSources, 'skill');\n // Pi keeps the first skill for a duplicated name. Selected domain plugins are\n // authoritative; shared Claude skills remain fallbacks for names no plugin owns.\n const pluginSkillNames = new Set(skillSources.map((skill) => skill.name));\n const fallbackSharedSkills = sharedSkillSources.filter((skill) => !pluginSkillNames.has(skill.name));\n skillDirectories.push(...fallbackSharedSkills.map((skill) => skill.path));\n skillSources.push(...fallbackSharedSkills);\n\n await assertUniqueAsync(agentSources, 'agent');\n if (agentSources.some((source) => source.name === DISPATCHER_AGENT_NAME)) {\n throw new Error(`Conflicting agent \"${DISPATCHER_AGENT_NAME}\": reserved by the agent harness`);\n }\n\n const agentDirectories: string[] = [];\n const outputDirectory = path.join(temporaryDirectory, 'agents');\n await fs.promises.rm(outputDirectory, { recursive: true, force: true });\n if (options.agents) {\n await fs.promises.mkdir(outputDirectory, { mode: 0o700 });\n for (const source of agentSources) {\n const adapted = adaptAgentDefinition(await fs.promises.readFile(source.path, 'utf8'));\n await fs.promises.writeFile(\n path.join(outputDirectory, `${assertSafeAgentName(adapted.name)}.md`),\n adapted.content,\n { mode: 0o600 },\n );\n }\n await fs.promises.writeFile(path.join(outputDirectory, `${DISPATCHER_AGENT_NAME}.md`), dispatcherAgentSource(), {\n mode: 0o600,\n });\n agentDirectories.push(outputDirectory);\n }\n\n let mcpConfigPath: string | undefined;\n if (options.mcp) {\n mcpConfigPath = path.join(temporaryDirectory, 'mcp.json');\n // Domains without an mcp allowlist resolve to undefined here, which leaves\n // the merged config untouched.\n const merged = await applyMcpAllowlist(\n await mergeMcpConfigsAsync(mcpPaths),\n options.mcpAllowlist,\n repoRoot,\n temporaryDirectory,\n );\n await fs.promises.writeFile(mcpConfigPath, `${JSON.stringify(merged, null, 2)}\\n`, {\n mode: 0o600,\n });\n }\n\n return {\n temporaryDirectory,\n skillDirectories,\n skillCount: skillSources.length,\n agentCount: agentSources.length,\n agentDirectories,\n pluginHooks,\n mcpConfigPath,\n pluginMcpConfigPaths,\n cleanup: () =>\n ownsDirectory ? fs.promises.rm(temporaryDirectory, { recursive: true, force: true }) : Promise.resolve(),\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ const e=require("../_virtual/_rolldown/runtime.cjs");let t=require("node:path");t=e.__toESM(t,1);let n=require("node:fs");n=e.__toESM(n,1);let r=require("node:crypto");r=e.__toESM(r,1);let i=require("node:os");i=e.__toESM(i,1);const a=[`cache`,`skills`],o=`.git`,s=`repo`;function c(e,n=i.default.homedir()){let r=l(e),o=d(r),s=o?`git:${o}`:`root:${r}`,c=f(s),u=f(`${s}\0worktree:${r}`),h=m(o,r),g=p(t.default.basename(r),`worktree`);return t.default.join(t.default.resolve(n),`.pi`,`.doom`,`sync`,`${h}--${c}`,`worktrees`,`${g}--${u}`,...a)}function l(e){let r=t.default.resolve(e);try{return n.default.realpathSync.native(r)}catch{return r}}function u(e){let r=t.default.join(e,o);try{let i=n.default.statSync(r);if(i.isDirectory())return l(r);if(!i.isFile())return;let a=/^gitdir:\s*(.+)$/imu.exec(n.default.readFileSync(r,`utf8`).trim());return a?.[1]?l(t.default.resolve(e,a[1].trim())):void 0}catch{return}}function d(e){let r=u(e);if(r)try{let e=n.default.readFileSync(t.default.join(r,`commondir`),`utf8`).trim();return e?l(t.default.resolve(r,e)):r}catch{return r}}function f(e){return r.default.createHash(`sha256`).update(e,`utf8`).digest(`hex`).slice(0,32)}function p(e,t){let n=e.normalize(`NFKD`).replace(/[\u0300-\u036f]/gu,``).replace(/[^A-Za-z0-9._-]+/gu,`-`).replace(/^[._-]+|[._-]+$/gu,``).slice(0,48).replace(/[._-]+$/gu,``);return n===``||n===`.`||n===`..`?t:n}function m(e,n){if(!e)return p(t.default.basename(n),s);let r=t.default.basename(e);return p(r===o?t.default.basename(t.default.dirname(e)):r,s)}exports.resolveSkillCacheDirectory=c,exports.sanitizeSyncLabel=p;
2
+ //# sourceMappingURL=skillCacheLocation.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skillCacheLocation.cjs","names":["os","path","fs","crypto"],"sources":["../../src/adapters/skillCacheLocation.ts"],"sourcesContent":["import crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nconst PI_DIRECTORY = '.pi';\nconst DOOM_CONFIG_DIRECTORY = '.doom';\nconst SYNC_DIRECTORY = 'sync';\nconst WORKTREES_DIRECTORY = 'worktrees';\nconst SKILL_CACHE_SEGMENTS = ['cache', 'skills'];\nconst GIT_DIRECTORY = '.git';\nconst COMMON_DIRECTORY_FILE = 'commondir';\nconst IDENTITY_HEX_LENGTH = 32;\nconst LABEL_MAX_LENGTH = 48;\nconst DEFAULT_REPOSITORY_LABEL = 'repo';\nconst DEFAULT_WORKTREE_LABEL = 'worktree';\n\n/**\n * The home-scoped skill manifest cache for one worktree.\n *\n * This mirrors the namespace the DoomPi launcher publishes into, so a session\n * that stages resources through the launcher and one that stages them through a\n * `/domains` switch hit the same manifests instead of rescanning every tree.\n * Two worktrees of one repository stay separate, and a checkout reached through\n * a symlink resolves to the same identity as the real path.\n */\nexport function resolveSkillCacheDirectory(repositoryRoot: string, homeDirectory: string = os.homedir()): string {\n const root = canonicalPath(repositoryRoot);\n const commonDirectory = gitCommonDirectory(root);\n const repositoryToken = commonDirectory ? `git:${commonDirectory}` : `root:${root}`;\n const repositoryId = identityHash(repositoryToken);\n const worktreeId = identityHash(`${repositoryToken}\\0worktree:${root}`);\n const repoLabel = repositoryLabel(commonDirectory, root);\n const worktreeLabel = sanitizeSyncLabel(path.basename(root), DEFAULT_WORKTREE_LABEL);\n return path.join(\n path.resolve(homeDirectory),\n PI_DIRECTORY,\n DOOM_CONFIG_DIRECTORY,\n SYNC_DIRECTORY,\n `${repoLabel}--${repositoryId}`,\n WORKTREES_DIRECTORY,\n `${worktreeLabel}--${worktreeId}`,\n ...SKILL_CACHE_SEGMENTS,\n );\n}\n\nfunction canonicalPath(target: string): string {\n const absolute = path.resolve(target);\n try {\n return fs.realpathSync.native(absolute);\n } catch {\n return absolute;\n }\n}\n\nfunction readGitDirectory(repositoryRoot: string): string | undefined {\n const gitPath = path.join(repositoryRoot, GIT_DIRECTORY);\n try {\n const stat = fs.statSync(gitPath);\n if (stat.isDirectory()) return canonicalPath(gitPath);\n if (!stat.isFile()) return undefined;\n const match = /^gitdir:\\s*(.+)$/imu.exec(fs.readFileSync(gitPath, 'utf8').trim());\n return match?.[1] ? canonicalPath(path.resolve(repositoryRoot, match[1].trim())) : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction gitCommonDirectory(repositoryRoot: string): string | undefined {\n const gitDirectory = readGitDirectory(repositoryRoot);\n if (!gitDirectory) return undefined;\n try {\n const relative = fs.readFileSync(path.join(gitDirectory, COMMON_DIRECTORY_FILE), 'utf8').trim();\n return relative ? canonicalPath(path.resolve(gitDirectory, relative)) : gitDirectory;\n } catch {\n return gitDirectory;\n }\n}\n\nfunction identityHash(value: string): string {\n return crypto.createHash('sha256').update(value, 'utf8').digest('hex').slice(0, IDENTITY_HEX_LENGTH);\n}\n\n/** Keeps a repository or worktree name usable as one path segment. */\nexport function sanitizeSyncLabel(value: string, fallback: string): string {\n const normalized = value\n .normalize('NFKD')\n .replace(/[\\u0300-\\u036f]/gu, '')\n .replace(/[^A-Za-z0-9._-]+/gu, '-')\n .replace(/^[._-]+|[._-]+$/gu, '')\n .slice(0, LABEL_MAX_LENGTH)\n .replace(/[._-]+$/gu, '');\n return normalized === '' || normalized === '.' || normalized === '..' ? fallback : normalized;\n}\n\nfunction repositoryLabel(commonDirectory: string | undefined, repositoryRoot: string): string {\n if (!commonDirectory) return sanitizeSyncLabel(path.basename(repositoryRoot), DEFAULT_REPOSITORY_LABEL);\n const base = path.basename(commonDirectory);\n const source = base === GIT_DIRECTORY ? path.basename(path.dirname(commonDirectory)) : base;\n return sanitizeSyncLabel(source, DEFAULT_REPOSITORY_LABEL);\n}\n"],"mappings":"mOAKA,MAIM,EAAuB,CAAC,QAAS,QAAQ,EACzC,EAAgB,OAIhB,EAA2B,OAYjC,SAAgB,EAA2B,EAAwB,EAAwBA,EAAAA,QAAG,QAAQ,EAAW,CAC/G,IAAM,EAAO,EAAc,CAAc,EACnC,EAAkB,EAAmB,CAAI,EACzC,EAAkB,EAAkB,OAAO,IAAoB,QAAQ,IACvE,EAAe,EAAa,CAAe,EAC3C,EAAa,EAAa,GAAG,EAAgB,aAAa,GAAM,EAChE,EAAY,EAAgB,EAAiB,CAAI,EACjD,EAAgB,EAAkBC,EAAAA,QAAK,SAAS,CAAI,EAAG,UAAsB,EACnF,OAAOA,EAAAA,QAAK,KACVA,EAAAA,QAAK,QAAQ,CAAa,EAC1B,MACA,QACA,OACA,GAAG,EAAU,IAAI,IACjB,YACA,GAAG,EAAc,IAAI,IACrB,GAAG,CACL,CACF,CAEA,SAAS,EAAc,EAAwB,CAC7C,IAAM,EAAWA,EAAAA,QAAK,QAAQ,CAAM,EACpC,GAAI,CACF,OAAOC,EAAAA,QAAG,aAAa,OAAO,CAAQ,CACxC,MAAQ,CACN,OAAO,CACT,CACF,CAEA,SAAS,EAAiB,EAA4C,CACpE,IAAM,EAAUD,EAAAA,QAAK,KAAK,EAAgB,CAAa,EACvD,GAAI,CACF,IAAM,EAAOC,EAAAA,QAAG,SAAS,CAAO,EAChC,GAAI,EAAK,YAAY,EAAG,OAAO,EAAc,CAAO,EACpD,GAAI,CAAC,EAAK,OAAO,EAAG,OACpB,IAAM,EAAQ,sBAAsB,KAAKA,EAAAA,QAAG,aAAa,EAAS,MAAM,CAAC,CAAC,KAAK,CAAC,EAChF,OAAO,IAAQ,GAAK,EAAcD,EAAAA,QAAK,QAAQ,EAAgB,EAAM,EAAE,CAAC,KAAK,CAAC,CAAC,EAAI,IAAA,EACrF,MAAQ,CACN,MACF,CACF,CAEA,SAAS,EAAmB,EAA4C,CACtE,IAAM,EAAe,EAAiB,CAAc,EAC/C,KACL,GAAI,CACF,IAAM,EAAWC,EAAAA,QAAG,aAAaD,EAAAA,QAAK,KAAK,EAAc,WAAqB,EAAG,MAAM,CAAC,CAAC,KAAK,EAC9F,OAAO,EAAW,EAAcA,EAAAA,QAAK,QAAQ,EAAc,CAAQ,CAAC,EAAI,CAC1E,MAAQ,CACN,OAAO,CACT,CACF,CAEA,SAAS,EAAa,EAAuB,CAC3C,OAAOE,EAAAA,QAAO,WAAW,QAAQ,CAAC,CAAC,OAAO,EAAO,MAAM,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,EAAG,EAAmB,CACrG,CAGA,SAAgB,EAAkB,EAAe,EAA0B,CACzE,IAAM,EAAa,EAChB,UAAU,MAAM,CAAC,CACjB,QAAQ,oBAAqB,EAAE,CAAC,CAChC,QAAQ,qBAAsB,GAAG,CAAC,CAClC,QAAQ,oBAAqB,EAAE,CAAC,CAChC,MAAM,EAAG,EAAgB,CAAC,CAC1B,QAAQ,YAAa,EAAE,EAC1B,OAAO,IAAe,IAAM,IAAe,KAAO,IAAe,KAAO,EAAW,CACrF,CAEA,SAAS,EAAgB,EAAqC,EAAgC,CAC5F,GAAI,CAAC,EAAiB,OAAO,EAAkBF,EAAAA,QAAK,SAAS,CAAc,EAAG,CAAwB,EACtG,IAAM,EAAOA,EAAAA,QAAK,SAAS,CAAe,EAE1C,OAAO,EADQ,IAAS,EAAgBA,EAAAA,QAAK,SAASA,EAAAA,QAAK,QAAQ,CAAe,CAAC,EAAI,EACtD,CAAwB,CAC3D"}
@@ -0,0 +1,16 @@
1
+ //#region src/adapters/skillCacheLocation.d.ts
2
+ /**
3
+ * The home-scoped skill manifest cache for one worktree.
4
+ *
5
+ * This mirrors the namespace the DoomPi launcher publishes into, so a session
6
+ * that stages resources through the launcher and one that stages them through a
7
+ * `/domains` switch hit the same manifests instead of rescanning every tree.
8
+ * Two worktrees of one repository stay separate, and a checkout reached through
9
+ * a symlink resolves to the same identity as the real path.
10
+ */
11
+ declare function resolveSkillCacheDirectory(repositoryRoot: string, homeDirectory?: string): string;
12
+ /** Keeps a repository or worktree name usable as one path segment. */
13
+ declare function sanitizeSyncLabel(value: string, fallback: string): string;
14
+ //#endregion
15
+ export { resolveSkillCacheDirectory, sanitizeSyncLabel };
16
+ //# sourceMappingURL=skillCacheLocation.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skillCacheLocation.d.cts","names":[],"sources":["../../src/adapters/skillCacheLocation.ts"],"mappings":";;;;;;;;;;iBA0BgB,2BAA2B,wBAAwB;;iBA0DnD,kBAAkB,eAAe"}
@@ -0,0 +1,16 @@
1
+ //#region src/adapters/skillCacheLocation.d.ts
2
+ /**
3
+ * The home-scoped skill manifest cache for one worktree.
4
+ *
5
+ * This mirrors the namespace the DoomPi launcher publishes into, so a session
6
+ * that stages resources through the launcher and one that stages them through a
7
+ * `/domains` switch hit the same manifests instead of rescanning every tree.
8
+ * Two worktrees of one repository stay separate, and a checkout reached through
9
+ * a symlink resolves to the same identity as the real path.
10
+ */
11
+ declare function resolveSkillCacheDirectory(repositoryRoot: string, homeDirectory?: string): string;
12
+ /** Keeps a repository or worktree name usable as one path segment. */
13
+ declare function sanitizeSyncLabel(value: string, fallback: string): string;
14
+ //#endregion
15
+ export { resolveSkillCacheDirectory, sanitizeSyncLabel };
16
+ //# sourceMappingURL=skillCacheLocation.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skillCacheLocation.d.mts","names":[],"sources":["../../src/adapters/skillCacheLocation.ts"],"mappings":";;;;;;;;;;iBA0BgB,2BAA2B,wBAAwB;;iBA0DnD,kBAAkB,eAAe"}
@@ -0,0 +1,2 @@
1
+ import e from"node:path";import t from"node:fs";import n from"node:crypto";import r from"node:os";const i=[`cache`,`skills`],a=`.git`,o=`repo`;function s(t,n=r.homedir()){let a=c(t),o=u(a),s=o?`git:${o}`:`root:${a}`,l=d(s),m=d(`${s}\0worktree:${a}`),h=p(o,a),g=f(e.basename(a),`worktree`);return e.join(e.resolve(n),`.pi`,`.doom`,`sync`,`${h}--${l}`,`worktrees`,`${g}--${m}`,...i)}function c(n){let r=e.resolve(n);try{return t.realpathSync.native(r)}catch{return r}}function l(n){let r=e.join(n,a);try{let i=t.statSync(r);if(i.isDirectory())return c(r);if(!i.isFile())return;let a=/^gitdir:\s*(.+)$/imu.exec(t.readFileSync(r,`utf8`).trim());return a?.[1]?c(e.resolve(n,a[1].trim())):void 0}catch{return}}function u(n){let r=l(n);if(r)try{let n=t.readFileSync(e.join(r,`commondir`),`utf8`).trim();return n?c(e.resolve(r,n)):r}catch{return r}}function d(e){return n.createHash(`sha256`).update(e,`utf8`).digest(`hex`).slice(0,32)}function f(e,t){let n=e.normalize(`NFKD`).replace(/[\u0300-\u036f]/gu,``).replace(/[^A-Za-z0-9._-]+/gu,`-`).replace(/^[._-]+|[._-]+$/gu,``).slice(0,48).replace(/[._-]+$/gu,``);return n===``||n===`.`||n===`..`?t:n}function p(t,n){if(!t)return f(e.basename(n),o);let r=e.basename(t);return f(r===a?e.basename(e.dirname(t)):r,o)}export{s as resolveSkillCacheDirectory,f as sanitizeSyncLabel};
2
+ //# sourceMappingURL=skillCacheLocation.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skillCacheLocation.mjs","names":[],"sources":["../../src/adapters/skillCacheLocation.ts"],"sourcesContent":["import crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nconst PI_DIRECTORY = '.pi';\nconst DOOM_CONFIG_DIRECTORY = '.doom';\nconst SYNC_DIRECTORY = 'sync';\nconst WORKTREES_DIRECTORY = 'worktrees';\nconst SKILL_CACHE_SEGMENTS = ['cache', 'skills'];\nconst GIT_DIRECTORY = '.git';\nconst COMMON_DIRECTORY_FILE = 'commondir';\nconst IDENTITY_HEX_LENGTH = 32;\nconst LABEL_MAX_LENGTH = 48;\nconst DEFAULT_REPOSITORY_LABEL = 'repo';\nconst DEFAULT_WORKTREE_LABEL = 'worktree';\n\n/**\n * The home-scoped skill manifest cache for one worktree.\n *\n * This mirrors the namespace the DoomPi launcher publishes into, so a session\n * that stages resources through the launcher and one that stages them through a\n * `/domains` switch hit the same manifests instead of rescanning every tree.\n * Two worktrees of one repository stay separate, and a checkout reached through\n * a symlink resolves to the same identity as the real path.\n */\nexport function resolveSkillCacheDirectory(repositoryRoot: string, homeDirectory: string = os.homedir()): string {\n const root = canonicalPath(repositoryRoot);\n const commonDirectory = gitCommonDirectory(root);\n const repositoryToken = commonDirectory ? `git:${commonDirectory}` : `root:${root}`;\n const repositoryId = identityHash(repositoryToken);\n const worktreeId = identityHash(`${repositoryToken}\\0worktree:${root}`);\n const repoLabel = repositoryLabel(commonDirectory, root);\n const worktreeLabel = sanitizeSyncLabel(path.basename(root), DEFAULT_WORKTREE_LABEL);\n return path.join(\n path.resolve(homeDirectory),\n PI_DIRECTORY,\n DOOM_CONFIG_DIRECTORY,\n SYNC_DIRECTORY,\n `${repoLabel}--${repositoryId}`,\n WORKTREES_DIRECTORY,\n `${worktreeLabel}--${worktreeId}`,\n ...SKILL_CACHE_SEGMENTS,\n );\n}\n\nfunction canonicalPath(target: string): string {\n const absolute = path.resolve(target);\n try {\n return fs.realpathSync.native(absolute);\n } catch {\n return absolute;\n }\n}\n\nfunction readGitDirectory(repositoryRoot: string): string | undefined {\n const gitPath = path.join(repositoryRoot, GIT_DIRECTORY);\n try {\n const stat = fs.statSync(gitPath);\n if (stat.isDirectory()) return canonicalPath(gitPath);\n if (!stat.isFile()) return undefined;\n const match = /^gitdir:\\s*(.+)$/imu.exec(fs.readFileSync(gitPath, 'utf8').trim());\n return match?.[1] ? canonicalPath(path.resolve(repositoryRoot, match[1].trim())) : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction gitCommonDirectory(repositoryRoot: string): string | undefined {\n const gitDirectory = readGitDirectory(repositoryRoot);\n if (!gitDirectory) return undefined;\n try {\n const relative = fs.readFileSync(path.join(gitDirectory, COMMON_DIRECTORY_FILE), 'utf8').trim();\n return relative ? canonicalPath(path.resolve(gitDirectory, relative)) : gitDirectory;\n } catch {\n return gitDirectory;\n }\n}\n\nfunction identityHash(value: string): string {\n return crypto.createHash('sha256').update(value, 'utf8').digest('hex').slice(0, IDENTITY_HEX_LENGTH);\n}\n\n/** Keeps a repository or worktree name usable as one path segment. */\nexport function sanitizeSyncLabel(value: string, fallback: string): string {\n const normalized = value\n .normalize('NFKD')\n .replace(/[\\u0300-\\u036f]/gu, '')\n .replace(/[^A-Za-z0-9._-]+/gu, '-')\n .replace(/^[._-]+|[._-]+$/gu, '')\n .slice(0, LABEL_MAX_LENGTH)\n .replace(/[._-]+$/gu, '');\n return normalized === '' || normalized === '.' || normalized === '..' ? fallback : normalized;\n}\n\nfunction repositoryLabel(commonDirectory: string | undefined, repositoryRoot: string): string {\n if (!commonDirectory) return sanitizeSyncLabel(path.basename(repositoryRoot), DEFAULT_REPOSITORY_LABEL);\n const base = path.basename(commonDirectory);\n const source = base === GIT_DIRECTORY ? path.basename(path.dirname(commonDirectory)) : base;\n return sanitizeSyncLabel(source, DEFAULT_REPOSITORY_LABEL);\n}\n"],"mappings":"kGAKA,MAIM,EAAuB,CAAC,QAAS,QAAQ,EACzC,EAAgB,OAIhB,EAA2B,OAYjC,SAAgB,EAA2B,EAAwB,EAAwB,EAAG,QAAQ,EAAW,CAC/G,IAAM,EAAO,EAAc,CAAc,EACnC,EAAkB,EAAmB,CAAI,EACzC,EAAkB,EAAkB,OAAO,IAAoB,QAAQ,IACvE,EAAe,EAAa,CAAe,EAC3C,EAAa,EAAa,GAAG,EAAgB,aAAa,GAAM,EAChE,EAAY,EAAgB,EAAiB,CAAI,EACjD,EAAgB,EAAkB,EAAK,SAAS,CAAI,EAAG,UAAsB,EACnF,OAAO,EAAK,KACV,EAAK,QAAQ,CAAa,EAC1B,MACA,QACA,OACA,GAAG,EAAU,IAAI,IACjB,YACA,GAAG,EAAc,IAAI,IACrB,GAAG,CACL,CACF,CAEA,SAAS,EAAc,EAAwB,CAC7C,IAAM,EAAW,EAAK,QAAQ,CAAM,EACpC,GAAI,CACF,OAAO,EAAG,aAAa,OAAO,CAAQ,CACxC,MAAQ,CACN,OAAO,CACT,CACF,CAEA,SAAS,EAAiB,EAA4C,CACpE,IAAM,EAAU,EAAK,KAAK,EAAgB,CAAa,EACvD,GAAI,CACF,IAAM,EAAO,EAAG,SAAS,CAAO,EAChC,GAAI,EAAK,YAAY,EAAG,OAAO,EAAc,CAAO,EACpD,GAAI,CAAC,EAAK,OAAO,EAAG,OACpB,IAAM,EAAQ,sBAAsB,KAAK,EAAG,aAAa,EAAS,MAAM,CAAC,CAAC,KAAK,CAAC,EAChF,OAAO,IAAQ,GAAK,EAAc,EAAK,QAAQ,EAAgB,EAAM,EAAE,CAAC,KAAK,CAAC,CAAC,EAAI,IAAA,EACrF,MAAQ,CACN,MACF,CACF,CAEA,SAAS,EAAmB,EAA4C,CACtE,IAAM,EAAe,EAAiB,CAAc,EAC/C,KACL,GAAI,CACF,IAAM,EAAW,EAAG,aAAa,EAAK,KAAK,EAAc,WAAqB,EAAG,MAAM,CAAC,CAAC,KAAK,EAC9F,OAAO,EAAW,EAAc,EAAK,QAAQ,EAAc,CAAQ,CAAC,EAAI,CAC1E,MAAQ,CACN,OAAO,CACT,CACF,CAEA,SAAS,EAAa,EAAuB,CAC3C,OAAO,EAAO,WAAW,QAAQ,CAAC,CAAC,OAAO,EAAO,MAAM,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,EAAG,EAAmB,CACrG,CAGA,SAAgB,EAAkB,EAAe,EAA0B,CACzE,IAAM,EAAa,EAChB,UAAU,MAAM,CAAC,CACjB,QAAQ,oBAAqB,EAAE,CAAC,CAChC,QAAQ,qBAAsB,GAAG,CAAC,CAClC,QAAQ,oBAAqB,EAAE,CAAC,CAChC,MAAM,EAAG,EAAgB,CAAC,CAC1B,QAAQ,YAAa,EAAE,EAC1B,OAAO,IAAe,IAAM,IAAe,KAAO,IAAe,KAAO,EAAW,CACrF,CAEA,SAAS,EAAgB,EAAqC,EAAgC,CAC5F,GAAI,CAAC,EAAiB,OAAO,EAAkB,EAAK,SAAS,CAAc,EAAG,CAAwB,EACtG,IAAM,EAAO,EAAK,SAAS,CAAe,EAE1C,OAAO,EADQ,IAAS,EAAgB,EAAK,SAAS,EAAK,QAAQ,CAAe,CAAC,EAAI,EACtD,CAAwB,CAC3D"}
@@ -0,0 +1,2 @@
1
+ let e=require("@agimon-ai/doompi-telemetry");function t(t={}){let n=(0,e.createDoomTelemetry)({serviceName:`doom-pi-domain`,packageName:`@agimon-ai/doompi-domain`,cwd:t.cwd,workspaceRoot:t.workspaceRoot,env:t.env,telemetryFactory:t.telemetryFactory,warn:t.warn,enableLogs:!0,enableTraces:!0});return{recordError:(e,t,r)=>n.recordError(e,t,r),recordEvent:(e,t)=>n.recordEvent(e,t)}}exports.createDomainTelemetry=t;
2
+ //# sourceMappingURL=logSinkTelemetry.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logSinkTelemetry.cjs","names":["createDoomTelemetry"],"sources":["../../../src/adapters/telemetry/logSinkTelemetry.ts"],"sourcesContent":["import { createDoomTelemetry, type DoomTelemetry, type DoomTelemetryOptions } from '@agimon-ai/doompi-telemetry';\nimport type { DomainTelemetry } from '../../types/telemetry.ts';\n\nconst SERVICE_NAME = 'doom-pi-domain';\nconst PACKAGE_NAME = '@agimon-ai/doompi-domain';\n\nexport interface DomainTelemetryOptions {\n cwd?: string;\n workspaceRoot?: string;\n env?: NodeJS.ProcessEnv;\n telemetryFactory?: NonNullable<DoomTelemetryOptions['telemetryFactory']>;\n warn?: (message: string) => void;\n}\n\nexport function createDomainTelemetry(options: DomainTelemetryOptions = {}): DomainTelemetry {\n const telemetry: DoomTelemetry = createDoomTelemetry({\n serviceName: SERVICE_NAME,\n packageName: PACKAGE_NAME,\n cwd: options.cwd,\n workspaceRoot: options.workspaceRoot,\n env: options.env,\n telemetryFactory: options.telemetryFactory,\n warn: options.warn,\n enableLogs: true,\n enableTraces: true,\n });\n return {\n recordError: (event, error, attributes) => telemetry.recordError(event, error, attributes),\n recordEvent: (event, attributes) => telemetry.recordEvent(event, attributes),\n };\n}\n"],"mappings":"6CAcA,SAAgB,EAAsB,EAAkC,CAAC,EAAoB,CAC3F,IAAM,GAAA,EAA2BA,EAAAA,oBAAAA,CAAoB,CACnD,YAAa,iBACb,YAAa,2BACb,IAAK,EAAQ,IACb,cAAe,EAAQ,cACvB,IAAK,EAAQ,IACb,iBAAkB,EAAQ,iBAC1B,KAAM,EAAQ,KACd,WAAY,GACZ,aAAc,EAChB,CAAC,EACD,MAAO,CACL,aAAc,EAAO,EAAO,IAAe,EAAU,YAAY,EAAO,EAAO,CAAU,EACzF,aAAc,EAAO,IAAe,EAAU,YAAY,EAAO,CAAU,CAC7E,CACF"}
@@ -0,0 +1,14 @@
1
+ import { DomainTelemetry } from "../../types/telemetry.cjs";
2
+ import { DoomTelemetryOptions } from "@agimon-ai/doompi-telemetry";
3
+ //#region src/adapters/telemetry/logSinkTelemetry.d.ts
4
+ interface DomainTelemetryOptions {
5
+ cwd?: string;
6
+ workspaceRoot?: string;
7
+ env?: NodeJS.ProcessEnv;
8
+ telemetryFactory?: NonNullable<DoomTelemetryOptions['telemetryFactory']>;
9
+ warn?: (message: string) => void;
10
+ }
11
+ declare function createDomainTelemetry(options?: DomainTelemetryOptions): DomainTelemetry;
12
+ //#endregion
13
+ export { DomainTelemetryOptions, createDomainTelemetry };
14
+ //# sourceMappingURL=logSinkTelemetry.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logSinkTelemetry.d.cts","names":[],"sources":["../../../src/adapters/telemetry/logSinkTelemetry.ts"],"mappings":";;;UAMiB;EACf;EACA;EACA,MAAM,OAAO;EACb,mBAAmB,YAAY;EAC/B,QAAQ;;iBAGM,sBAAsB,UAAS,yBAA8B"}
@@ -0,0 +1,14 @@
1
+ import { DomainTelemetry } from "../../types/telemetry.mjs";
2
+ import { DoomTelemetryOptions } from "@agimon-ai/doompi-telemetry";
3
+ //#region src/adapters/telemetry/logSinkTelemetry.d.ts
4
+ interface DomainTelemetryOptions {
5
+ cwd?: string;
6
+ workspaceRoot?: string;
7
+ env?: NodeJS.ProcessEnv;
8
+ telemetryFactory?: NonNullable<DoomTelemetryOptions['telemetryFactory']>;
9
+ warn?: (message: string) => void;
10
+ }
11
+ declare function createDomainTelemetry(options?: DomainTelemetryOptions): DomainTelemetry;
12
+ //#endregion
13
+ export { DomainTelemetryOptions, createDomainTelemetry };
14
+ //# sourceMappingURL=logSinkTelemetry.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logSinkTelemetry.d.mts","names":[],"sources":["../../../src/adapters/telemetry/logSinkTelemetry.ts"],"mappings":";;;UAMiB;EACf;EACA;EACA,MAAM,OAAO;EACb,mBAAmB,YAAY;EAC/B,QAAQ;;iBAGM,sBAAsB,UAAS,yBAA8B"}
@@ -0,0 +1,2 @@
1
+ import{createDoomTelemetry as e}from"@agimon-ai/doompi-telemetry";function t(t={}){let n=e({serviceName:`doom-pi-domain`,packageName:`@agimon-ai/doompi-domain`,cwd:t.cwd,workspaceRoot:t.workspaceRoot,env:t.env,telemetryFactory:t.telemetryFactory,warn:t.warn,enableLogs:!0,enableTraces:!0});return{recordError:(e,t,r)=>n.recordError(e,t,r),recordEvent:(e,t)=>n.recordEvent(e,t)}}export{t as createDomainTelemetry};
2
+ //# sourceMappingURL=logSinkTelemetry.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logSinkTelemetry.mjs","names":[],"sources":["../../../src/adapters/telemetry/logSinkTelemetry.ts"],"sourcesContent":["import { createDoomTelemetry, type DoomTelemetry, type DoomTelemetryOptions } from '@agimon-ai/doompi-telemetry';\nimport type { DomainTelemetry } from '../../types/telemetry.ts';\n\nconst SERVICE_NAME = 'doom-pi-domain';\nconst PACKAGE_NAME = '@agimon-ai/doompi-domain';\n\nexport interface DomainTelemetryOptions {\n cwd?: string;\n workspaceRoot?: string;\n env?: NodeJS.ProcessEnv;\n telemetryFactory?: NonNullable<DoomTelemetryOptions['telemetryFactory']>;\n warn?: (message: string) => void;\n}\n\nexport function createDomainTelemetry(options: DomainTelemetryOptions = {}): DomainTelemetry {\n const telemetry: DoomTelemetry = createDoomTelemetry({\n serviceName: SERVICE_NAME,\n packageName: PACKAGE_NAME,\n cwd: options.cwd,\n workspaceRoot: options.workspaceRoot,\n env: options.env,\n telemetryFactory: options.telemetryFactory,\n warn: options.warn,\n enableLogs: true,\n enableTraces: true,\n });\n return {\n recordError: (event, error, attributes) => telemetry.recordError(event, error, attributes),\n recordEvent: (event, attributes) => telemetry.recordEvent(event, attributes),\n };\n}\n"],"mappings":"kEAcA,SAAgB,EAAsB,EAAkC,CAAC,EAAoB,CAC3F,IAAM,EAA2B,EAAoB,CACnD,YAAa,iBACb,YAAa,2BACb,IAAK,EAAQ,IACb,cAAe,EAAQ,cACvB,IAAK,EAAQ,IACb,iBAAkB,EAAQ,iBAC1B,KAAM,EAAQ,KACd,WAAY,GACZ,aAAc,EAChB,CAAC,EACD,MAAO,CACL,aAAc,EAAO,EAAO,IAAe,EAAU,YAAY,EAAO,EAAO,CAAU,EACzF,aAAc,EAAO,IAAe,EAAU,YAAY,EAAO,CAAU,CAC7E,CACF"}
package/dist/apply.cjs ADDED
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./adapters/applyDomains.cjs");exports.applyDomains=e.applyDomains;
@@ -0,0 +1,2 @@
1
+ import { applyDomains } from "./adapters/applyDomains.cjs";
2
+ export { applyDomains };
@@ -0,0 +1,2 @@
1
+ import { applyDomains } from "./adapters/applyDomains.mjs";
2
+ export { applyDomains };
package/dist/apply.mjs ADDED
@@ -0,0 +1 @@
1
+ import{applyDomains as e}from"./adapters/applyDomains.mjs";export{e as applyDomains};
@@ -0,0 +1,2 @@
1
+ const e=require("../services/domainText.cjs"),t=require("../types/telemetry.cjs");let n=require("@agimon-ai/doompi-config/piContext"),r=require("@agimon-ai/doompi-extension-contracts/voice-tools"),i=require("@agimon-ai/doompi-extension-contracts/transition");const a=`info`;function o(e){if(!(0,r.commitVoiceReloadHandoff)(e.reloadHandoffToken,{sessionId:e.sessionId,hostGeneration:e.hostGeneration}))throw Error(`The voice reload handoff is stale or was already consumed.`)}async function s(t,n){let r=await n.catalog.list(t),[{MatrixPickerComponent:i},a]=await Promise.all([n.loadPicker(),n.catalog.describe(t)]);return t.ui.custom((t,n,o,s)=>new i({title:e.pickerTitle(r),items:e.domainItems(r.available,a),selected:[...r.effective],multi:!0},n,o,s))}function c(c,l,u){c.registerCommand(e.DOMAIN_COMMAND,{description:`Show the selected domains and pick a different set`,handler:async(d,f)=>{let p=(0,n.requireDoomConfigContext)(f).harness,m,h,g,_=!1;try{let n=e.voiceSwitchToken(d);if(n&&(m={sessionId:f.sessionManager.getSessionId()},h=u.handoffs.consume(n,m),!h))throw Error(`The voice domain switch token is stale or belongs to another session.`);let r=h?[...h.domains]:e.splitDomains(d),v=!1;if(!h&&r.length===0&&f.mode===`tui`){let e=await s(f,u);if(e===void 0)return;r=e,v=!0}if(!h&&r.length===0&&!v){f.ui.notify(e.domainSummary(await u.catalog.list(f)),a);return}r=await u.catalog.validate(f,r);let y=(0,i.requireDoomTransitionCoordinator)(f),b=h?`voice`:v?`ui`:`command`,x=await y.execute({sessionId:f.sessionManager.getSessionId(),hostGeneration:y.hostGeneration,operationId:h?.operationId??crypto.randomUUID(),source:b,target:{axis:`domains`,domains:r}},async(n,s)=>{await f.waitForIdle(),g=(0,i.prepareMinorModeReloadHandoff)(f,y.hostGeneration,s.operationId,s.previous.minorModes);let{persistHarnessSelection:d}=await u.loadConfigJournal();return d(c,await u.applyDomains(r,p)),h&&o(h),l.recordEvent(t.DOMAIN_EVENT.domainsSwitched,{"harness.domains.previous":p.domains.join(`,`),"harness.domains":r.join(`,`),"harness.transition.source":b,"harness.transition.disposition":s.disposition,"harness.transition.operation_id":s.operationId}),f.ui.notify(e.switchedSummary(r),a),_=!0,s.externalRelaunchRequired?`queued`:`applied`});if(x.outcome===`unchanged`)f.ui.notify(e.unchangedSummary(r),a),h&&(o(h),await f.waitForIdle(),_=!0);else if(x.outcome===`rejected`||x.outcome===`stale`)throw e.transitionError(x)}catch(n){_=!1,g?.discard(),g=void 0,h&&m&&(u.handoffs.discard(h.token,m),(0,r.discardVoiceReloadHandoff)(h.reloadHandoffToken,{sessionId:h.sessionId,hostGeneration:h.hostGeneration})),l.recordError(t.DOMAIN_EVENT.domainsSwitchFailed,n),f.ui.notify(e.errorMessage(n),`error`)}if(_)try{await f.reload()}catch(e){throw g?.discard(),e}}})}exports.registerDomainsCommand=c;
2
+ //# sourceMappingURL=domainsCommand.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domainsCommand.cjs","names":["commitVoiceReloadHandoff","pickerTitle","domainItems","DOMAIN_COMMAND","requireDoomConfigContext","voiceSwitchToken","splitDomains","domainSummary","requireDoomTransitionCoordinator","prepareMinorModeReloadHandoff","DOMAIN_EVENT","switchedSummary","unchangedSummary","transitionError","errorMessage"],"sources":["../../src/commands/domainsCommand.ts"],"sourcesContent":["import type { DoomHarnessContext, HarnessState } from '@agimon-ai/doompi-config/types';\nimport { requireDoomConfigContext } from '@agimon-ai/doompi-config/piContext';\nimport {\n type MinorModeReloadHandoffHandle,\n prepareMinorModeReloadHandoff,\n requireDoomTransitionCoordinator,\n type TransitionSource,\n} from '@agimon-ai/doompi-extension-contracts/transition';\nimport { commitVoiceReloadHandoff, discardVoiceReloadHandoff } from '@agimon-ai/doompi-extension-contracts/voice-tools';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport {\n DOMAIN_COMMAND,\n domainItems,\n domainSummary,\n errorMessage,\n pickerTitle,\n splitDomains,\n switchedSummary,\n transitionError,\n unchangedSummary,\n voiceSwitchToken,\n} from '../services/domainText.ts';\nimport type { DomainCompletion, DomainListing } from '../types/domains.ts';\nimport type { DomainSwitchHandoff, DomainSwitchHandoffStore } from '../types/handoff.ts';\nimport { DOMAIN_EVENT, type DomainTelemetry } from '../types/telemetry.ts';\n\nconst INFO = 'info';\nconst ERROR = 'error';\n\n/** Everything the manifest reader gives the command, resolved lazily behind it. */\nexport interface DomainCatalogPort {\n list(ctx: ExtensionContext): Promise<DomainListing>;\n validate(ctx: ExtensionContext, values: readonly string[]): Promise<string[]>;\n describe(ctx: ExtensionContext): Promise<Record<string, string | undefined>>;\n completions(root: string, textBeforeCursor: string): Promise<DomainCompletion | undefined>;\n}\n\nexport interface DomainsCommandDependencies {\n readonly catalog: DomainCatalogPort;\n readonly handoffs: DomainSwitchHandoffStore;\n readonly applyDomains: (domains: string[], state: DoomHarnessContext) => Promise<HarnessState>;\n readonly loadConfigJournal: () => Promise<typeof import('@agimon-ai/doompi-config/piContext')>;\n readonly loadPicker: () => Promise<typeof import('@agimon-ai/doompi-ui/components/matrixPicker')>;\n}\n\n/** Confirms the parked voice reload handoff, which the reload then acts on. */\nfunction commitReloadHandoff(queued: DomainSwitchHandoff): void {\n const committed = commitVoiceReloadHandoff(queued.reloadHandoffToken, {\n sessionId: queued.sessionId,\n hostGeneration: queued.hostGeneration,\n });\n if (!committed) throw new Error('The voice reload handoff is stale or was already consumed.');\n}\n\nasync function pickDomains(\n ctx: ExtensionContext,\n dependencies: DomainsCommandDependencies,\n): Promise<string[] | undefined> {\n const listing = await dependencies.catalog.list(ctx);\n const [{ MatrixPickerComponent }, descriptions] = await Promise.all([\n dependencies.loadPicker(),\n dependencies.catalog.describe(ctx),\n ]);\n // Domains compose, unlike a layer base, so this picker toggles with space and\n // confirms the whole set rather than replacing one value.\n return ctx.ui.custom<string[] | undefined>(\n (_tui, theme, keybindings, done) =>\n new MatrixPickerComponent(\n {\n title: pickerTitle(listing),\n items: domainItems(listing.available, descriptions),\n selected: [...listing.effective],\n multi: true,\n },\n theme,\n keybindings,\n done,\n ),\n );\n}\n\nexport function registerDomainsCommand(\n pi: ExtensionAPI,\n telemetry: DomainTelemetry,\n dependencies: DomainsCommandDependencies,\n): void {\n pi.registerCommand(DOMAIN_COMMAND, {\n description: 'Show the selected domains and pick a different set',\n handler: async (args, ctx) => {\n const state = requireDoomConfigContext(ctx).harness;\n let sessionIdentity: { readonly sessionId: string } | undefined;\n let queued: DomainSwitchHandoff | undefined;\n let minorModeReloadHandoff: MinorModeReloadHandoffHandle | undefined;\n let reloadRequested = false;\n try {\n const token = voiceSwitchToken(args);\n if (token) {\n sessionIdentity = { sessionId: ctx.sessionManager.getSessionId() };\n queued = dependencies.handoffs.consume(token, sessionIdentity);\n if (!queued) throw new Error('The voice domain switch token is stale or belongs to another session.');\n }\n\n let requested = queued ? [...queued.domains] : splitDomains(args);\n let pickerConfirmed = false;\n if (!queued && requested.length === 0 && ctx.mode === 'tui') {\n const chosen = await pickDomains(ctx, dependencies);\n if (chosen === undefined) return;\n requested = chosen;\n pickerConfirmed = true;\n }\n\n if (!queued && requested.length === 0 && !pickerConfirmed) {\n ctx.ui.notify(domainSummary(await dependencies.catalog.list(ctx)), INFO);\n return;\n }\n\n requested = await dependencies.catalog.validate(ctx, requested);\n const coordinator = requireDoomTransitionCoordinator(ctx);\n const source: TransitionSource = queued ? 'voice' : pickerConfirmed ? 'ui' : 'command';\n const result = await coordinator.execute(\n {\n sessionId: ctx.sessionManager.getSessionId(),\n hostGeneration: coordinator.hostGeneration,\n operationId: queued?.operationId ?? crypto.randomUUID(),\n source,\n target: { axis: 'domains', domains: requested },\n },\n async (_request, plan) => {\n await ctx.waitForIdle();\n minorModeReloadHandoff = prepareMinorModeReloadHandoff(\n ctx,\n coordinator.hostGeneration,\n plan.operationId,\n plan.previous.minorModes,\n );\n const { persistHarnessSelection } = await dependencies.loadConfigJournal();\n const updated = await dependencies.applyDomains(requested, state);\n persistHarnessSelection(pi, updated);\n if (queued) commitReloadHandoff(queued);\n\n void telemetry.recordEvent(DOMAIN_EVENT.domainsSwitched, {\n 'harness.domains.previous': state.domains.join(','),\n 'harness.domains': requested.join(','),\n 'harness.transition.source': source,\n 'harness.transition.disposition': plan.disposition,\n 'harness.transition.operation_id': plan.operationId,\n });\n ctx.ui.notify(switchedSummary(requested), INFO);\n reloadRequested = true;\n return plan.externalRelaunchRequired ? 'queued' : 'applied';\n },\n );\n if (result.outcome === 'unchanged') {\n ctx.ui.notify(unchangedSummary(requested), INFO);\n // A voice switch still has to reload: the follow-up command is the\n // only thing that consumes the handoff the tool already committed to.\n if (queued) {\n commitReloadHandoff(queued);\n await ctx.waitForIdle();\n reloadRequested = true;\n }\n } else if (result.outcome === 'rejected' || result.outcome === 'stale') {\n throw transitionError(result);\n }\n } catch (error) {\n reloadRequested = false;\n minorModeReloadHandoff?.discard();\n minorModeReloadHandoff = undefined;\n if (queued && sessionIdentity) {\n dependencies.handoffs.discard(queued.token, sessionIdentity);\n discardVoiceReloadHandoff(queued.reloadHandoffToken, {\n sessionId: queued.sessionId,\n hostGeneration: queued.hostGeneration,\n });\n }\n void telemetry.recordError(DOMAIN_EVENT.domainsSwitchFailed, error);\n ctx.ui.notify(errorMessage(error), ERROR);\n }\n\n if (reloadRequested) {\n try {\n // Reload must be the handler's terminal action: Pi invalidates this\n // command context as soon as the replacement session is active.\n await ctx.reload();\n } catch (error) {\n minorModeReloadHandoff?.discard();\n throw error;\n }\n }\n },\n });\n}\n"],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import { DomainTelemetry } from "../types/telemetry.cjs";
2
+ import { DomainCompletion, DomainListing } from "../types/domains.cjs";
3
+ import { DomainSwitchHandoffStore } from "../types/handoff.cjs";
4
+ import { DoomHarnessContext, HarnessState } from "@agimon-ai/doompi-config/types";
5
+ import { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
6
+ //#region src/commands/domainsCommand.d.ts
7
+ /** Everything the manifest reader gives the command, resolved lazily behind it. */
8
+ interface DomainCatalogPort {
9
+ list(ctx: ExtensionContext): Promise<DomainListing>;
10
+ validate(ctx: ExtensionContext, values: readonly string[]): Promise<string[]>;
11
+ describe(ctx: ExtensionContext): Promise<Record<string, string | undefined>>;
12
+ completions(root: string, textBeforeCursor: string): Promise<DomainCompletion | undefined>;
13
+ }
14
+ interface DomainsCommandDependencies {
15
+ readonly catalog: DomainCatalogPort;
16
+ readonly handoffs: DomainSwitchHandoffStore;
17
+ readonly applyDomains: (domains: string[], state: DoomHarnessContext) => Promise<HarnessState>;
18
+ readonly loadConfigJournal: () => Promise<typeof import('@agimon-ai/doompi-config/piContext')>;
19
+ readonly loadPicker: () => Promise<typeof import('@agimon-ai/doompi-ui/components/matrixPicker')>;
20
+ }
21
+ declare function registerDomainsCommand(pi: ExtensionAPI, telemetry: DomainTelemetry, dependencies: DomainsCommandDependencies): void;
22
+ //#endregion
23
+ export { DomainCatalogPort, DomainsCommandDependencies, registerDomainsCommand };
24
+ //# sourceMappingURL=domainsCommand.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domainsCommand.d.cts","names":[],"sources":["../../src/commands/domainsCommand.ts"],"mappings":";;;;;;;UA8BiB;EACf,KAAK,KAAK,mBAAmB,QAAQ;EACrC,SAAS,KAAK,kBAAkB,4BAA4B;EAC5D,SAAS,KAAK,mBAAmB,QAAQ;EACzC,YAAY,cAAc,2BAA2B,QAAQ;;UAG9C;WACN,SAAS;WACT,UAAU;WACV,eAAe,mBAAmB,OAAO,uBAAuB,QAAQ;WACxE,yBAAyB;WACzB,kBAAkB;;iBAuCb,uBACd,IAAI,cACJ,WAAW,iBACX,cAAc"}
@@ -0,0 +1,24 @@
1
+ import { DomainTelemetry } from "../types/telemetry.mjs";
2
+ import { DomainCompletion, DomainListing } from "../types/domains.mjs";
3
+ import { DomainSwitchHandoffStore } from "../types/handoff.mjs";
4
+ import { DoomHarnessContext, HarnessState } from "@agimon-ai/doompi-config/types";
5
+ import { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
6
+ //#region src/commands/domainsCommand.d.ts
7
+ /** Everything the manifest reader gives the command, resolved lazily behind it. */
8
+ interface DomainCatalogPort {
9
+ list(ctx: ExtensionContext): Promise<DomainListing>;
10
+ validate(ctx: ExtensionContext, values: readonly string[]): Promise<string[]>;
11
+ describe(ctx: ExtensionContext): Promise<Record<string, string | undefined>>;
12
+ completions(root: string, textBeforeCursor: string): Promise<DomainCompletion | undefined>;
13
+ }
14
+ interface DomainsCommandDependencies {
15
+ readonly catalog: DomainCatalogPort;
16
+ readonly handoffs: DomainSwitchHandoffStore;
17
+ readonly applyDomains: (domains: string[], state: DoomHarnessContext) => Promise<HarnessState>;
18
+ readonly loadConfigJournal: () => Promise<typeof import('@agimon-ai/doompi-config/piContext')>;
19
+ readonly loadPicker: () => Promise<typeof import('@agimon-ai/doompi-ui/components/matrixPicker')>;
20
+ }
21
+ declare function registerDomainsCommand(pi: ExtensionAPI, telemetry: DomainTelemetry, dependencies: DomainsCommandDependencies): void;
22
+ //#endregion
23
+ export { DomainCatalogPort, DomainsCommandDependencies, registerDomainsCommand };
24
+ //# sourceMappingURL=domainsCommand.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domainsCommand.d.mts","names":[],"sources":["../../src/commands/domainsCommand.ts"],"mappings":";;;;;;;UA8BiB;EACf,KAAK,KAAK,mBAAmB,QAAQ;EACrC,SAAS,KAAK,kBAAkB,4BAA4B;EAC5D,SAAS,KAAK,mBAAmB,QAAQ;EACzC,YAAY,cAAc,2BAA2B,QAAQ;;UAG9C;WACN,SAAS;WACT,UAAU;WACV,eAAe,mBAAmB,OAAO,uBAAuB,QAAQ;WACxE,yBAAyB;WACzB,kBAAkB;;iBAuCb,uBACd,IAAI,cACJ,WAAW,iBACX,cAAc"}
@@ -0,0 +1,2 @@
1
+ import{DOMAIN_COMMAND as e,domainItems as t,domainSummary as n,errorMessage as r,pickerTitle as i,splitDomains as a,switchedSummary as o,transitionError as s,unchangedSummary as c,voiceSwitchToken as l}from"../services/domainText.mjs";import{DOMAIN_EVENT as u}from"../types/telemetry.mjs";import{requireDoomConfigContext as d}from"@agimon-ai/doompi-config/piContext";import{commitVoiceReloadHandoff as f,discardVoiceReloadHandoff as p}from"@agimon-ai/doompi-extension-contracts/voice-tools";import{prepareMinorModeReloadHandoff as m,requireDoomTransitionCoordinator as h}from"@agimon-ai/doompi-extension-contracts/transition";const g=`info`;function _(e){if(!f(e.reloadHandoffToken,{sessionId:e.sessionId,hostGeneration:e.hostGeneration}))throw Error(`The voice reload handoff is stale or was already consumed.`)}async function v(e,n){let r=await n.catalog.list(e),[{MatrixPickerComponent:a},o]=await Promise.all([n.loadPicker(),n.catalog.describe(e)]);return e.ui.custom((e,n,s,c)=>new a({title:i(r),items:t(r.available,o),selected:[...r.effective],multi:!0},n,s,c))}function y(t,i,f){t.registerCommand(e,{description:`Show the selected domains and pick a different set`,handler:async(e,y)=>{let b=d(y).harness,x,S,C,w=!1;try{let r=l(e);if(r&&(x={sessionId:y.sessionManager.getSessionId()},S=f.handoffs.consume(r,x),!S))throw Error(`The voice domain switch token is stale or belongs to another session.`);let d=S?[...S.domains]:a(e),p=!1;if(!S&&d.length===0&&y.mode===`tui`){let e=await v(y,f);if(e===void 0)return;d=e,p=!0}if(!S&&d.length===0&&!p){y.ui.notify(n(await f.catalog.list(y)),g);return}d=await f.catalog.validate(y,d);let T=h(y),E=S?`voice`:p?`ui`:`command`,D=await T.execute({sessionId:y.sessionManager.getSessionId(),hostGeneration:T.hostGeneration,operationId:S?.operationId??crypto.randomUUID(),source:E,target:{axis:`domains`,domains:d}},async(e,n)=>{await y.waitForIdle(),C=m(y,T.hostGeneration,n.operationId,n.previous.minorModes);let{persistHarnessSelection:r}=await f.loadConfigJournal();return r(t,await f.applyDomains(d,b)),S&&_(S),i.recordEvent(u.domainsSwitched,{"harness.domains.previous":b.domains.join(`,`),"harness.domains":d.join(`,`),"harness.transition.source":E,"harness.transition.disposition":n.disposition,"harness.transition.operation_id":n.operationId}),y.ui.notify(o(d),g),w=!0,n.externalRelaunchRequired?`queued`:`applied`});if(D.outcome===`unchanged`)y.ui.notify(c(d),g),S&&(_(S),await y.waitForIdle(),w=!0);else if(D.outcome===`rejected`||D.outcome===`stale`)throw s(D)}catch(e){w=!1,C?.discard(),C=void 0,S&&x&&(f.handoffs.discard(S.token,x),p(S.reloadHandoffToken,{sessionId:S.sessionId,hostGeneration:S.hostGeneration})),i.recordError(u.domainsSwitchFailed,e),y.ui.notify(r(e),`error`)}if(w)try{await y.reload()}catch(e){throw C?.discard(),e}}})}export{y as registerDomainsCommand};
2
+ //# sourceMappingURL=domainsCommand.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domainsCommand.mjs","names":[],"sources":["../../src/commands/domainsCommand.ts"],"sourcesContent":["import type { DoomHarnessContext, HarnessState } from '@agimon-ai/doompi-config/types';\nimport { requireDoomConfigContext } from '@agimon-ai/doompi-config/piContext';\nimport {\n type MinorModeReloadHandoffHandle,\n prepareMinorModeReloadHandoff,\n requireDoomTransitionCoordinator,\n type TransitionSource,\n} from '@agimon-ai/doompi-extension-contracts/transition';\nimport { commitVoiceReloadHandoff, discardVoiceReloadHandoff } from '@agimon-ai/doompi-extension-contracts/voice-tools';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport {\n DOMAIN_COMMAND,\n domainItems,\n domainSummary,\n errorMessage,\n pickerTitle,\n splitDomains,\n switchedSummary,\n transitionError,\n unchangedSummary,\n voiceSwitchToken,\n} from '../services/domainText.ts';\nimport type { DomainCompletion, DomainListing } from '../types/domains.ts';\nimport type { DomainSwitchHandoff, DomainSwitchHandoffStore } from '../types/handoff.ts';\nimport { DOMAIN_EVENT, type DomainTelemetry } from '../types/telemetry.ts';\n\nconst INFO = 'info';\nconst ERROR = 'error';\n\n/** Everything the manifest reader gives the command, resolved lazily behind it. */\nexport interface DomainCatalogPort {\n list(ctx: ExtensionContext): Promise<DomainListing>;\n validate(ctx: ExtensionContext, values: readonly string[]): Promise<string[]>;\n describe(ctx: ExtensionContext): Promise<Record<string, string | undefined>>;\n completions(root: string, textBeforeCursor: string): Promise<DomainCompletion | undefined>;\n}\n\nexport interface DomainsCommandDependencies {\n readonly catalog: DomainCatalogPort;\n readonly handoffs: DomainSwitchHandoffStore;\n readonly applyDomains: (domains: string[], state: DoomHarnessContext) => Promise<HarnessState>;\n readonly loadConfigJournal: () => Promise<typeof import('@agimon-ai/doompi-config/piContext')>;\n readonly loadPicker: () => Promise<typeof import('@agimon-ai/doompi-ui/components/matrixPicker')>;\n}\n\n/** Confirms the parked voice reload handoff, which the reload then acts on. */\nfunction commitReloadHandoff(queued: DomainSwitchHandoff): void {\n const committed = commitVoiceReloadHandoff(queued.reloadHandoffToken, {\n sessionId: queued.sessionId,\n hostGeneration: queued.hostGeneration,\n });\n if (!committed) throw new Error('The voice reload handoff is stale or was already consumed.');\n}\n\nasync function pickDomains(\n ctx: ExtensionContext,\n dependencies: DomainsCommandDependencies,\n): Promise<string[] | undefined> {\n const listing = await dependencies.catalog.list(ctx);\n const [{ MatrixPickerComponent }, descriptions] = await Promise.all([\n dependencies.loadPicker(),\n dependencies.catalog.describe(ctx),\n ]);\n // Domains compose, unlike a layer base, so this picker toggles with space and\n // confirms the whole set rather than replacing one value.\n return ctx.ui.custom<string[] | undefined>(\n (_tui, theme, keybindings, done) =>\n new MatrixPickerComponent(\n {\n title: pickerTitle(listing),\n items: domainItems(listing.available, descriptions),\n selected: [...listing.effective],\n multi: true,\n },\n theme,\n keybindings,\n done,\n ),\n );\n}\n\nexport function registerDomainsCommand(\n pi: ExtensionAPI,\n telemetry: DomainTelemetry,\n dependencies: DomainsCommandDependencies,\n): void {\n pi.registerCommand(DOMAIN_COMMAND, {\n description: 'Show the selected domains and pick a different set',\n handler: async (args, ctx) => {\n const state = requireDoomConfigContext(ctx).harness;\n let sessionIdentity: { readonly sessionId: string } | undefined;\n let queued: DomainSwitchHandoff | undefined;\n let minorModeReloadHandoff: MinorModeReloadHandoffHandle | undefined;\n let reloadRequested = false;\n try {\n const token = voiceSwitchToken(args);\n if (token) {\n sessionIdentity = { sessionId: ctx.sessionManager.getSessionId() };\n queued = dependencies.handoffs.consume(token, sessionIdentity);\n if (!queued) throw new Error('The voice domain switch token is stale or belongs to another session.');\n }\n\n let requested = queued ? [...queued.domains] : splitDomains(args);\n let pickerConfirmed = false;\n if (!queued && requested.length === 0 && ctx.mode === 'tui') {\n const chosen = await pickDomains(ctx, dependencies);\n if (chosen === undefined) return;\n requested = chosen;\n pickerConfirmed = true;\n }\n\n if (!queued && requested.length === 0 && !pickerConfirmed) {\n ctx.ui.notify(domainSummary(await dependencies.catalog.list(ctx)), INFO);\n return;\n }\n\n requested = await dependencies.catalog.validate(ctx, requested);\n const coordinator = requireDoomTransitionCoordinator(ctx);\n const source: TransitionSource = queued ? 'voice' : pickerConfirmed ? 'ui' : 'command';\n const result = await coordinator.execute(\n {\n sessionId: ctx.sessionManager.getSessionId(),\n hostGeneration: coordinator.hostGeneration,\n operationId: queued?.operationId ?? crypto.randomUUID(),\n source,\n target: { axis: 'domains', domains: requested },\n },\n async (_request, plan) => {\n await ctx.waitForIdle();\n minorModeReloadHandoff = prepareMinorModeReloadHandoff(\n ctx,\n coordinator.hostGeneration,\n plan.operationId,\n plan.previous.minorModes,\n );\n const { persistHarnessSelection } = await dependencies.loadConfigJournal();\n const updated = await dependencies.applyDomains(requested, state);\n persistHarnessSelection(pi, updated);\n if (queued) commitReloadHandoff(queued);\n\n void telemetry.recordEvent(DOMAIN_EVENT.domainsSwitched, {\n 'harness.domains.previous': state.domains.join(','),\n 'harness.domains': requested.join(','),\n 'harness.transition.source': source,\n 'harness.transition.disposition': plan.disposition,\n 'harness.transition.operation_id': plan.operationId,\n });\n ctx.ui.notify(switchedSummary(requested), INFO);\n reloadRequested = true;\n return plan.externalRelaunchRequired ? 'queued' : 'applied';\n },\n );\n if (result.outcome === 'unchanged') {\n ctx.ui.notify(unchangedSummary(requested), INFO);\n // A voice switch still has to reload: the follow-up command is the\n // only thing that consumes the handoff the tool already committed to.\n if (queued) {\n commitReloadHandoff(queued);\n await ctx.waitForIdle();\n reloadRequested = true;\n }\n } else if (result.outcome === 'rejected' || result.outcome === 'stale') {\n throw transitionError(result);\n }\n } catch (error) {\n reloadRequested = false;\n minorModeReloadHandoff?.discard();\n minorModeReloadHandoff = undefined;\n if (queued && sessionIdentity) {\n dependencies.handoffs.discard(queued.token, sessionIdentity);\n discardVoiceReloadHandoff(queued.reloadHandoffToken, {\n sessionId: queued.sessionId,\n hostGeneration: queued.hostGeneration,\n });\n }\n void telemetry.recordError(DOMAIN_EVENT.domainsSwitchFailed, error);\n ctx.ui.notify(errorMessage(error), ERROR);\n }\n\n if (reloadRequested) {\n try {\n // Reload must be the handler's terminal action: Pi invalidates this\n // command context as soon as the replacement session is active.\n await ctx.reload();\n } catch (error) {\n minorModeReloadHandoff?.discard();\n throw error;\n }\n }\n },\n });\n}\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("../adapters/pi/extension.cjs");exports.default=e.default,exports.domainsExtension=e.default;
@@ -0,0 +1,2 @@
1
+ import domainsExtension from "../adapters/pi/extension.cjs";
2
+ export { domainsExtension as default, domainsExtension };
@@ -0,0 +1,2 @@
1
+ import domainsExtension from "../adapters/pi/extension.mjs";
2
+ export { domainsExtension as default, domainsExtension };
@@ -0,0 +1 @@
1
+ import e from"../adapters/pi/extension.mjs";export{e as default,e as domainsExtension};
package/dist/index.cjs ADDED
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./services/toolNames.cjs"),t=require("./types/domains.cjs"),n=require("./services/domainText.cjs"),r=require("./adapters/domainCatalog.cjs"),i=require("./adapters/domainSwitchHandoff.cjs"),a=require("./types/telemetry.cjs"),o=require("./commands/domainsCommand.cjs"),s=require("./adapters/telemetry/logSinkTelemetry.cjs"),c=require("./schemas/domainVoiceTools.cjs"),l=require("./adapters/pi/voiceTool.cjs"),u=require("./adapters/pi/extension.cjs");exports.DOMAIN_COMMAND=n.DOMAIN_COMMAND,exports.DOMAIN_EVENT=a.DOMAIN_EVENT,exports.DOMAIN_NAMES_SCHEMA=c.DOMAIN_NAMES_SCHEMA,exports.DOMAIN_SOURCE=t.DOMAIN_SOURCE,exports.DOMAIN_SWITCH_HANDOFF_MAX_DOMAINS=i.DOMAIN_SWITCH_HANDOFF_MAX_DOMAINS,exports.DOMAIN_SWITCH_HANDOFF_MAX_IDENTIFIER_LENGTH=i.DOMAIN_SWITCH_HANDOFF_MAX_IDENTIFIER_LENGTH,exports.DOMAIN_SWITCH_HANDOFF_MAX_OPERATION_LENGTH=i.DOMAIN_SWITCH_HANDOFF_MAX_OPERATION_LENGTH,exports.DOMAIN_SWITCH_HANDOFF_TTL_MS=i.DOMAIN_SWITCH_HANDOFF_TTL_MS,exports.EMPTY_DOMAIN_INPUT_SCHEMA=c.EMPTY_DOMAIN_INPUT_SCHEMA,exports.LIST_DOMAINS_RESULT_SCHEMA=c.LIST_DOMAINS_RESULT_SCHEMA,exports.NONE=n.NONE,exports.SAFE_DOMAIN_NAME=t.SAFE_DOMAIN_NAME,exports.SWITCH_DOMAINS_INPUT_SCHEMA=c.SWITCH_DOMAINS_INPUT_SCHEMA,exports.SWITCH_DOMAINS_RESULT_SCHEMA=c.SWITCH_DOMAINS_RESULT_SCHEMA,exports.VOICE_SWITCH_TOKEN_PREFIX=n.VOICE_SWITCH_TOKEN_PREFIX,exports.createDomainCatalog=r.createDomainCatalog,exports.createDomainSwitchHandoffStore=i.createDomainSwitchHandoffStore,exports.createDomainTelemetry=s.createDomainTelemetry,exports.domainItems=n.domainItems,exports.domainSummary=n.domainSummary,exports.domainsExtension=u.default,exports.errorMessage=n.errorMessage,exports.normalizeDomainNames=n.normalizeDomainNames,exports.pickerTitle=n.pickerTitle,exports.registerDomainVoiceCapabilities=l.registerDomainVoiceCapabilities,exports.registerDomainsCommand=o.registerDomainsCommand,exports.splitDomains=n.splitDomains,exports.switchedSummary=n.switchedSummary,exports.toPiToolName=e.toPiToolName,exports.transitionError=n.transitionError,exports.unchangedSummary=n.unchangedSummary,exports.voiceSwitchToken=n.voiceSwitchToken;
@@ -0,0 +1,13 @@
1
+ import { DOMAIN_EVENT, DomainEventAttributes, DomainEventName, DomainTelemetry } from "./types/telemetry.cjs";
2
+ import domainsExtension from "./adapters/pi/extension.cjs";
3
+ import { DOMAIN_SOURCE, DomainCompletion, DomainListing, SAFE_DOMAIN_NAME } from "./types/domains.cjs";
4
+ import { DomainCatalog, createDomainCatalog } from "./adapters/domainCatalog.cjs";
5
+ import { DomainSwitchHandoff, DomainSwitchHandoffIdentity, DomainSwitchHandoffRequest, DomainSwitchHandoffStore } from "./types/handoff.cjs";
6
+ import { DOMAIN_SWITCH_HANDOFF_MAX_DOMAINS, DOMAIN_SWITCH_HANDOFF_MAX_IDENTIFIER_LENGTH, DOMAIN_SWITCH_HANDOFF_MAX_OPERATION_LENGTH, DOMAIN_SWITCH_HANDOFF_TTL_MS, createDomainSwitchHandoffStore } from "./adapters/domainSwitchHandoff.cjs";
7
+ import { DomainCatalogPort, DomainsCommandDependencies, registerDomainsCommand } from "./commands/domainsCommand.cjs";
8
+ import { registerDomainVoiceCapabilities } from "./adapters/pi/voiceTool.cjs";
9
+ import { DomainTelemetryOptions, createDomainTelemetry } from "./adapters/telemetry/logSinkTelemetry.cjs";
10
+ import { DOMAIN_NAMES_SCHEMA, EMPTY_DOMAIN_INPUT_SCHEMA, LIST_DOMAINS_RESULT_SCHEMA, ListDomainsResult, SWITCH_DOMAINS_INPUT_SCHEMA, SWITCH_DOMAINS_RESULT_SCHEMA, SwitchDomainsInput, SwitchDomainsResult } from "./schemas/domainVoiceTools.cjs";
11
+ import { DOMAIN_COMMAND, NONE, VOICE_SWITCH_TOKEN_PREFIX, domainItems, domainSummary, errorMessage, normalizeDomainNames, pickerTitle, splitDomains, switchedSummary, transitionError, unchangedSummary, voiceSwitchToken } from "./services/domainText.cjs";
12
+ import { toPiToolName } from "./services/toolNames.cjs";
13
+ export { DOMAIN_COMMAND, DOMAIN_EVENT, DOMAIN_NAMES_SCHEMA, DOMAIN_SOURCE, DOMAIN_SWITCH_HANDOFF_MAX_DOMAINS, DOMAIN_SWITCH_HANDOFF_MAX_IDENTIFIER_LENGTH, DOMAIN_SWITCH_HANDOFF_MAX_OPERATION_LENGTH, DOMAIN_SWITCH_HANDOFF_TTL_MS, type DomainCatalog, type DomainCatalogPort, type DomainCompletion, type DomainEventAttributes, type DomainEventName, type DomainListing, type DomainSwitchHandoff, type DomainSwitchHandoffIdentity, type DomainSwitchHandoffRequest, type DomainSwitchHandoffStore, type DomainTelemetry, type DomainTelemetryOptions, type DomainsCommandDependencies, EMPTY_DOMAIN_INPUT_SCHEMA, LIST_DOMAINS_RESULT_SCHEMA, type ListDomainsResult, NONE, SAFE_DOMAIN_NAME, SWITCH_DOMAINS_INPUT_SCHEMA, SWITCH_DOMAINS_RESULT_SCHEMA, type SwitchDomainsInput, type SwitchDomainsResult, VOICE_SWITCH_TOKEN_PREFIX, createDomainCatalog, createDomainSwitchHandoffStore, createDomainTelemetry, domainItems, domainSummary, domainsExtension, errorMessage, normalizeDomainNames, pickerTitle, registerDomainVoiceCapabilities, registerDomainsCommand, splitDomains, switchedSummary, toPiToolName, transitionError, unchangedSummary, voiceSwitchToken };
@@ -0,0 +1,13 @@
1
+ import { DOMAIN_EVENT, DomainEventAttributes, DomainEventName, DomainTelemetry } from "./types/telemetry.mjs";
2
+ import domainsExtension from "./adapters/pi/extension.mjs";
3
+ import { DOMAIN_SOURCE, DomainCompletion, DomainListing, SAFE_DOMAIN_NAME } from "./types/domains.mjs";
4
+ import { DomainCatalog, createDomainCatalog } from "./adapters/domainCatalog.mjs";
5
+ import { DomainSwitchHandoff, DomainSwitchHandoffIdentity, DomainSwitchHandoffRequest, DomainSwitchHandoffStore } from "./types/handoff.mjs";
6
+ import { DOMAIN_SWITCH_HANDOFF_MAX_DOMAINS, DOMAIN_SWITCH_HANDOFF_MAX_IDENTIFIER_LENGTH, DOMAIN_SWITCH_HANDOFF_MAX_OPERATION_LENGTH, DOMAIN_SWITCH_HANDOFF_TTL_MS, createDomainSwitchHandoffStore } from "./adapters/domainSwitchHandoff.mjs";
7
+ import { DomainCatalogPort, DomainsCommandDependencies, registerDomainsCommand } from "./commands/domainsCommand.mjs";
8
+ import { registerDomainVoiceCapabilities } from "./adapters/pi/voiceTool.mjs";
9
+ import { DomainTelemetryOptions, createDomainTelemetry } from "./adapters/telemetry/logSinkTelemetry.mjs";
10
+ import { DOMAIN_NAMES_SCHEMA, EMPTY_DOMAIN_INPUT_SCHEMA, LIST_DOMAINS_RESULT_SCHEMA, ListDomainsResult, SWITCH_DOMAINS_INPUT_SCHEMA, SWITCH_DOMAINS_RESULT_SCHEMA, SwitchDomainsInput, SwitchDomainsResult } from "./schemas/domainVoiceTools.mjs";
11
+ import { DOMAIN_COMMAND, NONE, VOICE_SWITCH_TOKEN_PREFIX, domainItems, domainSummary, errorMessage, normalizeDomainNames, pickerTitle, splitDomains, switchedSummary, transitionError, unchangedSummary, voiceSwitchToken } from "./services/domainText.mjs";
12
+ import { toPiToolName } from "./services/toolNames.mjs";
13
+ export { DOMAIN_COMMAND, DOMAIN_EVENT, DOMAIN_NAMES_SCHEMA, DOMAIN_SOURCE, DOMAIN_SWITCH_HANDOFF_MAX_DOMAINS, DOMAIN_SWITCH_HANDOFF_MAX_IDENTIFIER_LENGTH, DOMAIN_SWITCH_HANDOFF_MAX_OPERATION_LENGTH, DOMAIN_SWITCH_HANDOFF_TTL_MS, type DomainCatalog, type DomainCatalogPort, type DomainCompletion, type DomainEventAttributes, type DomainEventName, type DomainListing, type DomainSwitchHandoff, type DomainSwitchHandoffIdentity, type DomainSwitchHandoffRequest, type DomainSwitchHandoffStore, type DomainTelemetry, type DomainTelemetryOptions, type DomainsCommandDependencies, EMPTY_DOMAIN_INPUT_SCHEMA, LIST_DOMAINS_RESULT_SCHEMA, type ListDomainsResult, NONE, SAFE_DOMAIN_NAME, SWITCH_DOMAINS_INPUT_SCHEMA, SWITCH_DOMAINS_RESULT_SCHEMA, type SwitchDomainsInput, type SwitchDomainsResult, VOICE_SWITCH_TOKEN_PREFIX, createDomainCatalog, createDomainSwitchHandoffStore, createDomainTelemetry, domainItems, domainSummary, domainsExtension, errorMessage, normalizeDomainNames, pickerTitle, registerDomainVoiceCapabilities, registerDomainsCommand, splitDomains, switchedSummary, toPiToolName, transitionError, unchangedSummary, voiceSwitchToken };
package/dist/index.mjs ADDED
@@ -0,0 +1 @@
1
+ import{toPiToolName as e}from"./services/toolNames.mjs";import{DOMAIN_SOURCE as t,SAFE_DOMAIN_NAME as n}from"./types/domains.mjs";import{DOMAIN_COMMAND as r,NONE as i,VOICE_SWITCH_TOKEN_PREFIX as a,domainItems as o,domainSummary as s,errorMessage as c,normalizeDomainNames as l,pickerTitle as u,splitDomains as d,switchedSummary as f,transitionError as p,unchangedSummary as m,voiceSwitchToken as h}from"./services/domainText.mjs";import{createDomainCatalog as g}from"./adapters/domainCatalog.mjs";import{DOMAIN_SWITCH_HANDOFF_MAX_DOMAINS as _,DOMAIN_SWITCH_HANDOFF_MAX_IDENTIFIER_LENGTH as v,DOMAIN_SWITCH_HANDOFF_MAX_OPERATION_LENGTH as y,DOMAIN_SWITCH_HANDOFF_TTL_MS as b,createDomainSwitchHandoffStore as x}from"./adapters/domainSwitchHandoff.mjs";import{DOMAIN_EVENT as S}from"./types/telemetry.mjs";import{registerDomainsCommand as C}from"./commands/domainsCommand.mjs";import{createDomainTelemetry as w}from"./adapters/telemetry/logSinkTelemetry.mjs";import{DOMAIN_NAMES_SCHEMA as T,EMPTY_DOMAIN_INPUT_SCHEMA as E,LIST_DOMAINS_RESULT_SCHEMA as D,SWITCH_DOMAINS_INPUT_SCHEMA as O,SWITCH_DOMAINS_RESULT_SCHEMA as k}from"./schemas/domainVoiceTools.mjs";import{registerDomainVoiceCapabilities as A}from"./adapters/pi/voiceTool.mjs";import j from"./adapters/pi/extension.mjs";export{r as DOMAIN_COMMAND,S as DOMAIN_EVENT,T as DOMAIN_NAMES_SCHEMA,t as DOMAIN_SOURCE,_ as DOMAIN_SWITCH_HANDOFF_MAX_DOMAINS,v as DOMAIN_SWITCH_HANDOFF_MAX_IDENTIFIER_LENGTH,y as DOMAIN_SWITCH_HANDOFF_MAX_OPERATION_LENGTH,b as DOMAIN_SWITCH_HANDOFF_TTL_MS,E as EMPTY_DOMAIN_INPUT_SCHEMA,D as LIST_DOMAINS_RESULT_SCHEMA,i as NONE,n as SAFE_DOMAIN_NAME,O as SWITCH_DOMAINS_INPUT_SCHEMA,k as SWITCH_DOMAINS_RESULT_SCHEMA,a as VOICE_SWITCH_TOKEN_PREFIX,g as createDomainCatalog,x as createDomainSwitchHandoffStore,w as createDomainTelemetry,o as domainItems,s as domainSummary,j as domainsExtension,c as errorMessage,l as normalizeDomainNames,u as pickerTitle,A as registerDomainVoiceCapabilities,C as registerDomainsCommand,d as splitDomains,f as switchedSummary,e as toPiToolName,p as transitionError,m as unchangedSummary,h as voiceSwitchToken};
package/dist/mcp.cjs ADDED
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./adapters/mcpFilter.cjs"),t=require("./adapters/mcpSessionEnvironment.cjs");exports.PROXY_SERVER_NAME=e.PROXY_SERVER_NAME,exports.applyMcpAllowlist=e.applyMcpAllowlist,exports.filterMcpServers=e.filterMcpServers,exports.filterProxyConfig=e.filterProxyConfig,exports.mcpSessionEnvironment=t.mcpSessionEnvironment,exports.persistMcpConfig=e.persistMcpConfig,exports.resolveMcpAllowlist=e.resolveMcpAllowlist;
package/dist/mcp.d.cts ADDED
@@ -0,0 +1,3 @@
1
+ import { PROXY_SERVER_NAME, applyMcpAllowlist, filterMcpServers, filterProxyConfig, persistMcpConfig, resolveMcpAllowlist } from "./adapters/mcpFilter.cjs";
2
+ import { McpSessionEnvironmentInput, mcpSessionEnvironment } from "./adapters/mcpSessionEnvironment.cjs";
3
+ export { type McpSessionEnvironmentInput, PROXY_SERVER_NAME, applyMcpAllowlist, filterMcpServers, filterProxyConfig, mcpSessionEnvironment, persistMcpConfig, resolveMcpAllowlist };
package/dist/mcp.d.mts ADDED
@@ -0,0 +1,3 @@
1
+ import { PROXY_SERVER_NAME, applyMcpAllowlist, filterMcpServers, filterProxyConfig, persistMcpConfig, resolveMcpAllowlist } from "./adapters/mcpFilter.mjs";
2
+ import { McpSessionEnvironmentInput, mcpSessionEnvironment } from "./adapters/mcpSessionEnvironment.mjs";
3
+ export { type McpSessionEnvironmentInput, PROXY_SERVER_NAME, applyMcpAllowlist, filterMcpServers, filterProxyConfig, mcpSessionEnvironment, persistMcpConfig, resolveMcpAllowlist };
package/dist/mcp.mjs ADDED
@@ -0,0 +1 @@
1
+ import{PROXY_SERVER_NAME as e,applyMcpAllowlist as t,filterMcpServers as n,filterProxyConfig as r,persistMcpConfig as i,resolveMcpAllowlist as a}from"./adapters/mcpFilter.mjs";import{mcpSessionEnvironment as o}from"./adapters/mcpSessionEnvironment.mjs";export{e as PROXY_SERVER_NAME,t as applyMcpAllowlist,n as filterMcpServers,r as filterProxyConfig,o as mcpSessionEnvironment,i as persistMcpConfig,a as resolveMcpAllowlist};
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./adapters/pluginMaterializer.cjs");exports.materializePluginEntries=e.materializePluginEntries;
@@ -0,0 +1,2 @@
1
+ import { PluginMaterializerOptions, PluginSourceMaterializers, materializePluginEntries } from "./adapters/pluginMaterializer.cjs";
2
+ export { type PluginMaterializerOptions, type PluginSourceMaterializers, materializePluginEntries };
@@ -0,0 +1,2 @@
1
+ import { PluginMaterializerOptions, PluginSourceMaterializers, materializePluginEntries } from "./adapters/pluginMaterializer.mjs";
2
+ export { type PluginMaterializerOptions, type PluginSourceMaterializers, materializePluginEntries };
@@ -0,0 +1 @@
1
+ import{materializePluginEntries as e}from"./adapters/pluginMaterializer.mjs";export{e as materializePluginEntries};
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./adapters/skillCacheLocation.cjs"),t=require("./adapters/resourceCollector.cjs");exports.DISPATCHER_AGENT_NAME=t.DISPATCHER_AGENT_NAME,exports.adaptAgentDefinition=t.adaptAgentDefinition,exports.collectResources=t.collectResources,exports.discoverSkills=t.discoverSkills,exports.discoverSkillsAsync=t.discoverSkillsAsync,exports.mergeMcpConfigs=t.mergeMcpConfigs,exports.mergeMcpConfigsAsync=t.mergeMcpConfigsAsync,exports.resolveSkillCacheDirectory=e.resolveSkillCacheDirectory,exports.sanitizeSyncLabel=e.sanitizeSyncLabel;
@@ -0,0 +1,4 @@
1
+ import { HarnessResourceOptions, HarnessResources, JsonObject, NamedResource } from "./types/resources.cjs";
2
+ import { DISPATCHER_AGENT_NAME, adaptAgentDefinition, collectResources, discoverSkills, discoverSkillsAsync, mergeMcpConfigs, mergeMcpConfigsAsync } from "./adapters/resourceCollector.cjs";
3
+ import { resolveSkillCacheDirectory, sanitizeSyncLabel } from "./adapters/skillCacheLocation.cjs";
4
+ export { DISPATCHER_AGENT_NAME, type HarnessResourceOptions, type HarnessResources, type JsonObject, type NamedResource, adaptAgentDefinition, collectResources, discoverSkills, discoverSkillsAsync, mergeMcpConfigs, mergeMcpConfigsAsync, resolveSkillCacheDirectory, sanitizeSyncLabel };
@@ -0,0 +1,4 @@
1
+ import { HarnessResourceOptions, HarnessResources, JsonObject, NamedResource } from "./types/resources.mjs";
2
+ import { DISPATCHER_AGENT_NAME, adaptAgentDefinition, collectResources, discoverSkills, discoverSkillsAsync, mergeMcpConfigs, mergeMcpConfigsAsync } from "./adapters/resourceCollector.mjs";
3
+ import { resolveSkillCacheDirectory, sanitizeSyncLabel } from "./adapters/skillCacheLocation.mjs";
4
+ export { DISPATCHER_AGENT_NAME, type HarnessResourceOptions, type HarnessResources, type JsonObject, type NamedResource, adaptAgentDefinition, collectResources, discoverSkills, discoverSkillsAsync, mergeMcpConfigs, mergeMcpConfigsAsync, resolveSkillCacheDirectory, sanitizeSyncLabel };
@@ -0,0 +1 @@
1
+ import{resolveSkillCacheDirectory as e,sanitizeSyncLabel as t}from"./adapters/skillCacheLocation.mjs";import{DISPATCHER_AGENT_NAME as n,adaptAgentDefinition as r,collectResources as i,discoverSkills as a,discoverSkillsAsync as o,mergeMcpConfigs as s,mergeMcpConfigsAsync as c}from"./adapters/resourceCollector.mjs";export{n as DISPATCHER_AGENT_NAME,r as adaptAgentDefinition,i as collectResources,a as discoverSkills,o as discoverSkillsAsync,s as mergeMcpConfigs,c as mergeMcpConfigsAsync,e as resolveSkillCacheDirectory,t as sanitizeSyncLabel};
@@ -0,0 +1,2 @@
1
+ const e=require("../types/domains.cjs");let t=require("@agimon-ai/doompi-extension-contracts/voice-tools"),n=require("typebox");const r=n.Type.Array(n.Type.String({minLength:1,maxLength:t.VOICE_TOOL_MAX_IDENTIFIER_LENGTH,pattern:e.SAFE_DOMAIN_NAME.source}),{maxItems:t.VOICE_TOOL_MAX_DOMAIN_COUNT}),i=n.Type.Object({},{additionalProperties:!1}),a=n.Type.Object({active:r,effective:r,available:r},{additionalProperties:!1}),o=n.Type.Object({domains:r},{additionalProperties:!1}),s=n.Type.Object({status:n.Type.Literal(`queued`),stopBatch:n.Type.Literal(`session-reload`)},{additionalProperties:!1});exports.DOMAIN_NAMES_SCHEMA=r,exports.EMPTY_DOMAIN_INPUT_SCHEMA=i,exports.LIST_DOMAINS_RESULT_SCHEMA=a,exports.SWITCH_DOMAINS_INPUT_SCHEMA=o,exports.SWITCH_DOMAINS_RESULT_SCHEMA=s;
2
+ //# sourceMappingURL=domainVoiceTools.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domainVoiceTools.cjs","names":["Type","VOICE_TOOL_MAX_IDENTIFIER_LENGTH","SAFE_DOMAIN_NAME","VOICE_TOOL_MAX_DOMAIN_COUNT"],"sources":["../../src/schemas/domainVoiceTools.ts"],"sourcesContent":["import {\n VOICE_TOOL_MAX_DOMAIN_COUNT,\n VOICE_TOOL_MAX_IDENTIFIER_LENGTH,\n} from '@agimon-ai/doompi-extension-contracts/voice-tools';\nimport { type Static, Type } from 'typebox';\nimport { SAFE_DOMAIN_NAME } from '../types/domains.ts';\n\nexport const DOMAIN_NAMES_SCHEMA = Type.Array(\n Type.String({ minLength: 1, maxLength: VOICE_TOOL_MAX_IDENTIFIER_LENGTH, pattern: SAFE_DOMAIN_NAME.source }),\n { maxItems: VOICE_TOOL_MAX_DOMAIN_COUNT },\n);\n\nexport const EMPTY_DOMAIN_INPUT_SCHEMA = Type.Object({}, { additionalProperties: false });\n\nexport const LIST_DOMAINS_RESULT_SCHEMA = Type.Object(\n {\n active: DOMAIN_NAMES_SCHEMA,\n effective: DOMAIN_NAMES_SCHEMA,\n available: DOMAIN_NAMES_SCHEMA,\n },\n { additionalProperties: false },\n);\n\nexport const SWITCH_DOMAINS_INPUT_SCHEMA = Type.Object(\n {\n domains: DOMAIN_NAMES_SCHEMA,\n },\n { additionalProperties: false },\n);\n\nexport const SWITCH_DOMAINS_RESULT_SCHEMA = Type.Object(\n {\n status: Type.Literal('queued'),\n stopBatch: Type.Literal('session-reload'),\n },\n { additionalProperties: false },\n);\n\nexport type ListDomainsResult = Static<typeof LIST_DOMAINS_RESULT_SCHEMA>;\nexport type SwitchDomainsInput = Static<typeof SWITCH_DOMAINS_INPUT_SCHEMA>;\nexport type SwitchDomainsResult = Static<typeof SWITCH_DOMAINS_RESULT_SCHEMA>;\n"],"mappings":"gIAOA,MAAa,EAAsBA,EAAAA,KAAK,MACtCA,EAAAA,KAAK,OAAO,CAAE,UAAW,EAAG,UAAWC,EAAAA,iCAAkC,QAASC,EAAAA,iBAAiB,MAAO,CAAC,EAC3G,CAAE,SAAUC,EAAAA,2BAA4B,CAC1C,EAEa,EAA4BH,EAAAA,KAAK,OAAO,CAAC,EAAG,CAAE,qBAAsB,EAAM,CAAC,EAE3E,EAA6BA,EAAAA,KAAK,OAC7C,CACE,OAAQ,EACR,UAAW,EACX,UAAW,CACb,EACA,CAAE,qBAAsB,EAAM,CAChC,EAEa,EAA8BA,EAAAA,KAAK,OAC9C,CACE,QAAS,CACX,EACA,CAAE,qBAAsB,EAAM,CAChC,EAEa,EAA+BA,EAAAA,KAAK,OAC/C,CACE,OAAQA,EAAAA,KAAK,QAAQ,QAAQ,EAC7B,UAAWA,EAAAA,KAAK,QAAQ,gBAAgB,CAC1C,EACA,CAAE,qBAAsB,EAAM,CAChC"}
@@ -0,0 +1,22 @@
1
+ import { Static, Type } from "typebox";
2
+ //#region src/schemas/domainVoiceTools.d.ts
3
+ declare const DOMAIN_NAMES_SCHEMA: Type.TArray<Type.TString>;
4
+ declare const EMPTY_DOMAIN_INPUT_SCHEMA: Type.TObject<{}>;
5
+ declare const LIST_DOMAINS_RESULT_SCHEMA: Type.TObject<{
6
+ active: Type.TArray<Type.TString>;
7
+ effective: Type.TArray<Type.TString>;
8
+ available: Type.TArray<Type.TString>;
9
+ }>;
10
+ declare const SWITCH_DOMAINS_INPUT_SCHEMA: Type.TObject<{
11
+ domains: Type.TArray<Type.TString>;
12
+ }>;
13
+ declare const SWITCH_DOMAINS_RESULT_SCHEMA: Type.TObject<{
14
+ status: Type.TLiteral<"queued">;
15
+ stopBatch: Type.TLiteral<"session-reload">;
16
+ }>;
17
+ type ListDomainsResult = Static<typeof LIST_DOMAINS_RESULT_SCHEMA>;
18
+ type SwitchDomainsInput = Static<typeof SWITCH_DOMAINS_INPUT_SCHEMA>;
19
+ type SwitchDomainsResult = Static<typeof SWITCH_DOMAINS_RESULT_SCHEMA>;
20
+ //#endregion
21
+ export { DOMAIN_NAMES_SCHEMA, EMPTY_DOMAIN_INPUT_SCHEMA, LIST_DOMAINS_RESULT_SCHEMA, ListDomainsResult, SWITCH_DOMAINS_INPUT_SCHEMA, SWITCH_DOMAINS_RESULT_SCHEMA, SwitchDomainsInput, SwitchDomainsResult };
22
+ //# sourceMappingURL=domainVoiceTools.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domainVoiceTools.d.cts","names":[],"sources":["../../src/schemas/domainVoiceTools.ts"],"mappings":";;cAOa,qBAAmB,KAAA,OAAA,KAAA;cAKnB,2BAAyB,KAAA;cAEzB,4BAA0B,KAAA;;;;;cAS1B,6BAA2B,KAAA;;;cAO3B,8BAA4B,KAAA;;;;KAQ7B,oBAAoB,cAAc;KAClC,qBAAqB,cAAc;KACnC,sBAAsB,cAAc"}