@intent-systems/nexus 2026.1.5-4 → 2026.1.5-8

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 (347) hide show
  1. package/dist/agents/agent-id.js +41 -0
  2. package/dist/agents/auth-profiles.js +114 -25
  3. package/dist/agents/identity-state.js +101 -0
  4. package/dist/agents/model-auth.js +1 -0
  5. package/dist/agents/model-fallback.js +15 -9
  6. package/dist/agents/model-selection.js +1 -1
  7. package/dist/agents/models-config.js +17 -11
  8. package/dist/agents/pi-embedded-runner.js +101 -9
  9. package/dist/agents/sandbox.js +12 -3
  10. package/dist/agents/skill-runner.js +41 -6
  11. package/dist/agents/skill-usage.js +117 -17
  12. package/dist/agents/skills-status.js +4 -3
  13. package/dist/agents/skills.js +38 -30
  14. package/dist/agents/subagent-registry.js +25 -11
  15. package/dist/agents/system-prompt.js +16 -0
  16. package/dist/agents/tool-policy.js +19 -3
  17. package/dist/agents/tools/browser-tool.js +5 -2
  18. package/dist/agents/tools/image-tool.js +93 -8
  19. package/dist/agents/tools/sessions-announce-target.js +5 -1
  20. package/dist/agents/workspace.js +81 -59
  21. package/dist/auto-reply/command-detection.js +2 -1
  22. package/dist/auto-reply/reply/directive-handling.js +153 -28
  23. package/dist/auto-reply/reply/directives.js +17 -2
  24. package/dist/auto-reply/reply/model-selection.js +8 -3
  25. package/dist/auto-reply/reply/queue.js +2 -2
  26. package/dist/auto-reply/reply.js +1 -1
  27. package/dist/auto-reply/thinking.js +15 -0
  28. package/dist/browser/chrome.js +1 -1
  29. package/dist/browser/client.js +2 -0
  30. package/dist/browser/config.js +6 -2
  31. package/dist/browser/pw-tools-core.js +3 -0
  32. package/dist/browser/routes/agent.js +14 -0
  33. package/dist/canvas-host/server.js +1 -1
  34. package/dist/capabilities/detector.js +46 -15
  35. package/dist/capabilities/registry.js +2 -1
  36. package/dist/cli/cloud-cli.js +70 -7
  37. package/dist/cli/credential-cli.js +214 -23
  38. package/dist/cli/gateway-cli.js +1 -1
  39. package/dist/cli/log-cli.js +25 -0
  40. package/dist/cli/pairing-cli.js +1 -1
  41. package/dist/cli/program.js +82 -8
  42. package/dist/cli/run-main.js +1 -1
  43. package/dist/cli/skills-cli.js +165 -30
  44. package/dist/cli/skills-hub-cli.js +68 -36
  45. package/dist/cli/tool-connector-cli.js +99 -24
  46. package/dist/cli/upstream-sync-cli.js +253 -96
  47. package/dist/cli/usage-cli.js +14 -0
  48. package/dist/commands/auth-choice-options.js +6 -1
  49. package/dist/commands/auth-choice.js +157 -5
  50. package/dist/commands/bootstrap-preset.js +26 -12
  51. package/dist/commands/capabilities.js +33 -6
  52. package/dist/commands/claude-md.js +3 -2
  53. package/dist/commands/config-view.js +1 -1
  54. package/dist/commands/config.js +85 -0
  55. package/dist/commands/configure.js +4 -4
  56. package/dist/commands/credential.js +497 -36
  57. package/dist/commands/cursor-hooks.js +240 -0
  58. package/dist/commands/cursor-rules.js +14 -188
  59. package/dist/commands/doctor.js +5 -4
  60. package/dist/commands/identity.js +29 -32
  61. package/dist/commands/init.js +304 -20
  62. package/dist/commands/log.js +134 -0
  63. package/dist/commands/models/fallbacks.js +1 -1
  64. package/dist/commands/models/image-fallbacks.js +1 -1
  65. package/dist/commands/models/list.js +1 -1
  66. package/dist/commands/models/scan.js +1 -1
  67. package/dist/commands/onboard-auth.js +27 -2
  68. package/dist/commands/onboard-eve-identity.js +8 -9
  69. package/dist/commands/onboard-non-interactive.js +4 -2
  70. package/dist/commands/onboard-quickstart.js +18 -11
  71. package/dist/commands/quest-state.js +271 -0
  72. package/dist/commands/quest.js +53 -13
  73. package/dist/commands/reset.js +1 -1
  74. package/dist/commands/sessions-ingest.js +5 -4
  75. package/dist/commands/setup.js +4 -2
  76. package/dist/commands/skills-manifest.js +89 -29
  77. package/dist/commands/status.js +193 -73
  78. package/dist/commands/suggestions.js +1 -1
  79. package/dist/commands/usage-tracking.js +32 -0
  80. package/dist/commands/usage-upload.js +6 -1
  81. package/dist/config/defaults.js +1 -3
  82. package/dist/config/includes.js +5 -7
  83. package/dist/config/io.js +88 -16
  84. package/dist/config/legacy.js +4 -2
  85. package/dist/config/paths.js +16 -0
  86. package/dist/config/sessions.js +9 -5
  87. package/dist/config/zod-schema.js +4 -3
  88. package/dist/control-plane/broker/broker.js +131 -78
  89. package/dist/control-plane/compaction.js +3 -5
  90. package/dist/control-plane/factory.js +2 -2
  91. package/dist/control-plane/index.js +2 -2
  92. package/dist/control-plane/odu/agents.js +28 -23
  93. package/dist/control-plane/odu/interaction-tools.js +62 -50
  94. package/dist/control-plane/odu/prompt-loader.js +8 -8
  95. package/dist/control-plane/odu/runtime.js +87 -75
  96. package/dist/control-plane/odu-control-plane.js +14 -12
  97. package/dist/control-plane/single-agent.js +13 -13
  98. package/dist/credentials/store.js +133 -7
  99. package/dist/daemon/launchd.js +14 -0
  100. package/dist/entry.js +0 -0
  101. package/dist/gateway/server-browser.js +5 -4
  102. package/dist/gateway/server-methods/cron.js +11 -1
  103. package/dist/gateway/server.js +14 -7
  104. package/dist/infra/bonjour.js +1 -1
  105. package/dist/infra/event-log.js +8 -2
  106. package/dist/infra/path-env.js +1 -2
  107. package/dist/infra/provider-usage.auth.js +5 -3
  108. package/dist/infra/provider-usage.fetch.claude.js +16 -6
  109. package/dist/infra/provider-usage.fetch.minimax.js +8 -3
  110. package/dist/infra/provider-usage.js +9 -5
  111. package/dist/infra/restart.js +2 -2
  112. package/dist/infra/usage-settings.js +78 -0
  113. package/dist/infra/usage-suggestions.js +17 -5
  114. package/dist/infra/usage-upload.js +38 -1
  115. package/dist/infra/voicewake.js +2 -2
  116. package/dist/media/image-ops.js +3 -1
  117. package/dist/memory/index.js +2 -381
  118. package/dist/native/nexus-cloud/darwin-arm64/nexus-cloud +0 -0
  119. package/dist/native/nexus-cloud/darwin-arm64/nexus-cloud-rs +0 -0
  120. package/dist/pairing/pairing-store.js +24 -0
  121. package/dist/providers/github-copilot-auth.js +1 -1
  122. package/dist/routing/resolve-route.js +6 -6
  123. package/dist/routing/session-key.js +3 -1
  124. package/dist/sessions/send-policy.js +5 -5
  125. package/dist/slack/monitor.js +22 -1
  126. package/dist/telegram/reaction-level.js +2 -1
  127. package/dist/utils.js +8 -3
  128. package/dist/wizard/onboarding.js +29 -7
  129. package/docs/AGENTS.default.md +1 -1
  130. package/docs/configuration.md +1 -1
  131. package/docs/feature-inventory/overview.md +2 -2
  132. package/docs/reference/templates/AGENTS.md +172 -109
  133. package/docs/templates/AGENTS.md +140 -199
  134. package/docs/templates/BOOTSTRAP.md +40 -20
  135. package/docs/templates/IDENTITY.md +6 -0
  136. package/docs/templates/USER.md +22 -2
  137. package/package.json +3 -1
  138. package/skills/{notion → connectors/notion}/SKILL.md +1 -1
  139. package/skills/{filesystem → guides/filesystem}/SKILL.md +1 -1
  140. package/skills/{onboarding → guides/onboarding}/SKILL.md +1 -1
  141. package/skills/{onboarding → guides/onboarding}/docs/CAPABILITY_TAXONOMY.md +5 -5
  142. package/skills/{onboarding → guides/onboarding}/docs/CLI_GRAMMAR.md +8 -8
  143. package/skills/{onboarding → guides/onboarding}/docs/CLI_GRAMMAR_ONBOARDING.md +2 -2
  144. package/skills/{onboarding → guides/onboarding}/docs/CLI_GRAMMAR_SKILLS.md +26 -20
  145. package/skills/{onboarding → guides/onboarding}/docs/GOAL_STATE_ARCHITECTURE.md +38 -43
  146. package/skills/{onboarding → guides/onboarding}/docs/NEXUS_SYSTEM_OVERVIEW.md +4 -4
  147. package/skills/{onboarding → guides/onboarding}/docs/SKILLS_HUB_SPEC.md +1 -1
  148. package/skills/{onboarding → guides/onboarding}/docs/SKILLS_SPECIFICATION.md +8 -7
  149. package/skills/{onboarding → guides/onboarding}/docs/SKILL_GATEWAY_DESIGN.md +16 -16
  150. package/skills/{onboarding → guides/onboarding}/docs/SKILL_GATEWAY_PRD.md +10 -12
  151. package/skills/guides/onboarding/docs/canonical/00_CONFLICT_ANALYSIS.md +463 -0
  152. package/skills/guides/onboarding/docs/canonical/01_NEXUS_OVERVIEW.md +167 -0
  153. package/skills/guides/onboarding/docs/canonical/02_CLI_REFERENCE.md +404 -0
  154. package/skills/guides/onboarding/docs/canonical/03_STATE_ARCHITECTURE.md +357 -0
  155. package/skills/guides/onboarding/docs/canonical/04_SKILL_SPECIFICATION.md +393 -0
  156. package/skills/guides/onboarding/docs/canonical/05_CAPABILITY_TAXONOMY.md +298 -0
  157. package/skills/guides/onboarding/docs/canonical/06_CAPABILITIES_REFERENCE.md +207 -0
  158. package/skills/guides/onboarding/docs/canonical/07_AGENT_BINDINGS.md +85 -0
  159. package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/nexus-cloud.md +2 -2
  160. package/skills/{onboarding → guides/onboarding}/scripts/ralph/progress.txt +1 -1
  161. package/skills/{nexus-cloud → tools/nexus-cloud}/SKILL.md +2 -1
  162. package/skills/{nexus-cloud → tools/nexus-cloud}/docs/setup.md +1 -1
  163. package/docs/templates/PROFILE.md +0 -14
  164. /package/skills/{brave-search → connectors/brave-search}/SKILL.md +0 -0
  165. /package/skills/{brave-search → connectors/brave-search}/docs/setup.md +0 -0
  166. /package/skills/{brave-search → connectors/brave-search}/docs/troubleshooting.md +0 -0
  167. /package/skills/{brave-search → connectors/brave-search}/docs/usage.md +0 -0
  168. /package/skills/{brave-search → connectors/brave-search}/scripts/content.mjs +0 -0
  169. /package/skills/{brave-search → connectors/brave-search}/scripts/search.mjs +0 -0
  170. /package/skills/{discord → connectors/discord}/SKILL.md +0 -0
  171. /package/skills/{gemini → connectors/gemini}/SKILL.md +0 -0
  172. /package/skills/{github → connectors/github}/SKILL.md +0 -0
  173. /package/skills/{github → connectors/github}/docs/setup.md +0 -0
  174. /package/skills/{github → connectors/github}/docs/troubleshooting.md +0 -0
  175. /package/skills/{google-oauth → connectors/google-oauth}/SKILL.md +0 -0
  176. /package/skills/{slack → connectors/slack}/SKILL.md +0 -0
  177. /package/skills/{telegram → connectors/telegram}/SKILL.md +0 -0
  178. /package/skills/{telegram → connectors/telegram}/docs/pairing.md +0 -0
  179. /package/skills/{telegram → connectors/telegram}/docs/setup.md +0 -0
  180. /package/skills/{telegram → connectors/telegram}/docs/webhook.md +0 -0
  181. /package/skills/{wacli → connectors/wacli}/SKILL.md +0 -0
  182. /package/skills/{wacli → connectors/wacli}/docs/auth.md +0 -0
  183. /package/skills/{wacli → connectors/wacli}/docs/backup.md +0 -0
  184. /package/skills/{wacli → connectors/wacli}/docs/troubleshooting.md +0 -0
  185. /package/skills/{browser-use-agent-sdk → guides/browser-use-agent-sdk}/SKILL.md +0 -0
  186. /package/skills/{json-render → guides/json-render}/SKILL.md +0 -0
  187. /package/skills/{json-render → guides/json-render}/assets/components/README.md +0 -0
  188. /package/skills/{json-render → guides/json-render}/assets/components/catalog.ts +0 -0
  189. /package/skills/{json-render → guides/json-render}/assets/components/registry.tsx +0 -0
  190. /package/skills/{json-render → guides/json-render}/assets/demo/App.css +0 -0
  191. /package/skills/{json-render → guides/json-render}/assets/demo/App.tsx +0 -0
  192. /package/skills/{json-render → guides/json-render}/assets/demo/README.md +0 -0
  193. /package/skills/{json-render → guides/json-render}/assets/demo/catalog.ts +0 -0
  194. /package/skills/{json-render → guides/json-render}/assets/demo/data/nexus-core.json +0 -0
  195. /package/skills/{json-render → guides/json-render}/assets/demo/index.css +0 -0
  196. /package/skills/{json-render → guides/json-render}/assets/demo/registry.tsx +0 -0
  197. /package/skills/{json-render → guides/json-render}/docs/nexus-state-demo.md +0 -0
  198. /package/skills/{json-render → guides/json-render}/docs/shadcn-preset.md +0 -0
  199. /package/skills/{json-render → guides/json-render}/scripts/create-vite-demo.sh +0 -0
  200. /package/skills/{json-render → guides/json-render}/scripts/llm-server/README.md +0 -0
  201. /package/skills/{json-render → guides/json-render}/scripts/llm-server/catalog.ts +0 -0
  202. /package/skills/{json-render → guides/json-render}/scripts/llm-server/package-lock.json +0 -0
  203. /package/skills/{json-render → guides/json-render}/scripts/llm-server/package.json +0 -0
  204. /package/skills/{json-render → guides/json-render}/scripts/llm-server/server.ts +0 -0
  205. /package/skills/{onboarding → guides/onboarding}/docs/CAPABILITIES.md +0 -0
  206. /package/skills/{onboarding → guides/onboarding}/docs/CLI_GRAMMAR_CREDENTIALS.md +0 -0
  207. /package/skills/{onboarding → guides/onboarding}/docs/DOCUMENTATION_OVERVIEW.md +0 -0
  208. /package/skills/{onboarding → guides/onboarding}/docs/ENTITY_MODEL.md +0 -0
  209. /package/skills/{onboarding → guides/onboarding}/docs/SKILL_INVENTORY.md +0 -0
  210. /package/skills/{onboarding → guides/onboarding}/docs/STATE_ARCHITECTURE.md +0 -0
  211. /package/skills/{onboarding → guides/onboarding}/docs/TROUBLESHOOTING.md +0 -0
  212. /package/skills/{onboarding → guides/onboarding}/docs/USER_JOURNEY.md +0 -0
  213. /package/skills/{onboarding → guides/onboarding}/docs/WOW_MOMENTS.md +0 -0
  214. /package/skills/{onboarding → guides/onboarding}/docs/agent-apple-id.md +0 -0
  215. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/1password.md +0 -0
  216. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/TEMPLATE.md +0 -0
  217. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/aix.md +0 -0
  218. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/bird.md +0 -0
  219. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/brave-search.md +0 -0
  220. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/comms.md +0 -0
  221. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/computer-use.md +0 -0
  222. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/cron-and-heartbeat.md +0 -0
  223. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/eve.md +0 -0
  224. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/github.md +0 -0
  225. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/gog.md +0 -0
  226. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/homebrew-prereqs.md +0 -0
  227. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/qmd.md +0 -0
  228. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/telegram.md +0 -0
  229. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/wacli.md +0 -0
  230. /package/skills/{onboarding → guides/onboarding}/docs/skill-deep-dives/weather.md +0 -0
  231. /package/skills/{onboarding → guides/onboarding}/scripts/ralph/prd.json +0 -0
  232. /package/skills/{onboarding → guides/onboarding}/scripts/ralph/prompt.md +0 -0
  233. /package/skills/{onboarding → guides/onboarding}/scripts/ralph/ralph.log +0 -0
  234. /package/skills/{onboarding → guides/onboarding}/scripts/ralph/ralph.sh +0 -0
  235. /package/skills/{onboarding → guides/onboarding}/scripts/setup-cursor-skills.sh +0 -0
  236. /package/skills/{1password → tools/1password}/SKILL.md +0 -0
  237. /package/skills/{1password → tools/1password}/docs/setup.md +0 -0
  238. /package/skills/{1password → tools/1password}/docs/troubleshooting.md +0 -0
  239. /package/skills/{1password → tools/1password}/references/cli-examples.md +0 -0
  240. /package/skills/{1password → tools/1password}/references/get-started.md +0 -0
  241. /package/skills/{agent-browser → tools/agent-browser}/SKILL.md +0 -0
  242. /package/skills/{agent-browser → tools/agent-browser}/docs/browser-use-eval.md +0 -0
  243. /package/skills/{agent-browser → tools/agent-browser}/docs/first-tests.md +0 -0
  244. /package/skills/{agent-browser → tools/agent-browser}/docs/wordle-nyt-eval.js +0 -0
  245. /package/skills/{aix → tools/aix}/SKILL.md +0 -0
  246. /package/skills/{aix → tools/aix}/docs/embeddings.md +0 -0
  247. /package/skills/{aix → tools/aix}/docs/setup.md +0 -0
  248. /package/skills/{aix → tools/aix}/docs/troubleshooting.md +0 -0
  249. /package/skills/{aix → tools/aix}/references/sql.md +0 -0
  250. /package/skills/{apple-notes → tools/apple-notes}/SKILL.md +0 -0
  251. /package/skills/{apple-reminders → tools/apple-reminders}/SKILL.md +0 -0
  252. /package/skills/{bear-notes → tools/bear-notes}/SKILL.md +0 -0
  253. /package/skills/{bird → tools/bird}/SKILL.md +0 -0
  254. /package/skills/{bird → tools/bird}/docs/auth.md +0 -0
  255. /package/skills/{bird → tools/bird}/docs/troubleshooting.md +0 -0
  256. /package/skills/{blogwatcher → tools/blogwatcher}/SKILL.md +0 -0
  257. /package/skills/{blucli → tools/blucli}/SKILL.md +0 -0
  258. /package/skills/{camsnap → tools/camsnap}/SKILL.md +0 -0
  259. /package/skills/{clawdhub → tools/clawdhub}/SKILL.md +0 -0
  260. /package/skills/{coding-agent → tools/coding-agent}/SKILL.md +0 -0
  261. /package/skills/{comms → tools/comms}/SKILL.md +0 -0
  262. /package/skills/{comms → tools/comms}/docs/adapters.md +0 -0
  263. /package/skills/{comms → tools/comms}/docs/setup.md +0 -0
  264. /package/skills/{comms → tools/comms}/docs/troubleshooting.md +0 -0
  265. /package/skills/{comms → tools/comms}/references/schema.md +0 -0
  266. /package/skills/{computer-use → tools/computer-use}/SKILL.md +0 -0
  267. /package/skills/{computer-use → tools/computer-use}/docs/open-interpreter.md +0 -0
  268. /package/skills/{computer-use → tools/computer-use}/docs/peekaboo.md +0 -0
  269. /package/skills/{computer-use → tools/computer-use}/docs/setup.md +0 -0
  270. /package/skills/{computer-use → tools/computer-use}/docs/troubleshooting.md +0 -0
  271. /package/skills/{eightctl → tools/eightctl}/SKILL.md +0 -0
  272. /package/skills/{eve → tools/eve}/SKILL.md +0 -0
  273. /package/skills/{eve → tools/eve}/docs/dual-account.md +0 -0
  274. /package/skills/{eve → tools/eve}/docs/intelligence.md +0 -0
  275. /package/skills/{eve → tools/eve}/docs/setup.md +0 -0
  276. /package/skills/{eve → tools/eve}/docs/troubleshooting.md +0 -0
  277. /package/skills/{eve → tools/eve}/scripts/setup-dual-account.sh +0 -0
  278. /package/skills/{food-order → tools/food-order}/SKILL.md +0 -0
  279. /package/skills/{gh → tools/gh}/SKILL.md +0 -0
  280. /package/skills/{gh → tools/gh}/docs/usage.md +0 -0
  281. /package/skills/{gifgrep → tools/gifgrep}/SKILL.md +0 -0
  282. /package/skills/{gog → tools/gog}/SKILL.md +0 -0
  283. /package/skills/{gog → tools/gog}/docs/portability.md +0 -0
  284. /package/skills/{gog → tools/gog}/docs/setup.md +0 -0
  285. /package/skills/{gog → tools/gog}/docs/troubleshooting.md +0 -0
  286. /package/skills/{gog → tools/gog}/scripts/cdp/README.md +0 -0
  287. /package/skills/{gog → tools/gog}/scripts/cdp/add_test_users.py +0 -0
  288. /package/skills/{gog → tools/gog}/scripts/cdp/auth_add_accounts.py +0 -0
  289. /package/skills/{gog → tools/gog}/scripts/cdp/auth_add_accounts_manual.py +0 -0
  290. /package/skills/{gog → tools/gog}/scripts/cdp/create_oauth_client.py +0 -0
  291. /package/skills/{gog → tools/gog}/scripts/cdp/launch_cdp_chrome.sh +0 -0
  292. /package/skills/{goplaces → tools/goplaces}/SKILL.md +0 -0
  293. /package/skills/{imsg → tools/imsg}/SKILL.md +0 -0
  294. /package/skills/{local-places → tools/local-places}/SERVER_README.md +0 -0
  295. /package/skills/{local-places → tools/local-places}/SKILL.md +0 -0
  296. /package/skills/{local-places → tools/local-places}/pyproject.toml +0 -0
  297. /package/skills/{local-places → tools/local-places}/src/local_places/__init__.py +0 -0
  298. /package/skills/{local-places → tools/local-places}/src/local_places/__pycache__/__init__.cpython-314.pyc +0 -0
  299. /package/skills/{local-places → tools/local-places}/src/local_places/__pycache__/google_places.cpython-314.pyc +0 -0
  300. /package/skills/{local-places → tools/local-places}/src/local_places/__pycache__/main.cpython-314.pyc +0 -0
  301. /package/skills/{local-places → tools/local-places}/src/local_places/__pycache__/schemas.cpython-314.pyc +0 -0
  302. /package/skills/{local-places → tools/local-places}/src/local_places/google_places.py +0 -0
  303. /package/skills/{local-places → tools/local-places}/src/local_places/main.py +0 -0
  304. /package/skills/{local-places → tools/local-places}/src/local_places/schemas.py +0 -0
  305. /package/skills/{mcporter → tools/mcporter}/SKILL.md +0 -0
  306. /package/skills/{model-usage → tools/model-usage}/SKILL.md +0 -0
  307. /package/skills/{model-usage → tools/model-usage}/references/codexbar-cli.md +0 -0
  308. /package/skills/{model-usage → tools/model-usage}/scripts/model_usage.py +0 -0
  309. /package/skills/{nano-banana-pro → tools/nano-banana-pro}/SKILL.md +0 -0
  310. /package/skills/{nano-banana-pro → tools/nano-banana-pro}/scripts/generate_image.py +0 -0
  311. /package/skills/{nano-pdf → tools/nano-pdf}/SKILL.md +0 -0
  312. /package/skills/{nexus-cloud → tools/nexus-cloud}/docs/security.md +0 -0
  313. /package/skills/{nexus-cloud → tools/nexus-cloud}/docs/troubleshooting.md +0 -0
  314. /package/skills/{obsidian → tools/obsidian}/SKILL.md +0 -0
  315. /package/skills/{openai-image-gen → tools/openai-image-gen}/SKILL.md +0 -0
  316. /package/skills/{openai-image-gen → tools/openai-image-gen}/scripts/gen.py +0 -0
  317. /package/skills/{openai-whisper → tools/openai-whisper}/SKILL.md +0 -0
  318. /package/skills/{openai-whisper-api → tools/openai-whisper-api}/SKILL.md +0 -0
  319. /package/skills/{openai-whisper-api → tools/openai-whisper-api}/scripts/transcribe.sh +0 -0
  320. /package/skills/{openhue → tools/openhue}/SKILL.md +0 -0
  321. /package/skills/{oracle → tools/oracle}/SKILL.md +0 -0
  322. /package/skills/{ordercli → tools/ordercli}/SKILL.md +0 -0
  323. /package/skills/{peekaboo → tools/peekaboo}/SKILL.md +0 -0
  324. /package/skills/{qmd → tools/qmd}/SKILL.md +0 -0
  325. /package/skills/{qmd → tools/qmd}/docs/mcp.md +0 -0
  326. /package/skills/{qmd → tools/qmd}/docs/ollama.md +0 -0
  327. /package/skills/{qmd → tools/qmd}/docs/setup.md +0 -0
  328. /package/skills/{sag → tools/sag}/SKILL.md +0 -0
  329. /package/skills/{skill-cli-template → tools/skill-cli-template}/SKILL.md +0 -0
  330. /package/skills/{songsee → tools/songsee}/SKILL.md +0 -0
  331. /package/skills/{sonoscli → tools/sonoscli}/SKILL.md +0 -0
  332. /package/skills/{spotify-player → tools/spotify-player}/SKILL.md +0 -0
  333. /package/skills/{summarize → tools/summarize}/SKILL.md +0 -0
  334. /package/skills/{things-mac → tools/things-mac}/SKILL.md +0 -0
  335. /package/skills/{tmux → tools/tmux}/SKILL.md +0 -0
  336. /package/skills/{tmux → tools/tmux}/scripts/find-sessions.sh +0 -0
  337. /package/skills/{tmux → tools/tmux}/scripts/wait-for-text.sh +0 -0
  338. /package/skills/{trello → tools/trello}/SKILL.md +0 -0
  339. /package/skills/{upstream-sync → tools/upstream-sync}/SKILL.md +0 -0
  340. /package/skills/{upstream-sync → tools/upstream-sync}/scripts/auto-port.sh +0 -0
  341. /package/skills/{upstream-sync → tools/upstream-sync}/scripts/check-all.sh +0 -0
  342. /package/skills/{upstream-sync → tools/upstream-sync}/scripts/check-nexus.sh +0 -0
  343. /package/skills/{upstream-sync → tools/upstream-sync}/scripts/check-pi-ai.sh +0 -0
  344. /package/skills/{video-frames → tools/video-frames}/SKILL.md +0 -0
  345. /package/skills/{video-frames → tools/video-frames}/scripts/frame.sh +0 -0
  346. /package/skills/{weather → tools/weather}/SKILL.md +0 -0
  347. /package/skills/{weather → tools/weather}/docs/usage.md +0 -0
@@ -1,131 +1,251 @@
1
1
  import fs from "node:fs";
2
- import path from "node:path";
2
+ import { resolveIdentitySnapshot } from "../agents/identity-state.js";
3
+ import { getAggregateStats } from "../agents/skill-usage.js";
3
4
  import { detectCapabilities } from "../capabilities/detector.js";
4
- import { listCredentials } from "./credential.js";
5
- import { resolveStateDir } from "../config/paths.js";
6
5
  import { defaultRuntime } from "../runtime.js";
7
- function readField(pathname, label) {
8
- try {
9
- const raw = fs.readFileSync(pathname, "utf-8");
10
- const regex = new RegExp(`^[-*]?\\s*${label}\\s*:\\s*(.+)$`, "im");
11
- const match = raw.match(regex);
12
- return match?.[1]?.trim();
13
- }
14
- catch {
15
- return undefined;
16
- }
6
+ import { listCredentials } from "./credential.js";
7
+ const STATUS_BOX_WIDTH = 62;
8
+ function clampText(text, width) {
9
+ if (text.length <= width)
10
+ return text;
11
+ return text.slice(0, width);
17
12
  }
18
- function getIdentitySnapshot() {
19
- const stateDir = resolveStateDir();
20
- const agentId = process.env.NEXUS_AGENT_ID?.trim() || "default";
21
- const agentIdentityDir = path.join(stateDir, "agents", agentId, "identity");
22
- const userIdentityDir = path.join(stateDir, "user", "identity");
23
- const onboardingDir = path.join(stateDir, "nexus", "onboarding");
24
- const agentIdentityPath = path.join(agentIdentityDir, "IDENTITY.md");
25
- const agentSoulPath = path.join(agentIdentityDir, "SOUL.md");
26
- const agentMemoryPath = path.join(agentIdentityDir, "MEMORY.md");
27
- const userProfilePath = path.join(userIdentityDir, "PROFILE.md");
28
- const bootstrapPath = path.join(onboardingDir, "BOOTSTRAP.md");
29
- const hasIdentity = fs.existsSync(agentIdentityPath) && fs.existsSync(userProfilePath);
30
- const agentName = readField(agentIdentityPath, "Name");
31
- const userName = readField(userProfilePath, "Name");
32
- return {
33
- agentId,
34
- agentName,
35
- userName,
36
- agentIdentityPath,
37
- agentSoulPath,
38
- agentMemoryPath,
39
- userProfilePath,
40
- bootstrapPath,
41
- hasIdentity,
42
- };
13
+ function centerText(text, width) {
14
+ const clamped = clampText(text, width);
15
+ const pad = Math.max(0, width - clamped.length);
16
+ const left = Math.floor(pad / 2);
17
+ const right = pad - left;
18
+ return `${" ".repeat(left)}${clamped}${" ".repeat(right)}`;
43
19
  }
20
+ function renderBox(lines, width) {
21
+ const top = `╔${"═".repeat(width)}╗`;
22
+ const bottom = `╚${"═".repeat(width)}╝`;
23
+ const body = lines.map((line) => `║${centerText(line, width)}║`);
24
+ return [top, ...body, bottom];
25
+ }
26
+ const FALLBACK_BOOTSTRAP_PROMPT = `# BOOTSTRAP.md - Welcome to Nexus
27
+
28
+ Identity setup is required.
29
+
30
+ For humans: start a short conversation and share your name, goals, and preferences.
31
+ For agents: write IDENTITY.md, SOUL.md, and MEMORY.md for the agent, plus state/user/IDENTITY.md for the user.
32
+ `;
44
33
  function readBootstrapPrompt(pathname) {
45
34
  try {
46
35
  return fs.readFileSync(pathname, "utf-8");
47
36
  }
48
37
  catch {
49
- return null;
38
+ return FALLBACK_BOOTSTRAP_PROMPT;
50
39
  }
51
40
  }
52
41
  function formatSuggestions(capabilities) {
53
42
  const picks = capabilities.filter((cap) => ["ready", "needs_setup", "needs_install", "broken"].includes(cap.status));
54
- const sorted = picks.sort((a, b) => a.status.localeCompare(b.status));
55
- return sorted.slice(0, 3).map((cap, idx) => ({
56
- id: cap.id,
57
- status: cap.status,
43
+ const priority = ["broken", "ready", "needs_setup", "needs_install"];
44
+ const sorted = picks.sort((a, b) => priority.indexOf(a.status) - priority.indexOf(b.status));
45
+ return sorted.slice(0, 3).map((cap, idx) => {
46
+ const action = cap.status === "broken"
47
+ ? "nexus credential list"
48
+ : `nexus capabilities --status ${cap.status.replace("_", "-")}`;
49
+ const title = cap.status === "ready"
50
+ ? `Try ${cap.id} (ready, never used)`
51
+ : cap.status === "needs_setup"
52
+ ? `Set up ${cap.id}`
53
+ : cap.status === "needs_install"
54
+ ? `Install ${cap.id}`
55
+ : `Fix ${cap.id}`;
56
+ return {
57
+ id: cap.id,
58
+ status: cap.status,
59
+ index: idx + 1,
60
+ title,
61
+ action,
62
+ };
63
+ });
64
+ }
65
+ function reindexSuggestions(suggestions) {
66
+ return suggestions.map((suggestion, idx) => ({
67
+ ...suggestion,
58
68
  index: idx + 1,
59
69
  }));
60
70
  }
61
71
  export async function statusCommand(opts, runtime = defaultRuntime) {
62
- const identity = getIdentitySnapshot();
72
+ const identityResolution = resolveIdentitySnapshot();
73
+ if (!identityResolution.ok) {
74
+ const payload = {
75
+ ok: false,
76
+ error: "multiple_agents",
77
+ agents: identityResolution.agentOptions,
78
+ };
79
+ if (opts.json) {
80
+ runtime.log(JSON.stringify(payload, null, 2));
81
+ }
82
+ else {
83
+ runtime.error("Multiple agents detected in state/agents.");
84
+ runtime.error(`Set NEXUS_AGENT_ID to one of: ${identityResolution.agentOptions.join(", ")}`);
85
+ }
86
+ runtime.exit(2);
87
+ return;
88
+ }
89
+ const identity = identityResolution.snapshot;
63
90
  const bootstrapPrompt = !identity.hasIdentity
64
91
  ? readBootstrapPrompt(identity.bootstrapPath)
65
92
  : null;
66
93
  const showBrief = opts.brief === true;
67
94
  const showCredentials = opts.credentials === true || (!opts.capabilities && !showBrief);
68
95
  const showCapabilities = opts.capabilities === true || (!opts.credentials && !showBrief);
69
- const credentials = showCredentials ? await listCredentials() : null;
70
- const capabilitySnapshot = showCapabilities ? detectCapabilities() : null;
71
- const suggestions = capabilitySnapshot ? formatSuggestions(capabilitySnapshot.capabilities) : [];
96
+ const showUsage = opts.usage === true ||
97
+ (!showBrief && !opts.capabilities && !opts.credentials);
98
+ const shouldLoadCredentials = showCredentials || !showBrief;
99
+ const shouldLoadCapabilities = showCapabilities || !showBrief;
100
+ const credentials = shouldLoadCredentials ? await listCredentials() : null;
101
+ const capabilitySnapshot = shouldLoadCapabilities
102
+ ? detectCapabilities()
103
+ : null;
104
+ const suggestions = capabilitySnapshot
105
+ ? formatSuggestions(capabilitySnapshot.capabilities)
106
+ : [];
107
+ const usage = showUsage
108
+ ? await getAggregateStats({ windowDays: 7, limit: 3 })
109
+ : null;
110
+ if (opts.quiet) {
111
+ runtime.exit(bootstrapPrompt ? 2 : 0);
112
+ return;
113
+ }
72
114
  if (opts.json) {
73
115
  runtime.log(JSON.stringify({
74
116
  platform: `${process.platform}/${process.arch}`,
75
117
  identity,
76
- bootstrap: bootstrapPrompt ? { required: true, prompt: bootstrapPrompt } : undefined,
118
+ bootstrap: bootstrapPrompt
119
+ ? { required: true, prompt: bootstrapPrompt }
120
+ : undefined,
77
121
  credentials: credentials ?? undefined,
78
122
  capabilities: capabilitySnapshot ?? undefined,
79
123
  suggestions,
124
+ usage: usage ?? undefined,
80
125
  }, null, 2));
81
126
  return;
82
127
  }
83
- runtime.log(`\nNexus Status (${process.platform}/${process.arch})`);
128
+ for (const line of renderBox(["Nexus Status", `${process.platform}/${process.arch}`], STATUS_BOX_WIDTH)) {
129
+ runtime.log(line);
130
+ }
84
131
  if (bootstrapPrompt) {
85
- runtime.log("\nBootstrap required (identity missing).");
132
+ runtime.log("");
133
+ for (const line of renderBox(["Welcome to Nexus!", "Identity setup required."], STATUS_BOX_WIDTH)) {
134
+ runtime.log(line);
135
+ }
86
136
  runtime.log(`\nBootstrap prompt (${identity.bootstrapPath}):\n`);
87
137
  runtime.log(bootstrapPrompt.trimEnd());
88
138
  return;
89
139
  }
90
- runtime.log("\nIdentity");
91
- runtime.log(` User: ${identity.userName ?? "(unknown)"} → ${identity.userProfilePath}`);
140
+ runtime.log("\n👤 Identity");
141
+ runtime.log(` User: ${identity.userName ?? "(unknown)"} → ${identity.userIdentityPath}`);
92
142
  runtime.log(` Agent: ${identity.agentName ?? "(unknown)"} (${identity.agentId}) → ${identity.agentIdentityPath}`);
93
143
  runtime.log(` → ${identity.agentSoulPath}`);
94
- runtime.log(` → ${identity.agentMemoryPath}`);
144
+ const credentialServices = credentials
145
+ ? Object.entries(credentials.services ?? {})
146
+ : [];
147
+ const credentialAccountCount = credentialServices.reduce((sum, [, info]) => sum + (info.accounts?.length ?? 0), 0);
95
148
  if (showCredentials && credentials) {
96
- const services = Object.entries(credentials.services ?? {});
97
- runtime.log(`\nCredentials (${services.length} services)`);
98
- for (const [service, info] of services) {
149
+ runtime.log(`\n🔑 Credentials (${credentialAccountCount} configured)`);
150
+ const statusIcon = {
151
+ active: "✅",
152
+ ready: "⭐",
153
+ broken: "❌",
154
+ };
155
+ const maxServices = 6;
156
+ const visibleServices = credentialServices.slice(0, maxServices);
157
+ for (const [service, info] of visibleServices) {
99
158
  const accounts = info.accounts ?? [];
100
- const summary = accounts.length > 0 ? `${accounts.length} account(s)` : "no accounts";
101
- runtime.log(` ${service}: ${summary}`);
159
+ if (accounts.length === 0) {
160
+ runtime.log(` ${service}: none`);
161
+ continue;
162
+ }
163
+ runtime.log(` ${service}`);
164
+ for (const account of accounts) {
165
+ const status = account.status ?? "ready";
166
+ const icon = statusIcon[status] ?? "•";
167
+ const suffix = account.lastError ? ` - ${account.lastError}` : "";
168
+ runtime.log(` ${icon} ${account.id} (${status})${suffix}`);
169
+ }
170
+ }
171
+ if (credentialServices.length > maxServices) {
172
+ runtime.log(` … +${credentialServices.length - maxServices} more services`);
102
173
  }
174
+ runtime.log(` Run 'nexus credential list' for full details`);
103
175
  }
104
176
  if (showCapabilities && capabilitySnapshot) {
105
- runtime.log(`\nCapabilities (${capabilitySnapshot.summary.active}/${capabilitySnapshot.summary.total} active)`);
106
- for (const [category, entries] of Object.entries(capabilitySnapshot.registry.categories)) {
107
- const categoryCaps = capabilitySnapshot.capabilities.filter((cap) => cap.category === category);
108
- const activeCount = categoryCaps.filter((cap) => cap.status === "active").length;
109
- if (categoryCaps.length === 0)
110
- continue;
111
- runtime.log(` ${category} (${activeCount}/${categoryCaps.length})`);
112
- const sample = categoryCaps.slice(0, 3);
113
- for (const cap of sample) {
177
+ const { summary } = capabilitySnapshot;
178
+ runtime.log("\n🎯 Capabilities");
179
+ runtime.log(` ✅ active: ${summary.active} ⭐ ready: ${summary.ready} 🔧 needs-setup: ${summary.needs_setup} 📥 needs-install: ${summary.needs_install}`);
180
+ if (summary.broken > 0) {
181
+ runtime.log(` ❌ broken: ${summary.broken}`);
182
+ }
183
+ if (summary.unavailable > 0) {
184
+ runtime.log(` ⛔ unavailable: ${summary.unavailable}`);
185
+ }
186
+ const quickWins = capabilitySnapshot.capabilities
187
+ .filter((cap) => cap.status === "ready")
188
+ .slice(0, 4);
189
+ if (quickWins.length > 0) {
190
+ runtime.log(" Quick wins:");
191
+ for (const cap of quickWins) {
114
192
  const providers = cap.providers.map((p) => p.id).join(", ");
115
- runtime.log(` - ${cap.id}: ${providers || cap.providersRaw}`);
193
+ runtime.log(` - ${cap.id}${providers ? ` (${providers})` : ""}`);
116
194
  }
117
195
  }
196
+ runtime.log(` Run 'nexus capabilities' for the full map`);
197
+ }
198
+ if (showUsage && usage) {
199
+ runtime.log("\n📊 Usage (last 7 days)");
200
+ const mostUsed = usage.topUsed && usage.topUsed.length > 0
201
+ ? usage.topUsed
202
+ .map((item) => `${item.name} (${item.runs})`)
203
+ .join(", ")
204
+ : usage.mostUsed
205
+ ? `${usage.mostUsed.name} (${usage.mostUsed.runs})`
206
+ : "none";
207
+ const readyUnused = usage.readyButUnused && usage.readyButUnused.length > 0
208
+ ? usage.readyButUnused.join(", ")
209
+ : "none";
210
+ runtime.log(` Most used: ${mostUsed}`);
211
+ runtime.log(` Ready but unused: ${readyUnused}`);
118
212
  }
119
- if (suggestions.length > 0) {
120
- runtime.log("\nSuggestions");
121
- for (const suggestion of suggestions) {
122
- runtime.log(` ${suggestion.index}. ${suggestion.id} (${suggestion.status})`);
213
+ let finalSuggestions = suggestions;
214
+ if (showCredentials && credentials && credentialAccountCount === 0) {
215
+ finalSuggestions = [
216
+ {
217
+ id: "credentials",
218
+ status: "ready",
219
+ index: 1,
220
+ title: "Set up credentials",
221
+ action: "nexus credential scan --deep",
222
+ },
223
+ ...finalSuggestions,
224
+ ];
225
+ }
226
+ finalSuggestions = reindexSuggestions(finalSuggestions).slice(0, 3);
227
+ if (finalSuggestions.length > 0) {
228
+ runtime.log("\n🎯 Suggestions");
229
+ for (const suggestion of finalSuggestions) {
230
+ runtime.log(` ${suggestion.index}. ${suggestion.title}`);
231
+ runtime.log(` → ${suggestion.action}`);
123
232
  }
124
233
  }
125
234
  runtime.log(`\nNext: run 'nexus capabilities' or 'nexus credential list' for details.`);
126
235
  }
127
236
  export async function getStatusSummary() {
128
- const identity = getIdentitySnapshot();
237
+ const resolution = resolveIdentitySnapshot();
238
+ if (!resolution.ok) {
239
+ return {
240
+ ok: false,
241
+ platform: `${process.platform}/${process.arch}`,
242
+ identity: {
243
+ agentId: "unknown",
244
+ hasIdentity: false,
245
+ },
246
+ };
247
+ }
248
+ const identity = resolution.snapshot;
129
249
  return {
130
250
  ok: true,
131
251
  platform: `${process.platform}/${process.arch}`,
@@ -1,5 +1,5 @@
1
- import { defaultRuntime } from "../runtime.js";
2
1
  import { buildUsageSuggestions } from "../infra/usage-suggestions.js";
2
+ import { defaultRuntime } from "../runtime.js";
3
3
  function parseKinds(raw) {
4
4
  if (!raw)
5
5
  return undefined;
@@ -0,0 +1,32 @@
1
+ import { fetchUsageTrackingSettings, updateUsageTrackingSettings, } from "../infra/usage-settings.js";
2
+ import { defaultRuntime } from "../runtime.js";
3
+ export async function usageTrackingCommand(opts, runtime = defaultRuntime) {
4
+ if (opts.enable && opts.disable) {
5
+ runtime.error("Choose either --enable or --disable.");
6
+ runtime.exit(1);
7
+ }
8
+ const requestedOptOut = opts.disable ? true : opts.enable ? false : null;
9
+ const result = requestedOptOut === null
10
+ ? await fetchUsageTrackingSettings()
11
+ : await updateUsageTrackingSettings(requestedOptOut);
12
+ if (!result) {
13
+ runtime.error("Usage tracking settings are unavailable (missing URL or token).");
14
+ runtime.exit(1);
15
+ }
16
+ if (opts.json) {
17
+ runtime.log(JSON.stringify(result, null, 2));
18
+ return;
19
+ }
20
+ if (!result.ok) {
21
+ const errorMessage = result.error === "not_allowed"
22
+ ? "Usage tracking is required for free accounts."
23
+ : result.error || "Failed to update usage tracking settings.";
24
+ runtime.error(errorMessage);
25
+ runtime.exit(1);
26
+ }
27
+ if (!result.canOptOut) {
28
+ runtime.log("Usage tracking is required for free accounts.");
29
+ return;
30
+ }
31
+ runtime.log(`Usage tracking ${result.optOut ? "disabled" : "enabled"}${result.planName ? ` (${result.planName})` : ""}`);
32
+ }
@@ -1,5 +1,5 @@
1
- import { defaultRuntime } from "../runtime.js";
2
1
  import { runUsageUpload } from "../infra/usage-upload.js";
2
+ import { defaultRuntime } from "../runtime.js";
3
3
  export async function usageUploadCommand(opts, runtime = defaultRuntime) {
4
4
  const result = await runUsageUpload({
5
5
  limit: opts.limit,
@@ -23,5 +23,10 @@ export async function usageUploadCommand(opts, runtime = defaultRuntime) {
23
23
  runtime.log(` uploaded: ${result.uploaded ?? 0}`);
24
24
  return;
25
25
  }
26
+ if (result.status === "disabled") {
27
+ runtime.log(`\nUsage upload disabled`);
28
+ runtime.log(` cleared_outbox: ${result.cleared ?? 0}`);
29
+ return;
30
+ }
26
31
  runtime.log("\nUsage upload complete");
27
32
  }
@@ -99,9 +99,7 @@ export function applyModelDefaults(cfg) {
99
99
  if (Object.keys(existingModels).length === 0)
100
100
  return cfg;
101
101
  let mutated = false;
102
- const nextModels = {
103
- ...existingModels,
104
- };
102
+ const nextModels = { ...existingModels };
105
103
  for (const [alias, target] of Object.entries(DEFAULT_MODEL_ALIASES)) {
106
104
  const entry = nextModels[target];
107
105
  if (!entry)
@@ -4,7 +4,7 @@
4
4
  * @example
5
5
  * ```json5
6
6
  * {
7
- * "$include": "./base.json5", // single file
7
+ * "$include": "./base.json5", // single file
8
8
  * "$include": ["./a.json5", "./b.json5"] // merge multiple
9
9
  * }
10
10
  * ```
@@ -52,7 +52,8 @@ export function deepMerge(target, source) {
52
52
  if (isPlainObject(target) && isPlainObject(source)) {
53
53
  const result = { ...target };
54
54
  for (const key of Object.keys(source)) {
55
- result[key] = key in result ? deepMerge(result[key], source[key]) : source[key];
55
+ result[key] =
56
+ key in result ? deepMerge(result[key], source[key]) : source[key];
56
57
  }
57
58
  return result;
58
59
  }
@@ -92,14 +93,11 @@ class IncludeProcessor {
92
93
  }
93
94
  processInclude(obj) {
94
95
  const includeValue = obj[INCLUDE_KEY];
95
- const otherKeys = Object.keys(obj).filter((k) => k !== INCLUDE_KEY);
96
+ const otherKeys = Object.keys(obj).filter((key) => key !== INCLUDE_KEY);
96
97
  const included = this.resolveInclude(includeValue);
97
98
  if (otherKeys.length === 0) {
98
99
  return included;
99
100
  }
100
- if (!isPlainObject(included)) {
101
- throw new ConfigIncludeError("Sibling keys require included content to be an object", typeof includeValue === "string" ? includeValue : INCLUDE_KEY);
102
- }
103
101
  // Merge included content with sibling keys
104
102
  const rest = {};
105
103
  for (const key of otherKeys) {
@@ -172,7 +170,7 @@ class IncludeProcessor {
172
170
  // Public API
173
171
  // ============================================================================
174
172
  const defaultResolver = {
175
- readFile: (p) => fs.readFileSync(p, "utf-8"),
173
+ readFile: (filePath) => fs.readFileSync(filePath, "utf-8"),
176
174
  parseJson: (raw) => JSON5.parse(raw),
177
175
  };
178
176
  /**
package/dist/config/io.js CHANGED
@@ -4,10 +4,12 @@ import path from "node:path";
4
4
  import JSON5 from "json5";
5
5
  import { loadShellEnvFallback, resolveShellEnvFallbackTimeoutMs, shouldEnableShellEnvFallback, } from "../infra/shell-env.js";
6
6
  import { applyIdentityDefaults, applyLoggingDefaults, applyMessageDefaults, applyModelDefaults, applySessionDefaults, applyTalkApiKey, } from "./defaults.js";
7
+ import { ConfigIncludeError, resolveConfigIncludes } from "./includes.js";
7
8
  import { findLegacyConfigIssues } from "./legacy.js";
8
- import { CONFIG_PATH_NEXUS, resolveConfigPath, resolveStateDir, } from "./paths.js";
9
+ import { migrateLegacyConfig } from "./legacy-migrate.js";
10
+ import { resolveConfigPath, resolveStateDir } from "./paths.js";
9
11
  import { validateConfigObject } from "./validation.js";
10
- import { NexusSchema } from "./zod-schema.js";
12
+ export { CircularIncludeError, ConfigIncludeError } from "./includes.js";
11
13
  const SHELL_ENV_EXPECTED_KEYS = [
12
14
  "OPENAI_API_KEY",
13
15
  "ANTHROPIC_API_KEY",
@@ -23,6 +25,22 @@ const SHELL_ENV_EXPECTED_KEYS = [
23
25
  "NEXUS_GATEWAY_TOKEN",
24
26
  "NEXUS_GATEWAY_PASSWORD",
25
27
  ];
28
+ function attachChannelAliases(cfg) {
29
+ const channels = cfg.channels ?? {};
30
+ const nextChannels = {
31
+ ...channels,
32
+ whatsapp: channels.whatsapp ?? cfg.whatsapp,
33
+ telegram: channels.telegram ?? cfg.telegram,
34
+ discord: channels.discord ?? cfg.discord,
35
+ slack: channels.slack ?? cfg.slack,
36
+ signal: channels.signal ?? cfg.signal,
37
+ imessage: channels.imessage ?? cfg.imessage,
38
+ };
39
+ const hasAny = Object.values(nextChannels).some((value) => value !== undefined);
40
+ if (!hasAny)
41
+ return cfg;
42
+ return { ...cfg, channels: nextChannels };
43
+ }
26
44
  function resolveConfigPathForDeps(deps) {
27
45
  if (deps.configPath)
28
46
  return deps.configPath;
@@ -48,8 +66,9 @@ export function parseConfigJson5(raw, json5 = JSON5) {
48
66
  }
49
67
  export function createConfigIO(overrides = {}) {
50
68
  const deps = normalizeDeps(overrides);
51
- const configPath = resolveConfigPathForDeps(deps);
69
+ const resolveConfigPath = () => resolveConfigPathForDeps(deps);
52
70
  function loadConfig() {
71
+ const configPath = resolveConfigPath();
53
72
  try {
54
73
  if (!deps.fs.existsSync(configPath)) {
55
74
  if (shouldEnableShellEnvFallback(deps.env)) {
@@ -65,17 +84,33 @@ export function createConfigIO(overrides = {}) {
65
84
  }
66
85
  const raw = deps.fs.readFileSync(configPath, "utf-8");
67
86
  const parsed = deps.json5.parse(raw);
68
- if (typeof parsed !== "object" || parsed === null)
87
+ const resolved = resolveConfigIncludes(parsed, configPath, {
88
+ readFile: (p) => deps.fs.readFileSync(p, "utf-8"),
89
+ parseJson: (json) => deps.json5.parse(json),
90
+ });
91
+ if (typeof resolved !== "object" || resolved === null)
69
92
  return {};
70
- const validated = NexusSchema.safeParse(parsed);
71
- if (!validated.success) {
93
+ const migrated = migrateLegacyConfig(resolved);
94
+ const candidate = migrated.config ?? resolved;
95
+ const validated = validateConfigObject(candidate);
96
+ if (!validated.ok) {
72
97
  deps.logger.error("Invalid config:");
73
- for (const iss of validated.error.issues) {
74
- deps.logger.error(`- ${iss.path.join(".")}: ${iss.message}`);
98
+ for (const iss of validated.issues) {
99
+ deps.logger.error(`- ${iss.path}: ${iss.message}`);
75
100
  }
76
101
  return {};
77
102
  }
78
- const cfg = applyModelDefaults(applySessionDefaults(applyLoggingDefaults(applyMessageDefaults(applyIdentityDefaults(validated.data)))));
103
+ if (migrated.config && migrated.changes.length > 0) {
104
+ deps.logger.warn(`Auto-migrated config: ${migrated.changes.join(" ")}`);
105
+ try {
106
+ deps.fs.writeFileSync(configPath, `${JSON.stringify(migrated.config, null, 2)}\n`);
107
+ }
108
+ catch (err) {
109
+ deps.logger.warn(`Failed to write migrated config: ${String(err)}`);
110
+ }
111
+ }
112
+ const cfg = applyModelDefaults(applySessionDefaults(applyLoggingDefaults(applyMessageDefaults(applyIdentityDefaults(validated.config)))));
113
+ const normalized = attachChannelAliases(cfg);
79
114
  const enabled = shouldEnableShellEnvFallback(deps.env) ||
80
115
  cfg.env?.shellEnv?.enabled === true;
81
116
  if (enabled) {
@@ -88,7 +123,7 @@ export function createConfigIO(overrides = {}) {
88
123
  resolveShellEnvFallbackTimeoutMs(deps.env),
89
124
  });
90
125
  }
91
- return cfg;
126
+ return normalized;
92
127
  }
93
128
  catch (err) {
94
129
  deps.logger.error(`Failed to read config at ${configPath}`, err);
@@ -96,9 +131,10 @@ export function createConfigIO(overrides = {}) {
96
131
  }
97
132
  }
98
133
  async function readConfigFileSnapshot() {
134
+ const configPath = resolveConfigPath();
99
135
  const exists = deps.fs.existsSync(configPath);
100
136
  if (!exists) {
101
- const config = applyTalkApiKey(applyModelDefaults(applySessionDefaults(applyMessageDefaults({}))));
137
+ const config = attachChannelAliases(applyTalkApiKey(applyModelDefaults(applySessionDefaults(applyMessageDefaults({})))));
102
138
  const legacyIssues = [];
103
139
  return {
104
140
  path: configPath,
@@ -128,8 +164,34 @@ export function createConfigIO(overrides = {}) {
128
164
  legacyIssues: [],
129
165
  };
130
166
  }
131
- const legacyIssues = findLegacyConfigIssues(parsedRes.parsed);
132
- const validated = validateConfigObject(parsedRes.parsed);
167
+ let resolved;
168
+ try {
169
+ resolved = resolveConfigIncludes(parsedRes.parsed, configPath, {
170
+ readFile: (p) => deps.fs.readFileSync(p, "utf-8"),
171
+ parseJson: (json) => deps.json5.parse(json),
172
+ });
173
+ }
174
+ catch (err) {
175
+ const message = err instanceof ConfigIncludeError
176
+ ? err.message
177
+ : `Include resolution failed: ${String(err)}`;
178
+ return {
179
+ path: configPath,
180
+ exists: true,
181
+ raw,
182
+ parsed: parsedRes.parsed,
183
+ valid: false,
184
+ config: {},
185
+ issues: [{ path: "", message }],
186
+ legacyIssues: [],
187
+ };
188
+ }
189
+ const migrated = migrateLegacyConfig(resolved);
190
+ const candidate = migrated.config ?? resolved;
191
+ const legacyIssues = migrated.config
192
+ ? []
193
+ : findLegacyConfigIssues(candidate);
194
+ const validated = validateConfigObject(candidate);
133
195
  if (!validated.ok) {
134
196
  return {
135
197
  path: configPath,
@@ -142,13 +204,22 @@ export function createConfigIO(overrides = {}) {
142
204
  legacyIssues,
143
205
  };
144
206
  }
207
+ if (migrated.config && migrated.changes.length > 0) {
208
+ deps.logger.warn(`Auto-migrated config: ${migrated.changes.join(" ")}`);
209
+ try {
210
+ deps.fs.writeFileSync(configPath, `${JSON.stringify(migrated.config, null, 2)}\n`);
211
+ }
212
+ catch (err) {
213
+ deps.logger.warn(`Failed to write migrated config: ${String(err)}`);
214
+ }
215
+ }
145
216
  return {
146
217
  path: configPath,
147
218
  exists: true,
148
219
  raw,
149
220
  parsed: parsedRes.parsed,
150
221
  valid: true,
151
- config: applyTalkApiKey(applyModelDefaults(applySessionDefaults(applyLoggingDefaults(applyMessageDefaults(validated.config))))),
222
+ config: attachChannelAliases(applyTalkApiKey(applyModelDefaults(applySessionDefaults(applyLoggingDefaults(applyMessageDefaults(validated.config)))))),
152
223
  issues: [],
153
224
  legacyIssues,
154
225
  };
@@ -167,6 +238,7 @@ export function createConfigIO(overrides = {}) {
167
238
  }
168
239
  }
169
240
  async function writeConfigFile(cfg) {
241
+ const configPath = resolveConfigPath();
170
242
  await deps.fs.promises.mkdir(path.dirname(configPath), {
171
243
  recursive: true,
172
244
  });
@@ -176,13 +248,13 @@ export function createConfigIO(overrides = {}) {
176
248
  await deps.fs.promises.writeFile(configPath, json, "utf-8");
177
249
  }
178
250
  return {
179
- configPath,
251
+ configPath: resolveConfigPath(),
180
252
  loadConfig,
181
253
  readConfigFileSnapshot,
182
254
  writeConfigFile,
183
255
  };
184
256
  }
185
- const defaultIO = createConfigIO({ configPath: CONFIG_PATH_NEXUS });
257
+ const defaultIO = createConfigIO();
186
258
  export const loadConfig = defaultIO.loadConfig;
187
259
  export const readConfigFileSnapshot = defaultIO.readConfigFileSnapshot;
188
260
  export const writeConfigFile = defaultIO.writeConfigFile;
@@ -138,7 +138,8 @@ const LEGACY_CONFIG_MIGRATIONS = [
138
138
  if (!match || typeof match !== "object")
139
139
  continue;
140
140
  const matchRecord = match;
141
- if (matchRecord.channel === undefined && matchRecord.provider !== undefined) {
141
+ if (matchRecord.channel === undefined &&
142
+ matchRecord.provider !== undefined) {
142
143
  matchRecord.channel = matchRecord.provider;
143
144
  delete matchRecord.provider;
144
145
  touched = true;
@@ -202,7 +203,8 @@ const LEGACY_CONFIG_MIGRATIONS = [
202
203
  if (!match || typeof match !== "object")
203
204
  continue;
204
205
  const matchRecord = match;
205
- if (matchRecord.channel === undefined && matchRecord.provider !== undefined) {
206
+ if (matchRecord.channel === undefined &&
207
+ matchRecord.provider !== undefined) {
206
208
  matchRecord.channel = matchRecord.provider;
207
209
  delete matchRecord.provider;
208
210
  touched = true;