@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
@@ -2,7 +2,7 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { formatSkillsForPrompt, loadSkillsFromDir, } from "@mariozechner/pi-coding-agent";
5
- import { MANAGED_SKILLS_DIR, resolveUserPath } from "../utils.js";
5
+ import { NEXUS_ROOT, resolveUserPath } from "../utils.js";
6
6
  function resolveBundledSkillsDir() {
7
7
  const override = process.env.NEXUS_BUNDLED_SKILLS_DIR?.trim();
8
8
  if (override)
@@ -41,6 +41,13 @@ function stripQuotes(value) {
41
41
  }
42
42
  return value;
43
43
  }
44
+ function resolveSkillRootDirs(rootDir) {
45
+ const typedDirs = ["tools", "connectors", "guides"].map((segment) => path.join(rootDir, segment));
46
+ const existingTyped = typedDirs.filter((dir) => fs.existsSync(dir));
47
+ if (existingTyped.length > 0)
48
+ return existingTyped;
49
+ return fs.existsSync(rootDir) ? [rootDir] : [];
50
+ }
44
51
  function parseFrontmatter(content) {
45
52
  const frontmatter = {};
46
53
  const normalized = content.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
@@ -212,7 +219,9 @@ function resolveNexusMetadata(frontmatter) {
212
219
  const requiresRaw = typeof metadataObj.requires === "object" && metadataObj.requires !== null
213
220
  ? metadataObj.requires
214
221
  : undefined;
215
- const installRaw = Array.isArray(metadataObj.install) ? metadataObj.install : [];
222
+ const installRaw = Array.isArray(metadataObj.install)
223
+ ? metadataObj.install
224
+ : [];
216
225
  const install = installRaw
217
226
  .map((entry) => parseInstallSpec(entry))
218
227
  .filter((entry) => Boolean(entry));
@@ -223,11 +232,19 @@ function resolveNexusMetadata(frontmatter) {
223
232
  : undefined;
224
233
  const provides = normalizeStringList(metadataObj.provides);
225
234
  return {
226
- always: typeof metadataObj.always === "boolean" ? metadataObj.always : undefined,
235
+ always: typeof metadataObj.always === "boolean"
236
+ ? metadataObj.always
237
+ : undefined,
227
238
  emoji: typeof metadataObj.emoji === "string" ? metadataObj.emoji : undefined,
228
- homepage: typeof metadataObj.homepage === "string" ? metadataObj.homepage : undefined,
229
- skillKey: typeof metadataObj.skillKey === "string" ? metadataObj.skillKey : undefined,
230
- primaryEnv: typeof metadataObj.primaryEnv === "string" ? metadataObj.primaryEnv : undefined,
239
+ homepage: typeof metadataObj.homepage === "string"
240
+ ? metadataObj.homepage
241
+ : undefined,
242
+ skillKey: typeof metadataObj.skillKey === "string"
243
+ ? metadataObj.skillKey
244
+ : undefined,
245
+ primaryEnv: typeof metadataObj.primaryEnv === "string"
246
+ ? metadataObj.primaryEnv
247
+ : undefined,
231
248
  os: osRaw.length > 0 ? osRaw : undefined,
232
249
  type,
233
250
  provides: provides.length > 0 ? provides : undefined,
@@ -251,7 +268,7 @@ export function getSkillMetadata(entry) {
251
268
  return entry.nexus;
252
269
  }
253
270
  function resolveSkillKey(skill, entry) {
254
- return entry ? getSkillMetadata(entry)?.skillKey ?? skill.name : skill.name;
271
+ return entry ? (getSkillMetadata(entry)?.skillKey ?? skill.name) : skill.name;
255
272
  }
256
273
  function shouldIncludeSkill(params) {
257
274
  const { entry, config } = params;
@@ -289,7 +306,8 @@ function shouldIncludeSkill(params) {
289
306
  continue;
290
307
  if (skillConfig?.env?.[envName])
291
308
  continue;
292
- if (skillConfig?.apiKey && getSkillMetadata(entry)?.primaryEnv === envName) {
309
+ if (skillConfig?.apiKey &&
310
+ getSkillMetadata(entry)?.primaryEnv === envName) {
293
311
  continue;
294
312
  }
295
313
  return false;
@@ -387,36 +405,24 @@ function loadSkillEntries(workspaceDir, opts) {
387
405
  }
388
406
  return [];
389
407
  };
390
- const managedSkillsDir = opts?.managedSkillsDir ?? MANAGED_SKILLS_DIR;
391
- const workspaceSkillsDir = path.join(workspaceDir, "skills");
408
+ const workspaceSkillsRoot = path.join(NEXUS_ROOT, "skills");
409
+ const userSkillsRoot = path.join(resolveUserPath(workspaceDir), "skills");
410
+ const managedSkillsDir = opts?.managedSkillsDir ?? path.join(workspaceSkillsRoot, "managed");
392
411
  const bundledSkillsDir = opts?.bundledSkillsDir ?? resolveBundledSkillsDir();
393
412
  const extraDirsRaw = opts?.config?.skills?.load?.extraDirs ?? [];
394
413
  const extraDirs = extraDirsRaw
395
414
  .map((d) => (typeof d === "string" ? d.trim() : ""))
396
415
  .filter(Boolean);
416
+ const loadFromDirs = (dirs, source) => dirs.flatMap((dir) => loadSkills({ dir, source }));
397
417
  const bundledSkills = bundledSkillsDir
398
- ? loadSkills({
399
- dir: bundledSkillsDir,
400
- source: "nexus-bundled",
401
- })
418
+ ? loadFromDirs(resolveSkillRootDirs(bundledSkillsDir), "nexus-bundled")
402
419
  : [];
403
- const extraSkills = extraDirs.flatMap((dir) => {
404
- const resolved = resolveUserPath(dir);
405
- return loadSkills({
406
- dir: resolved,
407
- source: "nexus-extra",
408
- });
409
- });
410
- const managedSkills = loadSkills({
411
- dir: managedSkillsDir,
412
- source: "nexus-managed",
413
- });
414
- const workspaceSkills = loadSkills({
415
- dir: workspaceSkillsDir,
416
- source: "nexus-workspace",
417
- });
420
+ const extraSkills = extraDirs.flatMap((dir) => loadFromDirs(resolveSkillRootDirs(resolveUserPath(dir)), "nexus-extra"));
421
+ const managedSkills = loadFromDirs(resolveSkillRootDirs(managedSkillsDir), "nexus-managed");
422
+ const workspaceSkills = loadFromDirs(resolveSkillRootDirs(workspaceSkillsRoot), "nexus-workspace");
423
+ const userSkills = loadFromDirs(resolveSkillRootDirs(userSkillsRoot), "nexus-user");
418
424
  const merged = new Map();
419
- // Precedence: extra < bundled < managed < workspace
425
+ // Precedence: extra < bundled < managed < workspace < user
420
426
  for (const skill of extraSkills)
421
427
  merged.set(skill.name, skill);
422
428
  for (const skill of bundledSkills)
@@ -425,6 +431,8 @@ function loadSkillEntries(workspaceDir, opts) {
425
431
  merged.set(skill.name, skill);
426
432
  for (const skill of workspaceSkills)
427
433
  merged.set(skill.name, skill);
434
+ for (const skill of userSkills)
435
+ merged.set(skill.name, skill);
428
436
  const skillEntries = Array.from(merged.values()).map((skill) => {
429
437
  let frontmatter = {};
430
438
  try {
@@ -2,26 +2,31 @@ import crypto from "node:crypto";
2
2
  import { loadConfig, STATE_DIR_NEXUS } from "../config/config.js";
3
3
  import { callGateway } from "../gateway/call.js";
4
4
  import { normalizeAgentId, parseAgentSessionKey, resolveAgentIdFromSessionKey, } from "../routing/session-key.js";
5
- import { resolveDisplaySessionKey, resolveInternalSessionKey, resolveMainSessionAlias, stripToolMessages, } from "./tools/sessions-helpers.js";
6
- import { resolveAnnounceTarget } from "./tools/sessions-announce-target.js";
5
+ import { createFileSubagentStore, } from "./subagent-registry.store.js";
7
6
  import { readLatestAssistantReply, runAgentStep } from "./tools/agent-step.js";
7
+ import { resolveAnnounceTarget } from "./tools/sessions-announce-target.js";
8
+ import { resolveDisplaySessionKey, resolveInternalSessionKey, resolveMainSessionAlias, stripToolMessages, } from "./tools/sessions-helpers.js";
8
9
  import { isAnnounceSkip } from "./tools/sessions-send-helpers.js";
9
- import { createFileSubagentStore, } from "./subagent-registry.store.js";
10
10
  function normalizeStoredEntry(entry) {
11
11
  if (!entry || typeof entry !== "object")
12
12
  return null;
13
13
  const sessionKey = typeof entry.sessionKey === "string" ? entry.sessionKey.trim() : "";
14
- const parentSessionKey = typeof entry.parentSessionKey === "string" ? entry.parentSessionKey.trim() : "";
14
+ const parentSessionKey = typeof entry.parentSessionKey === "string"
15
+ ? entry.parentSessionKey.trim()
16
+ : "";
15
17
  if (!sessionKey || !parentSessionKey)
16
18
  return null;
17
- const status = entry.status === "announced" || entry.status === "failed" || entry.status === "pending"
19
+ const status = entry.status === "announced" ||
20
+ entry.status === "failed" ||
21
+ entry.status === "pending"
18
22
  ? entry.status
19
23
  : "pending";
20
24
  const createdAt = typeof entry.createdAt === "string" && entry.createdAt.trim()
21
25
  ? entry.createdAt
22
26
  : new Date().toISOString();
23
27
  const agentId = normalizeAgentId(entry.agentId);
24
- const legacyRequester = entry.requesterProvider;
28
+ const legacyRequester = entry
29
+ .requesterProvider;
25
30
  return {
26
31
  ...entry,
27
32
  agentId,
@@ -36,8 +41,12 @@ function buildSubagentAnnouncePrompt(params) {
36
41
  const taskLine = params.task?.trim() ? params.task.trim() : "(not available)";
37
42
  const lines = [
38
43
  "Sub-agent announce step:",
39
- params.requesterSessionKey ? `Requester session: ${params.requesterSessionKey}.` : undefined,
40
- params.requesterChannel ? `Requester channel: ${params.requesterChannel}.` : undefined,
44
+ params.requesterSessionKey
45
+ ? `Requester session: ${params.requesterSessionKey}.`
46
+ : undefined,
47
+ params.requesterChannel
48
+ ? `Requester channel: ${params.requesterChannel}.`
49
+ : undefined,
41
50
  `Post target channel: ${params.announceChannel}.`,
42
51
  `Original task: ${taskLine}`,
43
52
  params.subagentReply
@@ -94,7 +103,9 @@ async function readSubagentTask(sessionKey) {
94
103
  }
95
104
  async function runSubagentAnnounceFlow(params) {
96
105
  let status = "pending";
97
- const timeoutMs = typeof params.timeoutMs === "number" && params.timeoutMs > 0 ? params.timeoutMs : 30_000;
106
+ const timeoutMs = typeof params.timeoutMs === "number" && params.timeoutMs > 0
107
+ ? params.timeoutMs
108
+ : 30_000;
98
109
  try {
99
110
  let reply = params.roundOneReply?.trim();
100
111
  if (!reply) {
@@ -140,7 +151,9 @@ async function runSubagentAnnounceFlow(params) {
140
151
  timeoutMs,
141
152
  lane: "nested",
142
153
  });
143
- if (!announceReply || !announceReply.trim() || isAnnounceSkip(announceReply)) {
154
+ if (!announceReply ||
155
+ !announceReply.trim() ||
156
+ isAnnounceSkip(announceReply)) {
144
157
  status = "announced";
145
158
  return status;
146
159
  }
@@ -178,7 +191,8 @@ async function runSubagentAnnounceFlow(params) {
178
191
  }
179
192
  }
180
193
  export function createSubagentRegistry(params) {
181
- const store = params?.store ?? createFileSubagentStore(params?.stateDir ?? STATE_DIR_NEXUS);
194
+ const store = params?.store ??
195
+ createFileSubagentStore(params?.stateDir ?? STATE_DIR_NEXUS);
182
196
  const entries = new Map();
183
197
  let initialized = false;
184
198
  let resumeInFlight = null;
@@ -82,6 +82,7 @@ export function buildAgentSystemPromptAppend(params) {
82
82
  const userTimezone = params.userTimezone?.trim();
83
83
  const userTime = params.userTime?.trim();
84
84
  const runtimeInfo = params.runtimeInfo;
85
+ const reactionGuidance = params.reactionGuidance;
85
86
  const runtimeLines = [];
86
87
  if (runtimeInfo?.host)
87
88
  runtimeLines.push(`Host: ${runtimeInfo.host}`);
@@ -124,6 +125,12 @@ export function buildAgentSystemPromptAppend(params) {
124
125
  : "",
125
126
  "TOOLS.md does not control tool availability; it is user guidance for how to use external tools.",
126
127
  "",
128
+ "## Nexus CLI Quick Reference",
129
+ "- nexus status: show overall status",
130
+ "- nexus gateway restart: restart the gateway process",
131
+ "- nexus usage upload: upload usage batches",
132
+ "Do not invent commands; run `nexus help` to list available commands.",
133
+ "",
127
134
  "## Workspace",
128
135
  `Your working directory is: ${params.workspaceDir}`,
129
136
  "Treat this directory as the single global workspace for file operations unless explicitly instructed otherwise.",
@@ -167,6 +174,15 @@ export function buildAgentSystemPromptAppend(params) {
167
174
  "- [[reply_to:<id>]] replies to a specific message id when you have it.",
168
175
  "Tags are stripped before sending; support depends on the current provider config.",
169
176
  "",
177
+ reactionGuidance && reactionGuidance.level && reactionGuidance.level !== "off"
178
+ ? "## Reactions"
179
+ : "",
180
+ reactionGuidance && reactionGuidance.level && reactionGuidance.level !== "off"
181
+ ? `Reactions are enabled for ${reactionGuidance.channel ?? "this channel"} in ${reactionGuidance.level.toUpperCase()} mode.`
182
+ : "",
183
+ reactionGuidance && reactionGuidance.level && reactionGuidance.level !== "off"
184
+ ? ""
185
+ : "",
170
186
  ];
171
187
  if (extraSystemPrompt) {
172
188
  lines.push("## Group Chat Context", extraSystemPrompt, "");
@@ -10,7 +10,12 @@ export const TOOL_GROUPS = {
10
10
  // Host/runtime execution tools
11
11
  "group:runtime": ["exec", "process"],
12
12
  // Session management tools
13
- "group:sessions": ["sessions_list", "sessions_history", "sessions_send", "sessions_spawn"],
13
+ "group:sessions": [
14
+ "sessions_list",
15
+ "sessions_history",
16
+ "sessions_send",
17
+ "sessions_spawn",
18
+ ],
14
19
  // UI helpers
15
20
  "group:ui": ["browser", "canvas"],
16
21
  // Automation + infra
@@ -43,10 +48,21 @@ const TOOL_PROFILES = {
43
48
  allow: ["sessions_list"],
44
49
  },
45
50
  coding: {
46
- allow: ["group:fs", "group:runtime", "group:sessions", "group:memory", "image"],
51
+ allow: [
52
+ "group:fs",
53
+ "group:runtime",
54
+ "group:sessions",
55
+ "group:memory",
56
+ "image",
57
+ ],
47
58
  },
48
59
  messaging: {
49
- allow: ["group:messaging", "sessions_list", "sessions_history", "sessions_send"],
60
+ allow: [
61
+ "group:messaging",
62
+ "sessions_list",
63
+ "sessions_history",
64
+ "sessions_send",
65
+ ],
50
66
  },
51
67
  full: {},
52
68
  };
@@ -1,8 +1,8 @@
1
1
  import { Type } from "@sinclair/typebox";
2
2
  import { browserCloseTab, browserFocusTab, browserOpenTab, browserSnapshot, browserStart, browserStatus, browserStop, browserTabs, } from "../../browser/client.js";
3
3
  import { browserAct, browserArmDialog, browserArmFileChooser, browserConsoleMessages, browserNavigate, browserPdfSave, browserScreenshotAction, } from "../../browser/client-actions.js";
4
- import { DEFAULT_AI_SNAPSHOT_MAX_CHARS } from "../../browser/constants.js";
5
4
  import { resolveBrowserConfig } from "../../browser/config.js";
5
+ import { DEFAULT_AI_SNAPSHOT_MAX_CHARS } from "../../browser/constants.js";
6
6
  import { loadConfig } from "../../config/config.js";
7
7
  import { imageResultFromFile, jsonResult, readStringParam, } from "./common.js";
8
8
  const BrowserActSchema = Type.Union([
@@ -178,11 +178,14 @@ export function createBrowserTool(opts) {
178
178
  params.maxChars > 0
179
179
  ? Math.floor(params.maxChars)
180
180
  : undefined;
181
- const resolvedMaxChars = format === "ai" ? maxChars ?? DEFAULT_AI_SNAPSHOT_MAX_CHARS : undefined;
181
+ const resolvedMaxChars = format === "ai"
182
+ ? (maxChars ?? DEFAULT_AI_SNAPSHOT_MAX_CHARS)
183
+ : undefined;
182
184
  const snapshot = await browserSnapshot(baseUrl, {
183
185
  format,
184
186
  targetId,
185
187
  limit,
188
+ maxChars: resolvedMaxChars,
186
189
  });
187
190
  if (snapshot.format === "ai") {
188
191
  return {
@@ -1,18 +1,92 @@
1
1
  import { complete, } from "@mariozechner/pi-ai";
2
2
  import { discoverAuthStorage, discoverModels, } from "@mariozechner/pi-coding-agent";
3
3
  import { Type } from "@sinclair/typebox";
4
+ import { listCredentialEntriesSync } from "../../credentials/store.js";
4
5
  import { resolveUserPath } from "../../utils.js";
5
6
  import { loadWebMedia } from "../../web/media.js";
6
- import { getApiKeyForModel } from "../model-auth.js";
7
+ import { DEFAULT_PROVIDER } from "../defaults.js";
8
+ import { getApiKeyForModel, getCustomProviderApiKey, resolveEnvApiKey, } from "../model-auth.js";
7
9
  import { runWithImageModelFallback } from "../model-fallback.js";
10
+ import { normalizeProviderId, parseModelRef } from "../model-selection.js";
8
11
  import { ensureNexusModelsJson } from "../models-config.js";
9
12
  import { extractAssistantText } from "../pi-embedded-utils.js";
10
13
  const DEFAULT_PROMPT = "Describe the image.";
11
- function ensureImageToolConfigured(cfg) {
12
- const imageModel = cfg?.agent?.imageModel;
13
- const primary = typeof imageModel === "string" ? imageModel.trim() : imageModel?.primary;
14
- const fallbacks = typeof imageModel === "object" ? (imageModel?.fallbacks ?? []) : [];
15
- return Boolean(primary?.trim() || fallbacks.length > 0);
14
+ const DEFAULT_IMAGE_MODELS = {
15
+ minimax: "minimax-vl-01",
16
+ openai: "gpt-5-mini",
17
+ anthropic: "claude-opus-4-5",
18
+ };
19
+ function normalizeImageModelConfig(value) {
20
+ if (typeof value === "string") {
21
+ const primary = value.trim();
22
+ return primary ? { primary } : null;
23
+ }
24
+ if (!value || typeof value !== "object")
25
+ return null;
26
+ const primary = typeof value.primary === "string" ? value.primary.trim() : "";
27
+ const fallbacks = Array.isArray(value.fallbacks)
28
+ ? value.fallbacks.map((raw) => String(raw ?? "").trim()).filter(Boolean)
29
+ : [];
30
+ if (!primary && fallbacks.length === 0)
31
+ return null;
32
+ return fallbacks.length > 0 ? { primary, fallbacks } : { primary };
33
+ }
34
+ function hasAuthForProvider(provider, cfg) {
35
+ const normalized = normalizeProviderId(provider);
36
+ if (resolveEnvApiKey(normalized))
37
+ return true;
38
+ if (getCustomProviderApiKey(cfg, normalized))
39
+ return true;
40
+ const entries = listCredentialEntriesSync();
41
+ return entries.some((entry) => normalizeProviderId(entry.service) === normalized);
42
+ }
43
+ function resolveImageModelFromConfig(cfg, provider) {
44
+ const providers = cfg?.models?.providers ?? {};
45
+ const entry = providers[provider];
46
+ for (const model of entry?.models ?? []) {
47
+ if (!model?.id)
48
+ continue;
49
+ if (Array.isArray(model.input) && model.input.includes("image")) {
50
+ return model.id;
51
+ }
52
+ }
53
+ return null;
54
+ }
55
+ export function resolveImageModelConfigForTool(params) {
56
+ void params.agentDir;
57
+ const explicit = normalizeImageModelConfig(params.cfg?.agent?.imageModel);
58
+ if (explicit)
59
+ return explicit;
60
+ const rawPrimary = typeof params.cfg?.agent?.model === "string"
61
+ ? params.cfg?.agent?.model
62
+ : params.cfg?.agent?.model?.primary;
63
+ if (!rawPrimary?.trim())
64
+ return null;
65
+ const parsed = parseModelRef(rawPrimary, DEFAULT_PROVIDER);
66
+ if (!parsed)
67
+ return null;
68
+ const provider = normalizeProviderId(parsed.provider);
69
+ const configImageModel = resolveImageModelFromConfig(params.cfg, provider);
70
+ const mapped = DEFAULT_IMAGE_MODELS[provider];
71
+ const primaryModelId = configImageModel ?? mapped;
72
+ if (!primaryModelId)
73
+ return null;
74
+ if (!hasAuthForProvider(provider, params.cfg))
75
+ return null;
76
+ const fallbacks = [];
77
+ for (const fallbackProvider of ["openai", "anthropic"]) {
78
+ if (fallbackProvider === provider)
79
+ continue;
80
+ const fallbackModelId = DEFAULT_IMAGE_MODELS[fallbackProvider];
81
+ if (!fallbackModelId)
82
+ continue;
83
+ if (hasAuthForProvider(fallbackProvider, params.cfg)) {
84
+ fallbacks.push(`${fallbackProvider}/${fallbackModelId}`);
85
+ }
86
+ }
87
+ return fallbacks.length > 0
88
+ ? { primary: `${provider}/${primaryModelId}`, fallbacks }
89
+ : { primary: `${provider}/${primaryModelId}` };
16
90
  }
17
91
  function pickMaxBytes(cfg, maxBytesMb) {
18
92
  if (typeof maxBytesMb === "number" &&
@@ -80,12 +154,23 @@ async function runImagePrompt(params) {
80
154
  };
81
155
  }
82
156
  export function createImageTool(options) {
83
- if (!ensureImageToolConfigured(options?.config))
157
+ const resolvedConfig = resolveImageModelConfigForTool({
158
+ cfg: options?.config,
159
+ agentDir: options?.agentDir,
160
+ });
161
+ if (!resolvedConfig)
84
162
  return null;
85
163
  const agentDir = options?.agentDir;
86
164
  if (!agentDir?.trim()) {
87
165
  throw new Error("createImageTool requires agentDir when enabled");
88
166
  }
167
+ const cfgWithImageModel = (() => {
168
+ const cfg = options?.config ?? {};
169
+ const agent = cfg.agent ?? {};
170
+ if (normalizeImageModelConfig(agent.imageModel))
171
+ return cfg;
172
+ return { ...cfg, agent: { ...agent, imageModel: resolvedConfig } };
173
+ })();
89
174
  return {
90
175
  label: "Image",
91
176
  name: "image",
@@ -121,7 +206,7 @@ export function createImageTool(options) {
121
206
  const mimeType = media.contentType ?? "image/png";
122
207
  const base64 = media.buffer.toString("base64");
123
208
  const result = await runImagePrompt({
124
- cfg: options?.config,
209
+ cfg: cfgWithImageModel,
125
210
  agentDir,
126
211
  modelOverride,
127
212
  prompt: promptRaw,
@@ -20,7 +20,11 @@ export async function resolveAnnounceTarget(params) {
20
20
  const sessions = Array.isArray(list?.sessions) ? list.sessions : [];
21
21
  const match = sessions.find((entry) => entry?.key === params.sessionKey) ??
22
22
  sessions.find((entry) => entry?.key === params.displayKey);
23
- const provider = typeof match?.lastProvider === "string" ? match.lastProvider : undefined;
23
+ const provider = typeof match?.lastChannel === "string"
24
+ ? match.lastChannel
25
+ : typeof match?.lastProvider === "string"
26
+ ? match.lastProvider
27
+ : undefined;
24
28
  const to = typeof match?.lastTo === "string" ? match.lastTo : undefined;
25
29
  const accountId = typeof match?.lastAccountId === "string"
26
30
  ? match.lastAccountId