@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,11 +1,13 @@
1
1
  import fs from "node:fs/promises";
2
2
  import os from "node:os";
3
+ import { streamSimple } from "@mariozechner/pi-ai";
3
4
  import { buildSystemPrompt, createAgentSession, discoverAuthStorage, discoverModels, SessionManager, SettingsManager, } from "@mariozechner/pi-coding-agent";
4
5
  import { formatToolAggregate } from "../auto-reply/tool-meta.js";
5
6
  import { getMachineDisplayName } from "../infra/machine-name.js";
6
7
  import { createSubsystemLogger } from "../logging.js";
7
8
  import { splitMediaFromOutput } from "../media/parse.js";
8
9
  import { enqueueCommandInLane, } from "../process/command-queue.js";
10
+ import { resolveTelegramReactionLevel } from "../telegram/reaction-level.js";
9
11
  import { resolveUserPath } from "../utils.js";
10
12
  import { resolveNexusAgentDir } from "./agent-paths.js";
11
13
  import { markAuthProfileCooldown, markAuthProfileGood, markAuthProfileUsed, } from "./auth-profiles.js";
@@ -18,7 +20,6 @@ import { extractAssistantText } from "./pi-embedded-utils.js";
18
20
  import { toToolDefinitions } from "./pi-tool-definition-adapter.js";
19
21
  import { createNexusCodingTools } from "./pi-tools.js";
20
22
  import { resolveSandboxContext } from "./sandbox.js";
21
- import { resolveTelegramReactionLevel } from "../telegram/reaction-level.js";
22
23
  import { applySkillEnvOverrides, applySkillEnvOverridesFromSnapshot, buildWorkspaceSkillSnapshot, loadWorkspaceSkillEntries, } from "./skills.js";
23
24
  import { buildAgentSystemPromptAppend } from "./system-prompt.js";
24
25
  import { normalizeUsage } from "./usage.js";
@@ -46,7 +47,7 @@ const GOOGLE_SCHEMA_UNSUPPORTED_KEYWORDS = new Set([
46
47
  "minProperties",
47
48
  "maxProperties",
48
49
  ]);
49
- function isAntigravityClaudeModel(provider, modelId) {
50
+ function _isAntigravityClaudeModel(provider, modelId) {
50
51
  if (provider !== "google-antigravity")
51
52
  return false;
52
53
  return modelId.trim().toLowerCase().includes("claude");
@@ -69,8 +70,9 @@ function findUnsupportedSchemaKeywords(schema, path) {
69
70
  }
70
71
  return violations;
71
72
  }
72
- function logToolSchemasForGoogle(params) {
73
- if (params.provider !== "google-antigravity" && params.provider !== "google-gemini-cli") {
73
+ function _logToolSchemasForGoogle(params) {
74
+ if (params.provider !== "google-antigravity" &&
75
+ params.provider !== "google-gemini-cli") {
74
76
  return;
75
77
  }
76
78
  const toolNames = params.tools.map((tool, index) => `${index}:${tool.name}`);
@@ -91,6 +93,89 @@ function logToolSchemasForGoogle(params) {
91
93
  }
92
94
  }
93
95
  }
96
+ /**
97
+ * Resolve provider-specific extra params from model config.
98
+ *
99
+ * Example config:
100
+ * agent.models["anthropic/claude-sonnet-4-5"].params.temperature = 0.7
101
+ * agent.models["openai/gpt-4.1-mini"].params.maxTokens = 8192
102
+ */
103
+ export function resolveExtraParams(params) {
104
+ const modelKey = `${params.provider}/${params.modelId}`;
105
+ const modelConfig = params.cfg?.agent?.models?.[modelKey];
106
+ let extraParams = modelConfig?.params ? { ...modelConfig.params } : undefined;
107
+ // Auto-enable thinking for ZAI GLM-4.x models when not explicitly configured.
108
+ // Skip if user explicitly disabled thinking via --thinking off.
109
+ if (params.provider === "zai" && params.thinkLevel !== "off") {
110
+ const modelIdLower = params.modelId.toLowerCase();
111
+ const isGlm4 = modelIdLower.includes("glm-4");
112
+ if (isGlm4) {
113
+ const hasThinkingConfig = extraParams?.thinking !== undefined;
114
+ if (!hasThinkingConfig) {
115
+ // GLM-4.7 supports preserved thinking (reasoning kept across turns).
116
+ // GLM-4.5/4.6 use interleaved thinking (reasoning cleared each turn).
117
+ const isGlm47 = modelIdLower.includes("glm-4.7");
118
+ const clearThinking = !isGlm47;
119
+ extraParams = {
120
+ ...extraParams,
121
+ thinking: {
122
+ type: "enabled",
123
+ clear_thinking: clearThinking,
124
+ },
125
+ };
126
+ log.debug(`auto-enabled thinking for ${modelKey}: type=enabled, clear_thinking=${clearThinking}`);
127
+ }
128
+ }
129
+ }
130
+ return extraParams;
131
+ }
132
+ /**
133
+ * Create a wrapped streamFn that injects extra params (like temperature) from config.
134
+ *
135
+ * This wraps the default streamSimple with config-driven params for each model.
136
+ */
137
+ function createStreamFnWithExtraParams(extraParams) {
138
+ if (!extraParams || Object.keys(extraParams).length === 0) {
139
+ return undefined;
140
+ }
141
+ const streamParams = {};
142
+ if (typeof extraParams.temperature === "number") {
143
+ streamParams.temperature = extraParams.temperature;
144
+ }
145
+ if (typeof extraParams.maxTokens === "number") {
146
+ streamParams.maxTokens = extraParams.maxTokens;
147
+ }
148
+ if (Object.keys(streamParams).length === 0) {
149
+ return undefined;
150
+ }
151
+ log.debug(`creating streamFn wrapper with params: ${JSON.stringify(streamParams)}`);
152
+ const wrappedStreamFn = (model, context, options) => {
153
+ const mergedOptions = {
154
+ ...streamParams,
155
+ ...options,
156
+ };
157
+ return streamSimple(model, context, mergedOptions);
158
+ };
159
+ return wrappedStreamFn;
160
+ }
161
+ /**
162
+ * Apply extra params (like temperature) to an agent's streamFn.
163
+ *
164
+ * Call this after createAgentSession to wire up config-driven model params.
165
+ */
166
+ function applyExtraParamsToAgent(agent, cfg, provider, modelId, thinkLevel) {
167
+ const extraParams = resolveExtraParams({
168
+ cfg,
169
+ provider,
170
+ modelId,
171
+ thinkLevel,
172
+ });
173
+ const wrappedStreamFn = createStreamFnWithExtraParams(extraParams);
174
+ if (wrappedStreamFn) {
175
+ log.debug(`applying extraParams to agent streamFn for ${provider}/${modelId}`);
176
+ agent.streamFn = wrappedStreamFn;
177
+ }
178
+ }
94
179
  /**
95
180
  * Limits conversation history to the last N user turns (and their associated
96
181
  * assistant responses). This reduces token usage for long-running DM sessions.
@@ -136,7 +221,9 @@ export function getDmHistoryLimitFromSessionKey(sessionKey, config, messageChann
136
221
  const raw = sessionKey?.trim() ?? "";
137
222
  if (!raw)
138
223
  return undefined;
139
- if (raw.startsWith("group:") || raw.includes(":group:") || raw.includes(":channel:")) {
224
+ if (raw.startsWith("group:") ||
225
+ raw.includes(":group:") ||
226
+ raw.includes(":channel:")) {
140
227
  return undefined;
141
228
  }
142
229
  const parts = raw.split(":").filter(Boolean);
@@ -176,7 +263,7 @@ export function getDmHistoryLimitFromSessionKey(sessionKey, config, messageChann
176
263
  return undefined;
177
264
  }
178
265
  }
179
- function resolveReactionGuidance(params) {
266
+ function _resolveReactionGuidance(params) {
180
267
  if (!params.config)
181
268
  return undefined;
182
269
  const rawChannel = params.messageChannel ?? params.messageProvider ?? "";
@@ -488,6 +575,7 @@ export async function compactEmbeddedPiSession(params) {
488
575
  skills: promptSkills,
489
576
  contextFiles,
490
577
  });
578
+ applyExtraParamsToAgent(session.agent, params.config, provider, modelId, params.thinkLevel);
491
579
  try {
492
580
  const prior = await sanitizeSessionMessagesImages(session.messages, "session:history");
493
581
  if (prior.length > 0) {
@@ -705,6 +793,7 @@ export async function runEmbeddedPiAgent(params) {
705
793
  skills: promptSkills,
706
794
  contextFiles,
707
795
  });
796
+ applyExtraParamsToAgent(session.agent, params.config, provider, modelId, thinkLevel);
708
797
  const prior = await sanitizeSessionMessagesImages(session.messages, "session:history");
709
798
  if (prior.length > 0) {
710
799
  session.agent.replaceMessages(prior);
@@ -837,7 +926,7 @@ export async function runEmbeddedPiAgent(params) {
837
926
  if (shouldRotate) {
838
927
  // Mark current profile for cooldown before rotating
839
928
  if (lastProfileId) {
840
- markAuthProfileCooldown({
929
+ void markAuthProfileCooldown({
841
930
  store: authStore,
842
931
  profileId: lastProfileId,
843
932
  });
@@ -906,13 +995,16 @@ export async function runEmbeddedPiAgent(params) {
906
995
  .filter((p) => p.text || p.mediaUrl || (p.mediaUrls && p.mediaUrls.length > 0));
907
996
  log.debug(`embedded run done: runId=${params.runId} sessionId=${params.sessionId} durationMs=${Date.now() - started} aborted=${aborted}`);
908
997
  if (lastProfileId) {
909
- markAuthProfileGood({
998
+ void markAuthProfileGood({
910
999
  store: authStore,
911
1000
  provider,
912
1001
  profileId: lastProfileId,
913
1002
  });
914
1003
  // Track usage for round-robin rotation
915
- markAuthProfileUsed({ store: authStore, profileId: lastProfileId });
1004
+ void markAuthProfileUsed({
1005
+ store: authStore,
1006
+ profileId: lastProfileId,
1007
+ });
916
1008
  }
917
1009
  return {
918
1010
  payloads: payloads.length ? payloads : undefined,
@@ -4,7 +4,7 @@ import fs from "node:fs/promises";
4
4
  import os from "node:os";
5
5
  import path from "node:path";
6
6
  import { startBrowserBridgeServer, stopBrowserBridgeServer, } from "../browser/bridge-server.js";
7
- import { resolveProfile } from "../browser/config.js";
7
+ import { resolveProfile, } from "../browser/config.js";
8
8
  import { DEFAULT_NEXUS_BROWSER_COLOR } from "../browser/constants.js";
9
9
  import { STATE_DIR_NEXUS } from "../config/config.js";
10
10
  import { defaultRuntime } from "../runtime.js";
@@ -27,7 +27,14 @@ const DEFAULT_TOOL_ALLOW = [
27
27
  "sessions_send",
28
28
  "sessions_spawn",
29
29
  ];
30
- const DEFAULT_TOOL_DENY = ["browser", "canvas", "nodes", "cron", "discord", "gateway"];
30
+ const DEFAULT_TOOL_DENY = [
31
+ "browser",
32
+ "canvas",
33
+ "nodes",
34
+ "cron",
35
+ "discord",
36
+ "gateway",
37
+ ];
31
38
  export const DEFAULT_SANDBOX_BROWSER_IMAGE = "nexus-sandbox-browser:bookworm-slim";
32
39
  export const DEFAULT_SANDBOX_COMMON_IMAGE = "nexus-sandbox-common:bookworm-slim";
33
40
  const DEFAULT_SANDBOX_BROWSER_PREFIX = "nexus-sbx-browser-";
@@ -490,7 +497,9 @@ async function ensureSandboxBrowser(params) {
490
497
  ? await readDockerPort(containerName, params.cfg.browser.noVncPort)
491
498
  : null;
492
499
  const existing = BROWSER_BRIDGES.get(params.sessionKey);
493
- const existingProfile = existing ? resolveProfile(existing.bridge.state.resolved, "nexus") : null;
500
+ const existingProfile = existing
501
+ ? resolveProfile(existing.bridge.state.resolved, "nexus")
502
+ : null;
494
503
  const shouldReuse = existing &&
495
504
  existing.containerName === containerName &&
496
505
  existingProfile?.cdpPort === mappedCdp;
@@ -2,15 +2,16 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { loadConfig } from "../config/config.js";
4
4
  import { runCommandWithTimeout } from "../process/exec.js";
5
- import { MANAGED_SKILLS_DIR, resolveUserPath } from "../utils.js";
6
- import { DEFAULT_AGENT_WORKSPACE_DIR } from "./workspace.js";
7
- import { buildWorkspaceSkillStatus } from "./skills-status.js";
8
- import { getSkillMetadata, hasBinary, loadWorkspaceSkillEntries, } from "./skills.js";
5
+ import { NEXUS_ROOT, resolveUserPath } from "../utils.js";
9
6
  import { getSkillExecutionType, getSkillScriptConfig, getSkillToolConfig, } from "./skill-tools.js";
7
+ import { recordSkillUsage } from "./skill-usage.js";
8
+ import { getSkillMetadata, hasBinary, loadWorkspaceSkillEntries, } from "./skills.js";
9
+ import { buildWorkspaceSkillStatus } from "./skills-status.js";
10
+ import { DEFAULT_AGENT_WORKSPACE_DIR } from "./workspace.js";
10
11
  function loadSkillContext(name) {
11
12
  const config = loadConfig();
12
13
  const workspaceDir = resolveUserPath(config.agent?.workspace ?? DEFAULT_AGENT_WORKSPACE_DIR);
13
- const managedSkillsDir = MANAGED_SKILLS_DIR;
14
+ const managedSkillsDir = path.join(NEXUS_ROOT, "skills", "managed");
14
15
  const entries = loadWorkspaceSkillEntries(workspaceDir, {
15
16
  config,
16
17
  managedSkillsDir,
@@ -90,8 +91,18 @@ export async function runSkill(name, args) {
90
91
  if (!entry) {
91
92
  return { ok: false, error: `Skill not found: ${name}` };
92
93
  }
94
+ const startedAt = Date.now();
95
+ const record = (ok) => {
96
+ recordSkillUsage(entry.skill.name, {
97
+ ts: Date.now(),
98
+ event: "run",
99
+ ok,
100
+ durationMs: Date.now() - startedAt,
101
+ });
102
+ };
93
103
  const execType = getSkillExecutionType(entry.skill.name);
94
104
  if (execType === "prompt") {
105
+ record(false);
95
106
  return {
96
107
  ok: false,
97
108
  error: "Skill is prompt-only and has no runnable command.",
@@ -100,13 +111,19 @@ export async function runSkill(name, args) {
100
111
  if (execType === "tool") {
101
112
  const toolConfig = getSkillToolConfig(entry.skill.name);
102
113
  if (!toolConfig?.tool) {
114
+ record(false);
103
115
  return { ok: false, error: "Skill tool configuration missing." };
104
116
  }
105
117
  if (!hasBinary(toolConfig.tool)) {
118
+ record(false);
106
119
  return { ok: false, error: `Missing binary: ${toolConfig.tool}` };
107
120
  }
108
- const result = await runCommandWithTimeout([toolConfig.tool, ...args], { timeoutMs: 300_000, cwd: entry.skill.baseDir });
121
+ const result = await runCommandWithTimeout([toolConfig.tool, ...args], {
122
+ timeoutMs: 300_000,
123
+ cwd: entry.skill.baseDir,
124
+ });
109
125
  if (result.code !== 0) {
126
+ record(false);
110
127
  return {
111
128
  ok: false,
112
129
  error: result.stderr || result.stdout || "Skill command failed.",
@@ -115,6 +132,7 @@ export async function runSkill(name, args) {
115
132
  code: result.code,
116
133
  };
117
134
  }
135
+ record(true);
118
136
  return {
119
137
  ok: true,
120
138
  stdout: result.stdout,
@@ -125,9 +143,11 @@ export async function runSkill(name, args) {
125
143
  if (execType === "script") {
126
144
  const scriptConfig = getSkillScriptConfig(entry.skill.name);
127
145
  if (!scriptConfig) {
146
+ record(false);
128
147
  return { ok: false, error: "Skill script configuration missing." };
129
148
  }
130
149
  if (!hasBinary(scriptConfig.runner)) {
150
+ record(false);
131
151
  return {
132
152
  ok: false,
133
153
  error: `Missing runner: ${scriptConfig.runner}`,
@@ -135,11 +155,13 @@ export async function runSkill(name, args) {
135
155
  }
136
156
  const scriptPath = path.join(entry.skill.baseDir, scriptConfig.script);
137
157
  if (!fs.existsSync(scriptPath)) {
158
+ record(false);
138
159
  return { ok: false, error: `Script not found: ${scriptConfig.script}` };
139
160
  }
140
161
  if (scriptConfig.requiredEnv?.length) {
141
162
  const missingEnv = scriptConfig.requiredEnv.filter((envName) => !process.env[envName]);
142
163
  if (missingEnv.length > 0) {
164
+ record(false);
143
165
  return {
144
166
  ok: false,
145
167
  error: `Missing env: ${missingEnv.join(", ")}`,
@@ -148,6 +170,7 @@ export async function runSkill(name, args) {
148
170
  }
149
171
  const result = await runCommandWithTimeout([scriptConfig.runner, scriptPath, ...args], { timeoutMs: 300_000, cwd: entry.skill.baseDir });
150
172
  if (result.code !== 0) {
173
+ record(false);
151
174
  return {
152
175
  ok: false,
153
176
  error: result.stderr || result.stdout || "Skill script failed.",
@@ -156,6 +179,7 @@ export async function runSkill(name, args) {
156
179
  code: result.code,
157
180
  };
158
181
  }
182
+ record(true);
159
183
  return {
160
184
  ok: true,
161
185
  stdout: result.stdout,
@@ -163,6 +187,7 @@ export async function runSkill(name, args) {
163
187
  code: result.code,
164
188
  };
165
189
  }
190
+ record(false);
166
191
  return { ok: false, error: "Unknown skill execution type." };
167
192
  }
168
193
  export async function verifySkill(name) {
@@ -175,6 +200,8 @@ export async function verifySkill(name) {
175
200
  return { ok: false, error: `Missing requirements: ${missingSummary}` };
176
201
  }
177
202
  const execType = getSkillExecutionType(entry.skill.name);
203
+ const metadata = getSkillMetadata(entry);
204
+ const metaType = metadata?.type;
178
205
  if (execType === "prompt") {
179
206
  return { ok: true, message: "Prompt-only skill requires no verification." };
180
207
  }
@@ -198,6 +225,14 @@ export async function verifySkill(name) {
198
225
  }
199
226
  return { ok: true, message: "Skill verified successfully." };
200
227
  }
228
+ if (execType === "unknown" && (metaType === "tool" || metaType === "connector")) {
229
+ const bins = metadata?.requires?.bins ?? metadata?.requires?.anyBins ?? [];
230
+ const missing = bins.filter((bin) => !hasBinary(bin));
231
+ if (missing.length > 0) {
232
+ return { ok: false, error: `Missing binary: ${missing.join(", ")}` };
233
+ }
234
+ return { ok: true, message: "Skill appears configured." };
235
+ }
201
236
  if (execType === "script") {
202
237
  const scriptConfig = getSkillScriptConfig(entry.skill.name);
203
238
  if (!scriptConfig) {
@@ -1,43 +1,143 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
1
3
  import { loadConfig } from "../config/config.js";
2
- import { MANAGED_SKILLS_DIR, resolveUserPath } from "../utils.js";
3
- import { DEFAULT_AGENT_WORKSPACE_DIR } from "./workspace.js";
4
- import { buildWorkspaceSkillStatus } from "./skills-status.js";
4
+ import { SKILLS_STATE_DIR, resolveUserPath } from "../utils.js";
5
5
  import { loadWorkspaceSkillEntries } from "./skills.js";
6
+ import { buildWorkspaceSkillStatus } from "./skills-status.js";
7
+ import { DEFAULT_AGENT_WORKSPACE_DIR } from "./workspace.js";
6
8
  function loadSkillEntries() {
7
9
  const config = loadConfig();
8
10
  const workspaceDir = resolveUserPath(config.agent?.workspace ?? DEFAULT_AGENT_WORKSPACE_DIR);
9
- const managedSkillsDir = MANAGED_SKILLS_DIR;
10
11
  const entries = loadWorkspaceSkillEntries(workspaceDir, {
11
12
  config,
12
- managedSkillsDir,
13
13
  });
14
- return { config, workspaceDir, managedSkillsDir, entries };
14
+ return { config, workspaceDir, entries };
15
+ }
16
+ function resolveUsageLogPath(name) {
17
+ return path.join(SKILLS_STATE_DIR, name, "usage.log");
18
+ }
19
+ function parseUsageEntry(line) {
20
+ try {
21
+ const parsed = JSON.parse(line);
22
+ if (typeof parsed?.ts !== "number")
23
+ return null;
24
+ if (parsed.event !== "use" && parsed.event !== "run")
25
+ return null;
26
+ if (typeof parsed.ok !== "boolean")
27
+ return null;
28
+ return parsed;
29
+ }
30
+ catch {
31
+ return null;
32
+ }
33
+ }
34
+ function readUsageEntries(name, sinceMs) {
35
+ const logPath = resolveUsageLogPath(name);
36
+ try {
37
+ const raw = fs.readFileSync(logPath, "utf-8");
38
+ const entries = [];
39
+ for (const line of raw.split(/\r?\n/)) {
40
+ if (!line.trim())
41
+ continue;
42
+ const entry = parseUsageEntry(line);
43
+ if (!entry)
44
+ continue;
45
+ if (sinceMs && entry.ts < sinceMs)
46
+ continue;
47
+ entries.push(entry);
48
+ }
49
+ return entries;
50
+ }
51
+ catch {
52
+ return [];
53
+ }
54
+ }
55
+ function hasUsageEntries(name) {
56
+ const logPath = resolveUsageLogPath(name);
57
+ try {
58
+ const stat = fs.statSync(logPath);
59
+ return stat.isFile() && stat.size > 0;
60
+ }
61
+ catch {
62
+ return false;
63
+ }
64
+ }
65
+ export function hasSkillUsage(name) {
66
+ return hasUsageEntries(name);
67
+ }
68
+ export function readSkillUsageEntries(name, opts) {
69
+ const entries = readUsageEntries(name, opts?.sinceMs);
70
+ if (opts?.limit && opts.limit > 0) {
71
+ return entries.slice(-opts.limit);
72
+ }
73
+ return entries;
74
+ }
75
+ export function recordSkillUsage(name, entry) {
76
+ const logPath = resolveUsageLogPath(name);
77
+ try {
78
+ fs.mkdirSync(path.dirname(logPath), { recursive: true });
79
+ fs.appendFileSync(logPath, `${JSON.stringify(entry)}\n`, "utf-8");
80
+ }
81
+ catch {
82
+ // ignore logging failures
83
+ }
15
84
  }
16
- export async function getSkillStats(name) {
85
+ export async function getSkillStats(name, opts) {
17
86
  const { entries } = loadSkillEntries();
18
87
  const entry = entries.find((item) => item.skill.name.toLowerCase() === name.toLowerCase());
19
88
  if (!entry)
20
89
  return null;
90
+ const sinceMs = opts?.windowDays && opts.windowDays > 0
91
+ ? Date.now() - opts.windowDays * 24 * 60 * 60 * 1000
92
+ : undefined;
93
+ const entriesUsed = readUsageEntries(entry.skill.name, sinceMs);
94
+ const runs = entriesUsed.length;
95
+ const errors = entriesUsed.filter((item) => !item.ok).length;
96
+ const lastTs = entriesUsed.reduce((max, item) => Math.max(max, item.ts), 0);
97
+ const durations = entriesUsed
98
+ .map((item) => item.durationMs)
99
+ .filter((val) => typeof val === "number" && val >= 0);
100
+ const avgDurationMs = durations.length > 0
101
+ ? Math.round(durations.reduce((sum, val) => sum + val, 0) / durations.length)
102
+ : undefined;
21
103
  return {
22
- runs: 0,
23
- errors: 0,
24
- lastUsed: undefined,
25
- avgDurationMs: undefined,
104
+ runs,
105
+ errors,
106
+ lastUsed: lastTs ? new Date(lastTs).toISOString() : undefined,
107
+ avgDurationMs,
26
108
  };
27
109
  }
28
- export async function getAggregateStats() {
29
- const { config, workspaceDir, managedSkillsDir, entries } = loadSkillEntries();
110
+ export async function getAggregateStats(opts) {
111
+ const { config, workspaceDir, entries } = loadSkillEntries();
30
112
  const status = buildWorkspaceSkillStatus(workspaceDir, {
31
113
  config,
32
- managedSkillsDir,
33
114
  entries,
34
115
  });
116
+ const sinceMs = opts?.windowDays && opts.windowDays > 0
117
+ ? Date.now() - opts.windowDays * 24 * 60 * 60 * 1000
118
+ : undefined;
119
+ const usageCounts = [];
120
+ let totalRuns = 0;
121
+ for (const entry of entries) {
122
+ const skillRuns = readUsageEntries(entry.skill.name, sinceMs).length;
123
+ if (skillRuns > 0) {
124
+ usageCounts.push({ name: entry.skill.name, runs: skillRuns });
125
+ }
126
+ totalRuns += skillRuns;
127
+ }
128
+ usageCounts.sort((a, b) => b.runs - a.runs);
129
+ const mostUsed = usageCounts[0];
130
+ const limit = typeof opts?.limit === "number" && opts.limit > 0 ? opts.limit : 5;
131
+ const topUsed = usageCounts.slice(0, limit);
35
132
  return {
36
- totalRuns: 0,
133
+ totalRuns,
37
134
  activeSkills: entries.length,
38
- mostUsed: undefined,
135
+ mostUsed: mostUsed
136
+ ? { name: mostUsed.name, runs: mostUsed.runs }
137
+ : undefined,
138
+ topUsed: topUsed.map((item) => ({ name: item.name, runs: item.runs })),
39
139
  readyButUnused: status.skills
40
- .filter((skill) => skill.eligible)
140
+ .filter((skill) => skill.eligible && !hasUsageEntries(skill.name))
41
141
  .map((skill) => skill.name),
42
142
  };
43
143
  }
@@ -1,5 +1,5 @@
1
1
  import path from "node:path";
2
- import { CONFIG_DIR } from "../utils.js";
2
+ import { NEXUS_ROOT } from "../utils.js";
3
3
  import { getSkillMetadata, hasBinary, isBundledSkillAllowed, isConfigPathTruthy, loadWorkspaceSkillEntries, resolveBundledAllowlist, resolveConfigPath, resolveSkillConfig, resolveSkillsInstallPreferences, } from "./skills.js";
4
4
  function resolveSkillKey(entry) {
5
5
  return getSkillMetadata(entry)?.skillKey ?? entry.skill.name;
@@ -92,7 +92,8 @@ function buildSkillStatus(entry, config, prefs) {
92
92
  continue;
93
93
  if (skillConfig?.env?.[envName])
94
94
  continue;
95
- if (skillConfig?.apiKey && getSkillMetadata(entry)?.primaryEnv === envName) {
95
+ if (skillConfig?.apiKey &&
96
+ getSkillMetadata(entry)?.primaryEnv === envName) {
96
97
  continue;
97
98
  }
98
99
  missingEnv.push(envName);
@@ -146,7 +147,7 @@ function buildSkillStatus(entry, config, prefs) {
146
147
  };
147
148
  }
148
149
  export function buildWorkspaceSkillStatus(workspaceDir, opts) {
149
- const managedSkillsDir = opts?.managedSkillsDir ?? path.join(CONFIG_DIR, "skills");
150
+ const managedSkillsDir = opts?.managedSkillsDir ?? path.join(NEXUS_ROOT, "skills", "managed");
150
151
  const skillEntries = opts?.entries ?? loadWorkspaceSkillEntries(workspaceDir, opts);
151
152
  const prefs = resolveSkillsInstallPreferences(opts?.config);
152
153
  return {