@xopcai/xopc 0.0.106 → 0.0.108

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 (183) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/dashscope/xopc.extension.json +7 -2
  3. package/dist/extensions/fal/xopc.extension.json +7 -2
  4. package/dist/extensions/feishu/src/adapters/gateway-setup.js +22 -26
  5. package/dist/extensions/feishu/src/adapters/gateway-setup.js.map +1 -1
  6. package/dist/extensions/feishu/xopc.extension.json +458 -26
  7. package/dist/extensions/google/xopc.extension.json +7 -2
  8. package/dist/extensions/minimax/xopc.extension.json +8 -2
  9. package/dist/extensions/openai/xopc.extension.json +7 -2
  10. package/dist/extensions/telegram/xopc.extension.json +10 -2
  11. package/dist/extensions/weixin/xopc.extension.json +57 -14
  12. package/dist/gateway/static/root/apple-touch-icon.png +0 -0
  13. package/dist/gateway/static/root/assets/agents-56kCGHdV.js +78 -0
  14. package/dist/gateway/static/root/assets/apps-page-Dd88J47r.js +1 -0
  15. package/dist/gateway/static/root/assets/channels-settings-Ckyvnvml.js +1 -0
  16. package/dist/gateway/static/root/assets/cron-page-DKo2ZdRA.js +1 -0
  17. package/dist/gateway/static/root/assets/{dist-OM9qGfm5.js → dist-dmxWdtPG.js} +1 -1
  18. package/dist/gateway/static/root/assets/{extension-debug-page-D-WHrr_w.js → extension-debug-page-iGpG-vpp.js} +1 -1
  19. package/dist/gateway/static/root/assets/{extension-page-CCgjSoKn.js → extension-page-I7-3uHiD.js} +1 -1
  20. package/dist/gateway/static/root/assets/{extension-settings-page-BJH5a-Gn.js → extension-settings-page-BisnHG7r.js} +1 -1
  21. package/dist/gateway/static/root/assets/{fetch-CkvRO30i.js → fetch-CFdKBnE6.js} +1 -1
  22. package/dist/gateway/static/root/assets/{gateway-startup-retry-BkKyRDrF.js → gateway-startup-retry-DdngdObI.js} +1 -1
  23. package/dist/gateway/static/root/assets/{heartbeat-config-api-CVyP6pFj.js → heartbeat-config-api-tbWAFPN8.js} +1 -1
  24. package/dist/gateway/static/root/assets/index-DI5_GsZt.css +1 -0
  25. package/dist/gateway/static/root/assets/index-slwUkhxH.js +4845 -0
  26. package/dist/gateway/static/root/assets/{logs-page-R6Vv_Ja6.js → logs-page-CCZiXrWu.js} +2 -2
  27. package/dist/gateway/static/root/assets/{note-detail-page-BUDarLhh.js → note-detail-page-BYbw2GLl.js} +4 -4
  28. package/dist/gateway/static/root/assets/{note-time-Cc2-T21g.js → note-time-Cya72Lte.js} +1 -1
  29. package/dist/gateway/static/root/assets/notes-page-DrAO7VRK.js +1 -0
  30. package/dist/gateway/static/root/assets/{schema-form-CrlOmEZt.js → schema-form-a6UJCK55.js} +1 -1
  31. package/dist/gateway/static/root/assets/sessions-page-DNU3Ymvz.js +1 -0
  32. package/dist/gateway/static/root/assets/{settings-advanced-gate-BBAQxxew.js → settings-advanced-gate-CyEJYTbw.js} +1 -1
  33. package/dist/gateway/static/root/assets/{settings-form-section-DjPD-ErC.js → settings-form-section-DpHo2ecA.js} +1 -1
  34. package/dist/gateway/static/root/assets/settings-page-YRwe4q56.js +3 -0
  35. package/dist/gateway/static/root/assets/{share-preview-page-BjvPht3V.js → share-preview-page-B7rf4QB4.js} +1 -1
  36. package/dist/gateway/static/root/assets/skills-page-we1NAt7u.js +2 -0
  37. package/dist/gateway/static/root/assets/{theme-store-DYgVdRB4.js → theme-store-BZozwAeK.js} +1 -1
  38. package/dist/gateway/static/root/assets/url-DQRqHuL-.js +3 -0
  39. package/dist/gateway/static/root/assets/voice-api-key-field-Btagks_B.js +1 -0
  40. package/dist/gateway/static/root/assets/{workflow-page.utils-D4sqR0yX.js → workflow-page.utils-DvzJKs6W.js} +1 -1
  41. package/dist/gateway/static/root/assets/workflows-page-BgOAgCOG.js +18 -0
  42. package/dist/gateway/static/root/favicon-16.png +0 -0
  43. package/dist/gateway/static/root/favicon-32.png +0 -0
  44. package/dist/gateway/static/root/favicon.ico +0 -0
  45. package/dist/gateway/static/root/favicon.svg +18 -0
  46. package/dist/gateway/static/root/index.html +11 -10
  47. package/dist/package.js +1 -1
  48. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.d.ts +4 -0
  49. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js +4 -2
  50. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js.map +1 -1
  51. package/dist/src/agent/starter-agents.d.ts +19 -0
  52. package/dist/src/agent/starter-agents.js +190 -0
  53. package/dist/src/agent/starter-agents.js.map +1 -0
  54. package/dist/src/agent/workflow/runtime.js +49 -15
  55. package/dist/src/agent/workflow/runtime.js.map +1 -1
  56. package/dist/src/agent/workflow/types.d.ts +11 -0
  57. package/dist/src/channels/catalog/channel-catalog-service.js +13 -0
  58. package/dist/src/channels/catalog/channel-catalog-service.js.map +1 -1
  59. package/dist/src/channels/plugins/types.adapters.d.ts +2 -0
  60. package/dist/src/cli/commands/extension-create.d.ts +2 -0
  61. package/dist/src/cli/commands/extension-create.js +165 -0
  62. package/dist/src/cli/commands/extension-create.js.map +1 -0
  63. package/dist/src/cli/commands/extension-dev.js +0 -2
  64. package/dist/src/cli/commands/extension-dev.js.map +1 -1
  65. package/dist/src/cli/commands/extension-marketplace.js +104 -80
  66. package/dist/src/cli/commands/extension-marketplace.js.map +1 -1
  67. package/dist/src/cli/commands/extension-pack.d.ts +13 -0
  68. package/dist/src/cli/commands/extension-pack.js +159 -91
  69. package/dist/src/cli/commands/extension-pack.js.map +1 -1
  70. package/dist/src/cli/commands/extension.d.ts +2 -0
  71. package/dist/src/cli/commands/extension.js +375 -3
  72. package/dist/src/cli/commands/extension.js.map +1 -1
  73. package/dist/src/cli/commands/gateway/run-foreground.js +1 -2
  74. package/dist/src/cli/commands/gateway/run-foreground.js.map +1 -1
  75. package/dist/src/cli/commands/onboard.js +0 -2
  76. package/dist/src/cli/commands/onboard.js.map +1 -1
  77. package/dist/src/cli/commands/setup.js +0 -2
  78. package/dist/src/cli/commands/setup.js.map +1 -1
  79. package/dist/src/cli/utils/init-workspace-core.js +9 -6
  80. package/dist/src/cli/utils/init-workspace-core.js.map +1 -1
  81. package/dist/src/config/paths.d.ts +2 -2
  82. package/dist/src/config/paths.js +10 -6
  83. package/dist/src/config/paths.js.map +1 -1
  84. package/dist/src/config/schema.d.ts +2 -0
  85. package/dist/src/config/schema.js +3 -1
  86. package/dist/src/config/schema.js.map +1 -1
  87. package/dist/src/extensions/api.d.ts +4 -2
  88. package/dist/src/extensions/api.js +31 -12
  89. package/dist/src/extensions/api.js.map +1 -1
  90. package/dist/src/extensions/discover-extensions.js +1 -0
  91. package/dist/src/extensions/discover-extensions.js.map +1 -1
  92. package/dist/src/extensions/install.d.ts +1 -0
  93. package/dist/src/extensions/install.js +51 -8
  94. package/dist/src/extensions/install.js.map +1 -1
  95. package/dist/src/extensions/loader.d.ts +0 -4
  96. package/dist/src/extensions/loader.js +54 -87
  97. package/dist/src/extensions/loader.js.map +1 -1
  98. package/dist/src/extensions/lockfile.d.ts +9 -1
  99. package/dist/src/extensions/lockfile.js.map +1 -1
  100. package/dist/src/extensions/normalize-manifest.js +20 -4
  101. package/dist/src/extensions/normalize-manifest.js.map +1 -1
  102. package/dist/src/extensions/package-contract.d.ts +12 -0
  103. package/dist/src/extensions/package-contract.js +59 -0
  104. package/dist/src/extensions/package-contract.js.map +1 -0
  105. package/dist/src/extensions/sdk/core.d.ts +1 -1
  106. package/dist/src/extensions/sdk/index.d.ts +1 -1
  107. package/dist/src/extensions/sdk/index.js.map +1 -1
  108. package/dist/src/extensions/types/manifest.d.ts +15 -0
  109. package/dist/src/gateway/agents-admin.d.ts +0 -8
  110. package/dist/src/gateway/agents-admin.js +1 -26
  111. package/dist/src/gateway/agents-admin.js.map +1 -1
  112. package/dist/src/gateway/hono/routes/agents.js +1 -55
  113. package/dist/src/gateway/hono/routes/agents.js.map +1 -1
  114. package/dist/src/gateway/hono/routes/channels.js +10 -1
  115. package/dist/src/gateway/hono/routes/channels.js.map +1 -1
  116. package/dist/src/gateway/hono/routes/workflows.js +130 -0
  117. package/dist/src/gateway/hono/routes/workflows.js.map +1 -1
  118. package/dist/src/gateway/service.d.ts +2 -0
  119. package/dist/src/gateway/service.js +44 -0
  120. package/dist/src/gateway/service.js.map +1 -1
  121. package/dist/src/notes/agent-context.d.ts +12 -4
  122. package/dist/src/notes/agent-context.js.map +1 -1
  123. package/dist/src/tui/backends/embedded-backend.js +0 -7
  124. package/dist/src/tui/backends/embedded-backend.js.map +1 -1
  125. package/dist/src/tui/backends/gateway-sse-backend.js +0 -7
  126. package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
  127. package/dist/src/tui/tui-backend.d.ts +0 -1
  128. package/dist/src/tui/tui-commands.js +1 -1
  129. package/dist/src/tui/tui-commands.js.map +1 -1
  130. package/dist/src/tui/tui-picker-overlay.js +1 -1
  131. package/dist/src/tui/tui-picker-overlay.js.map +1 -1
  132. package/dist/src/workflows/domain/definition-utils.d.ts +1 -0
  133. package/dist/src/workflows/domain/definition-utils.js +32 -2
  134. package/dist/src/workflows/domain/definition-utils.js.map +1 -1
  135. package/dist/src/workflows/domain/definition.d.ts +2 -0
  136. package/dist/src/workflows/domain/event.d.ts +2 -1
  137. package/dist/src/workflows/domain/index.d.ts +1 -0
  138. package/dist/src/workflows/domain/index.js +3 -2
  139. package/dist/src/workflows/domain/run.d.ts +27 -1
  140. package/dist/src/workflows/domain/run.js.map +1 -1
  141. package/dist/src/workflows/domain/schema-validation.d.ts +8 -0
  142. package/dist/src/workflows/domain/schema-validation.js +28 -0
  143. package/dist/src/workflows/domain/schema-validation.js.map +1 -0
  144. package/dist/src/workflows/draft/index.d.ts +3 -0
  145. package/dist/src/workflows/draft/index.js +3 -0
  146. package/dist/src/workflows/draft/workflow-draft-prompt.d.ts +23 -0
  147. package/dist/src/workflows/draft/workflow-draft-prompt.js +98 -0
  148. package/dist/src/workflows/draft/workflow-draft-prompt.js.map +1 -0
  149. package/dist/src/workflows/draft/workflow-draft-service.d.ts +12 -0
  150. package/dist/src/workflows/draft/workflow-draft-service.js +131 -0
  151. package/dist/src/workflows/draft/workflow-draft-service.js.map +1 -0
  152. package/dist/src/workflows/draft/workflow-draft-validator.d.ts +4 -0
  153. package/dist/src/workflows/draft/workflow-draft-validator.js +133 -0
  154. package/dist/src/workflows/draft/workflow-draft-validator.js.map +1 -0
  155. package/dist/src/workflows/draft/workflow-draft.types.d.ts +44 -0
  156. package/dist/src/workflows/draft/workflow-draft.types.js +1 -0
  157. package/dist/src/workflows/engine/projector.js +1 -0
  158. package/dist/src/workflows/engine/projector.js.map +1 -1
  159. package/dist/src/workflows/engine/workflow-engine.d.ts +18 -0
  160. package/dist/src/workflows/engine/workflow-engine.js +320 -11
  161. package/dist/src/workflows/engine/workflow-engine.js.map +1 -1
  162. package/dist/src/workflows/index.js +4 -3
  163. package/dist/src/workflows/service/workflow-run-service.d.ts +14 -3
  164. package/dist/src/workflows/service/workflow-run-service.js +227 -6
  165. package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
  166. package/dist/src/workflows/service/workflow-run-service.types.d.ts +7 -2
  167. package/package.json +4 -2
  168. package/dist/gateway/static/root/assets/agents-3eP0vqFO.js +0 -396
  169. package/dist/gateway/static/root/assets/apps-page-CZ2ZKrko.js +0 -1
  170. package/dist/gateway/static/root/assets/channels-settings-BbETa93K.js +0 -1
  171. package/dist/gateway/static/root/assets/cron-page-DCtUkHMu.js +0 -1
  172. package/dist/gateway/static/root/assets/index-BPYKW7FB.css +0 -1
  173. package/dist/gateway/static/root/assets/index-CEZxETzw.js +0 -4845
  174. package/dist/gateway/static/root/assets/notes-page-EAHl16bq.js +0 -1
  175. package/dist/gateway/static/root/assets/sessions-page-Ce_xuuSB.js +0 -1
  176. package/dist/gateway/static/root/assets/settings-page-KhQ9QgH0.js +0 -3
  177. package/dist/gateway/static/root/assets/skills-page-C0laq7l1.js +0 -2
  178. package/dist/gateway/static/root/assets/url-DPEStU4M.js +0 -3
  179. package/dist/gateway/static/root/assets/voice-api-key-field-DeGckWkl.js +0 -1
  180. package/dist/gateway/static/root/assets/workflows-page-DFjM95g5.js +0 -27
  181. package/dist/src/agent/builtin-agent-ids.d.ts +0 -2
  182. package/dist/src/agent/builtin-agent-ids.js +0 -17
  183. package/dist/src/agent/builtin-agent-ids.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"onboard.js","names":["runModelSetup","runChannelOnboard"],"sources":["../../../../src/cli/commands/onboard.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { select } from '@inquirer/prompts';\nimport { saveConfig } from '../../config/index.js';\nimport { register, formatExamples } from '../registry.js';\nimport type { CLIContext } from '../registry.js';\nimport type { Config } from '../../config/schema.js';\nimport { setupModel as runModelSetup } from './onboard/model.js';\nimport { colors } from '../utils/colors.js';\nimport { setupChannels as runChannelOnboard, getChannelConfigurators } from './onboard/channels/index.js';\nimport { seedMainAgentProfileMarkdown } from '../../agent/context/workspace-seed.js';\nimport { resolveGatewayLocalClientHost } from '../../config/gateway-bind.js';\nimport { initWorkspace } from '../utils/init-workspace.js';\nimport { ConfigSchema } from '../../config/schema.js';\n\nfunction isInteractive(): boolean {\n return process.stdin.isTTY && process.stdout.isTTY;\n}\n\nasync function setupNonInteractive(_configPath: string, existingConfig: Config): Promise<Config> {\n console.log('\\n🤖 AI Model Configuration (Non-Interactive Mode)\\n');\n console.log('Current config:', JSON.stringify(existingConfig.agents?.defaults?.models?.chat, null, 2));\n console.log('\\n💡 To configure in interactive mode, run: xopc onboard');\n console.log('💡 Or set up manually in:', _configPath);\n return existingConfig;\n}\n\nfunction createOnboardCommand(ctx: CLIContext): Command {\n const cmd = new Command('onboard')\n .description('Interactive setup wizard for xopc (gateway uses schema defaults)')\n .addHelpText(\n 'after',\n formatExamples([\n 'xopc onboard # Full interactive setup',\n 'xopc onboard --model # Configure LLM model only',\n 'xopc onboard --channels # Configure messaging channels',\n 'xopc onboard --gateway # Apply default gateway settings (quiet)',\n ])\n )\n .option('--model', 'Configure LLM provider and model')\n .option('--channels', 'Configure messaging channels')\n .option('--gateway', 'Configure gateway WebUI')\n .option('--all', 'Configure everything (default)')\n .action(async (options) => {\n try {\n await runOnboard(options, ctx);\n } catch (error: unknown) {\n const err = error as { name?: string; code?: string };\n if (err?.name === 'ExitPromptError' || err?.code === 'EXIT_PROMPT') {\n console.log('\\n\\n👋 Setup cancelled.');\n process.exit(0);\n }\n throw error;\n }\n });\n\n return cmd;\n}\n\ntype OnboardOptions = {\n model?: boolean;\n channels?: boolean;\n gateway?: boolean;\n all?: boolean;\n};\n\nasync function runOnboard(\n options: OnboardOptions,\n ctx: CLIContext\n): Promise<void> {\n console.log(colors.cyan('\\n🚀 Welcome to xopc setup!\\n'));\n console.log('═'.repeat(50));\n\n const workspacePath = ctx.workspacePath;\n const configPath = ctx.configPath;\n\n const initResult = await initWorkspace({ configPath, workspacePath });\n let config = initResult.config;\n\n // Determine what to configure based on options\n const doModel = options.model || options.all || (!options.channels && !options.gateway);\n const doChannels = options.channels || options.all || (!options.model && !options.gateway);\n const doGateway = options.gateway || options.all || (!options.model && !options.channels);\n const runFullWizard = !options.model && !options.channels && !options.gateway;\n /** Any setup step besides the unified launch prompt ran in interactive flow. */\n const didConfigurableSteps = doModel || doChannels || doGateway;\n\n if (!isInteractive()) {\n // Non-interactive mode\n if (doModel) {\n config = await setupNonInteractive(configPath, config);\n }\n if (doChannels) {\n console.log('\\n💬 Channels Configuration (Non-Interactive Mode)\\n');\n console.log('💡 To configure channels, edit the config file manually.');\n }\n if (doGateway) {\n console.log('\\n🌐 Gateway Configuration (Non-Interactive Mode)\\n');\n console.log('💡 To configure gateway, edit the config file manually.');\n }\n } else {\n // Interactive mode\n if (doModel) {\n config = await runModelSetup(config, ctx);\n }\n\n if (doChannels) {\n const channelIds = (await getChannelConfigurators(config)).map(c => c.id);\n console.log(colors.gray(`\\nChannel onboarding: ${channelIds.join(', ')}\\n`));\n config = await runChannelOnboard(config);\n }\n\n if (doGateway) {\n config = await setupGateway(config);\n }\n }\n\n // Save config once at the end\n await saveConfig(config as Config, configPath);\n\n seedMainAgentProfileMarkdown(config as Config);\n\n console.log('\\n' + '═'.repeat(50));\n console.log('\\n🎉 Setup Complete!\\n');\n\n const gatewayAuth = (config as any)?.gateway?.auth;\n const gatewayConfigured =\n gatewayAuth?.mode === 'token' &&\n typeof gatewayAuth?.token === 'string' &&\n gatewayAuth.token.length > 0;\n const port = (config as Config)?.gateway?.port ?? 18790;\n const displayHost = resolveGatewayLocalClientHost(config as Config);\n const gwToken = gatewayConfigured ? (gatewayAuth.token as string) : undefined;\n\n const showGatewaySummary = Boolean(gatewayConfigured && gwToken && (doGateway || runFullWizard));\n\n if (showGatewaySummary && gwToken) {\n const webuiUrl = `http://${displayHost}:${port}?token=${gwToken}`;\n console.log('🌐 Web console (browser) — start here');\n console.log(` Open: http://${displayHost}:${port}`);\n console.log(` Token: ${gwToken.slice(0, 8)}...${gwToken.slice(-8)}`);\n console.log(' Bookmark link (token is saved in the browser when you open it):');\n console.log(` ${webuiUrl}`);\n console.log('');\n }\n\n if (runFullWizard) {\n console.log('🚀 Next steps:');\n if (gatewayConfigured) {\n console.log(' 1. Choose how to launch below (gateway or terminal UI)');\n console.log(' 2. Or chat with: xopc agent -i');\n } else {\n console.log(' 1. Chat in the terminal: xopc agent -i');\n console.log(' 2. Optional: add the Web console: xopc onboard --gateway');\n }\n console.log('');\n } else if (doGateway && gatewayConfigured) {\n console.log('🚀 Next step:');\n console.log(' Start the gateway if it is not running, then open the Web console URL above.');\n console.log('');\n }\n\n console.log('📝 Usage:');\n console.log(' xopc agent -m \"Hello\" # Chat with AI');\n console.log(' xopc agent -i # Interactive mode');\n console.log(' xopc models list # List models');\n console.log(' xopc config validate # Validate xopc.json');\n console.log(' xopc auth list # View authentication');\n console.log(' xopc init # Full state dirs (if upgrading or missing data)');\n\n console.log('\\n📁 Files:');\n console.log(' Config:', configPath);\n console.log(' Workspace:', workspacePath);\n\n if (isInteractive() && didConfigurableSteps) {\n await promptLaunchAfterOnboard(config as Config, ctx, { doChannels });\n }\n\n process.exit(0);\n}\n\nasync function startGatewayAsService(config: Config, ctx: CLIContext): Promise<void> {\n const { startGatewayNow } = await import('./onboard/gateway.js');\n await startGatewayNow(config, ctx);\n}\n\nasync function promptLaunchAfterOnboard(\n config: Config,\n ctx: CLIContext,\n _flags: { doChannels: boolean },\n): Promise<void> {\n console.log('');\n const choice = await select<'tui' | 'gateway' | 'none'>({\n message: 'How do you want to launch xopc now?',\n choices: [\n {\n value: 'tui',\n name: 'Terminal UI (embedded)',\n description: 'xopc tui --local — no gateway process required',\n },\n {\n value: 'gateway',\n name: 'Gateway WebUI (OS service)',\n description: 'Install and start the HTTP gateway for the browser console',\n },\n {\n value: 'none',\n name: 'Exit — I will start manually',\n description: 'Finish setup without starting a runtime',\n },\n ],\n default: 'tui',\n });\n\n if (choice === 'gateway') {\n await startGatewayAsService(config, ctx);\n return;\n }\n\n if (choice === 'tui') {\n const { runTui } = await import('../../tui/tui.js');\n await runTui({ local: true });\n return;\n }\n\n console.log('\\n⏭️ You can start later:');\n console.log(' xopc gateway service install');\n console.log(' xopc gateway');\n console.log(' xopc tui --local');\n}\n\nasync function setupGateway(config: Config): Promise<Config> {\n console.log(colors.cyan('\\n🌐 Gateway WebUI\\n'));\n console.log(\n colors.gray(\n 'Applying defaults from config schema (127.0.0.1:18790, token auth; token generated if missing).\\n',\n ),\n );\n\n const gw = config.gateway ?? {};\n const { randomBytes } = await import('node:crypto');\n const authMode = gw.auth?.mode === 'none' ? ('none' as const) : ('token' as const);\n const token =\n authMode === 'token'\n ? typeof gw.auth?.token === 'string' && gw.auth.token.length > 0\n ? gw.auth.token\n : randomBytes(24).toString('hex')\n : undefined;\n\n const merged: Config = {\n ...config,\n gateway: {\n ...gw,\n bind: gw.bind ?? 'loopback',\n port: gw.port ?? 18790,\n auth:\n authMode === 'none'\n ? { mode: 'none' as const }\n : { mode: 'token' as const, token: token! },\n },\n };\n\n const parsed = ConfigSchema.parse(merged);\n console.log('✅ Gateway defaults applied.\\n');\n return parsed;\n}\n\nregister({\n id: 'onboard',\n name: 'onboard',\n description: 'Interactive setup wizard',\n factory: createOnboardCommand,\n metadata: {\n category: 'setup',\n examples: ['xopc onboard', 'xopc onboard --model', 'xopc onboard --channels'],\n },\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"onboard.js","names":["runModelSetup","runChannelOnboard"],"sources":["../../../../src/cli/commands/onboard.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { select } from '@inquirer/prompts';\nimport { saveConfig } from '../../config/index.js';\nimport { register, formatExamples } from '../registry.js';\nimport type { CLIContext } from '../registry.js';\nimport type { Config } from '../../config/schema.js';\nimport { setupModel as runModelSetup } from './onboard/model.js';\nimport { colors } from '../utils/colors.js';\nimport { setupChannels as runChannelOnboard, getChannelConfigurators } from './onboard/channels/index.js';\nimport { resolveGatewayLocalClientHost } from '../../config/gateway-bind.js';\nimport { initWorkspace } from '../utils/init-workspace.js';\nimport { ConfigSchema } from '../../config/schema.js';\n\nfunction isInteractive(): boolean {\n return process.stdin.isTTY && process.stdout.isTTY;\n}\n\nasync function setupNonInteractive(_configPath: string, existingConfig: Config): Promise<Config> {\n console.log('\\n🤖 AI Model Configuration (Non-Interactive Mode)\\n');\n console.log('Current config:', JSON.stringify(existingConfig.agents?.defaults?.models?.chat, null, 2));\n console.log('\\n💡 To configure in interactive mode, run: xopc onboard');\n console.log('💡 Or set up manually in:', _configPath);\n return existingConfig;\n}\n\nfunction createOnboardCommand(ctx: CLIContext): Command {\n const cmd = new Command('onboard')\n .description('Interactive setup wizard for xopc (gateway uses schema defaults)')\n .addHelpText(\n 'after',\n formatExamples([\n 'xopc onboard # Full interactive setup',\n 'xopc onboard --model # Configure LLM model only',\n 'xopc onboard --channels # Configure messaging channels',\n 'xopc onboard --gateway # Apply default gateway settings (quiet)',\n ])\n )\n .option('--model', 'Configure LLM provider and model')\n .option('--channels', 'Configure messaging channels')\n .option('--gateway', 'Configure gateway WebUI')\n .option('--all', 'Configure everything (default)')\n .action(async (options) => {\n try {\n await runOnboard(options, ctx);\n } catch (error: unknown) {\n const err = error as { name?: string; code?: string };\n if (err?.name === 'ExitPromptError' || err?.code === 'EXIT_PROMPT') {\n console.log('\\n\\n👋 Setup cancelled.');\n process.exit(0);\n }\n throw error;\n }\n });\n\n return cmd;\n}\n\ntype OnboardOptions = {\n model?: boolean;\n channels?: boolean;\n gateway?: boolean;\n all?: boolean;\n};\n\nasync function runOnboard(\n options: OnboardOptions,\n ctx: CLIContext\n): Promise<void> {\n console.log(colors.cyan('\\n🚀 Welcome to xopc setup!\\n'));\n console.log('═'.repeat(50));\n\n const workspacePath = ctx.workspacePath;\n const configPath = ctx.configPath;\n\n const initResult = await initWorkspace({ configPath, workspacePath });\n let config = initResult.config;\n\n // Determine what to configure based on options\n const doModel = options.model || options.all || (!options.channels && !options.gateway);\n const doChannels = options.channels || options.all || (!options.model && !options.gateway);\n const doGateway = options.gateway || options.all || (!options.model && !options.channels);\n const runFullWizard = !options.model && !options.channels && !options.gateway;\n /** Any setup step besides the unified launch prompt ran in interactive flow. */\n const didConfigurableSteps = doModel || doChannels || doGateway;\n\n if (!isInteractive()) {\n // Non-interactive mode\n if (doModel) {\n config = await setupNonInteractive(configPath, config);\n }\n if (doChannels) {\n console.log('\\n💬 Channels Configuration (Non-Interactive Mode)\\n');\n console.log('💡 To configure channels, edit the config file manually.');\n }\n if (doGateway) {\n console.log('\\n🌐 Gateway Configuration (Non-Interactive Mode)\\n');\n console.log('💡 To configure gateway, edit the config file manually.');\n }\n } else {\n // Interactive mode\n if (doModel) {\n config = await runModelSetup(config, ctx);\n }\n\n if (doChannels) {\n const channelIds = (await getChannelConfigurators(config)).map(c => c.id);\n console.log(colors.gray(`\\nChannel onboarding: ${channelIds.join(', ')}\\n`));\n config = await runChannelOnboard(config);\n }\n\n if (doGateway) {\n config = await setupGateway(config);\n }\n }\n\n // Save config once at the end\n await saveConfig(config as Config, configPath);\n\n console.log('\\n' + '═'.repeat(50));\n console.log('\\n🎉 Setup Complete!\\n');\n\n const gatewayAuth = (config as any)?.gateway?.auth;\n const gatewayConfigured =\n gatewayAuth?.mode === 'token' &&\n typeof gatewayAuth?.token === 'string' &&\n gatewayAuth.token.length > 0;\n const port = (config as Config)?.gateway?.port ?? 18790;\n const displayHost = resolveGatewayLocalClientHost(config as Config);\n const gwToken = gatewayConfigured ? (gatewayAuth.token as string) : undefined;\n\n const showGatewaySummary = Boolean(gatewayConfigured && gwToken && (doGateway || runFullWizard));\n\n if (showGatewaySummary && gwToken) {\n const webuiUrl = `http://${displayHost}:${port}?token=${gwToken}`;\n console.log('🌐 Web console (browser) — start here');\n console.log(` Open: http://${displayHost}:${port}`);\n console.log(` Token: ${gwToken.slice(0, 8)}...${gwToken.slice(-8)}`);\n console.log(' Bookmark link (token is saved in the browser when you open it):');\n console.log(` ${webuiUrl}`);\n console.log('');\n }\n\n if (runFullWizard) {\n console.log('🚀 Next steps:');\n if (gatewayConfigured) {\n console.log(' 1. Choose how to launch below (gateway or terminal UI)');\n console.log(' 2. Or chat with: xopc agent -i');\n } else {\n console.log(' 1. Chat in the terminal: xopc agent -i');\n console.log(' 2. Optional: add the Web console: xopc onboard --gateway');\n }\n console.log('');\n } else if (doGateway && gatewayConfigured) {\n console.log('🚀 Next step:');\n console.log(' Start the gateway if it is not running, then open the Web console URL above.');\n console.log('');\n }\n\n console.log('📝 Usage:');\n console.log(' xopc agent -m \"Hello\" # Chat with AI');\n console.log(' xopc agent -i # Interactive mode');\n console.log(' xopc models list # List models');\n console.log(' xopc config validate # Validate xopc.json');\n console.log(' xopc auth list # View authentication');\n console.log(' xopc init # Full state dirs (if upgrading or missing data)');\n\n console.log('\\n📁 Files:');\n console.log(' Config:', configPath);\n console.log(' Workspace:', workspacePath);\n\n if (isInteractive() && didConfigurableSteps) {\n await promptLaunchAfterOnboard(config as Config, ctx, { doChannels });\n }\n\n process.exit(0);\n}\n\nasync function startGatewayAsService(config: Config, ctx: CLIContext): Promise<void> {\n const { startGatewayNow } = await import('./onboard/gateway.js');\n await startGatewayNow(config, ctx);\n}\n\nasync function promptLaunchAfterOnboard(\n config: Config,\n ctx: CLIContext,\n _flags: { doChannels: boolean },\n): Promise<void> {\n console.log('');\n const choice = await select<'tui' | 'gateway' | 'none'>({\n message: 'How do you want to launch xopc now?',\n choices: [\n {\n value: 'tui',\n name: 'Terminal UI (embedded)',\n description: 'xopc tui --local — no gateway process required',\n },\n {\n value: 'gateway',\n name: 'Gateway WebUI (OS service)',\n description: 'Install and start the HTTP gateway for the browser console',\n },\n {\n value: 'none',\n name: 'Exit — I will start manually',\n description: 'Finish setup without starting a runtime',\n },\n ],\n default: 'tui',\n });\n\n if (choice === 'gateway') {\n await startGatewayAsService(config, ctx);\n return;\n }\n\n if (choice === 'tui') {\n const { runTui } = await import('../../tui/tui.js');\n await runTui({ local: true });\n return;\n }\n\n console.log('\\n⏭️ You can start later:');\n console.log(' xopc gateway service install');\n console.log(' xopc gateway');\n console.log(' xopc tui --local');\n}\n\nasync function setupGateway(config: Config): Promise<Config> {\n console.log(colors.cyan('\\n🌐 Gateway WebUI\\n'));\n console.log(\n colors.gray(\n 'Applying defaults from config schema (127.0.0.1:18790, token auth; token generated if missing).\\n',\n ),\n );\n\n const gw = config.gateway ?? {};\n const { randomBytes } = await import('node:crypto');\n const authMode = gw.auth?.mode === 'none' ? ('none' as const) : ('token' as const);\n const token =\n authMode === 'token'\n ? typeof gw.auth?.token === 'string' && gw.auth.token.length > 0\n ? gw.auth.token\n : randomBytes(24).toString('hex')\n : undefined;\n\n const merged: Config = {\n ...config,\n gateway: {\n ...gw,\n bind: gw.bind ?? 'loopback',\n port: gw.port ?? 18790,\n auth:\n authMode === 'none'\n ? { mode: 'none' as const }\n : { mode: 'token' as const, token: token! },\n },\n };\n\n const parsed = ConfigSchema.parse(merged);\n console.log('✅ Gateway defaults applied.\\n');\n return parsed;\n}\n\nregister({\n id: 'onboard',\n name: 'onboard',\n description: 'Interactive setup wizard',\n factory: createOnboardCommand,\n metadata: {\n category: 'setup',\n examples: ['xopc onboard', 'xopc onboard --model', 'xopc onboard --channels'],\n },\n});\n"],"mappings":"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"}
@@ -1,5 +1,4 @@
1
1
  import { formatExamples, register } from "../registry.js";
2
- import { seedMainAgentProfileMarkdown } from "../../agent/context/workspace-seed.js";
3
2
  import { initWorkspace } from "../utils/init-workspace.js";
4
3
  import { existsSync } from "fs";
5
4
  import { Command } from "commander";
@@ -27,7 +26,6 @@ function createSetupCommand(ctx) {
27
26
  else console.log("\n📝 Config already present (verified).");
28
27
  if (result.workspaceCreated) console.log("\n📁 Created workspace.");
29
28
  else console.log("\n📁 Workspace already present (verified).");
30
- seedMainAgentProfileMarkdown(result.config);
31
29
  console.log("\n" + "═".repeat(40));
32
30
  console.log("\n✅ Setup complete!\n");
33
31
  console.log("📁 Files:");
@@ -1 +1 @@
1
- {"version":3,"file":"setup.js","names":[],"sources":["../../../../src/cli/commands/setup.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { existsSync } from 'fs';\nimport { register, formatExamples, type CLIContext } from '../registry.js';\nimport { seedMainAgentProfileMarkdown } from '../../agent/context/workspace-seed.js';\nimport { initWorkspace } from '../utils/init-workspace.js';\n\nfunction createSetupCommand(ctx: CLIContext): Command {\n const cmd = new Command('setup')\n .description('Initialize config file and workspace directory')\n .addHelpText(\n 'after',\n formatExamples([\n 'xopc setup # Create config + workspace',\n 'xopc setup --workspace /path # Custom workspace path',\n 'xopc init # Full state dirs + agent profile seeds',\n ])\n )\n .option('--workspace <path>', 'Workspace directory path', ctx.workspacePath)\n .action(async (options) => {\n const workspacePath = options.workspace || ctx.workspacePath;\n const configPath = ctx.configPath;\n\n console.log('🔧 xopc Setup\\n');\n console.log('═'.repeat(40));\n\n // Check current status\n const configExists = existsSync(configPath);\n const workspaceExists = existsSync(workspacePath);\n\n console.log('\\n📊 Current Status:');\n console.log(` Config: ${configExists ? '✅ exists' : '❌ not found'}`);\n console.log(` Workspace: ${workspaceExists ? '✅ setup' : '❌ not found'}`);\n\n const result = await initWorkspace({ configPath, workspacePath });\n\n if (result.configCreated) {\n console.log('\\n📝 Created config file.');\n } else {\n console.log('\\n📝 Config already present (verified).');\n }\n\n if (result.workspaceCreated) {\n console.log('\\n📁 Created workspace.');\n } else {\n console.log('\\n📁 Workspace already present (verified).');\n }\n\n seedMainAgentProfileMarkdown(result.config);\n\n console.log('\\n' + '═'.repeat(40));\n console.log('\\n✅ Setup complete!\\n');\n\n console.log('📁 Files:');\n console.log(' Config:', configPath);\n console.log(' Workspace:', workspacePath);\n\n console.log('\\n🚀 Next Steps:');\n console.log(' xopc init # Full Agent OS dirs (optional, beyond setup)');\n console.log(' xopc onboard # Run full setup wizard');\n console.log(' xopc onboard --model # Configure model only');\n console.log(' xopc onboard --channels # Configure channels only');\n });\n\n return cmd;\n}\n\nregister({\n id: 'setup',\n name: 'setup',\n description: 'Initialize config file and workspace directory',\n factory: createSetupCommand,\n metadata: {\n category: 'setup',\n examples: [\n 'xopc setup',\n 'xopc setup --workspace ~/.my-workspace',\n ],\n },\n});\n"],"mappings":";;;;;;AAMA,SAAS,mBAAmB,KAA0B;AAyDpD,QAxDY,IAAI,QAAQ,QAAQ,CAC7B,YAAY,iDAAiD,CAC7D,YACC,SACA,eAAe;EACb;EACA;EACA;EACD,CAAC,CACH,CACA,OAAO,sBAAsB,4BAA4B,IAAI,cAAc,CAC3E,OAAO,OAAO,YAAY;EACzB,MAAM,gBAAgB,QAAQ,aAAa,IAAI;EAC/C,MAAM,aAAa,IAAI;AAEvB,UAAQ,IAAI,kBAAkB;AAC9B,UAAQ,IAAI,IAAI,OAAO,GAAG,CAAC;EAG3B,MAAM,eAAe,WAAW,WAAW;EAC3C,MAAM,kBAAkB,WAAW,cAAc;AAEjD,UAAQ,IAAI,uBAAuB;AACnC,UAAQ,IAAI,cAAc,eAAe,aAAa,gBAAgB;AACtE,UAAQ,IAAI,iBAAiB,kBAAkB,YAAY,gBAAgB;EAE3E,MAAM,SAAS,MAAM,cAAc;GAAE;GAAY;GAAe,CAAC;AAEjE,MAAI,OAAO,cACT,SAAQ,IAAI,4BAA4B;MAExC,SAAQ,IAAI,0CAA0C;AAGxD,MAAI,OAAO,iBACT,SAAQ,IAAI,0BAA0B;MAEtC,SAAQ,IAAI,6CAA6C;AAG3D,+BAA6B,OAAO,OAAO;AAE3C,UAAQ,IAAI,OAAO,IAAI,OAAO,GAAG,CAAC;AAClC,UAAQ,IAAI,wBAAwB;AAEpC,UAAQ,IAAI,YAAY;AACxB,UAAQ,IAAI,cAAc,WAAW;AACrC,UAAQ,IAAI,iBAAiB,cAAc;AAE3C,UAAQ,IAAI,mBAAmB;AAC/B,UAAQ,IAAI,6EAA6E;AACzF,UAAQ,IAAI,uDAAuD;AACnE,UAAQ,IAAI,sDAAsD;AAClE,UAAQ,IAAI,wDAAwD;GAG9D;;AAGZ,SAAS;CACP,IAAI;CACJ,MAAM;CACN,aAAa;CACb,SAAS;CACT,UAAU;EACR,UAAU;EACV,UAAU,CACR,cACA,yCACD;EACF;CACF,CAAC"}
1
+ {"version":3,"file":"setup.js","names":[],"sources":["../../../../src/cli/commands/setup.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { existsSync } from 'fs';\nimport { register, formatExamples, type CLIContext } from '../registry.js';\nimport { initWorkspace } from '../utils/init-workspace.js';\n\nfunction createSetupCommand(ctx: CLIContext): Command {\n const cmd = new Command('setup')\n .description('Initialize config file and workspace directory')\n .addHelpText(\n 'after',\n formatExamples([\n 'xopc setup # Create config + workspace',\n 'xopc setup --workspace /path # Custom workspace path',\n 'xopc init # Full state dirs + agent profile seeds',\n ])\n )\n .option('--workspace <path>', 'Workspace directory path', ctx.workspacePath)\n .action(async (options) => {\n const workspacePath = options.workspace || ctx.workspacePath;\n const configPath = ctx.configPath;\n\n console.log('🔧 xopc Setup\\n');\n console.log('═'.repeat(40));\n\n // Check current status\n const configExists = existsSync(configPath);\n const workspaceExists = existsSync(workspacePath);\n\n console.log('\\n📊 Current Status:');\n console.log(` Config: ${configExists ? '✅ exists' : '❌ not found'}`);\n console.log(` Workspace: ${workspaceExists ? '✅ setup' : '❌ not found'}`);\n\n const result = await initWorkspace({ configPath, workspacePath });\n\n if (result.configCreated) {\n console.log('\\n📝 Created config file.');\n } else {\n console.log('\\n📝 Config already present (verified).');\n }\n\n if (result.workspaceCreated) {\n console.log('\\n📁 Created workspace.');\n } else {\n console.log('\\n📁 Workspace already present (verified).');\n }\n\n console.log('\\n' + '═'.repeat(40));\n console.log('\\n✅ Setup complete!\\n');\n\n console.log('📁 Files:');\n console.log(' Config:', configPath);\n console.log(' Workspace:', workspacePath);\n\n console.log('\\n🚀 Next Steps:');\n console.log(' xopc init # Full Agent OS dirs (optional, beyond setup)');\n console.log(' xopc onboard # Run full setup wizard');\n console.log(' xopc onboard --model # Configure model only');\n console.log(' xopc onboard --channels # Configure channels only');\n });\n\n return cmd;\n}\n\nregister({\n id: 'setup',\n name: 'setup',\n description: 'Initialize config file and workspace directory',\n factory: createSetupCommand,\n metadata: {\n category: 'setup',\n examples: [\n 'xopc setup',\n 'xopc setup --workspace ~/.my-workspace',\n ],\n },\n});\n"],"mappings":";;;;;AAKA,SAAS,mBAAmB,KAA0B;AAuDpD,QAtDY,IAAI,QAAQ,QAAQ,CAC7B,YAAY,iDAAiD,CAC7D,YACC,SACA,eAAe;EACb;EACA;EACA;EACD,CAAC,CACH,CACA,OAAO,sBAAsB,4BAA4B,IAAI,cAAc,CAC3E,OAAO,OAAO,YAAY;EACzB,MAAM,gBAAgB,QAAQ,aAAa,IAAI;EAC/C,MAAM,aAAa,IAAI;AAEvB,UAAQ,IAAI,kBAAkB;AAC9B,UAAQ,IAAI,IAAI,OAAO,GAAG,CAAC;EAG3B,MAAM,eAAe,WAAW,WAAW;EAC3C,MAAM,kBAAkB,WAAW,cAAc;AAEjD,UAAQ,IAAI,uBAAuB;AACnC,UAAQ,IAAI,cAAc,eAAe,aAAa,gBAAgB;AACtE,UAAQ,IAAI,iBAAiB,kBAAkB,YAAY,gBAAgB;EAE3E,MAAM,SAAS,MAAM,cAAc;GAAE;GAAY;GAAe,CAAC;AAEjE,MAAI,OAAO,cACT,SAAQ,IAAI,4BAA4B;MAExC,SAAQ,IAAI,0CAA0C;AAGxD,MAAI,OAAO,iBACT,SAAQ,IAAI,0BAA0B;MAEtC,SAAQ,IAAI,6CAA6C;AAG3D,UAAQ,IAAI,OAAO,IAAI,OAAO,GAAG,CAAC;AAClC,UAAQ,IAAI,wBAAwB;AAEpC,UAAQ,IAAI,YAAY;AACxB,UAAQ,IAAI,cAAc,WAAW;AACrC,UAAQ,IAAI,iBAAiB,cAAc;AAE3C,UAAQ,IAAI,mBAAmB;AAC/B,UAAQ,IAAI,6EAA6E;AACzF,UAAQ,IAAI,uDAAuD;AACnE,UAAQ,IAAI,sDAAsD;AAClE,UAAQ,IAAI,wDAAwD;GAG9D;;AAGZ,SAAS;CACP,IAAI;CACJ,MAAM;CACN,aAAa;CACb,SAAS;CACT,UAAU;EACR,UAAU;EACV,UAAU,CACR,cACA,yCACD;EACF;CACF,CAAC"}
@@ -1,7 +1,8 @@
1
1
  import { ConfigSchema, init_schema } from "../../config/schema.js";
2
- import { init_loader, loadConfig, saveConfig } from "../../config/loader.js";
2
+ import { init_loader, saveConfig } from "../../config/loader.js";
3
+ import { ensureStarterAgentsInitialized } from "../../agent/starter-agents.js";
3
4
  import { randomBytes } from "node:crypto";
4
- import { existsSync, mkdirSync, readFileSync } from "node:fs";
5
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
5
6
  import { dirname } from "node:path";
6
7
  //#region src/cli/utils/init-workspace-core.ts
7
8
  init_schema();
@@ -37,7 +38,7 @@ async function initWorkspaceCore(options) {
37
38
  const configExisted = existsSync(configPath);
38
39
  const workspaceExisted = existsSync(workspacePath);
39
40
  let config;
40
- if (configExisted) config = loadConfig(configPath);
41
+ if (configExisted) config = await tryReadDiskConfig(configPath, assertChannelPlugins) ?? ConfigSchema.parse(void 0);
41
42
  else {
42
43
  config = ConfigSchema.parse(void 0);
43
44
  await assertChannelPluginsIfNeeded(config, assertChannelPlugins);
@@ -67,15 +68,17 @@ async function initWorkspaceCore(options) {
67
68
  }
68
69
  }
69
70
  };
70
- const nextFinal = ConfigSchema.parse(nextConfig);
71
+ const starterResult = ensureStarterAgentsInitialized(ConfigSchema.parse(nextConfig));
72
+ const nextFinal = ConfigSchema.parse(starterResult.config);
71
73
  await assertChannelPluginsIfNeeded(nextFinal, assertChannelPlugins);
72
- let needsWrite = configCreated;
74
+ let needsWrite = configCreated || starterResult.changed;
73
75
  if (!needsWrite) {
74
76
  const disk = await tryReadDiskConfig(configPath, assertChannelPlugins);
75
77
  if (!disk) needsWrite = true;
76
78
  else needsWrite = await serializeConfig(disk, assertChannelPlugins) !== await serializeConfig(nextFinal, assertChannelPlugins);
77
79
  }
78
- if (needsWrite) await saveConfig(nextFinal, configPath);
80
+ if (needsWrite) if (assertChannelPlugins) await saveConfig(nextFinal, configPath);
81
+ else writeFileSync(configPath, `${JSON.stringify(nextFinal, null, 2)}\n`, "utf8");
79
82
  return {
80
83
  config: nextFinal,
81
84
  token,
@@ -1 +1 @@
1
- {"version":3,"file":"init-workspace-core.js","names":[],"sources":["../../../../src/cli/utils/init-workspace-core.ts"],"sourcesContent":["import { randomBytes } from 'node:crypto';\nimport { existsSync, mkdirSync, readFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\n\nimport type { Config } from '../../config/schema.js';\nimport { ConfigSchema } from '../../config/schema.js';\nimport { loadConfig, saveConfig } from '../../config/loader.js';\n\nexport interface InitWorkspaceCoreOptions {\n configPath: string;\n workspacePath: string;\n /** When set with a new config file, overrides schema default port (e.g. Electron). */\n gatewayPort?: number;\n /**\n * When true, sets `agents.defaults.workspace` to `dirname(workspacePath)` (parent of the\n * Markdown root being initialised, e.g. `…/workspace` when `workspacePath` is `…/workspace/main`).\n */\n persistWorkspacePath?: boolean;\n /** Optional channel plugin validator (CLI/gateway only; Electron omits). */\n assertChannelPlugins?: (cfg: Config) => void | Promise<void>;\n}\n\nexport interface InitWorkspaceResult {\n /** Fully-initialised config (matches disk after any write). */\n config: Config;\n /** Gateway auth token (always present after init). */\n token: string;\n configCreated: boolean;\n workspaceCreated: boolean;\n}\n\nasync function assertChannelPluginsIfNeeded(\n cfg: Config,\n assert?: InitWorkspaceCoreOptions['assertChannelPlugins'],\n): Promise<void> {\n if (assert) await assert(cfg);\n}\n\nasync function serializeConfig(\n cfg: Config,\n assertChannelPlugins?: InitWorkspaceCoreOptions['assertChannelPlugins'],\n): Promise<string> {\n const validated = ConfigSchema.parse(cfg);\n await assertChannelPluginsIfNeeded(validated, assertChannelPlugins);\n return JSON.stringify(validated, null, 2);\n}\n\nasync function tryReadDiskConfig(\n configPath: string,\n assertChannelPlugins?: InitWorkspaceCoreOptions['assertChannelPlugins'],\n): Promise<Config | null> {\n try {\n const raw = readFileSync(configPath, 'utf-8');\n const cfg = ConfigSchema.parse(JSON.parse(raw) as unknown);\n await assertChannelPluginsIfNeeded(cfg, assertChannelPlugins);\n return cfg;\n } catch {\n return null;\n }\n}\n\n/**\n * Workspace + config initialisation without importing bundled channel plugins.\n * Used by Electron main; CLI/gateway should call {@link initWorkspace} instead.\n */\nexport async function initWorkspaceCore(options: InitWorkspaceCoreOptions): Promise<InitWorkspaceResult> {\n const gatewayPortDefaulted = options.gatewayPort ?? 18790;\n const persistWorkspacePath = options.persistWorkspacePath ?? false;\n const { configPath, workspacePath, assertChannelPlugins } = options;\n const persistedDefaultsWorkspace = persistWorkspacePath ? dirname(workspacePath) : undefined;\n\n mkdirSync(dirname(configPath), { recursive: true });\n\n const configExisted = existsSync(configPath);\n const workspaceExisted = existsSync(workspacePath);\n\n let config: Config;\n if (configExisted) {\n config = loadConfig(configPath);\n } else {\n config = ConfigSchema.parse(undefined);\n await assertChannelPluginsIfNeeded(config, assertChannelPlugins);\n }\n\n mkdirSync(workspacePath, { recursive: true });\n\n const configCreated = !configExisted;\n const workspaceCreated = !workspaceExisted;\n\n const hadToken =\n config.gateway?.auth?.mode === 'token' &&\n typeof config.gateway?.auth?.token === 'string' &&\n config.gateway.auth.token.length > 0;\n\n const token = hadToken ? (config.gateway!.auth!.token as string) : randomBytes(24).toString('hex');\n\n const port = configExisted\n ? (config.gateway?.port ?? gatewayPortDefaulted)\n : options.gatewayPort !== undefined\n ? gatewayPortDefaulted\n : (config.gateway?.port ?? 18790);\n\n const agentsDefaults = {\n ...config.agents.defaults,\n ...(persistedDefaultsWorkspace !== undefined ? { workspace: persistedDefaultsWorkspace } : {}),\n };\n\n const nextConfig: Config = {\n ...config,\n agents: {\n ...config.agents,\n defaults: agentsDefaults,\n },\n gateway: {\n ...config.gateway,\n port,\n auth: {\n ...config.gateway?.auth,\n mode: 'token' as const,\n token,\n },\n },\n };\n\n const nextFinal = ConfigSchema.parse(nextConfig);\n await assertChannelPluginsIfNeeded(nextFinal, assertChannelPlugins);\n\n let needsWrite = configCreated;\n if (!needsWrite) {\n const disk = await tryReadDiskConfig(configPath, assertChannelPlugins);\n if (!disk) {\n needsWrite = true;\n } else {\n needsWrite =\n (await serializeConfig(disk, assertChannelPlugins)) !==\n (await serializeConfig(nextFinal, assertChannelPlugins));\n }\n }\n\n if (needsWrite) {\n await saveConfig(nextFinal, configPath);\n }\n\n return {\n config: nextFinal,\n token,\n configCreated,\n workspaceCreated,\n };\n}\n"],"mappings":";;;;;;aAKsD;aACU;AAyBhE,eAAe,6BACb,KACA,QACe;AACf,KAAI,OAAQ,OAAM,OAAO,IAAI;;AAG/B,eAAe,gBACb,KACA,sBACiB;CACjB,MAAM,YAAY,aAAa,MAAM,IAAI;AACzC,OAAM,6BAA6B,WAAW,qBAAqB;AACnE,QAAO,KAAK,UAAU,WAAW,MAAM,EAAE;;AAG3C,eAAe,kBACb,YACA,sBACwB;AACxB,KAAI;EACF,MAAM,MAAM,aAAa,YAAY,QAAQ;EAC7C,MAAM,MAAM,aAAa,MAAM,KAAK,MAAM,IAAI,CAAY;AAC1D,QAAM,6BAA6B,KAAK,qBAAqB;AAC7D,SAAO;SACD;AACN,SAAO;;;;;;;AAQX,eAAsB,kBAAkB,SAAiE;CACvG,MAAM,uBAAuB,QAAQ,eAAe;CACpD,MAAM,uBAAuB,QAAQ,wBAAwB;CAC7D,MAAM,EAAE,YAAY,eAAe,yBAAyB;CAC5D,MAAM,6BAA6B,uBAAuB,QAAQ,cAAc,GAAG,KAAA;AAEnF,WAAU,QAAQ,WAAW,EAAE,EAAE,WAAW,MAAM,CAAC;CAEnD,MAAM,gBAAgB,WAAW,WAAW;CAC5C,MAAM,mBAAmB,WAAW,cAAc;CAElD,IAAI;AACJ,KAAI,cACF,UAAS,WAAW,WAAW;MAC1B;AACL,WAAS,aAAa,MAAM,KAAA,EAAU;AACtC,QAAM,6BAA6B,QAAQ,qBAAqB;;AAGlE,WAAU,eAAe,EAAE,WAAW,MAAM,CAAC;CAE7C,MAAM,gBAAgB,CAAC;CACvB,MAAM,mBAAmB,CAAC;CAO1B,MAAM,QAJJ,OAAO,SAAS,MAAM,SAAS,WAC/B,OAAO,OAAO,SAAS,MAAM,UAAU,YACvC,OAAO,QAAQ,KAAK,MAAM,SAAS,IAEX,OAAO,QAAS,KAAM,QAAmB,YAAY,GAAG,CAAC,SAAS,MAAM;CAElG,MAAM,OAAO,gBACR,OAAO,SAAS,QAAQ,uBACzB,QAAQ,gBAAgB,KAAA,IACtB,uBACC,OAAO,SAAS,QAAQ;CAE/B,MAAM,iBAAiB;EACrB,GAAG,OAAO,OAAO;EACjB,GAAI,+BAA+B,KAAA,IAAY,EAAE,WAAW,4BAA4B,GAAG,EAAE;EAC9F;CAED,MAAM,aAAqB;EACzB,GAAG;EACH,QAAQ;GACN,GAAG,OAAO;GACV,UAAU;GACX;EACD,SAAS;GACP,GAAG,OAAO;GACV;GACA,MAAM;IACJ,GAAG,OAAO,SAAS;IACnB,MAAM;IACN;IACD;GACF;EACF;CAED,MAAM,YAAY,aAAa,MAAM,WAAW;AAChD,OAAM,6BAA6B,WAAW,qBAAqB;CAEnE,IAAI,aAAa;AACjB,KAAI,CAAC,YAAY;EACf,MAAM,OAAO,MAAM,kBAAkB,YAAY,qBAAqB;AACtE,MAAI,CAAC,KACH,cAAa;MAEb,cACG,MAAM,gBAAgB,MAAM,qBAAqB,KACjD,MAAM,gBAAgB,WAAW,qBAAqB;;AAI7D,KAAI,WACF,OAAM,WAAW,WAAW,WAAW;AAGzC,QAAO;EACL,QAAQ;EACR;EACA;EACA;EACD"}
1
+ {"version":3,"file":"init-workspace-core.js","names":[],"sources":["../../../../src/cli/utils/init-workspace-core.ts"],"sourcesContent":["import { randomBytes } from 'node:crypto';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\n\nimport type { Config } from '../../config/schema.js';\nimport { ConfigSchema } from '../../config/schema.js';\nimport { saveConfig } from '../../config/loader.js';\nimport { ensureStarterAgentsInitialized } from '../../agent/starter-agents.js';\n\nexport interface InitWorkspaceCoreOptions {\n configPath: string;\n workspacePath: string;\n /** When set with a new config file, overrides schema default port (e.g. Electron). */\n gatewayPort?: number;\n /**\n * When true, sets `agents.defaults.workspace` to `dirname(workspacePath)` (parent of the\n * Markdown root being initialised, e.g. `…/workspace` when `workspacePath` is `…/workspace/main`).\n */\n persistWorkspacePath?: boolean;\n /** Optional channel plugin validator (CLI/gateway only; Electron omits). */\n assertChannelPlugins?: (cfg: Config) => void | Promise<void>;\n}\n\nexport interface InitWorkspaceResult {\n /** Fully-initialised config (matches disk after any write). */\n config: Config;\n /** Gateway auth token (always present after init). */\n token: string;\n configCreated: boolean;\n workspaceCreated: boolean;\n}\n\nasync function assertChannelPluginsIfNeeded(\n cfg: Config,\n assert?: InitWorkspaceCoreOptions['assertChannelPlugins'],\n): Promise<void> {\n if (assert) await assert(cfg);\n}\n\nasync function serializeConfig(\n cfg: Config,\n assertChannelPlugins?: InitWorkspaceCoreOptions['assertChannelPlugins'],\n): Promise<string> {\n const validated = ConfigSchema.parse(cfg);\n await assertChannelPluginsIfNeeded(validated, assertChannelPlugins);\n return JSON.stringify(validated, null, 2);\n}\n\nasync function tryReadDiskConfig(\n configPath: string,\n assertChannelPlugins?: InitWorkspaceCoreOptions['assertChannelPlugins'],\n): Promise<Config | null> {\n try {\n const raw = readFileSync(configPath, 'utf-8');\n const cfg = ConfigSchema.parse(JSON.parse(raw) as unknown);\n await assertChannelPluginsIfNeeded(cfg, assertChannelPlugins);\n return cfg;\n } catch {\n return null;\n }\n}\n\n/**\n * Workspace + config initialisation without importing bundled channel plugins.\n * Used by Electron main; CLI/gateway should call {@link initWorkspace} instead.\n */\nexport async function initWorkspaceCore(options: InitWorkspaceCoreOptions): Promise<InitWorkspaceResult> {\n const gatewayPortDefaulted = options.gatewayPort ?? 18790;\n const persistWorkspacePath = options.persistWorkspacePath ?? false;\n const { configPath, workspacePath, assertChannelPlugins } = options;\n const persistedDefaultsWorkspace = persistWorkspacePath ? dirname(workspacePath) : undefined;\n\n mkdirSync(dirname(configPath), { recursive: true });\n\n const configExisted = existsSync(configPath);\n const workspaceExisted = existsSync(workspacePath);\n\n let config: Config;\n if (configExisted) {\n config = (await tryReadDiskConfig(configPath, assertChannelPlugins)) ?? ConfigSchema.parse(undefined);\n } else {\n config = ConfigSchema.parse(undefined);\n await assertChannelPluginsIfNeeded(config, assertChannelPlugins);\n }\n\n mkdirSync(workspacePath, { recursive: true });\n\n const configCreated = !configExisted;\n const workspaceCreated = !workspaceExisted;\n\n const hadToken =\n config.gateway?.auth?.mode === 'token' &&\n typeof config.gateway?.auth?.token === 'string' &&\n config.gateway.auth.token.length > 0;\n\n const token = hadToken ? (config.gateway!.auth!.token as string) : randomBytes(24).toString('hex');\n\n const port = configExisted\n ? (config.gateway?.port ?? gatewayPortDefaulted)\n : options.gatewayPort !== undefined\n ? gatewayPortDefaulted\n : (config.gateway?.port ?? 18790);\n\n const agentsDefaults = {\n ...config.agents.defaults,\n ...(persistedDefaultsWorkspace !== undefined ? { workspace: persistedDefaultsWorkspace } : {}),\n };\n\n const nextConfig: Config = {\n ...config,\n agents: {\n ...config.agents,\n defaults: agentsDefaults,\n },\n gateway: {\n ...config.gateway,\n port,\n auth: {\n ...config.gateway?.auth,\n mode: 'token' as const,\n token,\n },\n },\n };\n\n const starterResult = ensureStarterAgentsInitialized(ConfigSchema.parse(nextConfig));\n const nextFinal = ConfigSchema.parse(starterResult.config);\n await assertChannelPluginsIfNeeded(nextFinal, assertChannelPlugins);\n\n let needsWrite = configCreated || starterResult.changed;\n if (!needsWrite) {\n const disk = await tryReadDiskConfig(configPath, assertChannelPlugins);\n if (!disk) {\n needsWrite = true;\n } else {\n needsWrite =\n (await serializeConfig(disk, assertChannelPlugins)) !==\n (await serializeConfig(nextFinal, assertChannelPlugins));\n }\n }\n\n if (needsWrite) {\n if (assertChannelPlugins) {\n await saveConfig(nextFinal, configPath);\n } else {\n writeFileSync(configPath, `${JSON.stringify(nextFinal, null, 2)}\\n`, 'utf8');\n }\n }\n\n return {\n config: nextFinal,\n token,\n configCreated,\n workspaceCreated,\n };\n}\n"],"mappings":";;;;;;;aAKsD;aACF;AA0BpD,eAAe,6BACb,KACA,QACe;AACf,KAAI,OAAQ,OAAM,OAAO,IAAI;;AAG/B,eAAe,gBACb,KACA,sBACiB;CACjB,MAAM,YAAY,aAAa,MAAM,IAAI;AACzC,OAAM,6BAA6B,WAAW,qBAAqB;AACnE,QAAO,KAAK,UAAU,WAAW,MAAM,EAAE;;AAG3C,eAAe,kBACb,YACA,sBACwB;AACxB,KAAI;EACF,MAAM,MAAM,aAAa,YAAY,QAAQ;EAC7C,MAAM,MAAM,aAAa,MAAM,KAAK,MAAM,IAAI,CAAY;AAC1D,QAAM,6BAA6B,KAAK,qBAAqB;AAC7D,SAAO;SACD;AACN,SAAO;;;;;;;AAQX,eAAsB,kBAAkB,SAAiE;CACvG,MAAM,uBAAuB,QAAQ,eAAe;CACpD,MAAM,uBAAuB,QAAQ,wBAAwB;CAC7D,MAAM,EAAE,YAAY,eAAe,yBAAyB;CAC5D,MAAM,6BAA6B,uBAAuB,QAAQ,cAAc,GAAG,KAAA;AAEnF,WAAU,QAAQ,WAAW,EAAE,EAAE,WAAW,MAAM,CAAC;CAEnD,MAAM,gBAAgB,WAAW,WAAW;CAC5C,MAAM,mBAAmB,WAAW,cAAc;CAElD,IAAI;AACJ,KAAI,cACF,UAAU,MAAM,kBAAkB,YAAY,qBAAqB,IAAK,aAAa,MAAM,KAAA,EAAU;MAChG;AACL,WAAS,aAAa,MAAM,KAAA,EAAU;AACtC,QAAM,6BAA6B,QAAQ,qBAAqB;;AAGlE,WAAU,eAAe,EAAE,WAAW,MAAM,CAAC;CAE7C,MAAM,gBAAgB,CAAC;CACvB,MAAM,mBAAmB,CAAC;CAO1B,MAAM,QAJJ,OAAO,SAAS,MAAM,SAAS,WAC/B,OAAO,OAAO,SAAS,MAAM,UAAU,YACvC,OAAO,QAAQ,KAAK,MAAM,SAAS,IAEX,OAAO,QAAS,KAAM,QAAmB,YAAY,GAAG,CAAC,SAAS,MAAM;CAElG,MAAM,OAAO,gBACR,OAAO,SAAS,QAAQ,uBACzB,QAAQ,gBAAgB,KAAA,IACtB,uBACC,OAAO,SAAS,QAAQ;CAE/B,MAAM,iBAAiB;EACrB,GAAG,OAAO,OAAO;EACjB,GAAI,+BAA+B,KAAA,IAAY,EAAE,WAAW,4BAA4B,GAAG,EAAE;EAC9F;CAED,MAAM,aAAqB;EACzB,GAAG;EACH,QAAQ;GACN,GAAG,OAAO;GACV,UAAU;GACX;EACD,SAAS;GACP,GAAG,OAAO;GACV;GACA,MAAM;IACJ,GAAG,OAAO,SAAS;IACnB,MAAM;IACN;IACD;GACF;EACF;CAED,MAAM,gBAAgB,+BAA+B,aAAa,MAAM,WAAW,CAAC;CACpF,MAAM,YAAY,aAAa,MAAM,cAAc,OAAO;AAC1D,OAAM,6BAA6B,WAAW,qBAAqB;CAEnE,IAAI,aAAa,iBAAiB,cAAc;AAChD,KAAI,CAAC,YAAY;EACf,MAAM,OAAO,MAAM,kBAAkB,YAAY,qBAAqB;AACtE,MAAI,CAAC,KACH,cAAa;MAEb,cACG,MAAM,gBAAgB,MAAM,qBAAqB,KACjD,MAAM,gBAAgB,WAAW,qBAAqB;;AAI7D,KAAI,WACF,KAAI,qBACF,OAAM,WAAW,WAAW,WAAW;KAEvC,eAAc,YAAY,GAAG,KAAK,UAAU,WAAW,MAAM,EAAE,CAAC,KAAK,OAAO;AAIhF,QAAO;EACL,QAAQ;EACR;EACA;EACA;EACD"}
@@ -185,8 +185,8 @@ export declare function resolveSkillsCachePath(config: Config, agentId: string):
185
185
  * Layout-dependent candidates (first existing wins):
186
186
  * - `XOPC_BUNDLED_EXTENSIONS_ROOT` (Electron packaged gateway override)
187
187
  * - `dist/src/config` → `dist/extensions` (npm / gateway)
188
- * - `src/config` → `extensions/` (dev, tsx)
189
- * - `out/server` → `dist/extensions` (Electron esbuild bundle)
188
+ * - `src/config` → `dist/extensions` when built, else `extensions/` (dev, tsx)
189
+ * - `out/server` → `dist/electron/extensions` (Electron extension bundles)
190
190
  */
191
191
  export declare function resolveBundledExtensionsDir(): string | null;
192
192
  /**
@@ -2,7 +2,7 @@ import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
2
2
  import { ENV_VARS, XOPC_DB_FILENAME, init_paths_state, resolveHomeDir, resolveStateDir, resolveXopcDatabasePath } from "./paths-state.js";
3
3
  import { init_workspace_defaults, resolveDefaultAgentWorkspaceDir } from "./workspace-defaults.js";
4
4
  import { init_agent_scope, resolveAgentDir as resolveAgentDir$1, resolveAgentHomeDir as resolveAgentHomeDir$1, resolveAgentProfileDir as resolveAgentProfileDir$1, resolveAgentProfileMarkdownPath as resolveAgentProfileMarkdownPath$1, resolveAgentWorkspaceDir } from "../agent/agent-scope.js";
5
- import { dirname, join } from "path";
5
+ import { dirname, join, sep } from "path";
6
6
  import { existsSync } from "fs";
7
7
  import { fileURLToPath } from "url";
8
8
  //#region src/config/paths.ts
@@ -239,17 +239,18 @@ function resolveSkillsCachePath(config, agentId) {
239
239
  * Layout-dependent candidates (first existing wins):
240
240
  * - `XOPC_BUNDLED_EXTENSIONS_ROOT` (Electron packaged gateway override)
241
241
  * - `dist/src/config` → `dist/extensions` (npm / gateway)
242
- * - `src/config` → `extensions/` (dev, tsx)
243
- * - `out/server` → `dist/extensions` (Electron esbuild bundle)
242
+ * - `src/config` → `dist/extensions` when built, else `extensions/` (dev, tsx)
243
+ * - `out/server` → `dist/electron/extensions` (Electron extension bundles)
244
244
  */
245
245
  function resolveBundledExtensionsDir() {
246
246
  const envDir = process.env[ENV_BUNDLED_EXTENSIONS_ROOT];
247
247
  if (envDir && existsSync(envDir)) return envDir;
248
248
  try {
249
249
  const srcDir = dirname(fileURLToPath(import.meta.url));
250
- const candidates = [
251
- join(srcDir, "..", "..", "extensions"),
250
+ const candidates = srcDir.endsWith(`${sep}out${sep}server`) ? [join(srcDir, "..", "..", "dist", "electron", "extensions")] : [
252
251
  join(srcDir, "..", "..", "dist", "extensions"),
252
+ join(srcDir, "..", "..", "extensions"),
253
+ join(srcDir, "..", "..", "..", "dist", "extensions"),
253
254
  join(srcDir, "..", "..", "..", "extensions")
254
255
  ];
255
256
  for (const dir of candidates) if (existsSync(dir)) return dir;
@@ -262,6 +263,8 @@ function resolveBundledExtensionsDir() {
262
263
  * Resolve the bundled skills directory (shipped with xopc)
263
264
  */
264
265
  function resolveBundledSkillsDir() {
266
+ const envDir = process.env[ENV_BUNDLED_SKILLS_ROOT];
267
+ if (envDir && existsSync(envDir)) return envDir;
265
268
  try {
266
269
  const srcDir = dirname(fileURLToPath(import.meta.url));
267
270
  const skillsDir = join(join(srcDir, "..", ".."), "skills");
@@ -290,12 +293,13 @@ function resolveExtensionSdkPath() {
290
293
  return join(process.cwd(), "src", "extensions", "sdk", "index.ts");
291
294
  }
292
295
  }
293
- var ENV_BUNDLED_EXTENSIONS_ROOT, FILENAMES, WORKSPACE_FILES;
296
+ var ENV_BUNDLED_EXTENSIONS_ROOT, ENV_BUNDLED_SKILLS_ROOT, FILENAMES, WORKSPACE_FILES;
294
297
  var init_paths = __esmMin((() => {
295
298
  init_agent_scope();
296
299
  init_paths_state();
297
300
  init_workspace_defaults();
298
301
  ENV_BUNDLED_EXTENSIONS_ROOT = "XOPC_BUNDLED_EXTENSIONS_ROOT";
302
+ ENV_BUNDLED_SKILLS_ROOT = "XOPC_BUNDLED_SKILLS_ROOT";
299
303
  FILENAMES = {
300
304
  CONFIG: "xopc.json",
301
305
  MODELS_JSON: "models.json",
@@ -1 +1 @@
1
- {"version":3,"file":"paths.js","names":["resolveAgentDirScoped","resolveAgentHomeScoped","resolveAgentProfileDirScoped","resolveAgentProfileMarkdownPathScoped"],"sources":["../../../src/config/paths.ts"],"sourcesContent":["import { join } from 'path';\nimport { fileURLToPath } from 'url';\nimport { dirname } from 'path';\nimport { existsSync } from 'fs';\n\nimport type { Config } from './schema.js';\nimport {\n resolveAgentDir as resolveAgentDirScoped,\n resolveAgentHomeDir as resolveAgentHomeScoped,\n resolveAgentProfileDir as resolveAgentProfileDirScoped,\n resolveAgentProfileMarkdownPath as resolveAgentProfileMarkdownPathScoped,\n resolveAgentWorkspaceDir,\n} from '../agent/agent-scope.js';\nimport { ENV_VARS, resolveStateDir } from './paths-state.js';\n\nexport { ENV_VARS, resolveHomeDir, resolveStateDir, resolveXopcDatabasePath, XOPC_DB_FILENAME } from './paths-state.js';\nexport { resolveDefaultAgentWorkspaceDir } from './workspace-defaults.js';\nexport {\n resolveAgentWorkspaceDir,\n resolveAgentDir as resolveAgentDirFromConfig,\n resolveAgentHomeDir as resolveAgentHomeDirFromConfig,\n} from '../agent/agent-scope.js';\n\n// ============================================\n// File Names\n// ============================================\nconst ENV_BUNDLED_EXTENSIONS_ROOT = 'XOPC_BUNDLED_EXTENSIONS_ROOT';\n\nexport const FILENAMES = {\n CONFIG: 'xopc.json',\n MODELS_JSON: 'models.json',\n /** Primary SQLite state database (`~/.xopc/xopc.db`). */\n XOPC_DB: 'xopc.db',\n EXTENSIONS_LOCK: 'extensions-lock.json',\n CREDENTIALS_PROFILES: 'auth-profiles.json',\n CRON_JOBS: 'jobs.json',\n WORKSPACE_STATE: 'workspace.json',\n SKILLS_CACHE: 'skills-cache.json',\n /** Hub / CLI install provenance for ~/.xopc/skills/<id>. */\n SKILLS_LOCK: 'skills-lock.json',\n PID: 'pid',\n STATUS: 'status.json',\n SOCKET: 'agent.sock',\n} as const;\n\n// ============================================\n// Workspace Files\n// ============================================\nexport const WORKSPACE_FILES = {\n SOUL: 'SOUL.md',\n IDENTITY: 'IDENTITY.md',\n USER: 'USER.md',\n AGENTS: 'AGENTS.md',\n TOOLS: 'TOOLS.md',\n HEARTBEAT: 'HEARTBEAT.md',\n MEMORY: 'MEMORY.md',\n} as const;\n\n// ============================================\n// Path Resolution Functions\n// ============================================\n\n/**\n * Resolve the main config file path\n */\nexport function resolveConfigPath(): string {\n return process.env[ENV_VARS.CONFIG_PATH] ?? join(resolveStateDir(), FILENAMES.CONFIG);\n}\n\n/**\n * Resolve the credentials directory\n */\nexport function resolveCredentialsDir(): string {\n return process.env[ENV_VARS.CREDENTIALS_DIR] ?? join(resolveStateDir(), 'credentials');\n}\n\n/**\n * Resolve the global auth-profiles.json path\n */\nexport function resolveAuthProfilesPath(): string {\n return join(resolveCredentialsDir(), FILENAMES.CREDENTIALS_PROFILES);\n}\n\n/**\n * Resolve OAuth token file path for a provider\n */\nexport function resolveOAuthPath(provider: string): string {\n return join(resolveCredentialsDir(), 'oauth', `${provider}.json`);\n}\n\n/**\n * Internal agent state dir: `stateDir/agents/<id>/agent/`\n * (credentials, inbox IPC, pid, agent.json — not the Markdown workspace).\n */\nexport function resolveAgentDir(config: Config, agentId: string): string {\n return resolveAgentDirScoped(config, agentId);\n}\n\n/**\n * Per-agent home: `stateDir/agents/<id>/` (sessions + `agent/`).\n */\nexport function resolveAgentHomeDir(config: Config, agentId: string): string {\n return resolveAgentHomeScoped(config, agentId);\n}\n\n/** Agent profile Markdown root: `stateDir/agents/<id>/profile/`. */\nexport function resolveAgentProfileDir(config: Config, agentId: string): string {\n return resolveAgentProfileDirScoped(config, agentId);\n}\n\n/** Single file under {@link resolveAgentProfileDir} (basename only). */\nexport function resolveAgentProfileMarkdownPath(config: Config, agentId: string, filename: string): string {\n return resolveAgentProfileMarkdownPathScoped(config, agentId, filename);\n}\n\n/**\n * Resolve a profile system Markdown path (SOUL.md, …) under the agent `profile/` directory.\n */\nexport function resolveWorkspaceFile(config: Config, filename: string, agentId: string): string {\n return join(resolveAgentProfileDirScoped(config, agentId), filename);\n}\n\n/**\n * OpenClaw-aligned: per-agent auth-profiles.json directly under agent dir (no credentials subdirectory).\n */\nexport function resolveAgentAuthProfilesPath(config: Config, agentId: string): string {\n return join(resolveAgentDir(config, agentId), FILENAMES.CREDENTIALS_PROFILES);\n}\n\n/**\n * Resolve the inbox directory for an agent\n */\nexport function resolveInboxDir(config: Config, agentId: string): string {\n return join(resolveAgentDir(config, agentId), 'inbox');\n}\n\n/**\n * Resolve the pending inbox directory\n */\nexport function resolveInboxPendingDir(config: Config, agentId: string): string {\n return join(resolveInboxDir(config, agentId), 'pending');\n}\n\n/**\n * Resolve the processed inbox directory\n */\nexport function resolveInboxProcessedDir(config: Config, agentId: string): string {\n return join(resolveInboxDir(config, agentId), 'processed');\n}\n\n/**\n * Resolve a specific inbox message path\n */\nexport function resolveInboxMessagePath(\n config: Config,\n messageId: string,\n pending: boolean,\n agentId: string,\n): string {\n const dir = pending ? resolveInboxPendingDir(config, agentId) : resolveInboxProcessedDir(config, agentId);\n return join(dir, `${messageId}.json`);\n}\n\n/**\n * Resolve the pid file path\n */\nexport function resolvePidPath(config: Config, agentId: string): string {\n return join(resolveAgentDir(config, agentId), FILENAMES.PID);\n}\n\n/**\n * Resolve the status.json path\n */\nexport function resolveStatusPath(config: Config, agentId: string): string {\n return join(resolveAgentDir(config, agentId), FILENAMES.STATUS);\n}\n\n/**\n * Resolve the Unix socket path\n */\nexport function resolveSocketPath(config: Config, agentId: string): string {\n return join(resolveAgentDir(config, agentId), FILENAMES.SOCKET);\n}\n\n/**\n * Resolve the extensions directory (global)\n */\nexport function resolveExtensionsDir(): string {\n return join(resolveStateDir(), 'extensions');\n}\n\n/**\n * Resolve the extensions lockfile path\n */\nexport function resolveExtensionsLockPath(): string {\n return join(resolveExtensionsDir(), FILENAMES.EXTENSIONS_LOCK);\n}\n\n/**\n * Per-agent extensions directory (`…/agents/<id>/agent/extensions/`) — used for discovery of\n * legacy or manually placed copies. CLI, web store, and `extensions dev` symlink installs use\n * {@link resolveExtensionsDir} (`~/.xopc/extensions`) only.\n */\nexport function resolveWorkspaceExtensionsDir(config: Config, agentId: string): string {\n return join(resolveAgentDir(config, agentId), 'extensions');\n}\n\n/**\n * Resolve the skills directory (global)\n */\nexport function resolveSkillsDir(): string {\n return join(resolveStateDir(), 'skills');\n}\n\n/**\n * Resolve a specific skill path\n */\nexport function resolveSkillPath(skillId: string): string {\n return join(resolveSkillsDir(), skillId, 'SKILL.md');\n}\n\n/**\n * Skills hub lock file (~/.xopc/skills-lock.json): install source + content hash per managed skill id.\n */\nexport function resolveSkillsLockPath(): string {\n return join(resolveStateDir(), FILENAMES.SKILLS_LOCK);\n}\n\n/**\n * Resolve the cron directory\n */\nexport function resolveCronDir(): string {\n return join(resolveStateDir(), 'cron');\n}\n\n/**\n * Resolve the cron jobs file path\n */\nexport function resolveCronJobsPath(): string {\n return join(resolveCronDir(), FILENAMES.CRON_JOBS);\n}\n\n/**\n * Resolve the logs directory\n */\nexport function resolveLogsDir(): string {\n return process.env[ENV_VARS.LOG_DIR] ?? join(resolveStateDir(), 'logs');\n}\n\n/**\n * Resolve a specific log file path\n */\nexport function resolveLogPath(date: string): string {\n return join(resolveLogsDir(), `xopc-${date}.log`);\n}\n\n/**\n * Resolve the bin directory\n */\nexport function resolveBinDir(): string {\n return join(resolveStateDir(), 'bin');\n}\n\n/**\n * Resolve the xopc CLI path\n */\nexport function resolveXopcBinPath(): string {\n return join(resolveBinDir(), 'xopc');\n}\n\n/**\n * Resolve the tools directory\n */\nexport function resolveToolsDir(): string {\n return join(resolveStateDir(), 'tools');\n}\n\n/**\n * Resolve the Node.js tools directory\n */\nexport function resolveNodeToolsDir(): string {\n return join(resolveToolsDir(), 'node');\n}\n\n/**\n * Resolve the current Node.js bin directory\n */\nexport function resolveNodeBinDir(): string {\n return join(resolveNodeToolsDir(), 'current', 'bin');\n}\n\n/**\n * Resolve the node binary path\n */\nexport function resolveNodeBinPath(): string {\n return join(resolveNodeBinDir(), 'node');\n}\n\n/**\n * Resolve the npm binary path\n */\nexport function resolveNpmBinPath(): string {\n return join(resolveNodeBinDir(), 'npm');\n}\n\n/**\n * Resolve the models.json path\n */\nexport function resolveModelsJsonPath(): string {\n return join(resolveStateDir(), FILENAMES.MODELS_JSON);\n}\n\n/**\n * OpenClaw-aligned: workspace setup state directory (`<workspace>/.xopc/`).\n */\nexport function resolveWorkspaceStateDir(config: Config, agentId: string): string {\n return join(resolveAgentWorkspaceDir(config, agentId), '.xopc');\n}\n\n/**\n * OpenClaw-aligned: workspace setup state file (`<workspace>/.xopc/workspace.json`).\n */\nexport function resolveWorkspaceStatePath(config: Config, agentId: string): string {\n return join(resolveWorkspaceStateDir(config, agentId), FILENAMES.WORKSPACE_STATE);\n}\n\n/**\n * Resolve the skills cache file path (internal agent state, under agent dir).\n */\nexport function resolveSkillsCachePath(config: Config, agentId: string): string {\n return join(resolveAgentDir(config, agentId), 'state', FILENAMES.SKILLS_CACHE);\n}\n\n/**\n * Resolve the bundled extensions directory (shipped with xopc).\n *\n * Layout-dependent candidates (first existing wins):\n * - `XOPC_BUNDLED_EXTENSIONS_ROOT` (Electron packaged gateway override)\n * - `dist/src/config` → `dist/extensions` (npm / gateway)\n * - `src/config` → `extensions/` (dev, tsx)\n * - `out/server` → `dist/extensions` (Electron esbuild bundle)\n */\nexport function resolveBundledExtensionsDir(): string | null {\n const envDir = process.env[ENV_BUNDLED_EXTENSIONS_ROOT];\n if (envDir && existsSync(envDir)) {\n return envDir;\n }\n\n try {\n const currentFile = fileURLToPath(import.meta.url);\n const srcDir = dirname(currentFile);\n const candidates = [\n join(srcDir, '..', '..', 'extensions'),\n join(srcDir, '..', '..', 'dist', 'extensions'),\n join(srcDir, '..', '..', '..', 'extensions'),\n ];\n for (const dir of candidates) {\n if (existsSync(dir)) {\n return dir;\n }\n }\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Resolve the bundled skills directory (shipped with xopc)\n */\nexport function resolveBundledSkillsDir(): string | null {\n try {\n const currentFile = fileURLToPath(import.meta.url);\n const srcDir = dirname(currentFile);\n \n // Production (npm): dist/config/paths.js -> ../../ -> package root -> skills\n const packageRoot = join(srcDir, '..', '..');\n const skillsDir = join(packageRoot, 'skills');\n if (existsSync(skillsDir)) {\n return skillsDir;\n }\n \n // Development (source): src/config/paths.js -> ../../../ -> package root -> skills\n const devPackageRoot = join(srcDir, '..', '..', '..');\n const devSkillsDir = join(devPackageRoot, 'skills');\n if (existsSync(devSkillsDir)) {\n return devSkillsDir;\n }\n \n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Path to extension-sdk entry (for jiti / extension loader aliases).\n */\nexport function resolveExtensionSdkPath(): string {\n try {\n const currentFile = fileURLToPath(import.meta.url);\n const srcDir = dirname(currentFile);\n const adjacent = join(srcDir, '..', 'extensions', 'sdk', 'index.ts');\n if (existsSync(adjacent)) {\n return adjacent;\n }\n const fromPackageRoot = join(srcDir, '..', '..', 'src', 'extensions', 'sdk', 'index.ts');\n if (existsSync(fromPackageRoot)) {\n return fromPackageRoot;\n }\n const cwd = join(process.cwd(), 'src', 'extensions', 'sdk', 'index.ts');\n if (existsSync(cwd)) {\n return cwd;\n }\n return adjacent;\n } catch {\n return join(process.cwd(), 'src', 'extensions', 'sdk', 'index.ts');\n }\n}\n\n// Re-export existsSync for bundled paths\nexport { existsSync };\n"],"mappings":"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"}
1
+ {"version":3,"file":"paths.js","names":["resolveAgentDirScoped","resolveAgentHomeScoped","resolveAgentProfileDirScoped","resolveAgentProfileMarkdownPathScoped"],"sources":["../../../src/config/paths.ts"],"sourcesContent":["import { join, sep } from 'path';\nimport { fileURLToPath } from 'url';\nimport { dirname } from 'path';\nimport { existsSync } from 'fs';\n\nimport type { Config } from './schema.js';\nimport {\n resolveAgentDir as resolveAgentDirScoped,\n resolveAgentHomeDir as resolveAgentHomeScoped,\n resolveAgentProfileDir as resolveAgentProfileDirScoped,\n resolveAgentProfileMarkdownPath as resolveAgentProfileMarkdownPathScoped,\n resolveAgentWorkspaceDir,\n} from '../agent/agent-scope.js';\nimport { ENV_VARS, resolveStateDir } from './paths-state.js';\n\nexport { ENV_VARS, resolveHomeDir, resolveStateDir, resolveXopcDatabasePath, XOPC_DB_FILENAME } from './paths-state.js';\nexport { resolveDefaultAgentWorkspaceDir } from './workspace-defaults.js';\nexport {\n resolveAgentWorkspaceDir,\n resolveAgentDir as resolveAgentDirFromConfig,\n resolveAgentHomeDir as resolveAgentHomeDirFromConfig,\n} from '../agent/agent-scope.js';\n\n// ============================================\n// File Names\n// ============================================\nconst ENV_BUNDLED_EXTENSIONS_ROOT = 'XOPC_BUNDLED_EXTENSIONS_ROOT';\nconst ENV_BUNDLED_SKILLS_ROOT = 'XOPC_BUNDLED_SKILLS_ROOT';\n\nexport const FILENAMES = {\n CONFIG: 'xopc.json',\n MODELS_JSON: 'models.json',\n /** Primary SQLite state database (`~/.xopc/xopc.db`). */\n XOPC_DB: 'xopc.db',\n EXTENSIONS_LOCK: 'extensions-lock.json',\n CREDENTIALS_PROFILES: 'auth-profiles.json',\n CRON_JOBS: 'jobs.json',\n WORKSPACE_STATE: 'workspace.json',\n SKILLS_CACHE: 'skills-cache.json',\n /** Hub / CLI install provenance for ~/.xopc/skills/<id>. */\n SKILLS_LOCK: 'skills-lock.json',\n PID: 'pid',\n STATUS: 'status.json',\n SOCKET: 'agent.sock',\n} as const;\n\n// ============================================\n// Workspace Files\n// ============================================\nexport const WORKSPACE_FILES = {\n SOUL: 'SOUL.md',\n IDENTITY: 'IDENTITY.md',\n USER: 'USER.md',\n AGENTS: 'AGENTS.md',\n TOOLS: 'TOOLS.md',\n HEARTBEAT: 'HEARTBEAT.md',\n MEMORY: 'MEMORY.md',\n} as const;\n\n// ============================================\n// Path Resolution Functions\n// ============================================\n\n/**\n * Resolve the main config file path\n */\nexport function resolveConfigPath(): string {\n return process.env[ENV_VARS.CONFIG_PATH] ?? join(resolveStateDir(), FILENAMES.CONFIG);\n}\n\n/**\n * Resolve the credentials directory\n */\nexport function resolveCredentialsDir(): string {\n return process.env[ENV_VARS.CREDENTIALS_DIR] ?? join(resolveStateDir(), 'credentials');\n}\n\n/**\n * Resolve the global auth-profiles.json path\n */\nexport function resolveAuthProfilesPath(): string {\n return join(resolveCredentialsDir(), FILENAMES.CREDENTIALS_PROFILES);\n}\n\n/**\n * Resolve OAuth token file path for a provider\n */\nexport function resolveOAuthPath(provider: string): string {\n return join(resolveCredentialsDir(), 'oauth', `${provider}.json`);\n}\n\n/**\n * Internal agent state dir: `stateDir/agents/<id>/agent/`\n * (credentials, inbox IPC, pid, agent.json — not the Markdown workspace).\n */\nexport function resolveAgentDir(config: Config, agentId: string): string {\n return resolveAgentDirScoped(config, agentId);\n}\n\n/**\n * Per-agent home: `stateDir/agents/<id>/` (sessions + `agent/`).\n */\nexport function resolveAgentHomeDir(config: Config, agentId: string): string {\n return resolveAgentHomeScoped(config, agentId);\n}\n\n/** Agent profile Markdown root: `stateDir/agents/<id>/profile/`. */\nexport function resolveAgentProfileDir(config: Config, agentId: string): string {\n return resolveAgentProfileDirScoped(config, agentId);\n}\n\n/** Single file under {@link resolveAgentProfileDir} (basename only). */\nexport function resolveAgentProfileMarkdownPath(config: Config, agentId: string, filename: string): string {\n return resolveAgentProfileMarkdownPathScoped(config, agentId, filename);\n}\n\n/**\n * Resolve a profile system Markdown path (SOUL.md, …) under the agent `profile/` directory.\n */\nexport function resolveWorkspaceFile(config: Config, filename: string, agentId: string): string {\n return join(resolveAgentProfileDirScoped(config, agentId), filename);\n}\n\n/**\n * OpenClaw-aligned: per-agent auth-profiles.json directly under agent dir (no credentials subdirectory).\n */\nexport function resolveAgentAuthProfilesPath(config: Config, agentId: string): string {\n return join(resolveAgentDir(config, agentId), FILENAMES.CREDENTIALS_PROFILES);\n}\n\n/**\n * Resolve the inbox directory for an agent\n */\nexport function resolveInboxDir(config: Config, agentId: string): string {\n return join(resolveAgentDir(config, agentId), 'inbox');\n}\n\n/**\n * Resolve the pending inbox directory\n */\nexport function resolveInboxPendingDir(config: Config, agentId: string): string {\n return join(resolveInboxDir(config, agentId), 'pending');\n}\n\n/**\n * Resolve the processed inbox directory\n */\nexport function resolveInboxProcessedDir(config: Config, agentId: string): string {\n return join(resolveInboxDir(config, agentId), 'processed');\n}\n\n/**\n * Resolve a specific inbox message path\n */\nexport function resolveInboxMessagePath(\n config: Config,\n messageId: string,\n pending: boolean,\n agentId: string,\n): string {\n const dir = pending ? resolveInboxPendingDir(config, agentId) : resolveInboxProcessedDir(config, agentId);\n return join(dir, `${messageId}.json`);\n}\n\n/**\n * Resolve the pid file path\n */\nexport function resolvePidPath(config: Config, agentId: string): string {\n return join(resolveAgentDir(config, agentId), FILENAMES.PID);\n}\n\n/**\n * Resolve the status.json path\n */\nexport function resolveStatusPath(config: Config, agentId: string): string {\n return join(resolveAgentDir(config, agentId), FILENAMES.STATUS);\n}\n\n/**\n * Resolve the Unix socket path\n */\nexport function resolveSocketPath(config: Config, agentId: string): string {\n return join(resolveAgentDir(config, agentId), FILENAMES.SOCKET);\n}\n\n/**\n * Resolve the extensions directory (global)\n */\nexport function resolveExtensionsDir(): string {\n return join(resolveStateDir(), 'extensions');\n}\n\n/**\n * Resolve the extensions lockfile path\n */\nexport function resolveExtensionsLockPath(): string {\n return join(resolveExtensionsDir(), FILENAMES.EXTENSIONS_LOCK);\n}\n\n/**\n * Per-agent extensions directory (`…/agents/<id>/agent/extensions/`) — used for discovery of\n * legacy or manually placed copies. CLI, web store, and `extensions dev` symlink installs use\n * {@link resolveExtensionsDir} (`~/.xopc/extensions`) only.\n */\nexport function resolveWorkspaceExtensionsDir(config: Config, agentId: string): string {\n return join(resolveAgentDir(config, agentId), 'extensions');\n}\n\n/**\n * Resolve the skills directory (global)\n */\nexport function resolveSkillsDir(): string {\n return join(resolveStateDir(), 'skills');\n}\n\n/**\n * Resolve a specific skill path\n */\nexport function resolveSkillPath(skillId: string): string {\n return join(resolveSkillsDir(), skillId, 'SKILL.md');\n}\n\n/**\n * Skills hub lock file (~/.xopc/skills-lock.json): install source + content hash per managed skill id.\n */\nexport function resolveSkillsLockPath(): string {\n return join(resolveStateDir(), FILENAMES.SKILLS_LOCK);\n}\n\n/**\n * Resolve the cron directory\n */\nexport function resolveCronDir(): string {\n return join(resolveStateDir(), 'cron');\n}\n\n/**\n * Resolve the cron jobs file path\n */\nexport function resolveCronJobsPath(): string {\n return join(resolveCronDir(), FILENAMES.CRON_JOBS);\n}\n\n/**\n * Resolve the logs directory\n */\nexport function resolveLogsDir(): string {\n return process.env[ENV_VARS.LOG_DIR] ?? join(resolveStateDir(), 'logs');\n}\n\n/**\n * Resolve a specific log file path\n */\nexport function resolveLogPath(date: string): string {\n return join(resolveLogsDir(), `xopc-${date}.log`);\n}\n\n/**\n * Resolve the bin directory\n */\nexport function resolveBinDir(): string {\n return join(resolveStateDir(), 'bin');\n}\n\n/**\n * Resolve the xopc CLI path\n */\nexport function resolveXopcBinPath(): string {\n return join(resolveBinDir(), 'xopc');\n}\n\n/**\n * Resolve the tools directory\n */\nexport function resolveToolsDir(): string {\n return join(resolveStateDir(), 'tools');\n}\n\n/**\n * Resolve the Node.js tools directory\n */\nexport function resolveNodeToolsDir(): string {\n return join(resolveToolsDir(), 'node');\n}\n\n/**\n * Resolve the current Node.js bin directory\n */\nexport function resolveNodeBinDir(): string {\n return join(resolveNodeToolsDir(), 'current', 'bin');\n}\n\n/**\n * Resolve the node binary path\n */\nexport function resolveNodeBinPath(): string {\n return join(resolveNodeBinDir(), 'node');\n}\n\n/**\n * Resolve the npm binary path\n */\nexport function resolveNpmBinPath(): string {\n return join(resolveNodeBinDir(), 'npm');\n}\n\n/**\n * Resolve the models.json path\n */\nexport function resolveModelsJsonPath(): string {\n return join(resolveStateDir(), FILENAMES.MODELS_JSON);\n}\n\n/**\n * OpenClaw-aligned: workspace setup state directory (`<workspace>/.xopc/`).\n */\nexport function resolveWorkspaceStateDir(config: Config, agentId: string): string {\n return join(resolveAgentWorkspaceDir(config, agentId), '.xopc');\n}\n\n/**\n * OpenClaw-aligned: workspace setup state file (`<workspace>/.xopc/workspace.json`).\n */\nexport function resolveWorkspaceStatePath(config: Config, agentId: string): string {\n return join(resolveWorkspaceStateDir(config, agentId), FILENAMES.WORKSPACE_STATE);\n}\n\n/**\n * Resolve the skills cache file path (internal agent state, under agent dir).\n */\nexport function resolveSkillsCachePath(config: Config, agentId: string): string {\n return join(resolveAgentDir(config, agentId), 'state', FILENAMES.SKILLS_CACHE);\n}\n\n/**\n * Resolve the bundled extensions directory (shipped with xopc).\n *\n * Layout-dependent candidates (first existing wins):\n * - `XOPC_BUNDLED_EXTENSIONS_ROOT` (Electron packaged gateway override)\n * - `dist/src/config` → `dist/extensions` (npm / gateway)\n * - `src/config` → `dist/extensions` when built, else `extensions/` (dev, tsx)\n * - `out/server` → `dist/electron/extensions` (Electron extension bundles)\n */\nexport function resolveBundledExtensionsDir(): string | null {\n const envDir = process.env[ENV_BUNDLED_EXTENSIONS_ROOT];\n if (envDir && existsSync(envDir)) {\n return envDir;\n }\n\n try {\n const currentFile = fileURLToPath(import.meta.url);\n const srcDir = dirname(currentFile);\n const isElectronServerBundle = srcDir.endsWith(`${sep}out${sep}server`);\n const candidates = isElectronServerBundle\n ? [join(srcDir, '..', '..', 'dist', 'electron', 'extensions')]\n : [\n // In source-tree dev, prefer compiled bundled extensions when present: manifests point\n // at built JavaScript entries (for example src/index.js), while source folders contain TS.\n join(srcDir, '..', '..', 'dist', 'extensions'),\n join(srcDir, '..', '..', 'extensions'),\n join(srcDir, '..', '..', '..', 'dist', 'extensions'),\n join(srcDir, '..', '..', '..', 'extensions'),\n ];\n for (const dir of candidates) {\n if (existsSync(dir)) {\n return dir;\n }\n }\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Resolve the bundled skills directory (shipped with xopc)\n */\nexport function resolveBundledSkillsDir(): string | null {\n const envDir = process.env[ENV_BUNDLED_SKILLS_ROOT];\n if (envDir && existsSync(envDir)) {\n return envDir;\n }\n\n try {\n const currentFile = fileURLToPath(import.meta.url);\n const srcDir = dirname(currentFile);\n \n // Production (npm): dist/config/paths.js -> ../../ -> package root -> skills\n const packageRoot = join(srcDir, '..', '..');\n const skillsDir = join(packageRoot, 'skills');\n if (existsSync(skillsDir)) {\n return skillsDir;\n }\n \n // Development (source): src/config/paths.js -> ../../../ -> package root -> skills\n const devPackageRoot = join(srcDir, '..', '..', '..');\n const devSkillsDir = join(devPackageRoot, 'skills');\n if (existsSync(devSkillsDir)) {\n return devSkillsDir;\n }\n \n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Path to extension-sdk entry (for jiti / extension loader aliases).\n */\nexport function resolveExtensionSdkPath(): string {\n try {\n const currentFile = fileURLToPath(import.meta.url);\n const srcDir = dirname(currentFile);\n const adjacent = join(srcDir, '..', 'extensions', 'sdk', 'index.ts');\n if (existsSync(adjacent)) {\n return adjacent;\n }\n const fromPackageRoot = join(srcDir, '..', '..', 'src', 'extensions', 'sdk', 'index.ts');\n if (existsSync(fromPackageRoot)) {\n return fromPackageRoot;\n }\n const cwd = join(process.cwd(), 'src', 'extensions', 'sdk', 'index.ts');\n if (existsSync(cwd)) {\n return cwd;\n }\n return adjacent;\n } catch {\n return join(process.cwd(), 'src', 'extensions', 'sdk', 'index.ts');\n }\n}\n\n// Re-export existsSync for bundled paths\nexport { existsSync };\n"],"mappings":"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"}
@@ -605,6 +605,7 @@ export declare const AgentsConfigSchema: z.ZodDefault<z.ZodObject<{
605
605
  }, z.core.$strip>>;
606
606
  params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
607
607
  }, z.core.$strip>>>;
608
+ starterAgentsInitializedVersion: z.ZodOptional<z.ZodNumber>;
608
609
  }, z.core.$strip>>;
609
610
  export { TelegramTopicConfigSchema, TelegramGroupConfigSchema, TelegramAccountConfigSchema, TelegramConfigSchema, } from '../../extensions/telegram/src/config-schema.js';
610
611
  export type { TelegramConfig } from '../../extensions/telegram/src/config-schema.js';
@@ -1905,6 +1906,7 @@ export declare const ConfigSchema: z.ZodDefault<z.ZodObject<{
1905
1906
  }, z.core.$strip>>;
1906
1907
  params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1907
1908
  }, z.core.$strip>>>;
1909
+ starterAgentsInitializedVersion: z.ZodOptional<z.ZodNumber>;
1908
1910
  }, z.core.$strip>>;
1909
1911
  bindings: z.ZodDefault<z.ZodArray<z.ZodObject<{
1910
1912
  id: z.ZodOptional<z.ZodString>;
@@ -401,7 +401,9 @@ summaryModel: z.string().optional() }).optional(),
401
401
  /** Default agent id when not specified (routing / session creation). */
402
402
  default: z.string().optional(),
403
403
  defaults: AgentDefaultsSchema.optional(),
404
- list: z.array(AgentConfigSchema).optional()
404
+ list: z.array(AgentConfigSchema).optional(),
405
+ /** One-time starter agent bootstrap marker. Agents remain ordinary list entries after initialization. */
406
+ starterAgentsInitializedVersion: z.number().int().min(0).optional()
405
407
  }).default({ defaults: {
406
408
  workspace: "~/.xopc/workspace",
407
409
  maxTokens: 8192,