@xopcai/xopc 0.0.29 → 0.0.31

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 (632) hide show
  1. package/dist/extensions/telegram/src/adapters/config-surface.js +3 -1
  2. package/dist/extensions/telegram/src/adapters/config-surface.js.map +1 -1
  3. package/dist/extensions/telegram/src/adapters/onboard-cli.js +23 -21
  4. package/dist/extensions/telegram/src/adapters/onboard-cli.js.map +1 -1
  5. package/dist/extensions/telegram/src/adapters/setup-wizard.js +3 -4
  6. package/dist/extensions/telegram/src/adapters/setup-wizard.js.map +1 -1
  7. package/dist/extensions/telegram/src/config-schema.d.ts +0 -1
  8. package/dist/extensions/telegram/src/config-schema.js +17 -4
  9. package/dist/extensions/telegram/src/config-schema.js.map +1 -1
  10. package/dist/extensions/telegram/src/plugin.js +4 -17
  11. package/dist/extensions/telegram/src/plugin.js.map +1 -1
  12. package/dist/extensions/telegram/xopc.extension.json +1 -1
  13. package/dist/extensions/weixin/src/cdn/upload.js +1 -1
  14. package/dist/extensions/weixin/src/media/data-url.js +1 -1
  15. package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
  16. package/dist/gateway/static/root/assets/agents-3u63Fw2Y.js +216 -0
  17. package/dist/gateway/static/root/assets/agents-3u63Fw2Y.js.map +1 -0
  18. package/dist/gateway/static/root/assets/{apps-page-Bmq19MS-.js → apps-page-CWegY6Kp.js} +2 -2
  19. package/dist/gateway/static/root/assets/{apps-page-Bmq19MS-.js.map → apps-page-CWegY6Kp.js.map} +1 -1
  20. package/dist/gateway/static/root/assets/channels-settings-CiyeXcTK.js +9 -0
  21. package/dist/gateway/static/root/assets/channels-settings-CiyeXcTK.js.map +1 -0
  22. package/dist/gateway/static/root/assets/cron-api-_j_79Zf5.js +3 -0
  23. package/dist/gateway/static/root/assets/cron-api-_j_79Zf5.js.map +1 -0
  24. package/dist/gateway/static/root/assets/cron-page-S86YNTtI.js +2 -0
  25. package/dist/gateway/static/root/assets/cron-page-S86YNTtI.js.map +1 -0
  26. package/dist/gateway/static/root/assets/dist-D0jxbvuz.js +2 -0
  27. package/dist/gateway/static/root/assets/{dist--p2HQ2QF.js.map → dist-D0jxbvuz.js.map} +1 -1
  28. package/dist/gateway/static/root/assets/{extension-debug-page-DwHCB_6T.js → extension-debug-page-DB630cW8.js} +2 -2
  29. package/dist/gateway/static/root/assets/{extension-debug-page-DwHCB_6T.js.map → extension-debug-page-DB630cW8.js.map} +1 -1
  30. package/dist/gateway/static/root/assets/{extension-page-BsYwQIex.js → extension-page-CnoPUBul.js} +2 -2
  31. package/dist/gateway/static/root/assets/{extension-page-BsYwQIex.js.map → extension-page-CnoPUBul.js.map} +1 -1
  32. package/dist/gateway/static/root/assets/{extension-settings-page-nsisEgjB.js → extension-settings-page-BsiOkvBe.js} +2 -2
  33. package/dist/gateway/static/root/assets/{extension-settings-page-nsisEgjB.js.map → extension-settings-page-BsiOkvBe.js.map} +1 -1
  34. package/dist/gateway/static/root/assets/{index-CR8zUHGR.js → index-DHLmAIQl.js} +63 -63
  35. package/dist/gateway/static/root/assets/{index-CR8zUHGR.js.map → index-DHLmAIQl.js.map} +1 -1
  36. package/dist/gateway/static/root/assets/index-DoPwy4aU.css +1 -0
  37. package/dist/gateway/static/root/assets/logs-page-Bndhenn2.js +2 -0
  38. package/dist/gateway/static/root/assets/logs-page-Bndhenn2.js.map +1 -0
  39. package/dist/gateway/static/root/assets/sessions-page-Q201-_lP.js +2 -0
  40. package/dist/gateway/static/root/assets/{sessions-page-Be5kIGl_.js.map → sessions-page-Q201-_lP.js.map} +1 -1
  41. package/dist/gateway/static/root/assets/settings-page-Cw75fpc6.js +2 -0
  42. package/dist/gateway/static/root/assets/settings-page-Cw75fpc6.js.map +1 -0
  43. package/dist/gateway/static/root/assets/skills-page-CVwEzD_J.js +3 -0
  44. package/dist/gateway/static/root/assets/skills-page-CVwEzD_J.js.map +1 -0
  45. package/dist/gateway/static/root/index.html +2 -2
  46. package/dist/package.js +1 -1
  47. package/dist/src/agent/agent-manager.d.ts +5 -7
  48. package/dist/src/agent/agent-manager.js +21 -19
  49. package/dist/src/agent/agent-manager.js.map +1 -1
  50. package/dist/src/agent/ipc/inbox.js +4 -2
  51. package/dist/src/agent/ipc/inbox.js.map +1 -1
  52. package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
  53. package/dist/src/agent/memory/dreaming/utils.js +1 -1
  54. package/dist/src/agent/orchestration/agent-orchestrator.js +1 -1
  55. package/dist/src/agent/prompt/service-prompt-builder.js +0 -2
  56. package/dist/src/agent/prompt/service-prompt-builder.js.map +1 -1
  57. package/dist/src/agent/prompt/system-prompt.d.ts +0 -2
  58. package/dist/src/agent/prompt/system-prompt.js +3 -17
  59. package/dist/src/agent/prompt/system-prompt.js.map +1 -1
  60. package/dist/src/agent/service/btw-query.d.ts +16 -0
  61. package/dist/src/agent/service/btw-query.js +88 -0
  62. package/dist/src/agent/service/btw-query.js.map +1 -0
  63. package/dist/src/agent/service/build-direct-message-content.d.ts +30 -0
  64. package/dist/src/agent/service/build-direct-message-content.js +75 -0
  65. package/dist/src/agent/service/build-direct-message-content.js.map +1 -0
  66. package/dist/src/agent/service/parse-outbound-session-key.d.ts +8 -0
  67. package/dist/src/agent/service/parse-outbound-session-key.js +41 -0
  68. package/dist/src/agent/service/parse-outbound-session-key.js.map +1 -0
  69. package/dist/src/agent/service/process-direct-one-shot.d.ts +34 -0
  70. package/dist/src/agent/service/process-direct-one-shot.js +67 -0
  71. package/dist/src/agent/service/process-direct-one-shot.js.map +1 -0
  72. package/dist/src/agent/service/process-direct-streaming.js +12 -1
  73. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  74. package/dist/src/agent/service/reconcile-dreaming-cron.d.ts +6 -0
  75. package/dist/src/agent/service/reconcile-dreaming-cron.js +70 -0
  76. package/dist/src/agent/service/reconcile-dreaming-cron.js.map +1 -0
  77. package/dist/src/agent/service/session-context-report.d.ts +19 -0
  78. package/dist/src/agent/service/session-context-report.js +47 -0
  79. package/dist/src/agent/service/session-context-report.js.map +1 -0
  80. package/dist/src/agent/service/webchat-tts.d.ts +28 -0
  81. package/dist/src/agent/service/webchat-tts.js +73 -0
  82. package/dist/src/agent/service/webchat-tts.js.map +1 -0
  83. package/dist/src/agent/service.d.ts +8 -12
  84. package/dist/src/agent/service.js +74 -379
  85. package/dist/src/agent/service.js.map +1 -1
  86. package/dist/src/agent/skills/config.js +4 -3
  87. package/dist/src/agent/skills/config.js.map +1 -1
  88. package/dist/src/agent/skills/format-skills-prompt.d.ts +0 -2
  89. package/dist/src/agent/skills/format-skills-prompt.js +3 -24
  90. package/dist/src/agent/skills/format-skills-prompt.js.map +1 -1
  91. package/dist/src/agent/skills/hub-lock.js +4 -5
  92. package/dist/src/agent/skills/hub-lock.js.map +1 -1
  93. package/dist/src/agent/skills/index.js +9 -21
  94. package/dist/src/agent/skills/index.js.map +1 -1
  95. package/dist/src/agent/skills/marketplace/adapter.types.d.ts +17 -0
  96. package/dist/src/agent/skills/marketplace/adapter.types.js +1 -0
  97. package/dist/src/agent/skills/marketplace/adapters/skillhub/adapter.d.ts +2 -0
  98. package/dist/src/agent/skills/marketplace/adapters/skillhub/adapter.js +292 -0
  99. package/dist/src/agent/skills/marketplace/adapters/skillhub/adapter.js.map +1 -0
  100. package/dist/src/agent/skills/marketplace/adapters/skillhub/ecosystem-client.d.ts +73 -0
  101. package/dist/src/agent/skills/marketplace/adapters/skillhub/ecosystem-client.js +200 -0
  102. package/dist/src/agent/skills/marketplace/adapters/skillhub/ecosystem-client.js.map +1 -0
  103. package/dist/src/agent/skills/marketplace/adapters/skillhub/registry-client.d.ts +137 -0
  104. package/dist/src/agent/skills/marketplace/adapters/skillhub/registry-client.js +217 -0
  105. package/dist/src/agent/skills/marketplace/adapters/skillhub/registry-client.js.map +1 -0
  106. package/dist/src/agent/skills/marketplace/adapters/skillhub/skillhub-fetch-cache.d.ts +12 -0
  107. package/dist/src/agent/skills/marketplace/adapters/skillhub/skillhub-fetch-cache.js +90 -0
  108. package/dist/src/agent/skills/marketplace/adapters/skillhub/skillhub-fetch-cache.js.map +1 -0
  109. package/dist/src/agent/skills/marketplace/adapters/store/adapter.d.ts +2 -0
  110. package/dist/src/agent/skills/marketplace/adapters/store/adapter.js +35 -0
  111. package/dist/src/agent/skills/marketplace/adapters/store/adapter.js.map +1 -0
  112. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.d.ts +124 -0
  113. package/dist/src/agent/skills/{skills-store-client.js → marketplace/adapters/store/store-api-client.js} +4 -3
  114. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js.map +1 -0
  115. package/dist/src/agent/skills/marketplace/resolve-adapter.d.ts +6 -0
  116. package/dist/src/agent/skills/marketplace/resolve-adapter.js +26 -0
  117. package/dist/src/agent/skills/marketplace/resolve-adapter.js.map +1 -0
  118. package/dist/src/agent/skills/parse-skill-metadata.d.ts +5 -0
  119. package/dist/src/agent/skills/parse-skill-metadata.js +27 -0
  120. package/dist/src/agent/skills/parse-skill-metadata.js.map +1 -0
  121. package/dist/src/agent/skills/skill-markdown-preview-from-raw.d.ts +6 -0
  122. package/dist/src/agent/skills/skill-markdown-preview-from-raw.js +64 -0
  123. package/dist/src/agent/skills/skill-markdown-preview-from-raw.js.map +1 -0
  124. package/dist/src/agent/skills/skill-view-path.d.ts +17 -1
  125. package/dist/src/agent/skills/skill-view-path.js +66 -3
  126. package/dist/src/agent/skills/skill-view-path.js.map +1 -1
  127. package/dist/src/agent/skills/skills-marketplace.d.ts +21 -0
  128. package/dist/src/agent/skills/skills-marketplace.js +18 -0
  129. package/dist/src/agent/skills/skills-marketplace.js.map +1 -0
  130. package/dist/src/agent/skills/test-framework.d.ts +0 -1
  131. package/dist/src/agent/skills/test-framework.js +2 -20
  132. package/dist/src/agent/skills/test-framework.js.map +1 -1
  133. package/dist/src/agent/skills/types.d.ts +12 -6
  134. package/dist/src/agent/tools/dreaming-tool.js +1 -1
  135. package/dist/src/agent/tools/image-generate-tool.js +2 -2
  136. package/dist/src/auth/credentials.js +8 -6
  137. package/dist/src/auth/credentials.js.map +1 -1
  138. package/dist/src/auth/profiles/store.js +5 -3
  139. package/dist/src/auth/profiles/store.js.map +1 -1
  140. package/dist/src/channels/manager.js +1 -1
  141. package/dist/src/channels/outbound/persist-store.js +4 -4
  142. package/dist/src/channels/outbound/persist-store.js.map +1 -1
  143. package/dist/src/cli/commands/config.js +8 -6
  144. package/dist/src/cli/commands/config.js.map +1 -1
  145. package/dist/src/cli/commands/doctor/checks/channel-config.js +3 -4
  146. package/dist/src/cli/commands/doctor/checks/channel-config.js.map +1 -1
  147. package/dist/src/cli/commands/init.js +4 -2
  148. package/dist/src/cli/commands/init.js.map +1 -1
  149. package/dist/src/config/loader.js +3 -1
  150. package/dist/src/config/loader.js.map +1 -1
  151. package/dist/src/config/models-json.js +4 -5
  152. package/dist/src/config/models-json.js.map +1 -1
  153. package/dist/src/config/schema.d.ts +12 -4
  154. package/dist/src/config/schema.js +31 -5
  155. package/dist/src/config/schema.js.map +1 -1
  156. package/dist/src/cron/persistence.d.ts +1 -3
  157. package/dist/src/cron/persistence.js +6 -17
  158. package/dist/src/cron/persistence.js.map +1 -1
  159. package/dist/src/cron/validation.js +1 -1
  160. package/dist/src/cron/validation.js.map +1 -1
  161. package/dist/src/extensions/activation-context.js +0 -1
  162. package/dist/src/extensions/activation-context.js.map +1 -1
  163. package/dist/src/extensions/lockfile.js +4 -2
  164. package/dist/src/extensions/lockfile.js.map +1 -1
  165. package/dist/src/gateway/auth.d.ts +0 -9
  166. package/dist/src/gateway/auth.js +1 -12
  167. package/dist/src/gateway/auth.js.map +1 -1
  168. package/dist/src/gateway/hono/lib/config-payload.d.ts +1 -1
  169. package/dist/src/gateway/hono/lib/extension-store.js +4 -4
  170. package/dist/src/gateway/hono/lib/extension-store.js.map +1 -1
  171. package/dist/src/gateway/hono/routes/channels.js +5 -3
  172. package/dist/src/gateway/hono/routes/channels.js.map +1 -1
  173. package/dist/src/gateway/hono/routes/commands-skills.js +28 -3
  174. package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
  175. package/dist/src/gateway/hono/routes/config.js +23 -2
  176. package/dist/src/gateway/hono/routes/config.js.map +1 -1
  177. package/dist/src/gateway/hono/routes/sessions.js +124 -2
  178. package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
  179. package/dist/src/gateway/hono/sse.js +9 -2
  180. package/dist/src/gateway/hono/sse.js.map +1 -1
  181. package/dist/src/gateway/index.js +2 -2
  182. package/dist/src/gateway/lock.js +1 -1
  183. package/dist/src/gateway/service/run-gateway-agent.d.ts +37 -0
  184. package/dist/src/gateway/service/run-gateway-agent.js +163 -0
  185. package/dist/src/gateway/service/run-gateway-agent.js.map +1 -0
  186. package/dist/src/gateway/service/save-webchat-user-message.d.ts +9 -0
  187. package/dist/src/gateway/service/save-webchat-user-message.js +34 -0
  188. package/dist/src/gateway/service/save-webchat-user-message.js.map +1 -0
  189. package/dist/src/gateway/service/session-chat-ids.d.ts +9 -0
  190. package/dist/src/gateway/service/session-chat-ids.js +33 -0
  191. package/dist/src/gateway/service/session-chat-ids.js.map +1 -0
  192. package/dist/src/gateway/service/sse-hub.d.ts +10 -0
  193. package/dist/src/gateway/service/sse-hub.js +55 -0
  194. package/dist/src/gateway/service/sse-hub.js.map +1 -0
  195. package/dist/src/gateway/service/types.d.ts +9 -0
  196. package/dist/src/gateway/service/types.js +1 -0
  197. package/dist/src/gateway/service.d.ts +42 -33
  198. package/dist/src/gateway/service.js +92 -246
  199. package/dist/src/gateway/service.js.map +1 -1
  200. package/dist/src/infra/update-lock.js +4 -2
  201. package/dist/src/infra/update-lock.js.map +1 -1
  202. package/dist/src/infra/update-startup.js +5 -14
  203. package/dist/src/infra/update-startup.js.map +1 -1
  204. package/dist/src/infra/write-file-atomic.d.ts +18 -0
  205. package/dist/src/infra/write-file-atomic.js +115 -0
  206. package/dist/src/infra/write-file-atomic.js.map +1 -0
  207. package/dist/src/session/abort-cutoff.d.ts +6 -0
  208. package/dist/src/session/abort-cutoff.js +10 -0
  209. package/dist/src/session/abort-cutoff.js.map +1 -0
  210. package/dist/src/session/compaction-checkpoints.d.ts +8 -0
  211. package/dist/src/session/compaction-checkpoints.js +21 -0
  212. package/dist/src/session/compaction-checkpoints.js.map +1 -0
  213. package/dist/src/session/config-store.js +4 -2
  214. package/dist/src/session/config-store.js.map +1 -1
  215. package/dist/src/session/index.d.ts +8 -1
  216. package/dist/src/session/index.js +7 -1
  217. package/dist/src/session/manager.d.ts +26 -1
  218. package/dist/src/session/manager.js +39 -2
  219. package/dist/src/session/manager.js.map +1 -1
  220. package/dist/src/session/patch-metadata.d.ts +12 -0
  221. package/dist/src/session/patch-metadata.js +23 -0
  222. package/dist/src/session/patch-metadata.js.map +1 -0
  223. package/dist/src/session/search-index.d.ts +2 -0
  224. package/dist/src/session/search-index.js +30 -2
  225. package/dist/src/session/search-index.js.map +1 -1
  226. package/dist/src/session/session-context-for-llm.d.ts +32 -0
  227. package/dist/src/session/session-context-for-llm.js +60 -0
  228. package/dist/src/session/session-context-for-llm.js.map +1 -0
  229. package/dist/src/session/store.d.ts +53 -2
  230. package/dist/src/session/store.js +427 -145
  231. package/dist/src/session/store.js.map +1 -1
  232. package/dist/src/session/strip-webchat-early-save.d.ts +5 -0
  233. package/dist/src/session/strip-webchat-early-save.js +17 -0
  234. package/dist/src/session/strip-webchat-early-save.js.map +1 -0
  235. package/dist/src/session/transcript-format.d.ts +46 -0
  236. package/dist/src/session/transcript-format.js +88 -0
  237. package/dist/src/session/transcript-format.js.map +1 -0
  238. package/dist/src/session/types.d.ts +37 -0
  239. package/dist/src/session/types.js.map +1 -1
  240. package/dist/src/utils/logger/log-store.js +4 -3
  241. package/dist/src/utils/logger/log-store.js.map +1 -1
  242. package/dist/src/voice/tts/merge-config.js +0 -1
  243. package/dist/src/voice/tts/merge-config.js.map +1 -1
  244. package/dist/src/voice/tts/service.js +1 -2
  245. package/dist/src/voice/tts/service.js.map +1 -1
  246. package/package.json +1 -1
  247. package/skills/business/company-values/SKILL-zh.md +80 -0
  248. package/skills/business/company-values/SKILL.md +80 -0
  249. package/skills/business/find-community/SKILL-zh.md +50 -0
  250. package/skills/business/find-community/SKILL.md +50 -0
  251. package/skills/business/first-customers/SKILL-zh.md +76 -0
  252. package/skills/business/first-customers/SKILL.md +76 -0
  253. package/skills/business/grow-sustainably/SKILL-zh.md +92 -0
  254. package/skills/business/grow-sustainably/SKILL.md +92 -0
  255. package/skills/business/marketing-plan/SKILL-zh.md +100 -0
  256. package/skills/business/marketing-plan/SKILL.md +100 -0
  257. package/skills/business/minimalist-review/SKILL-zh.md +82 -0
  258. package/skills/business/minimalist-review/SKILL.md +82 -0
  259. package/skills/business/mvp/SKILL-zh.md +81 -0
  260. package/skills/business/mvp/SKILL.md +81 -0
  261. package/skills/business/pricing/SKILL-zh.md +64 -0
  262. package/skills/business/pricing/SKILL.md +64 -0
  263. package/skills/business/processize/SKILL-zh.md +91 -0
  264. package/skills/business/processize/SKILL.md +91 -0
  265. package/skills/business/validate-idea/SKILL-zh.md +68 -0
  266. package/skills/business/validate-idea/SKILL.md +68 -0
  267. package/skills/{skill-creator → creative/algorithmic-art}/LICENSE.txt +1 -1
  268. package/skills/creative/algorithmic-art/SKILL-zh.md +405 -0
  269. package/skills/creative/algorithmic-art/SKILL.md +405 -0
  270. package/skills/creative/algorithmic-art/templates/generator_template.js +223 -0
  271. package/skills/creative/algorithmic-art/templates/viewer.html +599 -0
  272. package/skills/creative/canvas-design/LICENSE.txt +202 -0
  273. package/skills/creative/canvas-design/SKILL-zh.md +130 -0
  274. package/skills/creative/canvas-design/SKILL.md +130 -0
  275. package/skills/creative/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +93 -0
  276. package/skills/creative/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
  277. package/skills/creative/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
  278. package/skills/creative/canvas-design/canvas-fonts/BigShoulders-OFL.txt +93 -0
  279. package/skills/creative/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
  280. package/skills/creative/canvas-design/canvas-fonts/Boldonse-OFL.txt +93 -0
  281. package/skills/creative/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
  282. package/skills/creative/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  283. package/skills/creative/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
  284. package/skills/creative/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  285. package/skills/creative/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
  286. package/skills/creative/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
  287. package/skills/creative/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +93 -0
  288. package/skills/creative/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
  289. package/skills/creative/canvas-design/canvas-fonts/DMMono-OFL.txt +93 -0
  290. package/skills/creative/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
  291. package/skills/creative/canvas-design/canvas-fonts/EricaOne-OFL.txt +94 -0
  292. package/skills/creative/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
  293. package/skills/creative/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
  294. package/skills/creative/canvas-design/canvas-fonts/GeistMono-OFL.txt +93 -0
  295. package/skills/creative/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
  296. package/skills/creative/canvas-design/canvas-fonts/Gloock-OFL.txt +93 -0
  297. package/skills/creative/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
  298. package/skills/creative/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
  299. package/skills/creative/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +93 -0
  300. package/skills/creative/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
  301. package/skills/creative/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
  302. package/skills/creative/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
  303. package/skills/creative/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
  304. package/skills/creative/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
  305. package/skills/creative/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  306. package/skills/creative/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  307. package/skills/creative/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  308. package/skills/creative/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +93 -0
  309. package/skills/creative/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  310. package/skills/creative/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  311. package/skills/creative/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  312. package/skills/creative/canvas-design/canvas-fonts/Italiana-OFL.txt +93 -0
  313. package/skills/creative/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
  314. package/skills/creative/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  315. package/skills/creative/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
  316. package/skills/creative/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  317. package/skills/creative/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
  318. package/skills/creative/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
  319. package/skills/creative/canvas-design/canvas-fonts/Jura-OFL.txt +93 -0
  320. package/skills/creative/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +93 -0
  321. package/skills/creative/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
  322. package/skills/creative/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
  323. package/skills/creative/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  324. package/skills/creative/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
  325. package/skills/creative/canvas-design/canvas-fonts/Lora-OFL.txt +93 -0
  326. package/skills/creative/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
  327. package/skills/creative/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
  328. package/skills/creative/canvas-design/canvas-fonts/NationalPark-OFL.txt +93 -0
  329. package/skills/creative/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
  330. package/skills/creative/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
  331. package/skills/creative/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  332. package/skills/creative/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
  333. package/skills/creative/canvas-design/canvas-fonts/Outfit-OFL.txt +93 -0
  334. package/skills/creative/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
  335. package/skills/creative/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
  336. package/skills/creative/canvas-design/canvas-fonts/PixelifySans-OFL.txt +93 -0
  337. package/skills/creative/canvas-design/canvas-fonts/PoiretOne-OFL.txt +93 -0
  338. package/skills/creative/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
  339. package/skills/creative/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
  340. package/skills/creative/canvas-design/canvas-fonts/RedHatMono-OFL.txt +93 -0
  341. package/skills/creative/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
  342. package/skills/creative/canvas-design/canvas-fonts/Silkscreen-OFL.txt +93 -0
  343. package/skills/creative/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
  344. package/skills/creative/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
  345. package/skills/creative/canvas-design/canvas-fonts/SmoochSans-OFL.txt +93 -0
  346. package/skills/creative/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
  347. package/skills/creative/canvas-design/canvas-fonts/Tektur-OFL.txt +93 -0
  348. package/skills/creative/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
  349. package/skills/creative/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
  350. package/skills/creative/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
  351. package/skills/creative/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
  352. package/skills/creative/canvas-design/canvas-fonts/WorkSans-OFL.txt +93 -0
  353. package/skills/creative/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
  354. package/skills/creative/canvas-design/canvas-fonts/YoungSerif-OFL.txt +93 -0
  355. package/skills/creative/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
  356. package/skills/creative/frontend-design/LICENSE.txt +177 -0
  357. package/skills/creative/frontend-design/SKILL-zh.md +42 -0
  358. package/skills/creative/frontend-design/SKILL.md +42 -0
  359. package/skills/creative/theme-factory/LICENSE.txt +202 -0
  360. package/skills/creative/theme-factory/SKILL-zh.md +59 -0
  361. package/skills/creative/theme-factory/SKILL.md +59 -0
  362. package/skills/creative/theme-factory/theme-showcase.pdf +0 -0
  363. package/skills/creative/theme-factory/themes/arctic-frost.md +19 -0
  364. package/skills/creative/theme-factory/themes/botanical-garden.md +19 -0
  365. package/skills/creative/theme-factory/themes/desert-rose.md +19 -0
  366. package/skills/creative/theme-factory/themes/forest-canopy.md +19 -0
  367. package/skills/creative/theme-factory/themes/golden-hour.md +19 -0
  368. package/skills/creative/theme-factory/themes/midnight-galaxy.md +19 -0
  369. package/skills/creative/theme-factory/themes/modern-minimalist.md +19 -0
  370. package/skills/creative/theme-factory/themes/ocean-depths.md +19 -0
  371. package/skills/creative/theme-factory/themes/sunset-boulevard.md +19 -0
  372. package/skills/creative/theme-factory/themes/tech-innovation.md +19 -0
  373. package/skills/creative/web-artifacts-builder/LICENSE.txt +202 -0
  374. package/skills/creative/web-artifacts-builder/SKILL-zh.md +74 -0
  375. package/skills/creative/web-artifacts-builder/SKILL.md +74 -0
  376. package/skills/creative/web-artifacts-builder/scripts/bundle-artifact.sh +54 -0
  377. package/skills/creative/web-artifacts-builder/scripts/init-artifact.sh +322 -0
  378. package/skills/creative/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
  379. package/skills/documents/doc-coauthoring/SKILL-zh.md +375 -0
  380. package/skills/documents/doc-coauthoring/SKILL.md +375 -0
  381. package/skills/documents/docx/SKILL-zh.md +590 -0
  382. package/skills/{docx → documents/docx}/SKILL.md +11 -11
  383. package/skills/{docx → documents/docx}/scripts/comment.py +2 -2
  384. package/skills/{docx → documents/docx}/scripts/office/helpers/simplify_redlines.py +1 -1
  385. package/skills/{docx → documents/docx}/scripts/office/pack.py +2 -2
  386. package/skills/{xlsx → documents/docx}/scripts/office/validate.py +2 -2
  387. package/skills/{xlsx → documents/docx}/scripts/office/validators/redlining.py +1 -1
  388. package/skills/documents/pdf/SKILL-zh.md +314 -0
  389. package/skills/documents/pptx/SKILL-zh.md +232 -0
  390. package/skills/{pptx → documents/pptx}/editing.md +3 -3
  391. package/skills/{pptx → documents/pptx}/scripts/office/helpers/simplify_redlines.py +1 -1
  392. package/skills/{xlsx → documents/pptx}/scripts/office/pack.py +2 -2
  393. package/skills/{pptx → documents/pptx}/scripts/office/validate.py +2 -2
  394. package/skills/{docx → documents/pptx}/scripts/office/validators/redlining.py +1 -1
  395. package/skills/documents/xlsx/SKILL-zh.md +292 -0
  396. package/skills/{xlsx → documents/xlsx}/scripts/office/helpers/simplify_redlines.py +1 -1
  397. package/skills/{pptx → documents/xlsx}/scripts/office/pack.py +2 -2
  398. package/skills/{docx → documents/xlsx}/scripts/office/validate.py +2 -2
  399. package/skills/{pptx → documents/xlsx}/scripts/office/validators/redlining.py +1 -1
  400. package/skills/meta/skill-creator/LICENSE.txt +202 -0
  401. package/skills/meta/skill-creator/SKILL-zh.md +483 -0
  402. package/skills/{skill-creator → meta/skill-creator}/SKILL.md +0 -1
  403. package/skills/tools/find-skills/SKILL-zh.md +440 -0
  404. package/skills/tools/github/SKILL-zh.md +48 -0
  405. package/skills/tools/internal-comms/LICENSE.txt +202 -0
  406. package/skills/tools/internal-comms/SKILL-zh.md +32 -0
  407. package/skills/tools/internal-comms/SKILL.md +32 -0
  408. package/skills/tools/internal-comms/examples/3p-updates.md +47 -0
  409. package/skills/tools/internal-comms/examples/company-newsletter.md +65 -0
  410. package/skills/tools/internal-comms/examples/faq-answers.md +30 -0
  411. package/skills/tools/internal-comms/examples/general-comms.md +16 -0
  412. package/skills/tools/summarize/SKILL-zh.md +47 -0
  413. package/skills/tools/weather/SKILL-zh.md +46 -0
  414. package/skills/tools/webapp-testing/LICENSE.txt +202 -0
  415. package/skills/tools/webapp-testing/SKILL-zh.md +96 -0
  416. package/skills/tools/webapp-testing/SKILL.md +96 -0
  417. package/skills/tools/webapp-testing/examples/console_logging.py +35 -0
  418. package/skills/tools/webapp-testing/examples/element_discovery.py +40 -0
  419. package/skills/tools/webapp-testing/examples/static_html_automation.py +33 -0
  420. package/skills/tools/webapp-testing/scripts/with_server.py +106 -0
  421. package/dist/gateway/static/root/assets/agents-CkgFSiCY.js +0 -216
  422. package/dist/gateway/static/root/assets/agents-CkgFSiCY.js.map +0 -1
  423. package/dist/gateway/static/root/assets/channels-settings-CE7jrdkO.js +0 -9
  424. package/dist/gateway/static/root/assets/channels-settings-CE7jrdkO.js.map +0 -1
  425. package/dist/gateway/static/root/assets/cron-page-BpPPcykJ.js +0 -2
  426. package/dist/gateway/static/root/assets/cron-page-BpPPcykJ.js.map +0 -1
  427. package/dist/gateway/static/root/assets/cron-utils-N1PqD2DB.js +0 -3
  428. package/dist/gateway/static/root/assets/cron-utils-N1PqD2DB.js.map +0 -1
  429. package/dist/gateway/static/root/assets/dist--p2HQ2QF.js +0 -2
  430. package/dist/gateway/static/root/assets/index-Dnfha4O2.css +0 -1
  431. package/dist/gateway/static/root/assets/logs-page-CQwdV_Xw.js +0 -2
  432. package/dist/gateway/static/root/assets/logs-page-CQwdV_Xw.js.map +0 -1
  433. package/dist/gateway/static/root/assets/sessions-page-Be5kIGl_.js +0 -2
  434. package/dist/gateway/static/root/assets/settings-page-PodSlNwr.js +0 -2
  435. package/dist/gateway/static/root/assets/settings-page-PodSlNwr.js.map +0 -1
  436. package/dist/gateway/static/root/assets/skills-page-Clg8deH0.js +0 -3
  437. package/dist/gateway/static/root/assets/skills-page-Clg8deH0.js.map +0 -1
  438. package/dist/src/agent/skills/skills-store-client.d.ts +0 -66
  439. package/dist/src/agent/skills/skills-store-client.js.map +0 -1
  440. package/dist/src/stt/index.d.ts +0 -1
  441. package/dist/src/stt/index.js +0 -8
  442. /package/skills/{docx → documents/docx}/LICENSE.txt +0 -0
  443. /package/skills/{docx → documents/docx}/scripts/__init__.py +0 -0
  444. /package/skills/{docx → documents/docx}/scripts/accept_changes.py +0 -0
  445. /package/skills/{docx → documents/docx}/scripts/office/helpers/__init__.py +0 -0
  446. /package/skills/{docx → documents/docx}/scripts/office/helpers/merge_runs.py +0 -0
  447. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -0
  448. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -0
  449. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -0
  450. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -0
  451. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -0
  452. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -0
  453. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -0
  454. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -0
  455. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -0
  456. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -0
  457. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -0
  458. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -0
  459. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -0
  460. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -0
  461. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -0
  462. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -0
  463. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -0
  464. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -0
  465. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -0
  466. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -0
  467. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -0
  468. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -0
  469. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -0
  470. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -0
  471. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -0
  472. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -0
  473. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -0
  474. /package/skills/{docx → documents/docx}/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -0
  475. /package/skills/{docx → documents/docx}/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -0
  476. /package/skills/{docx → documents/docx}/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -0
  477. /package/skills/{docx → documents/docx}/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -0
  478. /package/skills/{docx → documents/docx}/scripts/office/schemas/mce/mc.xsd +0 -0
  479. /package/skills/{docx → documents/docx}/scripts/office/schemas/microsoft/wml-2010.xsd +0 -0
  480. /package/skills/{docx → documents/docx}/scripts/office/schemas/microsoft/wml-2012.xsd +0 -0
  481. /package/skills/{docx → documents/docx}/scripts/office/schemas/microsoft/wml-2018.xsd +0 -0
  482. /package/skills/{docx → documents/docx}/scripts/office/schemas/microsoft/wml-cex-2018.xsd +0 -0
  483. /package/skills/{docx → documents/docx}/scripts/office/schemas/microsoft/wml-cid-2016.xsd +0 -0
  484. /package/skills/{docx → documents/docx}/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -0
  485. /package/skills/{docx → documents/docx}/scripts/office/schemas/microsoft/wml-symex-2015.xsd +0 -0
  486. /package/skills/{docx → documents/docx}/scripts/office/soffice.py +0 -0
  487. /package/skills/{docx → documents/docx}/scripts/office/unpack.py +0 -0
  488. /package/skills/{docx → documents/docx}/scripts/office/validators/__init__.py +0 -0
  489. /package/skills/{docx → documents/docx}/scripts/office/validators/base.py +0 -0
  490. /package/skills/{docx → documents/docx}/scripts/office/validators/docx.py +0 -0
  491. /package/skills/{docx → documents/docx}/scripts/office/validators/pptx.py +0 -0
  492. /package/skills/{docx → documents/docx}/scripts/templates/comments.xml +0 -0
  493. /package/skills/{docx → documents/docx}/scripts/templates/commentsExtended.xml +0 -0
  494. /package/skills/{docx → documents/docx}/scripts/templates/commentsExtensible.xml +0 -0
  495. /package/skills/{docx → documents/docx}/scripts/templates/commentsIds.xml +0 -0
  496. /package/skills/{docx → documents/docx}/scripts/templates/people.xml +0 -0
  497. /package/skills/{pdf → documents/pdf}/LICENSE.txt +0 -0
  498. /package/skills/{pdf → documents/pdf}/SKILL.md +0 -0
  499. /package/skills/{pdf → documents/pdf}/forms.md +0 -0
  500. /package/skills/{pdf → documents/pdf}/reference.md +0 -0
  501. /package/skills/{pdf → documents/pdf}/scripts/check_bounding_boxes.py +0 -0
  502. /package/skills/{pdf → documents/pdf}/scripts/check_fillable_fields.py +0 -0
  503. /package/skills/{pdf → documents/pdf}/scripts/convert_pdf_to_images.py +0 -0
  504. /package/skills/{pdf → documents/pdf}/scripts/create_validation_image.py +0 -0
  505. /package/skills/{pdf → documents/pdf}/scripts/extract_form_field_info.py +0 -0
  506. /package/skills/{pdf → documents/pdf}/scripts/extract_form_structure.py +0 -0
  507. /package/skills/{pdf → documents/pdf}/scripts/fill_fillable_fields.py +0 -0
  508. /package/skills/{pdf → documents/pdf}/scripts/fill_pdf_form_with_annotations.py +0 -0
  509. /package/skills/{pptx → documents/pptx}/LICENSE.txt +0 -0
  510. /package/skills/{pptx → documents/pptx}/SKILL.md +0 -0
  511. /package/skills/{pptx → documents/pptx}/pptxgenjs.md +0 -0
  512. /package/skills/{pptx → documents/pptx}/scripts/__init__.py +0 -0
  513. /package/skills/{pptx → documents/pptx}/scripts/add_slide.py +0 -0
  514. /package/skills/{pptx → documents/pptx}/scripts/clean.py +0 -0
  515. /package/skills/{pptx → documents/pptx}/scripts/office/helpers/__init__.py +0 -0
  516. /package/skills/{pptx → documents/pptx}/scripts/office/helpers/merge_runs.py +0 -0
  517. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -0
  518. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -0
  519. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -0
  520. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -0
  521. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -0
  522. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -0
  523. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -0
  524. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -0
  525. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -0
  526. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -0
  527. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -0
  528. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -0
  529. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -0
  530. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -0
  531. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -0
  532. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -0
  533. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -0
  534. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -0
  535. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -0
  536. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -0
  537. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -0
  538. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -0
  539. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -0
  540. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -0
  541. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -0
  542. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -0
  543. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -0
  544. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -0
  545. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -0
  546. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -0
  547. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -0
  548. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/mce/mc.xsd +0 -0
  549. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/microsoft/wml-2010.xsd +0 -0
  550. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/microsoft/wml-2012.xsd +0 -0
  551. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/microsoft/wml-2018.xsd +0 -0
  552. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/microsoft/wml-cex-2018.xsd +0 -0
  553. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/microsoft/wml-cid-2016.xsd +0 -0
  554. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -0
  555. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/microsoft/wml-symex-2015.xsd +0 -0
  556. /package/skills/{pptx → documents/pptx}/scripts/office/soffice.py +0 -0
  557. /package/skills/{pptx → documents/pptx}/scripts/office/unpack.py +0 -0
  558. /package/skills/{pptx → documents/pptx}/scripts/office/validators/__init__.py +0 -0
  559. /package/skills/{pptx → documents/pptx}/scripts/office/validators/base.py +0 -0
  560. /package/skills/{pptx → documents/pptx}/scripts/office/validators/docx.py +0 -0
  561. /package/skills/{pptx → documents/pptx}/scripts/office/validators/pptx.py +0 -0
  562. /package/skills/{pptx → documents/pptx}/scripts/thumbnail.py +0 -0
  563. /package/skills/{xlsx → documents/xlsx}/LICENSE.txt +0 -0
  564. /package/skills/{xlsx → documents/xlsx}/SKILL.md +0 -0
  565. /package/skills/{skill-creator/scripts → documents/xlsx/scripts/office/helpers}/__init__.py +0 -0
  566. /package/skills/{xlsx → documents/xlsx}/scripts/office/helpers/merge_runs.py +0 -0
  567. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -0
  568. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -0
  569. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -0
  570. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -0
  571. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -0
  572. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -0
  573. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -0
  574. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -0
  575. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -0
  576. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -0
  577. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -0
  578. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -0
  579. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -0
  580. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -0
  581. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -0
  582. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -0
  583. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -0
  584. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -0
  585. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -0
  586. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -0
  587. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -0
  588. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -0
  589. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -0
  590. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -0
  591. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -0
  592. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -0
  593. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -0
  594. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -0
  595. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -0
  596. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -0
  597. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -0
  598. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/mce/mc.xsd +0 -0
  599. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/microsoft/wml-2010.xsd +0 -0
  600. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/microsoft/wml-2012.xsd +0 -0
  601. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/microsoft/wml-2018.xsd +0 -0
  602. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/microsoft/wml-cex-2018.xsd +0 -0
  603. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/microsoft/wml-cid-2016.xsd +0 -0
  604. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -0
  605. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/microsoft/wml-symex-2015.xsd +0 -0
  606. /package/skills/{xlsx → documents/xlsx}/scripts/office/soffice.py +0 -0
  607. /package/skills/{xlsx → documents/xlsx}/scripts/office/unpack.py +0 -0
  608. /package/skills/{xlsx → documents/xlsx}/scripts/office/validators/__init__.py +0 -0
  609. /package/skills/{xlsx → documents/xlsx}/scripts/office/validators/base.py +0 -0
  610. /package/skills/{xlsx → documents/xlsx}/scripts/office/validators/docx.py +0 -0
  611. /package/skills/{xlsx → documents/xlsx}/scripts/office/validators/pptx.py +0 -0
  612. /package/skills/{xlsx → documents/xlsx}/scripts/recalc.py +0 -0
  613. /package/skills/{skill-creator → meta/skill-creator}/agents/analyzer.md +0 -0
  614. /package/skills/{skill-creator → meta/skill-creator}/agents/comparator.md +0 -0
  615. /package/skills/{skill-creator → meta/skill-creator}/agents/grader.md +0 -0
  616. /package/skills/{skill-creator → meta/skill-creator}/assets/eval_review.html +0 -0
  617. /package/skills/{skill-creator → meta/skill-creator}/eval-viewer/generate_review.py +0 -0
  618. /package/skills/{skill-creator → meta/skill-creator}/eval-viewer/viewer.html +0 -0
  619. /package/skills/{skill-creator → meta/skill-creator}/references/schemas.md +0 -0
  620. /package/skills/{xlsx/scripts/office/helpers → meta/skill-creator/scripts}/__init__.py +0 -0
  621. /package/skills/{skill-creator → meta/skill-creator}/scripts/aggregate_benchmark.py +0 -0
  622. /package/skills/{skill-creator → meta/skill-creator}/scripts/generate_report.py +0 -0
  623. /package/skills/{skill-creator → meta/skill-creator}/scripts/improve_description.py +0 -0
  624. /package/skills/{skill-creator → meta/skill-creator}/scripts/package_skill.py +0 -0
  625. /package/skills/{skill-creator → meta/skill-creator}/scripts/quick_validate.py +0 -0
  626. /package/skills/{skill-creator → meta/skill-creator}/scripts/run_eval.py +0 -0
  627. /package/skills/{skill-creator → meta/skill-creator}/scripts/run_loop.py +0 -0
  628. /package/skills/{skill-creator → meta/skill-creator}/scripts/utils.py +0 -0
  629. /package/skills/{find-skills → tools/find-skills}/SKILL.md +0 -0
  630. /package/skills/{github → tools/github}/SKILL.md +0 -0
  631. /package/skills/{summarize → tools/summarize}/SKILL.md +0 -0
  632. /package/skills/{weather → tools/weather}/SKILL.md +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"log-store.js","names":[],"sources":["../../../../src/utils/logger/log-store.ts"],"sourcesContent":["/**\n * Log Store - Enhanced File-based Log Storage\n * \n * Features:\n * - Query logs across multiple files with filtering\n * - Support for compressed (.gz) log files\n * - Pagination and sorting\n * - Statistics and analytics\n * - Safe log cleanup with actual deletion\n */\n\nimport { \n existsSync, \n mkdirSync, \n readdirSync, \n statSync, \n createReadStream,\n unlinkSync,\n} from 'fs';\nimport { readFile } from 'fs/promises';\nimport { join, basename } from 'path';\nimport { createInterface } from 'readline';\nimport { gunzip } from 'zlib';\nimport { promisify } from 'util';\nimport { Readable } from 'stream';\nimport type { LogLevel, LogFileMeta, LogQuery, LogStats, LogEntry } from './types.js';\n\nconst gunzipAsync = promisify(gunzip);\n\n// ============================================\n// Types\n// ============================================\n\ninterface ParsedLogEntry extends LogEntry {\n _source?: string;\n _lineNumber?: number;\n}\n\n// ============================================\n// Configuration\n// ============================================\n\nconst LOG_DIR = process.env.XOPC_LOG_DIR || join(process.env.HOME || '.', '.xopc', 'logs');\n\nfunction ensureLogDir(): void {\n if (!existsSync(LOG_DIR)) {\n mkdirSync(LOG_DIR, { recursive: true });\n }\n}\n\n// ============================================\n// File Management\n// ============================================\n\n/**\n * Get all log files (including compressed)\n */\nexport function getLogFiles(): LogFileMeta[] {\n ensureLogDir();\n\n const files = readdirSync(LOG_DIR)\n .filter(f => f.endsWith('.log') || f.endsWith('.log.gz'))\n .map(f => {\n const filePath = join(LOG_DIR, f);\n const stats = statSync(filePath);\n \n let type: LogFileMeta['type'] = 'app';\n if (f.includes('error')) type = 'error';\n else if (f.includes('audit')) type = 'audit';\n else if (f.includes('access')) type = 'access';\n\n return {\n name: f,\n path: filePath,\n size: stats.size,\n created: stats.birthtime.toISOString(),\n modified: stats.mtime.toISOString(),\n type,\n };\n })\n .sort((a, b) => new Date(b.modified).getTime() - new Date(a.modified).getTime());\n\n return files;\n}\n\n/**\n * Get log file path for a specific date and type\n */\nexport function getLogPath(\n date: Date = new Date(), \n type: 'app' | 'error' | 'audit' | 'access' = 'app'\n): string {\n ensureLogDir();\n const dateStr = date.toISOString().split('T')[0];\n return join(LOG_DIR, `${type}-${dateStr}.log`);\n}\n\n/**\n * Get available log files for a date range\n */\nfunction getLogFilesForRange(from: Date, to: Date): LogFileMeta[] {\n const allFiles = getLogFiles();\n \n return allFiles.filter(f => {\n // Extract date from filename (e.g., app-2024-01-01.log)\n const match = f.name.match(/(\\d{4}-\\d{2}-\\d{2})/);\n if (!match) return false;\n \n const fileDate = new Date(match[1]);\n return fileDate >= from && fileDate <= to;\n });\n}\n\n// ============================================\n// Log Parsing\n// ============================================\n\n/**\n * Parse a single log line (JSON format from pino)\n */\nfunction parseLogLine(line: string, source?: string, lineNumber?: number): ParsedLogEntry | null {\n const trimmed = line.trim();\n if (!trimmed) return null;\n\n try {\n // Try JSON format (pino default)\n const parsed = JSON.parse(trimmed);\n \n // Convert pino numeric level to string (10=trace, 20=debug, 30=info, 40=warn, 50=error, 60=fatal)\n const levelNum = typeof parsed.level === 'number' ? parsed.level : 30;\n const levelMap: Record<number, string> = {\n 10: 'trace',\n 20: 'debug',\n 30: 'info',\n 40: 'warn',\n 50: 'error',\n 60: 'fatal',\n };\n\n return {\n timestamp: parsed.time || parsed.timestamp || '',\n level: levelMap[levelNum] || (parsed.level?.toString() || 'info').toLowerCase(),\n message: parsed.msg || parsed.message || '',\n module: parsed.module,\n prefix: parsed.prefix,\n service: parsed.service,\n extension: parsed.extension,\n requestId: parsed.requestId,\n sessionId: parsed.sessionId,\n _source: source,\n _lineNumber: lineNumber,\n ...parsed,\n };\n } catch {\n // Fallback: try to parse pino's text format\n const match = trimmed.match(/^\\[([^\\]]+)\\]\\s+(\\w+):\\s+(.+)$/);\n if (match) {\n return {\n timestamp: match[1],\n level: match[2].toLowerCase() as LogLevel,\n message: match[3],\n _source: source,\n _lineNumber: lineNumber,\n };\n }\n \n // Plain text fallback\n return {\n timestamp: new Date().toISOString(),\n level: 'info',\n message: trimmed,\n _source: source,\n _lineNumber: lineNumber,\n };\n }\n}\n\n// ============================================\n// Streaming\n// ============================================\n\n/**\n * Create a readable stream for a log file (handles .gz files)\n */\nasync function createLogFileStream(filePath: string): Promise<Readable> {\n if (filePath.endsWith('.gz')) {\n const compressed = await readFile(filePath);\n const decompressed = await gunzipAsync(compressed);\n return Readable.from(decompressed.toString('utf-8').split('\\n'));\n }\n \n return createReadStream(filePath, { encoding: 'utf-8' });\n}\n\n/**\n * Stream and filter log entries from a file\n */\nasync function* streamLogFile(\n filePath: string,\n query: LogQuery = {}\n): AsyncGenerator<ParsedLogEntry> {\n if (!existsSync(filePath)) return;\n\n const fileName = basename(filePath);\n let stream: Readable;\n \n try {\n stream = await createLogFileStream(filePath);\n } catch {\n return;\n }\n\n const rl = createInterface({ \n input: stream,\n crlfDelay: Infinity \n });\n\n let lineNumber = 0;\n\n try {\n for await (const line of rl) {\n lineNumber++;\n const entry = parseLogLine(line, fileName, lineNumber);\n if (!entry) continue;\n\n // Apply filters\n if (!matchesQuery(entry, query)) continue;\n\n yield entry;\n }\n } finally {\n rl.close();\n }\n}\n\n/**\n * Check if a log entry matches the query filters\n */\nfunction matchesQuery(entry: ParsedLogEntry, query: LogQuery): boolean {\n // Filter by levels\n if (query.levels?.length && !query.levels.includes(entry.level as LogLevel)) {\n return false;\n }\n\n // Filter by time range\n if (query.from) {\n const fromDate = new Date(query.from);\n const entryDate = new Date(entry.timestamp);\n if (entryDate < fromDate) return false;\n }\n if (query.to) {\n const toDate = new Date(query.to);\n const entryDate = new Date(entry.timestamp);\n if (entryDate > toDate) return false;\n }\n\n // Filter by keyword (search in message and context fields)\n if (query.q) {\n const keyword = query.q.toLowerCase();\n const searchable = [\n entry.message,\n entry.module,\n entry.prefix,\n entry.service,\n entry.extension,\n entry.requestId,\n entry.sessionId,\n ]\n .filter(Boolean)\n .map(String)\n .join(' ')\n .toLowerCase();\n \n if (!searchable.includes(keyword)) return false;\n }\n\n // Filter by specific fields\n if (query.module && entry.module !== query.module) return false;\n if (query.extension && entry.extension !== query.extension) return false;\n if (query.service && entry.service !== query.service) return false;\n if (query.requestId && entry.requestId !== query.requestId) return false;\n if (query.sessionId && entry.sessionId !== query.sessionId) return false;\n\n return true;\n}\n\n// ============================================\n// Query API\n// ============================================\n\n/**\n * Query logs across multiple files\n */\nexport async function queryLogs(query: LogQuery = {}): Promise<LogEntry[]> {\n ensureLogDir();\n\n const results: ParsedLogEntry[] = [];\n const files = getLogFiles();\n\n // Filter files by date range if specified\n let relevantFiles = files;\n if (query.from || query.to) {\n const fromDate = query.from ? new Date(query.from) : new Date(0);\n const toDate = query.to ? new Date(query.to) : new Date();\n relevantFiles = getLogFilesForRange(fromDate, toDate);\n }\n\n // Query each file\n for (const file of relevantFiles) {\n for await (const entry of streamLogFile(file.path, query)) {\n results.push(entry);\n\n // Early exit if limit reached\n const limit = query.limit || 100;\n if (results.length >= limit) {\n break;\n }\n }\n\n if (query.limit && results.length >= query.limit) {\n break;\n }\n }\n\n // Sort by timestamp\n const order = query.order || 'desc';\n results.sort((a, b) => {\n const diff = new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime();\n return order === 'desc' ? diff : -diff;\n });\n\n // Apply offset/limit\n const offset = query.offset || 0;\n const limit = query.limit || 100;\n return results.slice(offset, offset + limit).map(({ _source, _lineNumber, ...rest }) => rest);\n}\n\n/**\n * Get recent logs (convenience method)\n */\nexport async function getRecentLogs(options?: {\n level?: LogLevel;\n limit?: number;\n module?: string;\n}): Promise<LogEntry[]> {\n return queryLogs({\n levels: options?.level ? [options.level] : undefined,\n limit: options?.limit || 50,\n module: options?.module,\n order: 'desc',\n });\n}\n\n/**\n * Search logs by keyword\n */\nexport async function searchLogs(\n keyword: string,\n options?: {\n from?: string;\n to?: string;\n limit?: number;\n }\n): Promise<LogEntry[]> {\n return queryLogs({\n q: keyword,\n ...options,\n limit: options?.limit || 100,\n });\n}\n\n/**\n * Get logs for a specific request/session\n */\nexport async function getLogsByContext(\n contextType: 'requestId' | 'sessionId',\n contextValue: string,\n limit: number = 100\n): Promise<LogEntry[]> {\n return queryLogs({\n [contextType]: contextValue,\n limit,\n order: 'asc',\n });\n}\n\n// ============================================\n// Statistics\n// ============================================\n\n/**\n * Get available log levels from actual log data\n */\nexport async function getLogLevelsFromData(): Promise<LogLevel[]> {\n const levels = new Set<LogLevel>();\n const files = getLogFiles().slice(0, 3); // Check last 3 files\n\n for (const file of files) {\n for await (const entry of streamLogFile(file.path, { limit: 500 })) {\n levels.add(entry.level as LogLevel);\n }\n }\n\n return Array.from(levels).sort();\n}\n\n/**\n * Get available modules from log data\n */\nexport async function getLogModules(): Promise<string[]> {\n const modules = new Set<string>();\n const files = getLogFiles().slice(0, 7);\n\n for (const file of files) {\n for await (const entry of streamLogFile(file.path, { limit: 1000 })) {\n if (entry.module) modules.add(entry.module);\n if (entry.prefix) modules.add(entry.prefix);\n }\n }\n\n return Array.from(modules).filter(Boolean).sort();\n}\n\n/**\n * Get log statistics by level (sampled from recent files)\n */\nexport async function getLogStats(): Promise<LogStats> {\n const files = getLogFiles();\n\n // Count by level (sample from recent files)\n const byLevel: Record<LogLevel, number> = {\n trace: 0,\n debug: 0,\n info: 0,\n warn: 0,\n error: 0,\n fatal: 0,\n silent: 0,\n };\n\n for (const file of files.slice(0, 7)) {\n for await (const entry of streamLogFile(file.path, { limit: 1000 })) {\n if (entry.level in byLevel) {\n byLevel[entry.level as LogLevel]++;\n }\n }\n }\n\n return { byLevel };\n}\n\n// ============================================\n// Cleanup\n// ============================================\n\n/**\n * Clean old logs (actually deletes files)\n */\nexport function cleanOldLogs(keepDays: number = 7): {\n deleted: number;\n freedBytes: number;\n errors: string[];\n} {\n const cutoff = new Date();\n cutoff.setDate(cutoff.getDate() - keepDays);\n\n let deleted = 0;\n let freedBytes = 0;\n const errors: string[] = [];\n\n const files = getLogFiles();\n for (const file of files) {\n const fileDate = new Date(file.modified);\n if (fileDate < cutoff) {\n try {\n const size = file.size;\n unlinkSync(file.path);\n deleted++;\n freedBytes += size;\n } catch (err) {\n errors.push(`Failed to delete ${file.name}: ${err}`);\n }\n }\n }\n\n return { deleted, freedBytes, errors };\n}\n\n/**\n * Clean logs by size (keep total under limit)\n */\nfunction _cleanBySize(maxTotalMB: number = 500): {\n deleted: number;\n freedBytes: number;\n errors: string[];\n} {\n const maxBytes = maxTotalMB * 1024 * 1024;\n const files = getLogFiles();\n \n let totalSize = files.reduce((sum, f) => sum + f.size, 0);\n let deleted = 0;\n let freedBytes = 0;\n const errors: string[] = [];\n\n // Delete oldest files until under limit\n for (const file of files.slice().reverse()) {\n if (totalSize <= maxBytes) break;\n\n try {\n unlinkSync(file.path);\n freedBytes += file.size;\n totalSize -= file.size;\n deleted++;\n } catch (err) {\n errors.push(`Failed to delete ${file.name}: ${err}`);\n }\n }\n\n return { deleted, freedBytes, errors };\n}\n\n// ============================================\n// Log Levels\n// ============================================\n\nconst LOG_LEVELS: LogLevel[] = ['trace', 'debug', 'info', 'warn', 'error', 'fatal'];\n\n/**\n * Get available log levels\n */\nexport function getLogLevels(): LogLevel[] {\n return [...LOG_LEVELS];\n}\n\n// ============================================\n// Exports\n// ============================================\n\nexport { LOG_DIR };\nexport type { LogEntry, LogQuery, LogFileMeta, LogStats } from './types.js';\n"],"mappings":"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"}
1
+ {"version":3,"file":"log-store.js","names":[],"sources":["../../../../src/utils/logger/log-store.ts"],"sourcesContent":["/**\n * Log Store - Enhanced File-based Log Storage\n * \n * Features:\n * - Query logs across multiple files with filtering\n * - Support for compressed (.gz) log files\n * - Pagination and sorting\n * - Statistics and analytics\n * - Safe log cleanup with actual deletion\n */\n\nimport { \n existsSync, \n mkdirSync, \n readdirSync, \n statSync, \n createReadStream,\n unlinkSync,\n} from 'fs';\nimport { readFile } from 'fs/promises';\nimport { join, basename } from 'path';\nimport { createInterface } from 'readline';\nimport { gunzip } from 'zlib';\nimport { promisify } from 'util';\nimport { Readable } from 'stream';\nimport type { LogLevel, LogFileMeta, LogQuery, LogStats, LogEntry } from './types.js';\n\nconst gunzipAsync = promisify(gunzip);\n\n// ============================================\n// Types\n// ============================================\n\ninterface ParsedLogEntry extends LogEntry {\n _source?: string;\n _lineNumber?: number;\n}\n\n// ============================================\n// Configuration\n// ============================================\n\nconst LOG_DIR = process.env.XOPC_LOG_DIR || join(process.env.HOME || '.', '.xopc', 'logs');\n\nfunction ensureLogDir(): void {\n if (!existsSync(LOG_DIR)) {\n mkdirSync(LOG_DIR, { recursive: true });\n }\n}\n\n// ============================================\n// File Management\n// ============================================\n\n/**\n * Get all log files (including compressed)\n */\nexport function getLogFiles(): LogFileMeta[] {\n ensureLogDir();\n\n const files = readdirSync(LOG_DIR)\n .filter(f => f.endsWith('.log') || f.endsWith('.log.gz'))\n .map(f => {\n const filePath = join(LOG_DIR, f);\n const stats = statSync(filePath);\n \n let type: LogFileMeta['type'] = 'app';\n if (f.includes('error')) type = 'error';\n else if (f.includes('audit')) type = 'audit';\n else if (f.includes('access')) type = 'access';\n\n return {\n name: f,\n path: filePath,\n size: stats.size,\n created: stats.birthtime.toISOString(),\n modified: stats.mtime.toISOString(),\n type,\n };\n })\n .sort((a, b) => new Date(b.modified).getTime() - new Date(a.modified).getTime());\n\n return files;\n}\n\n/**\n * Get log file path for a specific date and type\n */\nexport function getLogPath(\n date: Date = new Date(), \n type: 'app' | 'error' | 'audit' | 'access' = 'app'\n): string {\n ensureLogDir();\n const dateStr = date.toISOString().split('T')[0];\n return join(LOG_DIR, `${type}-${dateStr}.log`);\n}\n\n/**\n * Get available log files for a date range\n */\nfunction getLogFilesForRange(from: Date, to: Date): LogFileMeta[] {\n const allFiles = getLogFiles();\n \n return allFiles.filter(f => {\n // Extract date from filename (e.g., app-2024-01-01.log)\n const match = f.name.match(/(\\d{4}-\\d{2}-\\d{2})/);\n if (!match) return false;\n \n const fileDate = new Date(match[1]);\n return fileDate >= from && fileDate <= to;\n });\n}\n\n// ============================================\n// Log Parsing\n// ============================================\n\n/**\n * Parse a single log line (JSON format from pino)\n */\nfunction parseLogLine(line: string, source?: string, lineNumber?: number): ParsedLogEntry | null {\n const trimmed = line.trim();\n if (!trimmed) return null;\n\n try {\n // Try JSON format (pino default)\n const parsed = JSON.parse(trimmed);\n \n // Convert pino numeric level to string (10=trace, 20=debug, 30=info, 40=warn, 50=error, 60=fatal)\n const levelNum = typeof parsed.level === 'number' ? parsed.level : 30;\n const levelMap: Record<number, string> = {\n 10: 'trace',\n 20: 'debug',\n 30: 'info',\n 40: 'warn',\n 50: 'error',\n 60: 'fatal',\n };\n\n return {\n timestamp: parsed.time || parsed.timestamp || '',\n level: levelMap[levelNum] || (parsed.level?.toString() || 'info').toLowerCase(),\n message: parsed.msg || parsed.message || '',\n module: parsed.module,\n prefix: parsed.prefix,\n service: parsed.service,\n extension: parsed.extension,\n requestId: parsed.requestId,\n sessionId: parsed.sessionId,\n _source: source,\n _lineNumber: lineNumber,\n ...parsed,\n };\n } catch {\n // Fallback: try to parse pino's text format\n const match = trimmed.match(/^\\[([^\\]]+)\\]\\s+(\\w+):\\s+(.+)$/);\n if (match) {\n return {\n timestamp: match[1],\n level: match[2].toLowerCase() as LogLevel,\n message: match[3],\n _source: source,\n _lineNumber: lineNumber,\n };\n }\n \n // Plain text fallback\n return {\n timestamp: new Date().toISOString(),\n level: 'info',\n message: trimmed,\n _source: source,\n _lineNumber: lineNumber,\n };\n }\n}\n\n// ============================================\n// Streaming\n// ============================================\n\n/**\n * Create a readable stream for a log file (handles .gz files)\n */\nasync function createLogFileStream(filePath: string): Promise<Readable> {\n if (filePath.endsWith('.gz')) {\n const compressed = await readFile(filePath);\n const decompressed = await gunzipAsync(compressed);\n return Readable.from(decompressed.toString('utf-8').split('\\n'));\n }\n \n return createReadStream(filePath, { encoding: 'utf-8' });\n}\n\n/**\n * Stream and filter log entries from a file\n */\nasync function* streamLogFile(\n filePath: string,\n query: LogQuery = {}\n): AsyncGenerator<ParsedLogEntry> {\n if (!existsSync(filePath)) return;\n\n const fileName = basename(filePath);\n let stream: Readable;\n \n try {\n stream = await createLogFileStream(filePath);\n } catch {\n return;\n }\n\n const rl = createInterface({ \n input: stream,\n crlfDelay: Infinity \n });\n\n let lineNumber = 0;\n\n try {\n for await (const line of rl) {\n lineNumber++;\n const entry = parseLogLine(line, fileName, lineNumber);\n if (!entry) continue;\n\n // Apply filters\n if (!matchesQuery(entry, query)) continue;\n\n yield entry;\n }\n } finally {\n rl.close();\n }\n}\n\n/**\n * Check if a log entry matches the query filters\n */\nfunction matchesQuery(entry: ParsedLogEntry, query: LogQuery): boolean {\n // Filter by levels\n if (query.levels?.length && !query.levels.includes(entry.level as LogLevel)) {\n return false;\n }\n\n // Filter by time range\n if (query.from) {\n const fromDate = new Date(query.from);\n const entryDate = new Date(entry.timestamp);\n if (entryDate < fromDate) return false;\n }\n if (query.to) {\n const toDate = new Date(query.to);\n const entryDate = new Date(entry.timestamp);\n if (entryDate > toDate) return false;\n }\n\n // Filter by keyword (search in message and context fields)\n if (query.q) {\n const keyword = query.q.toLowerCase();\n const searchable = [\n entry.message,\n entry.module,\n entry.prefix,\n entry.service,\n entry.extension,\n entry.requestId,\n entry.sessionId,\n ]\n .filter(Boolean)\n .map(String)\n .join(' ')\n .toLowerCase();\n \n if (!searchable.includes(keyword)) return false;\n }\n\n // Filter by specific fields\n if (query.module && entry.module !== query.module) return false;\n if (query.extension && entry.extension !== query.extension) return false;\n if (query.service && entry.service !== query.service) return false;\n if (query.requestId && entry.requestId !== query.requestId) return false;\n if (query.sessionId && entry.sessionId !== query.sessionId) return false;\n\n return true;\n}\n\n// ============================================\n// Query API\n// ============================================\n\n/** Cap matched rows before sort/slice so query stays bounded on huge log dirs. */\nconst QUERY_LOGS_MAX_MATCHED = 25_000;\n\n/**\n * Query logs across multiple files\n */\nexport async function queryLogs(query: LogQuery = {}): Promise<LogEntry[]> {\n ensureLogDir();\n\n const results: ParsedLogEntry[] = [];\n const files = getLogFiles();\n\n // Filter files by date range if specified\n let relevantFiles = files;\n if (query.from || query.to) {\n const fromDate = query.from ? new Date(query.from) : new Date(0);\n const toDate = query.to ? new Date(query.to) : new Date();\n relevantFiles = getLogFilesForRange(fromDate, toDate);\n }\n\n // Collect all matches (files are newest-first; lines in each file are time-asc).\n // Do not stop at `limit` while streaming — that only captured the oldest tail of\n // early files and made \"newest first\" wrong after sort.\n for (const file of relevantFiles) {\n if (results.length >= QUERY_LOGS_MAX_MATCHED) break;\n for await (const entry of streamLogFile(file.path, query)) {\n results.push(entry);\n if (results.length >= QUERY_LOGS_MAX_MATCHED) break;\n }\n }\n\n // Sort by timestamp\n const order = query.order || 'desc';\n results.sort((a, b) => {\n const diff = new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime();\n return order === 'desc' ? diff : -diff;\n });\n\n // Apply offset/limit\n const offset = query.offset || 0;\n const limit = query.limit || 100;\n return results.slice(offset, offset + limit).map(({ _source, _lineNumber, ...rest }) => rest);\n}\n\n/**\n * Get recent logs (convenience method)\n */\nexport async function getRecentLogs(options?: {\n level?: LogLevel;\n limit?: number;\n module?: string;\n}): Promise<LogEntry[]> {\n return queryLogs({\n levels: options?.level ? [options.level] : undefined,\n limit: options?.limit || 50,\n module: options?.module,\n order: 'desc',\n });\n}\n\n/**\n * Search logs by keyword\n */\nexport async function searchLogs(\n keyword: string,\n options?: {\n from?: string;\n to?: string;\n limit?: number;\n }\n): Promise<LogEntry[]> {\n return queryLogs({\n q: keyword,\n ...options,\n limit: options?.limit || 100,\n });\n}\n\n/**\n * Get logs for a specific request/session\n */\nexport async function getLogsByContext(\n contextType: 'requestId' | 'sessionId',\n contextValue: string,\n limit: number = 100\n): Promise<LogEntry[]> {\n return queryLogs({\n [contextType]: contextValue,\n limit,\n order: 'asc',\n });\n}\n\n// ============================================\n// Statistics\n// ============================================\n\n/**\n * Get available log levels from actual log data\n */\nexport async function getLogLevelsFromData(): Promise<LogLevel[]> {\n const levels = new Set<LogLevel>();\n const files = getLogFiles().slice(0, 3); // Check last 3 files\n\n for (const file of files) {\n for await (const entry of streamLogFile(file.path, { limit: 500 })) {\n levels.add(entry.level as LogLevel);\n }\n }\n\n return Array.from(levels).sort();\n}\n\n/**\n * Get available modules from log data\n */\nexport async function getLogModules(): Promise<string[]> {\n const modules = new Set<string>();\n const files = getLogFiles().slice(0, 7);\n\n for (const file of files) {\n for await (const entry of streamLogFile(file.path, { limit: 1000 })) {\n if (entry.module) modules.add(entry.module);\n if (entry.prefix) modules.add(entry.prefix);\n }\n }\n\n return Array.from(modules).filter(Boolean).sort();\n}\n\n/**\n * Get log statistics by level (sampled from recent files)\n */\nexport async function getLogStats(): Promise<LogStats> {\n const files = getLogFiles();\n\n // Count by level (sample from recent files)\n const byLevel: Record<LogLevel, number> = {\n trace: 0,\n debug: 0,\n info: 0,\n warn: 0,\n error: 0,\n fatal: 0,\n silent: 0,\n };\n\n for (const file of files.slice(0, 7)) {\n for await (const entry of streamLogFile(file.path, { limit: 1000 })) {\n if (entry.level in byLevel) {\n byLevel[entry.level as LogLevel]++;\n }\n }\n }\n\n return { byLevel };\n}\n\n// ============================================\n// Cleanup\n// ============================================\n\n/**\n * Clean old logs (actually deletes files)\n */\nexport function cleanOldLogs(keepDays: number = 7): {\n deleted: number;\n freedBytes: number;\n errors: string[];\n} {\n const cutoff = new Date();\n cutoff.setDate(cutoff.getDate() - keepDays);\n\n let deleted = 0;\n let freedBytes = 0;\n const errors: string[] = [];\n\n const files = getLogFiles();\n for (const file of files) {\n const fileDate = new Date(file.modified);\n if (fileDate < cutoff) {\n try {\n const size = file.size;\n unlinkSync(file.path);\n deleted++;\n freedBytes += size;\n } catch (err) {\n errors.push(`Failed to delete ${file.name}: ${err}`);\n }\n }\n }\n\n return { deleted, freedBytes, errors };\n}\n\n/**\n * Clean logs by size (keep total under limit)\n */\nfunction _cleanBySize(maxTotalMB: number = 500): {\n deleted: number;\n freedBytes: number;\n errors: string[];\n} {\n const maxBytes = maxTotalMB * 1024 * 1024;\n const files = getLogFiles();\n \n let totalSize = files.reduce((sum, f) => sum + f.size, 0);\n let deleted = 0;\n let freedBytes = 0;\n const errors: string[] = [];\n\n // Delete oldest files until under limit\n for (const file of files.slice().reverse()) {\n if (totalSize <= maxBytes) break;\n\n try {\n unlinkSync(file.path);\n freedBytes += file.size;\n totalSize -= file.size;\n deleted++;\n } catch (err) {\n errors.push(`Failed to delete ${file.name}: ${err}`);\n }\n }\n\n return { deleted, freedBytes, errors };\n}\n\n// ============================================\n// Log Levels\n// ============================================\n\nconst LOG_LEVELS: LogLevel[] = ['trace', 'debug', 'info', 'warn', 'error', 'fatal'];\n\n/**\n * Get available log levels\n */\nexport function getLogLevels(): LogLevel[] {\n return [...LOG_LEVELS];\n}\n\n// ============================================\n// Exports\n// ============================================\n\nexport { LOG_DIR };\nexport type { LogEntry, LogQuery, LogFileMeta, LogStats } from './types.js';\n"],"mappings":"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"}
@@ -7,7 +7,6 @@ import { isTTSAvailable } from "./factory.js";
7
7
  */
8
8
  function normalizeTtsTrigger(raw) {
9
9
  const t = typeof raw === "string" ? raw.toLowerCase() : "";
10
- if (t === "auto") return "inbound";
11
10
  if (t === "off" || t === "always" || t === "inbound" || t === "tagged") return t;
12
11
  return DEFAULT_TTS_CONFIG.trigger;
13
12
  }
@@ -1 +1 @@
1
- {"version":3,"file":"merge-config.js","names":[],"sources":["../../../../src/voice/tts/merge-config.ts"],"sourcesContent":["import type { Config } from '../../config/schema.js';\nimport { DEFAULT_TTS_CONFIG, type TTSConfig } from './types.js';\nimport { isTTSAvailable } from './factory.js';\n\n/**\n * Merge persisted app config `tts` with defaults to a full {@link TTSConfig}\n * for validation (provider chain, env-based keys, etc.).\n */\nfunction normalizeTtsTrigger(raw: unknown): TTSConfig['trigger'] {\n const t = typeof raw === 'string' ? raw.toLowerCase() : '';\n if (t === 'auto') return 'inbound';\n if (t === 'off' || t === 'always' || t === 'inbound' || t === 'tagged') return t;\n return DEFAULT_TTS_CONFIG.trigger;\n}\n\nexport function mergeTtsConfigFromAppConfig(tts: Config['tts'] | undefined): TTSConfig {\n const p = (tts ?? {}) as Partial<TTSConfig>;\n return {\n ...DEFAULT_TTS_CONFIG,\n ...p,\n enabled: p.enabled ?? DEFAULT_TTS_CONFIG.enabled,\n provider: p.provider ?? DEFAULT_TTS_CONFIG.provider,\n trigger: normalizeTtsTrigger((p as { trigger?: unknown }).trigger ?? DEFAULT_TTS_CONFIG.trigger),\n fallback: {\n ...DEFAULT_TTS_CONFIG.fallback!,\n ...p.fallback,\n },\n modelOverrides: {\n ...DEFAULT_TTS_CONFIG.modelOverrides!,\n ...p.modelOverrides,\n },\n alibaba: { ...DEFAULT_TTS_CONFIG.alibaba, ...p.alibaba },\n openai: { ...DEFAULT_TTS_CONFIG.openai, ...p.openai },\n edge: { ...DEFAULT_TTS_CONFIG.edge, ...p.edge },\n minimax: { ...DEFAULT_TTS_CONFIG.minimax, ...p.minimax },\n summarization: {\n ...DEFAULT_TTS_CONFIG.summarization,\n ...p.summarization,\n },\n };\n}\n\n/**\n * User-facing hint when TTS is enabled in settings but no provider can run.\n */\nexport function formatTtsSetupHint(): string {\n return (\n `⚠️ *TTS is on, but no provider can run yet.*\\n\\n` +\n `Configure one of the following in \\`~/.xopc/xopc.json\\` (or env):\\n` +\n `• *OpenAI*: \\`OPENAI_API_KEY\\` or \\`tts.openai.apiKey\\` (and optional \\`tts.openai.model\\` / \\`tts.openai.voice\\`)\\n` +\n `• *Alibaba*: \\`DASHSCOPE_API_KEY\\` or \\`tts.alibaba.apiKey\\`\\n` +\n `• *MiniMax*: \\`MINIMAX_API_KEY\\` or \\`tts.minimax.apiKey\\` (and optional \\`tts.minimax.model\\` / \\`tts.minimax.voice\\`)\\n` +\n `• *Edge* (no key): \\`/tts provider edge\\` — ensure \\`tts.edge.enabled\\` is not \\`false\\`\\n\\n` +\n `You can also use the gateway Web UI → Settings → Voice.`\n );\n}\n\n/**\n * Append readiness / setup guidance when TTS is enabled but unavailable.\n */\nexport function appendTtsReadinessNote(content: string, appConfig: Config | undefined): string {\n const effective = mergeTtsConfigFromAppConfig(appConfig?.tts);\n if (!effective.enabled) {\n return content;\n }\n if (isTTSAvailable(effective)) {\n return content;\n }\n return `${content}\\n\\n${formatTtsSetupHint()}`;\n}\n"],"mappings":";;;;;;;AAQA,SAAS,oBAAoB,KAAoC;CAC/D,MAAM,IAAI,OAAO,QAAQ,WAAW,IAAI,aAAa,GAAG;AACxD,KAAI,MAAM,OAAQ,QAAO;AACzB,KAAI,MAAM,SAAS,MAAM,YAAY,MAAM,aAAa,MAAM,SAAU,QAAO;AAC/E,QAAO,mBAAmB;;AAG5B,SAAgB,4BAA4B,KAA2C;CACrF,MAAM,IAAK,OAAO,EAAE;AACpB,QAAO;EACL,GAAG;EACH,GAAG;EACH,SAAS,EAAE,WAAW,mBAAmB;EACzC,UAAU,EAAE,YAAY,mBAAmB;EAC3C,SAAS,oBAAqB,EAA4B,WAAW,mBAAmB,QAAQ;EAChG,UAAU;GACR,GAAG,mBAAmB;GACtB,GAAG,EAAE;GACN;EACD,gBAAgB;GACd,GAAG,mBAAmB;GACtB,GAAG,EAAE;GACN;EACD,SAAS;GAAE,GAAG,mBAAmB;GAAS,GAAG,EAAE;GAAS;EACxD,QAAQ;GAAE,GAAG,mBAAmB;GAAQ,GAAG,EAAE;GAAQ;EACrD,MAAM;GAAE,GAAG,mBAAmB;GAAM,GAAG,EAAE;GAAM;EAC/C,SAAS;GAAE,GAAG,mBAAmB;GAAS,GAAG,EAAE;GAAS;EACxD,eAAe;GACb,GAAG,mBAAmB;GACtB,GAAG,EAAE;GACN;EACF;;;;;AAMH,SAAgB,qBAA6B;AAC3C,QACE;;;;;AAaJ,SAAgB,uBAAuB,SAAiB,WAAuC;CAC7F,MAAM,YAAY,4BAA4B,WAAW,IAAI;AAC7D,KAAI,CAAC,UAAU,QACb,QAAO;AAET,KAAI,eAAe,UAAU,CAC3B,QAAO;AAET,QAAO,GAAG,QAAQ,MAAM,oBAAoB"}
1
+ {"version":3,"file":"merge-config.js","names":[],"sources":["../../../../src/voice/tts/merge-config.ts"],"sourcesContent":["import type { Config } from '../../config/schema.js';\nimport { DEFAULT_TTS_CONFIG, type TTSConfig } from './types.js';\nimport { isTTSAvailable } from './factory.js';\n\n/**\n * Merge persisted app config `tts` with defaults to a full {@link TTSConfig}\n * for validation (provider chain, env-based keys, etc.).\n */\nfunction normalizeTtsTrigger(raw: unknown): TTSConfig['trigger'] {\n const t = typeof raw === 'string' ? raw.toLowerCase() : '';\n if (t === 'off' || t === 'always' || t === 'inbound' || t === 'tagged') return t;\n return DEFAULT_TTS_CONFIG.trigger;\n}\n\nexport function mergeTtsConfigFromAppConfig(tts: Config['tts'] | undefined): TTSConfig {\n const p = (tts ?? {}) as Partial<TTSConfig>;\n return {\n ...DEFAULT_TTS_CONFIG,\n ...p,\n enabled: p.enabled ?? DEFAULT_TTS_CONFIG.enabled,\n provider: p.provider ?? DEFAULT_TTS_CONFIG.provider,\n trigger: normalizeTtsTrigger((p as { trigger?: unknown }).trigger ?? DEFAULT_TTS_CONFIG.trigger),\n fallback: {\n ...DEFAULT_TTS_CONFIG.fallback!,\n ...p.fallback,\n },\n modelOverrides: {\n ...DEFAULT_TTS_CONFIG.modelOverrides!,\n ...p.modelOverrides,\n },\n alibaba: { ...DEFAULT_TTS_CONFIG.alibaba, ...p.alibaba },\n openai: { ...DEFAULT_TTS_CONFIG.openai, ...p.openai },\n edge: { ...DEFAULT_TTS_CONFIG.edge, ...p.edge },\n minimax: { ...DEFAULT_TTS_CONFIG.minimax, ...p.minimax },\n summarization: {\n ...DEFAULT_TTS_CONFIG.summarization,\n ...p.summarization,\n },\n };\n}\n\n/**\n * User-facing hint when TTS is enabled in settings but no provider can run.\n */\nexport function formatTtsSetupHint(): string {\n return (\n `⚠️ *TTS is on, but no provider can run yet.*\\n\\n` +\n `Configure one of the following in \\`~/.xopc/xopc.json\\` (or env):\\n` +\n `• *OpenAI*: \\`OPENAI_API_KEY\\` or \\`tts.openai.apiKey\\` (and optional \\`tts.openai.model\\` / \\`tts.openai.voice\\`)\\n` +\n `• *Alibaba*: \\`DASHSCOPE_API_KEY\\` or \\`tts.alibaba.apiKey\\`\\n` +\n `• *MiniMax*: \\`MINIMAX_API_KEY\\` or \\`tts.minimax.apiKey\\` (and optional \\`tts.minimax.model\\` / \\`tts.minimax.voice\\`)\\n` +\n `• *Edge* (no key): \\`/tts provider edge\\` — ensure \\`tts.edge.enabled\\` is not \\`false\\`\\n\\n` +\n `You can also use the gateway Web UI → Settings → Voice.`\n );\n}\n\n/**\n * Append readiness / setup guidance when TTS is enabled but unavailable.\n */\nexport function appendTtsReadinessNote(content: string, appConfig: Config | undefined): string {\n const effective = mergeTtsConfigFromAppConfig(appConfig?.tts);\n if (!effective.enabled) {\n return content;\n }\n if (isTTSAvailable(effective)) {\n return content;\n }\n return `${content}\\n\\n${formatTtsSetupHint()}`;\n}\n"],"mappings":";;;;;;;AAQA,SAAS,oBAAoB,KAAoC;CAC/D,MAAM,IAAI,OAAO,QAAQ,WAAW,IAAI,aAAa,GAAG;AACxD,KAAI,MAAM,SAAS,MAAM,YAAY,MAAM,aAAa,MAAM,SAAU,QAAO;AAC/E,QAAO,mBAAmB;;AAG5B,SAAgB,4BAA4B,KAA2C;CACrF,MAAM,IAAK,OAAO,EAAE;AACpB,QAAO;EACL,GAAG;EACH,GAAG;EACH,SAAS,EAAE,WAAW,mBAAmB;EACzC,UAAU,EAAE,YAAY,mBAAmB;EAC3C,SAAS,oBAAqB,EAA4B,WAAW,mBAAmB,QAAQ;EAChG,UAAU;GACR,GAAG,mBAAmB;GACtB,GAAG,EAAE;GACN;EACD,gBAAgB;GACd,GAAG,mBAAmB;GACtB,GAAG,EAAE;GACN;EACD,SAAS;GAAE,GAAG,mBAAmB;GAAS,GAAG,EAAE;GAAS;EACxD,QAAQ;GAAE,GAAG,mBAAmB;GAAQ,GAAG,EAAE;GAAQ;EACrD,MAAM;GAAE,GAAG,mBAAmB;GAAM,GAAG,EAAE;GAAM;EAC/C,SAAS;GAAE,GAAG,mBAAmB;GAAS,GAAG,EAAE;GAAS;EACxD,eAAe;GACb,GAAG,mBAAmB;GACtB,GAAG,EAAE;GACN;EACF;;;;;AAMH,SAAgB,qBAA6B;AAC3C,QACE;;;;;AAaJ,SAAgB,uBAAuB,SAAiB,WAAuC;CAC7F,MAAM,YAAY,4BAA4B,WAAW,IAAI;AAC7D,KAAI,CAAC,UAAU,QACb,QAAO;AAET,KAAI,eAAe,UAAU,CAC3B,QAAO;AAET,QAAO,GAAG,QAAQ,MAAM,oBAAoB"}
@@ -38,8 +38,7 @@ function shouldUseTTS(config, inboundAudio) {
38
38
  useTTS: false,
39
39
  reason: "TTS disabled"
40
40
  };
41
- const triggerRaw = config.trigger ?? "off";
42
- const trigger = triggerRaw === "auto" ? "inbound" : triggerRaw;
41
+ const trigger = config.trigger ?? "off";
43
42
  switch (trigger) {
44
43
  case "off": return {
45
44
  useTTS: false,
@@ -1 +1 @@
1
- {"version":3,"file":"service.js","names":[],"sources":["../../../../src/voice/tts/service.ts"],"sourcesContent":["import type { TTSConfig, TTSAutoMode, TTSResultWithTracking } from './types.js';\n\nexport interface ChannelAudioFormat {\n format: string;\n voiceCompatible: boolean;\n}\n\n/** Per-channel encoding for outbound TTS. Only ids that xopc actually delivers on are listed; anything else uses `default`. */\nconst CHANNEL_OUTPUT_FORMATS: Record<string, ChannelAudioFormat> = {\n telegram: { format: 'opus', voiceCompatible: true },\n /** Weixin ilink: VoiceItem encode_type 7 = MP3 per API types. */\n weixin: { format: 'mp3', voiceCompatible: true },\n webchat: { format: 'mp3', voiceCompatible: false },\n cli: { format: 'mp3', voiceCompatible: false },\n default: { format: 'mp3', voiceCompatible: false },\n};\n\nexport function getChannelOutputFormat(channel?: string): ChannelAudioFormat {\n if (!channel) return CHANNEL_OUTPUT_FORMATS.default;\n return CHANNEL_OUTPUT_FORMATS[channel.toLowerCase()] || CHANNEL_OUTPUT_FORMATS.default;\n}\n\nexport function getSupportedChannels(): string[] {\n return Object.keys(CHANNEL_OUTPUT_FORMATS).filter((k) => k !== 'default');\n}\n\nexport function isVoiceCompatibleChannel(channel: string): boolean {\n return getChannelOutputFormat(channel).voiceCompatible;\n}\n\nexport interface TTSContext {\n channel?: string;\n chatId?: string;\n}\n\nexport interface TTSDecision {\n useTTS: boolean;\n reason: string;\n}\n\nexport function shouldUseTTS(config: TTSConfig | undefined, inboundAudio?: boolean): TTSDecision {\n if (!config?.enabled) {\n return { useTTS: false, reason: 'TTS disabled' };\n }\n\n const triggerRaw = (config.trigger ?? 'off') as string;\n const trigger = triggerRaw === 'auto' ? 'inbound' : triggerRaw;\n\n switch (trigger) {\n case 'off':\n return { useTTS: false, reason: 'trigger=off' };\n case 'always':\n return { useTTS: true, reason: 'trigger=always' };\n case 'inbound':\n return inboundAudio === true\n ? { useTTS: true, reason: 'trigger=inbound + inboundAudio=true' }\n : { useTTS: false, reason: 'trigger=inbound but no inbound audio' };\n case 'tagged':\n return { useTTS: false, reason: 'trigger=tagged (directive check in TTS module)' };\n default:\n return { useTTS: false, reason: `unknown trigger=${trigger}` };\n }\n}\n\nexport class TTSService {\n constructor(private config: TTSConfig) {}\n\n isEnabled(): boolean {\n return this.config.enabled;\n }\n\n getTriggerMode(): TTSAutoMode {\n return this.config.trigger;\n }\n\n async speak(text: string, context?: TTSContext): Promise<TTSResultWithTracking> {\n const { speak } = await import('./index.js');\n return speak(text, this.config, {\n tts: {\n format: getChannelOutputFormat(context?.channel).format as 'opus' | 'mp3' | 'wav',\n },\n });\n }\n}\n"],"mappings":";;AAQA,MAAM,yBAA6D;CACjE,UAAU;EAAE,QAAQ;EAAQ,iBAAiB;EAAM;;CAEnD,QAAQ;EAAE,QAAQ;EAAO,iBAAiB;EAAM;CAChD,SAAS;EAAE,QAAQ;EAAO,iBAAiB;EAAO;CAClD,KAAK;EAAE,QAAQ;EAAO,iBAAiB;EAAO;CAC9C,SAAS;EAAE,QAAQ;EAAO,iBAAiB;EAAO;CACnD;AAED,SAAgB,uBAAuB,SAAsC;AAC3E,KAAI,CAAC,QAAS,QAAO,uBAAuB;AAC5C,QAAO,uBAAuB,QAAQ,aAAa,KAAK,uBAAuB;;AAGjF,SAAgB,uBAAiC;AAC/C,QAAO,OAAO,KAAK,uBAAuB,CAAC,QAAQ,MAAM,MAAM,UAAU;;AAG3E,SAAgB,yBAAyB,SAA0B;AACjE,QAAO,uBAAuB,QAAQ,CAAC;;AAazC,SAAgB,aAAa,QAA+B,cAAqC;AAC/F,KAAI,CAAC,QAAQ,QACX,QAAO;EAAE,QAAQ;EAAO,QAAQ;EAAgB;CAGlD,MAAM,aAAc,OAAO,WAAW;CACtC,MAAM,UAAU,eAAe,SAAS,YAAY;AAEpD,SAAQ,SAAR;EACE,KAAK,MACH,QAAO;GAAE,QAAQ;GAAO,QAAQ;GAAe;EACjD,KAAK,SACH,QAAO;GAAE,QAAQ;GAAM,QAAQ;GAAkB;EACnD,KAAK,UACH,QAAO,iBAAiB,OACpB;GAAE,QAAQ;GAAM,QAAQ;GAAuC,GAC/D;GAAE,QAAQ;GAAO,QAAQ;GAAwC;EACvE,KAAK,SACH,QAAO;GAAE,QAAQ;GAAO,QAAQ;GAAkD;EACpF,QACE,QAAO;GAAE,QAAQ;GAAO,QAAQ,mBAAmB;GAAW;;;AAIpE,IAAa,aAAb,MAAwB;CACtB,YAAY,QAA2B;AAAnB,OAAA,SAAA;;CAEpB,YAAqB;AACnB,SAAO,KAAK,OAAO;;CAGrB,iBAA8B;AAC5B,SAAO,KAAK,OAAO;;CAGrB,MAAM,MAAM,MAAc,SAAsD;EAC9E,MAAM,EAAE,UAAU,MAAM,OAAO;AAC/B,SAAO,MAAM,MAAM,KAAK,QAAQ,EAC9B,KAAK,EACH,QAAQ,uBAAuB,SAAS,QAAQ,CAAC,QAClD,EACF,CAAC"}
1
+ {"version":3,"file":"service.js","names":[],"sources":["../../../../src/voice/tts/service.ts"],"sourcesContent":["import type { TTSConfig, TTSAutoMode, TTSResultWithTracking } from './types.js';\n\nexport interface ChannelAudioFormat {\n format: string;\n voiceCompatible: boolean;\n}\n\n/** Per-channel encoding for outbound TTS. Only ids that xopc actually delivers on are listed; anything else uses `default`. */\nconst CHANNEL_OUTPUT_FORMATS: Record<string, ChannelAudioFormat> = {\n telegram: { format: 'opus', voiceCompatible: true },\n /** Weixin ilink: VoiceItem encode_type 7 = MP3 per API types. */\n weixin: { format: 'mp3', voiceCompatible: true },\n webchat: { format: 'mp3', voiceCompatible: false },\n cli: { format: 'mp3', voiceCompatible: false },\n default: { format: 'mp3', voiceCompatible: false },\n};\n\nexport function getChannelOutputFormat(channel?: string): ChannelAudioFormat {\n if (!channel) return CHANNEL_OUTPUT_FORMATS.default;\n return CHANNEL_OUTPUT_FORMATS[channel.toLowerCase()] || CHANNEL_OUTPUT_FORMATS.default;\n}\n\nexport function getSupportedChannels(): string[] {\n return Object.keys(CHANNEL_OUTPUT_FORMATS).filter((k) => k !== 'default');\n}\n\nexport function isVoiceCompatibleChannel(channel: string): boolean {\n return getChannelOutputFormat(channel).voiceCompatible;\n}\n\nexport interface TTSContext {\n channel?: string;\n chatId?: string;\n}\n\nexport interface TTSDecision {\n useTTS: boolean;\n reason: string;\n}\n\nexport function shouldUseTTS(config: TTSConfig | undefined, inboundAudio?: boolean): TTSDecision {\n if (!config?.enabled) {\n return { useTTS: false, reason: 'TTS disabled' };\n }\n\n const trigger = (config.trigger ?? 'off') as string;\n\n switch (trigger) {\n case 'off':\n return { useTTS: false, reason: 'trigger=off' };\n case 'always':\n return { useTTS: true, reason: 'trigger=always' };\n case 'inbound':\n return inboundAudio === true\n ? { useTTS: true, reason: 'trigger=inbound + inboundAudio=true' }\n : { useTTS: false, reason: 'trigger=inbound but no inbound audio' };\n case 'tagged':\n return { useTTS: false, reason: 'trigger=tagged (directive check in TTS module)' };\n default:\n return { useTTS: false, reason: `unknown trigger=${trigger}` };\n }\n}\n\nexport class TTSService {\n constructor(private config: TTSConfig) {}\n\n isEnabled(): boolean {\n return this.config.enabled;\n }\n\n getTriggerMode(): TTSAutoMode {\n return this.config.trigger;\n }\n\n async speak(text: string, context?: TTSContext): Promise<TTSResultWithTracking> {\n const { speak } = await import('./index.js');\n return speak(text, this.config, {\n tts: {\n format: getChannelOutputFormat(context?.channel).format as 'opus' | 'mp3' | 'wav',\n },\n });\n }\n}\n"],"mappings":";;AAQA,MAAM,yBAA6D;CACjE,UAAU;EAAE,QAAQ;EAAQ,iBAAiB;EAAM;;CAEnD,QAAQ;EAAE,QAAQ;EAAO,iBAAiB;EAAM;CAChD,SAAS;EAAE,QAAQ;EAAO,iBAAiB;EAAO;CAClD,KAAK;EAAE,QAAQ;EAAO,iBAAiB;EAAO;CAC9C,SAAS;EAAE,QAAQ;EAAO,iBAAiB;EAAO;CACnD;AAED,SAAgB,uBAAuB,SAAsC;AAC3E,KAAI,CAAC,QAAS,QAAO,uBAAuB;AAC5C,QAAO,uBAAuB,QAAQ,aAAa,KAAK,uBAAuB;;AAGjF,SAAgB,uBAAiC;AAC/C,QAAO,OAAO,KAAK,uBAAuB,CAAC,QAAQ,MAAM,MAAM,UAAU;;AAG3E,SAAgB,yBAAyB,SAA0B;AACjE,QAAO,uBAAuB,QAAQ,CAAC;;AAazC,SAAgB,aAAa,QAA+B,cAAqC;AAC/F,KAAI,CAAC,QAAQ,QACX,QAAO;EAAE,QAAQ;EAAO,QAAQ;EAAgB;CAGlD,MAAM,UAAW,OAAO,WAAW;AAEnC,SAAQ,SAAR;EACE,KAAK,MACH,QAAO;GAAE,QAAQ;GAAO,QAAQ;GAAe;EACjD,KAAK,SACH,QAAO;GAAE,QAAQ;GAAM,QAAQ;GAAkB;EACnD,KAAK,UACH,QAAO,iBAAiB,OACpB;GAAE,QAAQ;GAAM,QAAQ;GAAuC,GAC/D;GAAE,QAAQ;GAAO,QAAQ;GAAwC;EACvE,KAAK,SACH,QAAO;GAAE,QAAQ;GAAO,QAAQ;GAAkD;EACpF,QACE,QAAO;GAAE,QAAQ;GAAO,QAAQ,mBAAmB;GAAW;;;AAIpE,IAAa,aAAb,MAAwB;CACtB,YAAY,QAA2B;AAAnB,OAAA,SAAA;;CAEpB,YAAqB;AACnB,SAAO,KAAK,OAAO;;CAGrB,iBAA8B;AAC5B,SAAO,KAAK,OAAO;;CAGrB,MAAM,MAAM,MAAc,SAAsD;EAC9E,MAAM,EAAE,UAAU,MAAM,OAAO;AAC/B,SAAO,MAAM,MAAM,KAAK,QAAQ,EAC9B,KAAK,EACH,QAAQ,uBAAuB,SAAS,QAAQ,CAAC,QAClD,EACF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xopcai/xopc",
3
- "version": "0.0.29",
3
+ "version": "0.0.31",
4
4
  "description": "Personal AI assistant: CLI, gateway (HTTP/WebSocket + React console), Telegram and WeChat (Weixin) channels — TypeScript, 20+ LLM providers via pi-ai, extensions and skills.",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",
@@ -0,0 +1,80 @@
1
+ ---
2
+ name: company-values
3
+ description: 帮助极简业务定义公司价值观和文化。当有人正在设置公司文化、准备招聘,或想要明确公司代表什么时使用。
4
+ ---
5
+
6
+ 你是一位商业顾问,践行着萨希尔·拉维尼亚的《极简企业家》哲学。帮助用户定义他们的公司价值观 — 他们文化的基础。
7
+
8
+ ## 核心原则
9
+
10
+ **在招聘之前关注文化。** 在你招聘任何人之前,定义人们想要为什么样的公司工作。价值观就是你做到这一点的途径。它们不是通用的两个字命令 — 它们是用来以非显而易见的方式陈述非显而易见的事情。
11
+
12
+ ## 为什么价值观重要
13
+
14
+ - 价值观告诉员工每天如何表现,在极端情况下也如何表现
15
+ - 它们比 1000 页的手册更高效 — 好的价值观会留在脑海中
16
+ - 它们吸引正确的人("这完全是我想要的工作!")并排斥错误的人("这不适合我") — 两者都有价值
17
+ - 它们让你自己和你的团队都有责任
18
+ - 价值观超越你个人。它们允许公司在你的个人参与之外扩展。
19
+
20
+ ## Gumroad 的价值观(作为起点)
21
+
22
+ ### 1. 由工作来评判
23
+ - 重要的是创作者和客户的体验
24
+ - "我们发送给创作者的一切都是最高质量的,即每件事都经过多人审核"
25
+ - "如果帮助我们交付更优质的产品,我们对员工流失没有问题"
26
+ - "在你交付之后才收到关于本可以改善创作者生活的反馈,应该被视为失败"
27
+
28
+ ### 2. 寻求超线性
29
+ - 最终比任何线性函数增长更快的函数
30
+ - "我们有固定的小时数,而有无限的创作者收入可以实现"
31
+ - "每一天你都在你的时间投资上产生超线性回报"
32
+ - 人们可能会超越他们的角色并离开去创业 — 那样很好
33
+
34
+ ### 3. 每个人都是 CEO
35
+ - "你是你职能的 CEO,你有责任确保它以高水平执行"
36
+ - "像 CEO 向董事会寻求批准一样思考,而不是像员工向经理寻求方向"
37
+ - "如果有人需要问你事情进展如何,事情进展得并不好"
38
+
39
+ ### 4. 敢于开放
40
+ - "如果有 Gumroad 的秘密,就是这个:我们追求完全的信息对称"
41
+ - 让入职文档公开,在 Twitter 上分享财务状况
42
+ - 向整个公司披露每个人的薪资
43
+ - 没有会议,没有秘密,没有错失恐惧
44
+
45
+ ## 如何创建你自己的价值观
46
+
47
+ 引导用户:
48
+
49
+ 1. **你相信什么大多数人都不相信的?** 价值观应该是非显而易见的,有时甚至是两极分化的。
50
+
51
+ 2. **当没有人看着时,人们应该如何表现?** 价值观是为了那些没有经理在场的时候。
52
+
53
+ 3. **你会因为什么解雇一个人,即使他们表现很好?** 这揭示了你真正的价值观。
54
+
55
+ 4. **你会庆祝什么,即使它没有直接帮助底线?** 那也是一种价值观。
56
+
57
+ 5. **把它们写成故事,而不是口号。** "专注用户"是一个口号。Nordstrom 在服装店接受轮胎退换是通过故事传达价值观。
58
+
59
+ ## 价值观的运作
60
+
61
+ - 公开传达它们 — 在招聘信息、你的网站、你的入职培训中
62
+ - 在反馈中使用它们:"这符合我们的 X 价值观"或"这不符合我们的 Y 价值观"
63
+ - 定期回顾它们 — 价值观随着公司成长而演变
64
+ - Simply Eloped 使用首字母缩略词 CACAO:以客户为中心、有雄心、有同情心、适应性强、有主人翁精神
65
+
66
+ ## 远程工作和责任
67
+
68
+ 如果你远程工作(而且你可能应该):
69
+ - 所有沟通都是深思熟虑和异步的
70
+ - 使用 Slack 进行即时接近沟通,GitHub 进行异步代码审查,Notion 进行长期文档记录
71
+ - 人们在他们进行深度工作时发出信号,并设置自己的时间表
72
+ - 基于可用性建立,而不是监控
73
+
74
+ ## 输出
75
+
76
+ 帮助用户起草:
77
+ 1. 3-5 条带有描述和示例故事的公司价值观
78
+ 2. 每条价值观如何在招聘决策中体现
79
+ 3. 每条价值观如何在日常工作中体现
80
+ 4. 每条价值观的反模式(它 NOT 意味着什么)
@@ -0,0 +1,80 @@
1
+ ---
2
+ name: company-values
3
+ description: Help define company values and culture for a minimalist business. Use when someone is setting up their company culture, preparing to hire, or wanting to codify what their company stands for.
4
+ ---
5
+
6
+ You are a business advisor channeling the philosophy of The Minimalist Entrepreneur by Sahil Lavingia. Help the user define their company values — the foundation of their culture.
7
+
8
+ ## Core Principle
9
+
10
+ **Focus on culture before hiring.** Before you hire anyone, define what kind of company people want to work for. Values are how you do that. They're not generic two-word commandments — they're for stating the non-obvious, in non-obvious ways.
11
+
12
+ ## Why Values Matter
13
+
14
+ - Values tell employees how to behave every day AND in extreme situations
15
+ - They're more efficient than 1,000-page manuals — good values stick in the brain
16
+ - They attract the right people ("THIS IS EXACTLY THE JOB FOR ME!") and repel the wrong ones ("this isn't for me") — both are valuable
17
+ - They let you hold yourself AND your team accountable
18
+ - Values supersede you. They allow the company to scale beyond your personal involvement.
19
+
20
+ ## Gumroad's Values (As Starting Points)
21
+
22
+ ### 1. Judged by the Work
23
+ - What matters is the experience creators and customers have
24
+ - "Everything we send to creators is of the highest quality, meaning everything is reviewed by multiple people"
25
+ - "We are okay with employee churn if it helps us ship a superior product"
26
+ - "It should be considered a failure to receive feedback on something that could have made a creator's life better AFTER you shipped"
27
+
28
+ ### 2. Seek Superlinearities
29
+ - A function that eventually grows faster than any linear one
30
+ - "We have a fixed number of hours, and an unlimited amount of creator income to actualize"
31
+ - "Every day you are producing superlinear returns on your time investment"
32
+ - People may outgrow their role and leave to start their own company — that's great
33
+
34
+ ### 3. Everyone is a CEO
35
+ - "You are the CEO of your function, and it is your responsibility to make sure it is executing at a high level"
36
+ - "Think like a CEO asking for approval from their board, not like an employee asking their manager for direction"
37
+ - "If someone needs to ask you how things are going, they are not going well"
38
+
39
+ ### 4. Dare to Be Open
40
+ - "If there's a Gumroad secret, it's this one: we aim for complete information symmetry"
41
+ - Make onboarding documents public, share financials on Twitter
42
+ - Disclose everyone's salary to the whole company
43
+ - No meetings, no secrets, no FOMO
44
+
45
+ ## How to Create Your Own Values
46
+
47
+ Walk the user through:
48
+
49
+ 1. **What do you believe that most people don't?** Values should be non-obvious and sometimes polarizing.
50
+
51
+ 2. **How should people behave when no one is watching?** Values are for the moments without a manager present.
52
+
53
+ 3. **What would you fire someone for, even if they're performing well?** That reveals your true values.
54
+
55
+ 4. **What would you celebrate, even if it didn't directly help the bottom line?** That's also a value.
56
+
57
+ 5. **Write them as stories, not slogans.** "Focus on the user" is a slogan. Nordstrom accepting tire returns at a clothing store is a value communicated through story.
58
+
59
+ ## Operationalizing Values
60
+
61
+ - Communicate them publicly — in job posts, on your website, in your onboarding
62
+ - Use them in feedback: "This aligns with our value of X" or "This doesn't reflect our value of Y"
63
+ - Revisit them regularly — values evolve as your company grows
64
+ - Simply Eloped uses the acronym CACAO: Customer-centric, Ambitious, Compassionate, Adaptable, Ownership
65
+
66
+ ## Remote Work and Accountability
67
+
68
+ If you're remote (and you probably should be):
69
+ - All communication is thoughtful and asynchronous
70
+ - Use Slack for near-immediate, GitHub for async code review, Notion for long-term documentation
71
+ - People signal when they're doing deep work and set their own schedules
72
+ - Build around availability, not surveillance
73
+
74
+ ## Output
75
+
76
+ Help the user draft:
77
+ 1. 3-5 company values with descriptions and example stories
78
+ 2. How each value should show up in hiring decisions
79
+ 3. How each value should show up in day-to-day work
80
+ 4. Anti-patterns for each value (what it does NOT mean)
@@ -0,0 +1,50 @@
1
+ ---
2
+ name: find-community
3
+ description: 帮助识别和评估社区,以围绕极简业务进行构建。当有人正在寻找商业想法、试图找到他们的社区,或想知道作为企业家从哪里开始时使用。
4
+ ---
5
+
6
+ 你是一位商业顾问,践行着萨希尔·拉维尼亚的《极简企业家》哲学。帮助用户找到他们的社区 — 极简业务的基础。
7
+
8
+ ## 核心原则
9
+
10
+ **从社区开始,而不是从产品想法开始。** 最好的极简业务是由那些已经深深融入某个社区并注意到值得解决的问题的人构建的。你不是"找到"一个社区 — 你已经属于好几个了。
11
+
12
+ ## 框架: 识别你的社区
13
+
14
+ 引导用户回答这些问题:
15
+
16
+ 1. **你已经是哪些社区的一员了?** 广泛思考:专业团体、爱好社区、在线论坛、本地组织、基于身份认同的群体、校友网络、宗教社区、家长群体等。
17
+
18
+ 2. **你把时间花在哪里上网?** Reddit、Discord、Slack 群组、Twitter/X、论坛、Facebook 群组、Substack、YouTube 社区等。
19
+
20
+ 3. **你听到人们反复抱怨哪些问题?** 最好的商业想法来自你深刻理解的社区内持续、反复出现的痛点。
21
+
22
+ 4. **哪个社区会让你兴奋地服务多年?** 这不是一个周末项目 — 你将为这些人服务很长时间。
23
+
24
+ ## 评估标准
25
+
26
+ 对于每个潜在社区,帮助评估:
27
+
28
+ - **你是真正的成员吗?** 你应该理解社区的语言、价值观和文化。你应该做出贡献,而不是仅仅潜伏。
29
+ - **这个问题是否痛苦到人们愿意付费解决?** 不是每个问题都是生意。标准是:人们会为此交换金钱吗?
30
+ - **你能接触到这些人吗?** 你知道他们聚集在哪里吗?你能直接联系他们吗?
31
+ - **社区规模足够但不太大吗?** 你想要一个你能主导的细分市场,而不是一个你永远无法脱颖而出的广阔市场。
32
+
33
+ ## 关键洞察
34
+
35
+ "不要从商业想法开始。从人开始。正如 Sahil 所写:社区是起点。你的工作是成为一个社区的支柱,真正做出贡献,并注意到哪些问题持续存在。"
36
+
37
+ ## 需要注意的反模式
38
+
39
+ - 试图从零开始发明一个社区,而不是加入现有的
40
+ - 完全基于市场规模选择社区,而不是出于真正的兴趣
41
+ - 跳过社区参与,直接跳到"我能卖什么"
42
+ - 目标受众太宽泛(例如,"每个上网的人")
43
+
44
+ ## 输出
45
+
46
+ 帮助用户缩小到 1-3 个他们可以现实地服务的社区,并识别每个社区的具体问题。对于每个社区,注明:
47
+ - 社区
48
+ - 持续存在的问题
49
+ - 用户如何与这个社区有联系
50
+ - 这个社区在哪里聚集(线上和线下)
@@ -0,0 +1,50 @@
1
+ ---
2
+ name: find-community
3
+ description: Help identify and evaluate communities to build a minimalist business around. Use when someone is looking for a business idea, trying to find their community, or wondering where to start as an entrepreneur.
4
+ ---
5
+
6
+ You are a business advisor channeling the philosophy of The Minimalist Entrepreneur by Sahil Lavingia. Help the user find their community — the foundation of a minimalist business.
7
+
8
+ ## Core Principle
9
+
10
+ **Start with community, not with a product idea.** The best minimalist businesses are built by people who are already deeply embedded in a community and notice a problem worth solving. You don't "find" a community — you already belong to several.
11
+
12
+ ## Framework: Identify Your Communities
13
+
14
+ Walk the user through these questions:
15
+
16
+ 1. **What communities are you already a part of?** Think broadly: professional groups, hobby communities, online forums, local organizations, identity-based groups, alumni networks, religious communities, parent groups, etc.
17
+
18
+ 2. **Where do you spend your time online?** Reddit, Discord, Slack groups, Twitter/X, forums, Facebook groups, Substacks, YouTube communities, etc.
19
+
20
+ 3. **What problems do you hear people complain about repeatedly?** The best business ideas come from persistent, recurring pain points within communities you understand deeply.
21
+
22
+ 4. **Which of these communities would you be excited to serve for years?** This isn't a weekend project — you'll be serving these people for a long time.
23
+
24
+ ## Evaluation Criteria
25
+
26
+ For each potential community, help evaluate:
27
+
28
+ - **Are you a genuine member?** You should understand the community's language, values, and culture. You should be contributing, not just lurking.
29
+ - **Is the problem painful enough that people would pay for a solution?** Not every problem is a business. The bar is: would people exchange money for this?
30
+ - **Can you reach these people?** Do you know where they gather? Can you contact them directly?
31
+ - **Is the community large enough but not too large?** You want a niche you can dominate, not a market so broad you'll never stand out.
32
+
33
+ ## Key Insight
34
+
35
+ "Don't start with a business idea. Start with the people. As Sahil writes: communities are the starting point. Your job is to become a pillar of a community, contribute genuinely, and notice what problems persist."
36
+
37
+ ## Anti-patterns to Watch For
38
+
39
+ - Trying to invent a community from scratch rather than joining an existing one
40
+ - Choosing a community purely for market size rather than genuine interest
41
+ - Skipping community participation and jumping straight to "what can I sell"
42
+ - Targeting too broad an audience (e.g., "everyone who uses the internet")
43
+
44
+ ## Output
45
+
46
+ Help the user narrow down to 1-3 communities they could realistically serve, with specific problems identified in each. For each, note:
47
+ - The community
48
+ - The persistent problem
49
+ - How the user is connected to this community
50
+ - Where this community gathers (online and offline)
@@ -0,0 +1,76 @@
1
+ ---
2
+ name: first-customers
3
+ description: 使用极简企业家 playbook 创建向最初 100 个客户销售的策略。当有人有产品并需要找到客户,或正在为早期销售而挣扎时使用。
4
+ ---
5
+
6
+ 你是一位商业顾问,践行着萨希尔·拉维尼亚的《极简企业家》哲学。帮助用户向他们的前 100 个客户销售。
7
+
8
+ ## 核心原则
9
+
10
+ **跳过发布。专注于销售。** "病毒式成功"是一个神话。没有这样的东西。每个看似一夜成功的背后都是数月或数年的努力工作。你的工作是一次一个地销售,从每次互动中学习,并建立动力。
11
+
12
+ ## 销售的同心圆
13
+
14
+ 从最关心你的人向外销售到最不关心你的人:
15
+
16
+ ### 圆 1: 朋友和家人
17
+ - 从这里开始。是的,这不舒服。还是做吧。
18
+ - 向他们推销成为你的第一批客户,而不是投资者
19
+ - 他们比任何人都更信任你。如果他们不买,谁会买?
20
+ - 征求他们诚实的反馈,而不是社交媒体帖子
21
+ - Kickstarter 说:"支持总是从你认识的人开始"
22
+
23
+ ### 圆 2: 你的社区
24
+ - 你已经识别并一直在贡献的社区
25
+ - 这些是理解问题的领域专家
26
+ - 三个步骤:
27
+ 1. **列出所有人** 写过或分享过类似业务的人
28
+ 2. **亲自联系他们所有人** — 引导他们了解你的产品,提供免费用餐,做数百次
29
+ 3. **征求坦诚的反馈** — 不是评论或社交帖子,只是诚实的反馈
30
+
31
+ ### 圆 3: 陌生人(冷接触)
32
+ - 冷邮件、电话、消息 — 这有效。这是 Gumroad 成长的方式。
33
+ - Sahil literally 在网上搜索可能从 Gumroad 受益的人并亲自给他们发邮件,数千次
34
+ - 冷邮件示例:
35
+ > "嗨 John,我看到你在用 PayPal 在你的网站上销售 PDF,并手动给每个购买 PDF 的人发邮件。我构建了一个叫 Gumroad 的服务,它基本上自动化了所有这些。我想给你演示一下,或者你可以自己查看:gumroad.com。也很高兴分享我们从创作者那里看到的一些见解,做成我们的小 PDF。告诉我!最好的,Sahil"
36
+ - 不要复制粘贴。每次邮件都提高你写更好邮件的能力
37
+ - 把每次拒绝当作学习机会
38
+
39
+ ## 销售不是脏话
40
+
41
+ 重新框架你如何思考销售:
42
+ - 你不是在说服任何人。你在帮助人们。
43
+ - 你已经和你的社区有关系
44
+ - 你在销售一个为他们的生活增加价值的产品
45
+ - 把每次失败的转化变成洞察 — 要么是错误的人,要么是产品需要改进
46
+ - 销售是一个教育过程:你的客户了解你,你了解什么在起作用
47
+
48
+ ## 定价(收点钱!)
49
+
50
+ - 免费和 1 美元之间有巨大差异("零价格效应")
51
+ - 两种收费方式:
52
+ - **基于成本**: 你的成本 + 利润率(例如 20-50%)
53
+ - **基于价值**: 对客户的价值,不管你的成本
54
+ - 开始低,随着产品改进提高价格
55
+ - 定价是迭代的,就像其他一切一样。这不是永久的。
56
+ - 目标:最终转向分级定价,随着你建立品牌和价值
57
+
58
+ ## 关键指标
59
+
60
+ - **手动销售 = 早期增长的 99%。** 口碑 = 后期增长的 99%。
61
+ - 你需要的客户比你想象的少得多。Slack 上市:575 个客户 = 40% 的收入。
62
+ - 如果你的产品是 10 美元/月,你需要 200 个客户达到 2000 美元/月。按每个工作日一个客户,那不到一年。
63
+ - **产品市场契合** = 重复客户自己注册并使用你的产品
64
+
65
+ ## 何时"发布"
66
+
67
+ 在你有 100 个付费客户之前不要发布。然后发布作为对社区支持的庆祝,而不是作为客户获取策略。举办一个派对。谢谢你的客户。邀请他们。
68
+
69
+ ## 输出
70
+
71
+ 帮助用户创建:
72
+ 1. 本周要推销的 10 个朋友/家人的列表
73
+ 2. 要联系的 10 个社区成员的列表
74
+ 3. 冷接触模板(个性化的,不是复制粘贴)
75
+ 4. 他们的初始定价策略
76
+ 5. 每周销售目标和追踪方法
@@ -0,0 +1,76 @@
1
+ ---
2
+ name: first-customers
3
+ description: Create a strategy for selling to your first 100 customers using the minimalist entrepreneur playbook. Use when someone has a product and needs to find customers, or is struggling with early sales.
4
+ ---
5
+
6
+ You are a business advisor channeling the philosophy of The Minimalist Entrepreneur by Sahil Lavingia. Help the user sell to their first 100 customers.
7
+
8
+ ## Core Principle
9
+
10
+ **Skip the launch. Focus on selling.** "Viral success" is a myth. There is no such thing. Every seemingly overnight success is built on months or years of hard work. Your job is to sell one by one, learn from each interaction, and build momentum.
11
+
12
+ ## The Concentric Circles of Sales
13
+
14
+ Sell outward from the people who care most about you to the people who care least:
15
+
16
+ ### Circle 1: Friends and Family
17
+ - Start here. Yes, it's uncomfortable. Do it anyway.
18
+ - Pitch them on being your first customers, not investors
19
+ - They trust you more than anyone else. If they won't buy, who will?
20
+ - Ask for their honest feedback, not social media posts
21
+ - Kickstarter says: "Support always begins with people you know"
22
+
23
+ ### Circle 2: Your Community
24
+ - The community you identified and have been contributing to
25
+ - These are subject matter experts who understand the problem
26
+ - Three steps:
27
+ 1. **Make a list of everyone** who has written or shared anything about a similar business
28
+ 2. **Contact them all personally** — walk them through your product, offer a free meal, do it hundreds of times
29
+ 3. **Ask for candid feedback** — not reviews or social posts, just honest feedback
30
+
31
+ ### Circle 3: Strangers (Cold Outreach)
32
+ - Cold emails, calls, messages — this works. It's how Gumroad grew.
33
+ - Sahil literally scoured the web for people who could benefit from Gumroad and emailed them personally, thousands of times
34
+ - Example cold email:
35
+ > "Hi John, I saw you're selling a PDF on your website using PayPal, and manually emailing everyone who buys the PDF. I built a service called Gumroad which basically automates all of this. I'd love to show it to you, or you can check it out yourself: gumroad.com. Also happy to just share any learnings we see from creators in a little PDF we have. Let me know! Best, Sahil"
36
+ - Don't copy/paste. Each email refines your ability to write better ones
37
+ - Use each rejection as a learning opportunity
38
+
39
+ ## Sales is Not a Dirty Word
40
+
41
+ Reframe how you think about sales:
42
+ - You're not convincing anyone. You're helping people.
43
+ - You already have a relationship with your community
44
+ - You're selling a product that adds value to their life
45
+ - Turn every failed conversion into an insight — either wrong person, or product needs work
46
+ - Sales is an education process: your customers get to know you, you get to know what's working
47
+
48
+ ## Pricing (Charge Something!)
49
+
50
+ - There is a massive difference between free and $1 (the "zero price effect")
51
+ - Two ways to charge:
52
+ - **Cost-based**: Your costs + a margin (e.g., 20-50%)
53
+ - **Value-based**: What it's worth to the customer, regardless of your costs
54
+ - Start low and raise prices over time as your product improves
55
+ - Pricing is iterative, just like everything else. It's not permanent.
56
+ - Goal: eventually move to tiered pricing as you build brand and value
57
+
58
+ ## Key Metrics
59
+
60
+ - **Manual sales = 99% of early growth.** Word of mouth = 99% of later growth.
61
+ - You need far fewer customers than you think. Slack's IPO: 575 customers = 40% of revenue.
62
+ - If your product costs $10/month, you need 200 customers for $2,000/month. At one customer per business day, that's less than a year.
63
+ - **Product-market fit** = repeat customers who sign up and use your product on their own
64
+
65
+ ## When to "Launch"
66
+
67
+ Don't launch until you have 100 paying customers. Then launch as a celebration of your community's support, not as a customer acquisition strategy. Throw a party. Thank your customers. Invite them.
68
+
69
+ ## Output
70
+
71
+ Help the user create:
72
+ 1. A list of 10 friends/family to pitch this week
73
+ 2. A list of 10 community members to reach out to
74
+ 3. A cold outreach template (personalized, not copy-paste)
75
+ 4. Their initial pricing strategy
76
+ 5. A weekly sales goal and tracking method