gipity 1.0.355 → 1.0.365

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 (409) hide show
  1. package/dist/capture/sources/claude-code.js +76 -11
  2. package/dist/commands/add.js +44 -27
  3. package/dist/commands/generate.js +16 -13
  4. package/dist/commands/page-eval.js +42 -3
  5. package/dist/commands/page-inspect.js +32 -4
  6. package/dist/commands/page-screenshot.js +34 -23
  7. package/dist/commands/page-test.js +86 -0
  8. package/dist/commands/page.js +5 -3
  9. package/dist/commands/service.js +56 -0
  10. package/dist/commands/skill.js +2 -1
  11. package/dist/commands/text.js +148 -0
  12. package/dist/commands/workflow.js +10 -14
  13. package/dist/config.js +8 -1
  14. package/dist/help-skills.js +1 -0
  15. package/dist/helpers/output.js +7 -1
  16. package/dist/helpers/text-analysis.js +200 -0
  17. package/dist/hooks/capture-runner.js +32 -8
  18. package/dist/index.js +31 -2
  19. package/dist/knowledge.js +13 -3
  20. package/dist/relay/daemon.js +11 -1
  21. package/dist/relay/stream-json.js +45 -8
  22. package/dist/setup.js +18 -4
  23. package/dist/sync.js +14 -2
  24. package/package.json +8 -7
  25. package/dist/__tests__/adopt-cwd.test.d.ts +0 -1
  26. package/dist/__tests__/adopt-cwd.test.js +0 -176
  27. package/dist/__tests__/adopt-cwd.test.js.map +0 -1
  28. package/dist/__tests__/capture-transcript.test.d.ts +0 -1
  29. package/dist/__tests__/capture-transcript.test.js +0 -92
  30. package/dist/__tests__/capture-transcript.test.js.map +0 -1
  31. package/dist/__tests__/claude-noninteractive.test.d.ts +0 -1
  32. package/dist/__tests__/claude-noninteractive.test.js +0 -92
  33. package/dist/__tests__/claude-noninteractive.test.js.map +0 -1
  34. package/dist/__tests__/claude-trust.test.d.ts +0 -1
  35. package/dist/__tests__/claude-trust.test.js +0 -71
  36. package/dist/__tests__/claude-trust.test.js.map +0 -1
  37. package/dist/__tests__/cli-cmd-add.test.d.ts +0 -1
  38. package/dist/__tests__/cli-cmd-add.test.js +0 -45
  39. package/dist/__tests__/cli-cmd-add.test.js.map +0 -1
  40. package/dist/__tests__/cli-cmd-agent.test.d.ts +0 -1
  41. package/dist/__tests__/cli-cmd-agent.test.js +0 -76
  42. package/dist/__tests__/cli-cmd-agent.test.js.map +0 -1
  43. package/dist/__tests__/cli-cmd-approval.test.d.ts +0 -1
  44. package/dist/__tests__/cli-cmd-approval.test.js +0 -47
  45. package/dist/__tests__/cli-cmd-approval.test.js.map +0 -1
  46. package/dist/__tests__/cli-cmd-audit.test.d.ts +0 -1
  47. package/dist/__tests__/cli-cmd-audit.test.js +0 -33
  48. package/dist/__tests__/cli-cmd-audit.test.js.map +0 -1
  49. package/dist/__tests__/cli-cmd-chat.test.d.ts +0 -1
  50. package/dist/__tests__/cli-cmd-chat.test.js +0 -94
  51. package/dist/__tests__/cli-cmd-chat.test.js.map +0 -1
  52. package/dist/__tests__/cli-cmd-credits.test.d.ts +0 -1
  53. package/dist/__tests__/cli-cmd-credits.test.js +0 -66
  54. package/dist/__tests__/cli-cmd-credits.test.js.map +0 -1
  55. package/dist/__tests__/cli-cmd-db.test.d.ts +0 -1
  56. package/dist/__tests__/cli-cmd-db.test.js +0 -95
  57. package/dist/__tests__/cli-cmd-db.test.js.map +0 -1
  58. package/dist/__tests__/cli-cmd-deploy.test.d.ts +0 -1
  59. package/dist/__tests__/cli-cmd-deploy.test.js +0 -53
  60. package/dist/__tests__/cli-cmd-deploy.test.js.map +0 -1
  61. package/dist/__tests__/cli-cmd-domain.test.d.ts +0 -1
  62. package/dist/__tests__/cli-cmd-domain.test.js +0 -73
  63. package/dist/__tests__/cli-cmd-domain.test.js.map +0 -1
  64. package/dist/__tests__/cli-cmd-email.test.d.ts +0 -1
  65. package/dist/__tests__/cli-cmd-email.test.js +0 -31
  66. package/dist/__tests__/cli-cmd-email.test.js.map +0 -1
  67. package/dist/__tests__/cli-cmd-file.test.d.ts +0 -1
  68. package/dist/__tests__/cli-cmd-file.test.js +0 -86
  69. package/dist/__tests__/cli-cmd-file.test.js.map +0 -1
  70. package/dist/__tests__/cli-cmd-fn.test.d.ts +0 -1
  71. package/dist/__tests__/cli-cmd-fn.test.js +0 -50
  72. package/dist/__tests__/cli-cmd-fn.test.js.map +0 -1
  73. package/dist/__tests__/cli-cmd-generate.test.d.ts +0 -1
  74. package/dist/__tests__/cli-cmd-generate.test.js +0 -46
  75. package/dist/__tests__/cli-cmd-generate.test.js.map +0 -1
  76. package/dist/__tests__/cli-cmd-gmail.test.d.ts +0 -1
  77. package/dist/__tests__/cli-cmd-gmail.test.js +0 -49
  78. package/dist/__tests__/cli-cmd-gmail.test.js.map +0 -1
  79. package/dist/__tests__/cli-cmd-info.test.d.ts +0 -1
  80. package/dist/__tests__/cli-cmd-info.test.js +0 -52
  81. package/dist/__tests__/cli-cmd-info.test.js.map +0 -1
  82. package/dist/__tests__/cli-cmd-init.test.d.ts +0 -1
  83. package/dist/__tests__/cli-cmd-init.test.js +0 -76
  84. package/dist/__tests__/cli-cmd-init.test.js.map +0 -1
  85. package/dist/__tests__/cli-cmd-job.test.d.ts +0 -1
  86. package/dist/__tests__/cli-cmd-job.test.js +0 -204
  87. package/dist/__tests__/cli-cmd-job.test.js.map +0 -1
  88. package/dist/__tests__/cli-cmd-location.test.d.ts +0 -1
  89. package/dist/__tests__/cli-cmd-location.test.js +0 -58
  90. package/dist/__tests__/cli-cmd-location.test.js.map +0 -1
  91. package/dist/__tests__/cli-cmd-login.test.d.ts +0 -1
  92. package/dist/__tests__/cli-cmd-login.test.js +0 -41
  93. package/dist/__tests__/cli-cmd-login.test.js.map +0 -1
  94. package/dist/__tests__/cli-cmd-logout.test.d.ts +0 -1
  95. package/dist/__tests__/cli-cmd-logout.test.js +0 -20
  96. package/dist/__tests__/cli-cmd-logout.test.js.map +0 -1
  97. package/dist/__tests__/cli-cmd-logs.test.d.ts +0 -1
  98. package/dist/__tests__/cli-cmd-logs.test.js +0 -40
  99. package/dist/__tests__/cli-cmd-logs.test.js.map +0 -1
  100. package/dist/__tests__/cli-cmd-memory.test.d.ts +0 -1
  101. package/dist/__tests__/cli-cmd-memory.test.js +0 -58
  102. package/dist/__tests__/cli-cmd-memory.test.js.map +0 -1
  103. package/dist/__tests__/cli-cmd-page-inspect.test.d.ts +0 -1
  104. package/dist/__tests__/cli-cmd-page-inspect.test.js +0 -47
  105. package/dist/__tests__/cli-cmd-page-inspect.test.js.map +0 -1
  106. package/dist/__tests__/cli-cmd-page.test.d.ts +0 -1
  107. package/dist/__tests__/cli-cmd-page.test.js +0 -90
  108. package/dist/__tests__/cli-cmd-page.test.js.map +0 -1
  109. package/dist/__tests__/cli-cmd-plan.test.d.ts +0 -1
  110. package/dist/__tests__/cli-cmd-plan.test.js +0 -81
  111. package/dist/__tests__/cli-cmd-plan.test.js.map +0 -1
  112. package/dist/__tests__/cli-cmd-project.test.d.ts +0 -1
  113. package/dist/__tests__/cli-cmd-project.test.js +0 -61
  114. package/dist/__tests__/cli-cmd-project.test.js.map +0 -1
  115. package/dist/__tests__/cli-cmd-rbac.test.d.ts +0 -1
  116. package/dist/__tests__/cli-cmd-rbac.test.js +0 -39
  117. package/dist/__tests__/cli-cmd-rbac.test.js.map +0 -1
  118. package/dist/__tests__/cli-cmd-realtime.test.d.ts +0 -1
  119. package/dist/__tests__/cli-cmd-realtime.test.js +0 -51
  120. package/dist/__tests__/cli-cmd-realtime.test.js.map +0 -1
  121. package/dist/__tests__/cli-cmd-records.test.d.ts +0 -1
  122. package/dist/__tests__/cli-cmd-records.test.js +0 -67
  123. package/dist/__tests__/cli-cmd-records.test.js.map +0 -1
  124. package/dist/__tests__/cli-cmd-relay.test.d.ts +0 -1
  125. package/dist/__tests__/cli-cmd-relay.test.js +0 -100
  126. package/dist/__tests__/cli-cmd-relay.test.js.map +0 -1
  127. package/dist/__tests__/cli-cmd-sandbox.test.d.ts +0 -1
  128. package/dist/__tests__/cli-cmd-sandbox.test.js +0 -46
  129. package/dist/__tests__/cli-cmd-sandbox.test.js.map +0 -1
  130. package/dist/__tests__/cli-cmd-scaffold.test.d.ts +0 -1
  131. package/dist/__tests__/cli-cmd-scaffold.test.js +0 -30
  132. package/dist/__tests__/cli-cmd-scaffold.test.js.map +0 -1
  133. package/dist/__tests__/cli-cmd-skill.test.d.ts +0 -1
  134. package/dist/__tests__/cli-cmd-skill.test.js +0 -40
  135. package/dist/__tests__/cli-cmd-skill.test.js.map +0 -1
  136. package/dist/__tests__/cli-cmd-test.test.d.ts +0 -1
  137. package/dist/__tests__/cli-cmd-test.test.js +0 -58
  138. package/dist/__tests__/cli-cmd-test.test.js.map +0 -1
  139. package/dist/__tests__/cli-cmd-workflow.test.d.ts +0 -1
  140. package/dist/__tests__/cli-cmd-workflow.test.js +0 -84
  141. package/dist/__tests__/cli-cmd-workflow.test.js.map +0 -1
  142. package/dist/__tests__/cli-e2e-live.test.d.ts +0 -1
  143. package/dist/__tests__/cli-e2e-live.test.js +0 -144
  144. package/dist/__tests__/cli-e2e-live.test.js.map +0 -1
  145. package/dist/__tests__/cli-smoke.test.d.ts +0 -1
  146. package/dist/__tests__/cli-smoke.test.js +0 -69
  147. package/dist/__tests__/cli-smoke.test.js.map +0 -1
  148. package/dist/__tests__/config.test.d.ts +0 -1
  149. package/dist/__tests__/config.test.js +0 -95
  150. package/dist/__tests__/config.test.js.map +0 -1
  151. package/dist/__tests__/flag-aliases.test.d.ts +0 -1
  152. package/dist/__tests__/flag-aliases.test.js +0 -53
  153. package/dist/__tests__/flag-aliases.test.js.map +0 -1
  154. package/dist/__tests__/helpers/mock-server.d.ts +0 -52
  155. package/dist/__tests__/helpers/mock-server.js +0 -86
  156. package/dist/__tests__/helpers/mock-server.js.map +0 -1
  157. package/dist/__tests__/helpers/spawn-cli.d.ts +0 -30
  158. package/dist/__tests__/helpers/spawn-cli.js +0 -72
  159. package/dist/__tests__/helpers/spawn-cli.js.map +0 -1
  160. package/dist/__tests__/helpers/test-home.d.ts +0 -22
  161. package/dist/__tests__/helpers/test-home.js +0 -35
  162. package/dist/__tests__/helpers/test-home.js.map +0 -1
  163. package/dist/__tests__/hook-capture.test.d.ts +0 -1
  164. package/dist/__tests__/hook-capture.test.js +0 -65
  165. package/dist/__tests__/hook-capture.test.js.map +0 -1
  166. package/dist/__tests__/prompts.test.d.ts +0 -1
  167. package/dist/__tests__/prompts.test.js +0 -129
  168. package/dist/__tests__/prompts.test.js.map +0 -1
  169. package/dist/__tests__/push-cas.test.d.ts +0 -1
  170. package/dist/__tests__/push-cas.test.js +0 -133
  171. package/dist/__tests__/push-cas.test.js.map +0 -1
  172. package/dist/__tests__/relay-bridge-abort.test.d.ts +0 -1
  173. package/dist/__tests__/relay-bridge-abort.test.js +0 -65
  174. package/dist/__tests__/relay-bridge-abort.test.js.map +0 -1
  175. package/dist/__tests__/relay-daemon.test.d.ts +0 -1
  176. package/dist/__tests__/relay-daemon.test.js +0 -232
  177. package/dist/__tests__/relay-daemon.test.js.map +0 -1
  178. package/dist/__tests__/relay-ingest-contract.test.d.ts +0 -1
  179. package/dist/__tests__/relay-ingest-contract.test.js +0 -76
  180. package/dist/__tests__/relay-ingest-contract.test.js.map +0 -1
  181. package/dist/__tests__/relay-installers.test.d.ts +0 -1
  182. package/dist/__tests__/relay-installers.test.js +0 -95
  183. package/dist/__tests__/relay-installers.test.js.map +0 -1
  184. package/dist/__tests__/relay-machine-id.test.d.ts +0 -1
  185. package/dist/__tests__/relay-machine-id.test.js +0 -41
  186. package/dist/__tests__/relay-machine-id.test.js.map +0 -1
  187. package/dist/__tests__/relay-pair.test.d.ts +0 -1
  188. package/dist/__tests__/relay-pair.test.js.map +0 -1
  189. package/dist/__tests__/relay-redact.test.d.ts +0 -1
  190. package/dist/__tests__/relay-redact.test.js +0 -78
  191. package/dist/__tests__/relay-redact.test.js.map +0 -1
  192. package/dist/__tests__/relay-state.test.d.ts +0 -1
  193. package/dist/__tests__/relay-state.test.js +0 -85
  194. package/dist/__tests__/relay-state.test.js.map +0 -1
  195. package/dist/__tests__/setup-skills-block.test.d.ts +0 -1
  196. package/dist/__tests__/setup-skills-block.test.js +0 -65
  197. package/dist/__tests__/setup-skills-block.test.js.map +0 -1
  198. package/dist/__tests__/stream-json.test.d.ts +0 -1
  199. package/dist/__tests__/stream-json.test.js +0 -186
  200. package/dist/__tests__/stream-json.test.js.map +0 -1
  201. package/dist/__tests__/sync-apply.test.d.ts +0 -1
  202. package/dist/__tests__/sync-apply.test.js +0 -457
  203. package/dist/__tests__/sync-apply.test.js.map +0 -1
  204. package/dist/__tests__/sync-lock.test.d.ts +0 -1
  205. package/dist/__tests__/sync-lock.test.js +0 -105
  206. package/dist/__tests__/sync-lock.test.js.map +0 -1
  207. package/dist/__tests__/sync.test.d.ts +0 -1
  208. package/dist/__tests__/sync.test.js +0 -160
  209. package/dist/__tests__/sync.test.js.map +0 -1
  210. package/dist/__tests__/template-vars.test.d.ts +0 -1
  211. package/dist/__tests__/template-vars.test.js +0 -119
  212. package/dist/__tests__/template-vars.test.js.map +0 -1
  213. package/dist/__tests__/updater.test.d.ts +0 -1
  214. package/dist/__tests__/updater.test.js +0 -95
  215. package/dist/__tests__/updater.test.js.map +0 -1
  216. package/dist/__tests__/upload.test.d.ts +0 -1
  217. package/dist/__tests__/upload.test.js +0 -92
  218. package/dist/__tests__/upload.test.js.map +0 -1
  219. package/dist/__tests__/utils.test.d.ts +0 -1
  220. package/dist/__tests__/utils.test.js +0 -69
  221. package/dist/__tests__/utils.test.js.map +0 -1
  222. package/dist/adopt-cwd.d.ts +0 -69
  223. package/dist/adopt-cwd.js.map +0 -1
  224. package/dist/api.d.ts +0 -41
  225. package/dist/api.js.map +0 -1
  226. package/dist/auth.d.ts +0 -17
  227. package/dist/auth.js.map +0 -1
  228. package/dist/banner.d.ts +0 -6
  229. package/dist/banner.js.map +0 -1
  230. package/dist/capture/sources/claude-code.d.ts +0 -78
  231. package/dist/capture/sources/claude-code.js.map +0 -1
  232. package/dist/coding-guidelines.d.ts +0 -9
  233. package/dist/coding-guidelines.js.map +0 -1
  234. package/dist/colors.d.ts +0 -22
  235. package/dist/colors.js.map +0 -1
  236. package/dist/commands/add.d.ts +0 -2
  237. package/dist/commands/add.js.map +0 -1
  238. package/dist/commands/agent.d.ts +0 -2
  239. package/dist/commands/agent.js.map +0 -1
  240. package/dist/commands/api.d.ts +0 -1
  241. package/dist/commands/api.js.map +0 -1
  242. package/dist/commands/approval.d.ts +0 -2
  243. package/dist/commands/approval.js.map +0 -1
  244. package/dist/commands/audit.d.ts +0 -2
  245. package/dist/commands/audit.js.map +0 -1
  246. package/dist/commands/browser.d.ts +0 -2
  247. package/dist/commands/browser.js.map +0 -1
  248. package/dist/commands/chat.d.ts +0 -2
  249. package/dist/commands/chat.js.map +0 -1
  250. package/dist/commands/checkpoint.d.ts +0 -2
  251. package/dist/commands/checkpoint.js.map +0 -1
  252. package/dist/commands/claude.d.ts +0 -16
  253. package/dist/commands/claude.js.map +0 -1
  254. package/dist/commands/credits.d.ts +0 -2
  255. package/dist/commands/credits.js.map +0 -1
  256. package/dist/commands/db.d.ts +0 -2
  257. package/dist/commands/db.js.map +0 -1
  258. package/dist/commands/deploy.d.ts +0 -2
  259. package/dist/commands/deploy.js.map +0 -1
  260. package/dist/commands/doctor.d.ts +0 -2
  261. package/dist/commands/doctor.js.map +0 -1
  262. package/dist/commands/domain.d.ts +0 -2
  263. package/dist/commands/domain.js.map +0 -1
  264. package/dist/commands/email.d.ts +0 -2
  265. package/dist/commands/email.js.map +0 -1
  266. package/dist/commands/file.d.ts +0 -2
  267. package/dist/commands/file.js.map +0 -1
  268. package/dist/commands/fn.d.ts +0 -2
  269. package/dist/commands/fn.js.map +0 -1
  270. package/dist/commands/generate.d.ts +0 -2
  271. package/dist/commands/generate.js.map +0 -1
  272. package/dist/commands/gmail.d.ts +0 -2
  273. package/dist/commands/gmail.js.map +0 -1
  274. package/dist/commands/hook-capture.d.ts +0 -15
  275. package/dist/commands/hook-capture.js.map +0 -1
  276. package/dist/commands/init.d.ts +0 -2
  277. package/dist/commands/init.js.map +0 -1
  278. package/dist/commands/job.d.ts +0 -2
  279. package/dist/commands/job.js.map +0 -1
  280. package/dist/commands/location.d.ts +0 -9
  281. package/dist/commands/location.js.map +0 -1
  282. package/dist/commands/login.d.ts +0 -2
  283. package/dist/commands/login.js.map +0 -1
  284. package/dist/commands/logout.d.ts +0 -2
  285. package/dist/commands/logout.js.map +0 -1
  286. package/dist/commands/logs.d.ts +0 -2
  287. package/dist/commands/logs.js.map +0 -1
  288. package/dist/commands/memory.d.ts +0 -2
  289. package/dist/commands/memory.js.map +0 -1
  290. package/dist/commands/page-eval.d.ts +0 -2
  291. package/dist/commands/page-eval.js.map +0 -1
  292. package/dist/commands/page-inspect.d.ts +0 -2
  293. package/dist/commands/page-inspect.js.map +0 -1
  294. package/dist/commands/page-screenshot.d.ts +0 -2
  295. package/dist/commands/page-screenshot.js.map +0 -1
  296. package/dist/commands/page.d.ts +0 -2
  297. package/dist/commands/page.js.map +0 -1
  298. package/dist/commands/plan.d.ts +0 -2
  299. package/dist/commands/plan.js.map +0 -1
  300. package/dist/commands/project.d.ts +0 -2
  301. package/dist/commands/project.js.map +0 -1
  302. package/dist/commands/push.d.ts +0 -2
  303. package/dist/commands/push.js.map +0 -1
  304. package/dist/commands/rbac.d.ts +0 -2
  305. package/dist/commands/rbac.js.map +0 -1
  306. package/dist/commands/realtime.d.ts +0 -2
  307. package/dist/commands/realtime.js.map +0 -1
  308. package/dist/commands/records.d.ts +0 -2
  309. package/dist/commands/records.js.map +0 -1
  310. package/dist/commands/relay-install.d.ts +0 -11
  311. package/dist/commands/relay-install.js.map +0 -1
  312. package/dist/commands/relay.d.ts +0 -9
  313. package/dist/commands/relay.js.map +0 -1
  314. package/dist/commands/sandbox.d.ts +0 -2
  315. package/dist/commands/sandbox.js.map +0 -1
  316. package/dist/commands/scaffold.d.ts +0 -2
  317. package/dist/commands/scaffold.js.map +0 -1
  318. package/dist/commands/skill.d.ts +0 -2
  319. package/dist/commands/skill.js.map +0 -1
  320. package/dist/commands/skills.d.ts +0 -2
  321. package/dist/commands/skills.js.map +0 -1
  322. package/dist/commands/start-cc.d.ts +0 -2
  323. package/dist/commands/start-cc.js.map +0 -1
  324. package/dist/commands/status.d.ts +0 -2
  325. package/dist/commands/status.js.map +0 -1
  326. package/dist/commands/sync.d.ts +0 -2
  327. package/dist/commands/sync.js.map +0 -1
  328. package/dist/commands/test.d.ts +0 -2
  329. package/dist/commands/test.js.map +0 -1
  330. package/dist/commands/uninstall.d.ts +0 -10
  331. package/dist/commands/uninstall.js.map +0 -1
  332. package/dist/commands/update.d.ts +0 -2
  333. package/dist/commands/update.js.map +0 -1
  334. package/dist/commands/upload.d.ts +0 -2
  335. package/dist/commands/upload.js.map +0 -1
  336. package/dist/commands/workflow.d.ts +0 -2
  337. package/dist/commands/workflow.js.map +0 -1
  338. package/dist/config.d.ts +0 -39
  339. package/dist/config.js.map +0 -1
  340. package/dist/flag-aliases.d.ts +0 -17
  341. package/dist/flag-aliases.js.map +0 -1
  342. package/dist/gip3dw-guide.d.ts +0 -7
  343. package/dist/gip3dw-guide.js.map +0 -1
  344. package/dist/gipcc.d.ts +0 -2
  345. package/dist/gipcc.js.map +0 -1
  346. package/dist/gipccd.d.ts +0 -2
  347. package/dist/gipccd.js.map +0 -1
  348. package/dist/help-skills.d.ts +0 -7
  349. package/dist/help-skills.js.map +0 -1
  350. package/dist/helpers/command.d.ts +0 -12
  351. package/dist/helpers/command.js.map +0 -1
  352. package/dist/helpers/index.d.ts +0 -6
  353. package/dist/helpers/index.js.map +0 -1
  354. package/dist/helpers/output.d.ts +0 -22
  355. package/dist/helpers/output.js.map +0 -1
  356. package/dist/helpers/sync.d.ts +0 -13
  357. package/dist/helpers/sync.js.map +0 -1
  358. package/dist/hooks/capture-runner.d.ts +0 -24
  359. package/dist/hooks/capture-runner.js.map +0 -1
  360. package/dist/index.d.ts +0 -2
  361. package/dist/index.js.map +0 -1
  362. package/dist/knowledge.d.ts +0 -11
  363. package/dist/knowledge.js.map +0 -1
  364. package/dist/platform-overview.d.ts +0 -9
  365. package/dist/platform-overview.js.map +0 -1
  366. package/dist/project-setup.d.ts +0 -29
  367. package/dist/project-setup.js.map +0 -1
  368. package/dist/prompts.d.ts +0 -80
  369. package/dist/prompts.js.map +0 -1
  370. package/dist/provider-docs.d.ts +0 -27
  371. package/dist/provider-docs.js.map +0 -1
  372. package/dist/relay/daemon.d.ts +0 -47
  373. package/dist/relay/daemon.js.map +0 -1
  374. package/dist/relay/device-http.d.ts +0 -9
  375. package/dist/relay/device-http.js.map +0 -1
  376. package/dist/relay/installers.d.ts +0 -24
  377. package/dist/relay/installers.js.map +0 -1
  378. package/dist/relay/machine-id.d.ts +0 -2
  379. package/dist/relay/machine-id.js.map +0 -1
  380. package/dist/relay/onboarding.d.ts +0 -8
  381. package/dist/relay/onboarding.js.map +0 -1
  382. package/dist/relay/paths.d.ts +0 -5
  383. package/dist/relay/paths.js.map +0 -1
  384. package/dist/relay/redact.d.ts +0 -34
  385. package/dist/relay/redact.js.map +0 -1
  386. package/dist/relay/state.d.ts +0 -39
  387. package/dist/relay/state.js.map +0 -1
  388. package/dist/relay/stream-json.d.ts +0 -105
  389. package/dist/relay/stream-json.js.map +0 -1
  390. package/dist/relay/transcripts.d.ts +0 -60
  391. package/dist/relay/transcripts.js.map +0 -1
  392. package/dist/setup.d.ts +0 -101
  393. package/dist/setup.js.map +0 -1
  394. package/dist/sync.d.ts +0 -74
  395. package/dist/sync.js.map +0 -1
  396. package/dist/template-vars.d.ts +0 -32
  397. package/dist/template-vars.js.map +0 -1
  398. package/dist/updater/bootstrap.d.ts +0 -13
  399. package/dist/updater/bootstrap.js.map +0 -1
  400. package/dist/updater/check.d.ts +0 -12
  401. package/dist/updater/check.js.map +0 -1
  402. package/dist/updater/shim.d.ts +0 -2
  403. package/dist/updater/shim.js.map +0 -1
  404. package/dist/updater/state.d.ts +0 -24
  405. package/dist/updater/state.js.map +0 -1
  406. package/dist/upload.d.ts +0 -40
  407. package/dist/upload.js.map +0 -1
  408. package/dist/utils.d.ts +0 -39
  409. package/dist/utils.js.map +0 -1
@@ -0,0 +1,86 @@
1
+ import { Command } from 'commander';
2
+ import { post } from '../api.js';
3
+ import { brand, bold, muted, warning, success, error as clrError } from '../colors.js';
4
+ import { run } from '../helpers/index.js';
5
+ // Lines worth surfacing - genuine errors and crash signatures, not benign warnings.
6
+ const BAD = /^error:|uncaught|unhandled|message handler error|\bcrash|RuntimeError/i;
7
+ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
8
+ /** Run one passive page load via the inspect endpoint and return its console. */
9
+ async function inspectClient(url, waitMs, i) {
10
+ try {
11
+ const res = await post('/tools/browser/inspect', { url, waitMs });
12
+ return { i, lines: res.data.console ?? [] };
13
+ }
14
+ catch (err) {
15
+ return { i, lines: [], error: err instanceof Error ? err.message : String(err) };
16
+ }
17
+ }
18
+ // Headless multi-client realtime check: spin N staggered browser clients at a
19
+ // deployed URL and flag error/crash lines across their consoles. The verifier
20
+ // for realtime apps (host election, presence, world sync, reconnection) -
21
+ // promotes the internal multi-client-test script to a first-class command.
22
+ //
23
+ // Passive page loads only: each client just loads the URL and settles. An app
24
+ // that connects to realtime only after a user action (e.g. a lobby that joins
25
+ // on a button press) needs a URL-param test mode so the load alone exercises
26
+ // the path - see the app-realtime skill.
27
+ export const pageTestCommand = new Command('test')
28
+ .description('Multi-client realtime check: load a URL in N staggered headless clients, flag console errors')
29
+ .argument('<url>', 'Deployed URL to load in every client')
30
+ .option('--clients <n>', 'Number of headless clients to launch', '2')
31
+ .option('--stagger <s>', 'Seconds between client starts (client 0 settles first, e.g. as host)', '12')
32
+ .option('--wait <ms>', 'Milliseconds each client stays open after load (max 30000)', '24000')
33
+ .option('--json', 'Output as JSON')
34
+ .action((url, opts) => run('Page test', async () => {
35
+ const clients = Math.max(1, parseInt(opts.clients, 10) || 2);
36
+ const stagger = Math.max(0, parseInt(opts.stagger, 10) || 0);
37
+ const wait = Math.min(30000, Math.max(2000, parseInt(opts.wait, 10) || 24000));
38
+ if (!opts.json) {
39
+ console.log(`\n${brand('Page test')} ${bold(url)}`);
40
+ console.log(` ${muted(`${clients} client(s), stagger ${stagger}s, ${wait}ms open each`)}\n`);
41
+ }
42
+ const runs = [];
43
+ for (let i = 0; i < clients; i++) {
44
+ runs.push((async () => {
45
+ await sleep(i * stagger * 1000);
46
+ if (!opts.json)
47
+ console.log(` ${muted(`client ${i}${i === 0 ? ' (first)' : ''} starting`)}`);
48
+ return inspectClient(url, wait, i);
49
+ })());
50
+ }
51
+ const results = (await Promise.all(runs)).sort((a, b) => a.i - b.i);
52
+ let problems = 0;
53
+ for (const r of results) {
54
+ if (r.error)
55
+ problems++;
56
+ else
57
+ problems += r.lines.filter((l) => BAD.test(l)).length;
58
+ }
59
+ if (opts.json) {
60
+ console.log(JSON.stringify({ url, clients, stagger, wait, problems, results }));
61
+ if (problems > 0)
62
+ process.exitCode = 1;
63
+ return;
64
+ }
65
+ for (const r of results) {
66
+ console.log(`\n${bold(`=== client ${r.i}${r.i === 0 ? ' (first)' : ''} ===`)}`);
67
+ if (r.error) {
68
+ console.log(` ${clrError(`page inspect failed: ${r.error}`)}`);
69
+ continue;
70
+ }
71
+ if (r.lines.length === 0) {
72
+ console.log(` ${muted('(no console output)')}`);
73
+ continue;
74
+ }
75
+ for (const line of r.lines) {
76
+ const bad = BAD.test(line);
77
+ console.log(` ${bad ? warning('⚠ ' + line) : ' ' + line}`);
78
+ }
79
+ }
80
+ console.log(problems === 0
81
+ ? `\n${success('✓ no error/crash lines across all clients')}\n`
82
+ : `\n${clrError(`⚠ ${problems} error/crash line(s) flagged above`)}\n`);
83
+ if (problems > 0)
84
+ process.exitCode = 1;
85
+ }));
86
+ //# sourceMappingURL=page-test.js.map
@@ -2,15 +2,17 @@ import { Command } from 'commander';
2
2
  import { pageInspectCommand } from './page-inspect.js';
3
3
  import { pageScreenshotCommand } from './page-screenshot.js';
4
4
  import { pageEvalCommand } from './page-eval.js';
5
+ import { pageTestCommand } from './page-test.js';
5
6
  // Parent namespace grouping the page/browser diagnostics under one command:
6
- // gipity page inspect | eval | screenshot
7
+ // gipity page inspect | eval | screenshot | test
7
8
  // Each subcommand is canonical for its capability; the namespace keeps the
8
9
  // top-level surface lean and makes the siblings discoverable via `page --help`.
9
10
  export const pageCommand = new Command('page')
10
- .description('Inspect, evaluate, and screenshot web pages (page inspect | eval | screenshot)')
11
+ .description('Inspect, evaluate, screenshot, and multi-client test web pages (page inspect | eval | screenshot | test)')
11
12
  .addCommand(pageInspectCommand)
12
13
  .addCommand(pageEvalCommand)
13
- .addCommand(pageScreenshotCommand);
14
+ .addCommand(pageScreenshotCommand)
15
+ .addCommand(pageTestCommand);
14
16
  // No subcommand → show help instead of commander's terse error.
15
17
  pageCommand.action(() => {
16
18
  pageCommand.help();
@@ -0,0 +1,56 @@
1
+ import { Command } from 'commander';
2
+ import { get, post } from '../api.js';
3
+ import { requireConfig } from '../config.js';
4
+ import { bold, muted } from '../colors.js';
5
+ import { run } from '../helpers/index.js';
6
+ /** Known app-service endpoints, shown by `gipity service list` and used to
7
+ * give a helpful hint on typos. POST endpoints take a JSON body; GET
8
+ * endpoints (model/voice listings) are reached with `--get`. */
9
+ const SERVICES = [
10
+ { name: 'llm', method: 'POST', desc: 'Chat completion ({ prompt | messages, model?, ... })' },
11
+ { name: 'llm/models', method: 'GET', desc: 'List available LLM models' },
12
+ { name: 'image', method: 'POST', desc: 'Generate an image ({ prompt, provider?, size? })' },
13
+ { name: 'image/models', method: 'GET', desc: 'List image providers/models' },
14
+ { name: 'tts', method: 'POST', desc: 'Text-to-speech ({ text, voice?, ... })' },
15
+ { name: 'tts/voices', method: 'GET', desc: 'List TTS voices' },
16
+ { name: 'sound', method: 'POST', desc: 'Sound effect ({ prompt, duration_seconds? })' },
17
+ { name: 'music', method: 'POST', desc: 'Music generation ({ prompt, duration_seconds? })' },
18
+ { name: 'video', method: 'POST', desc: 'Video generation ({ prompt, ... })' },
19
+ { name: 'location/ip', method: 'POST', desc: 'IP geolocation ({ ip? })' },
20
+ { name: 'location/geocode', method: 'POST', desc: 'Reverse geocode ({ lat, lon })' },
21
+ ];
22
+ export const serviceCommand = new Command('service')
23
+ .description('Call a Gipity app service (LLM, image, music, TTS, ...)');
24
+ serviceCommand
25
+ .command('list')
26
+ .description('List callable app services')
27
+ .action(() => run('Services', async () => {
28
+ requireConfig();
29
+ const width = SERVICES.reduce((m, s) => Math.max(m, s.name.length), 0);
30
+ console.log('');
31
+ console.log('Call one with `gipity service call <name> \'{"json":"body"}\'`');
32
+ console.log(muted('(GET endpoints like llm/models, tts/voices take --get and no body)'));
33
+ console.log('');
34
+ for (const s of SERVICES) {
35
+ console.log(` ${bold(s.name.padEnd(width))} ${muted(`[${s.method}] ${s.desc}`)}`);
36
+ }
37
+ console.log('');
38
+ }));
39
+ serviceCommand
40
+ .command('call <name> [body]')
41
+ .description('Call an app service by name (e.g. llm, image, music). Uses your logged-in session - no token wrangling.')
42
+ .option('--data <json>', 'JSON request body (alternative to the positional [body])')
43
+ .option('--get', 'Issue a GET (for listing endpoints like llm/models, tts/voices)')
44
+ .option('--json', 'Output compact JSON')
45
+ .action((name, bodyArg, opts) => run('Call', async () => {
46
+ const config = requireConfig();
47
+ // Encode each path segment but preserve the `/` separators so subpaths
48
+ // like `location/geocode` and `llm/models` resolve correctly.
49
+ const path = name.split('/').map(encodeURIComponent).join('/');
50
+ const url = `/api/${config.projectGuid}/services/${path}`;
51
+ const res = opts.get
52
+ ? await get(url)
53
+ : await post(url, JSON.parse(bodyArg || opts.data || '{}'));
54
+ console.log(opts.json ? JSON.stringify(res) : JSON.stringify(res, null, 2));
55
+ }));
56
+ //# sourceMappingURL=service.js.map
@@ -16,7 +16,8 @@ skillCommand
16
16
  process.exit(1);
17
17
  }
18
18
  const res = await get(`/skills?agent=${config.agentGuid}`);
19
- printList(res.data, opts, 'No skills available.', s => `${bold(s.name)} ${muted(s.description)}`);
19
+ const width = res.data.reduce((m, s) => Math.max(m, s.name.length), 0);
20
+ printList(res.data, opts, 'No skills available.', s => ` ${bold(s.name.padEnd(width))} ${muted(s.description)}`, 'Read one with `gipity skill read <name>`:');
20
21
  }));
21
22
  skillCommand
22
23
  .command('read <name>')
@@ -0,0 +1,148 @@
1
+ import { Command } from 'commander';
2
+ import { readFileSync } from 'fs';
3
+ import { run } from '../helpers/command.js';
4
+ import { error as clrError, bold, dim, brand } from '../colors.js';
5
+ import { analyzeText, countOccurrences, findPositions, nthWord, nthChar, areAnagrams, } from '../helpers/text-analysis.js';
6
+ /** Read text from --file, a positional arg, or stdin (in that precedence). */
7
+ function resolveInput(args, opts) {
8
+ if (opts.file)
9
+ return readFileSync(opts.file, 'utf-8');
10
+ if (args.length)
11
+ return args.join(' ');
12
+ // No arg → read stdin (supports `echo … | gipity text analyze`).
13
+ try {
14
+ return readFileSync(0, 'utf-8');
15
+ }
16
+ catch {
17
+ return '';
18
+ }
19
+ }
20
+ function formatProfile(a) {
21
+ const L = [];
22
+ const row = (label, val) => L.push(` ${label.padEnd(22)}${val}`);
23
+ L.push(bold('Counts'));
24
+ row('Characters', a.characters);
25
+ row('Chars (no spaces)', a.charactersNoSpaces);
26
+ row('Chars (no whitespace)', a.charactersNoWhitespace);
27
+ row('Letters', a.letters);
28
+ row(' Uppercase', a.uppercase);
29
+ row(' Lowercase', a.lowercase);
30
+ row(' Vowels (a-z)', a.vowels);
31
+ row(' Consonants (a-z)', a.consonants);
32
+ row('Digits', a.digits);
33
+ row('Punctuation/symbols', a.punctuation);
34
+ row('Whitespace', a.whitespace);
35
+ row('Spaces', a.spaces);
36
+ if (a.other)
37
+ row('Other', a.other);
38
+ L.push('');
39
+ L.push(bold('Words & structure'));
40
+ row('Words', a.words);
41
+ row('Unique words', a.uniqueWords);
42
+ row('Sentences', a.sentences);
43
+ row('Lines', a.lines);
44
+ row('Paragraphs', a.paragraphs);
45
+ if (a.words) {
46
+ row('Longest word', `${a.longestWord} (${[...a.longestWord].length})`);
47
+ row('Shortest word', `${a.shortestWord} (${[...a.shortestWord].length})`);
48
+ row('Avg word length', a.averageWordLength);
49
+ }
50
+ L.push('');
51
+ L.push(bold('Letter frequency') + dim(' (a–z, case-insensitive)'));
52
+ if (a.letterFrequency.length) {
53
+ const freq = a.letterFrequency
54
+ .map((f) => `${f.letter}:${f.count}`)
55
+ .join(' ');
56
+ L.push(` ${freq}`);
57
+ }
58
+ else {
59
+ L.push(dim(' (no letters)'));
60
+ }
61
+ if (a.wordFrequency.length) {
62
+ L.push('');
63
+ L.push(bold('Top words'));
64
+ L.push(' ' + a.wordFrequency.map((w) => `${w.word}:${w.count}`).join(' '));
65
+ }
66
+ L.push('');
67
+ L.push(bold('Other'));
68
+ row('Reversed', a.reversed);
69
+ row('Palindrome', a.isPalindrome ? 'yes' : 'no');
70
+ return L.join('\n');
71
+ }
72
+ const analyzeCommand = new Command('analyze')
73
+ .description('Deterministic character/word analysis of text (local, no network)')
74
+ .argument('[text...]', 'Text to analyze (or pipe via stdin, or use --file)')
75
+ .option('--file <path>', 'Read text from a file')
76
+ .option('--count <substring>', 'Count occurrences of a substring')
77
+ .option('--find <substring>', 'List 1-indexed positions of a substring')
78
+ .option('--word <n>', 'Return the Nth word (negative counts from the end)', (v) => parseInt(v, 10))
79
+ .option('--char <n>', 'Return the Nth character (negative counts from the end)', (v) => parseInt(v, 10))
80
+ .option('--anagram <other>', 'Check whether the text is an anagram of <other>')
81
+ .option('--whole-word', 'Match whole words only (for --count)')
82
+ .option('--case-sensitive', 'Make --count / --find case-sensitive')
83
+ .option('--json', 'Output as JSON')
84
+ .action((args, opts) => run('Text analyze', async () => {
85
+ const text = resolveInput(args, opts);
86
+ if (text === '' && !opts.file) {
87
+ console.error(clrError('No text. Pass it as an argument, pipe via stdin, or use --file.'));
88
+ process.exit(1);
89
+ }
90
+ // Targeted queries short-circuit the full profile.
91
+ if (opts.count !== undefined) {
92
+ const r = countOccurrences(text, opts.count, !!opts.caseSensitive, !!opts.wholeWord);
93
+ if (opts.json)
94
+ return void console.log(JSON.stringify(r));
95
+ const mode = [
96
+ r.caseSensitive ? 'case-sensitive' : 'case-insensitive',
97
+ r.wholeWord ? 'whole-word' : null,
98
+ ].filter(Boolean).join(', ');
99
+ const counts = r.wholeWord
100
+ ? `${r.nonOverlapping}`
101
+ : `${r.nonOverlapping} non-overlapping, ${r.overlapping} overlapping`;
102
+ console.log(` "${r.needle}" (${mode}): ${counts}`);
103
+ return;
104
+ }
105
+ if (opts.find !== undefined) {
106
+ const positions = findPositions(text, opts.find, !!opts.caseSensitive);
107
+ if (opts.json)
108
+ return void console.log(JSON.stringify({ needle: opts.find, positions }));
109
+ console.log(positions.length
110
+ ? ` "${opts.find}" at: ${positions.join(', ')}`
111
+ : dim(` "${opts.find}" not found`));
112
+ return;
113
+ }
114
+ if (opts.anagram !== undefined) {
115
+ const r = areAnagrams(text, opts.anagram);
116
+ if (opts.json)
117
+ return void console.log(JSON.stringify(r));
118
+ console.log(` ${r.isAnagram ? 'yes' : 'no'} - anagram of "${opts.anagram}"`);
119
+ return;
120
+ }
121
+ if (opts.word !== undefined) {
122
+ const w = nthWord(text, opts.word);
123
+ if (opts.json)
124
+ return void console.log(JSON.stringify({ word: w, n: opts.word }));
125
+ console.log(w === null ? dim(' (out of range)') : ` ${w}`);
126
+ return;
127
+ }
128
+ if (opts.char !== undefined) {
129
+ const c = nthChar(text, opts.char);
130
+ if (opts.json)
131
+ return void console.log(JSON.stringify({ char: c, n: opts.char }));
132
+ console.log(c === null ? dim(' (out of range)') : ` ${c}`);
133
+ return;
134
+ }
135
+ const analysis = analyzeText(text);
136
+ if (opts.json)
137
+ return void console.log(JSON.stringify(analysis));
138
+ console.log(formatProfile(analysis));
139
+ }));
140
+ // Parent namespace. One capability today (analyze); namespaced for a lean
141
+ // top-level surface and room for future text operations.
142
+ export const textCommand = new Command('text')
143
+ .description(`Deterministic text analysis - char/word counts, frequency, occurrences (${brand('text analyze')})`)
144
+ .addCommand(analyzeCommand);
145
+ textCommand.action(() => {
146
+ textCommand.help();
147
+ });
148
+ //# sourceMappingURL=text.js.map
@@ -158,24 +158,20 @@ workflowCommand
158
158
  printResult(`Deleted "${wf.name}".`, opts, { deleted: wf.name, short_guid: wf.short_guid });
159
159
  }));
160
160
  // Resolve a workflow by name within the linked project (like `gipity fn`), or
161
- // by short_guid anywhere. Names are unique per active project workflow (DB
162
- // constraint), so a bare name in this project is unambiguous; the same name in
163
- // another project is a different workflow and simply isn't matched here.
161
+ // by short_guid anywhere. Uses the single account-wide `/workflows` list (the
162
+ // same endpoint the bare `workflow` list hits) so the whole command stays on
163
+ // one route tree. Names are unique per active project workflow (DB constraint),
164
+ // so we scope by the current project's slug; a short_guid resolves anywhere.
164
165
  async function resolveWorkflow(name) {
165
- const { projectGuid } = requireConfig();
166
- const res = await get(`/projects/${projectGuid}/workflows`);
167
- const list = res.data ?? [];
168
- // Exact short_guid match wins — unambiguous override.
169
- const byGuid = list.find(w => w.short_guid === name);
166
+ const { projectSlug } = requireConfig();
167
+ const res = await get('/workflows');
168
+ const all = res.data ?? [];
169
+ // Exact short_guid match wins anywhere — unambiguous override.
170
+ const byGuid = all.find(w => w.short_guid === name);
170
171
  if (byGuid)
171
172
  return byGuid;
172
- const byName = list.filter(w => w.name === name);
173
+ const byName = all.filter(w => w.project_slug === projectSlug && w.name === name);
173
174
  if (byName.length === 0) {
174
- // Fall back to a global short_guid lookup (e.g. account-level workflows).
175
- const all = await get('/workflows');
176
- const global = (all.data ?? []).find(w => w.short_guid === name);
177
- if (global)
178
- return global;
179
175
  console.error(clrError(`Workflow "${name}" not found in this project.`));
180
176
  process.exit(1);
181
177
  }
package/dist/config.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { readFileSync, writeFileSync, existsSync } from 'fs';
2
- import { resolve } from 'path';
2
+ import { dirname, resolve } from 'path';
3
3
  const CONFIG_FILE = '.gipity.json';
4
4
  let cached = null;
5
5
  let cachedPath = null;
@@ -30,6 +30,13 @@ export function getConfigPath() {
30
30
  cachedPath = findConfigPath();
31
31
  return cachedPath;
32
32
  }
33
+ /** Directory holding the project's `.gipity.json` (the project root), found by
34
+ * walking up from cwd. Returns null when there's no linked project in the tree
35
+ * (e.g. one-off mode), in which case callers should anchor to cwd. */
36
+ export function getProjectRoot() {
37
+ const path = getConfigPath();
38
+ return path ? dirname(path) : null;
39
+ }
33
40
  export function getConfig() {
34
41
  if (cached)
35
42
  return cached;
@@ -5,6 +5,7 @@ import { muted } from './colors.js';
5
5
  export const HELP_SKILL_MAP = {
6
6
  fn: 'app-development',
7
7
  db: 'app-development',
8
+ text: 'text-analysis',
8
9
  };
9
10
  /**
10
11
  * Fetch a skill by name from the server and print its content.
@@ -28,7 +28,7 @@ export function printResult(text, opts, jsonData) {
28
28
  * Print a list with JSON mode, empty state, and per-item formatting.
29
29
  * Replaces the most common output pattern across all commands.
30
30
  */
31
- export function printList(data, opts, emptyMsg, formatter) {
31
+ export function printList(data, opts, emptyMsg, formatter, header) {
32
32
  if (opts.json) {
33
33
  console.log(JSON.stringify(data));
34
34
  return;
@@ -38,6 +38,12 @@ export function printList(data, opts, emptyMsg, formatter) {
38
38
  console.log(emptyMsg);
39
39
  }
40
40
  else {
41
+ // A `header` is a one-line lead-in (e.g. "Read one with `gipity skill
42
+ // read <name>`:") that tells the reader what the listed names are for.
43
+ if (header) {
44
+ console.log(header);
45
+ console.log('');
46
+ }
41
47
  for (const item of data) {
42
48
  console.log(formatter(item));
43
49
  }
@@ -0,0 +1,200 @@
1
+ /**
2
+ * text-analysis.ts - Pure, deterministic text analysis.
3
+ *
4
+ * MIRRORED from platform/packages/shared/src/text-analysis.ts. The CLI ships
5
+ * standalone (it does not depend on @easyclaw/shared), so this is a hand copy
6
+ * of the canonical logic - same pattern as the TEMPLATES/KITS catalog mirror
7
+ * in add.ts / prompts.ts. The drift guard in cli-cmd-text.test.ts asserts the
8
+ * body below stays byte-identical to the shared source (the source of truth).
9
+ *
10
+ * Everything operates on Unicode code points (via `[...text]`) so multi-byte
11
+ * characters count as one, and the category counts always sum to the total.
12
+ */
13
+ /** How many top entries the word-frequency list keeps. */
14
+ export const WORD_FREQUENCY_TOP = 10;
15
+ const VOWELS = new Set(['a', 'e', 'i', 'o', 'u']);
16
+ /** Split into Unicode code points (so emoji / accented chars count as one). */
17
+ function chars(text) {
18
+ return [...text];
19
+ }
20
+ /** Whitespace-separated tokens, empties dropped. */
21
+ function tokenize(text) {
22
+ return text.split(/\s+/).filter(Boolean);
23
+ }
24
+ /** Strip leading/trailing punctuation/symbols from a token for word identity. */
25
+ function trimWordPunct(token) {
26
+ return token.replace(/^[\p{P}\p{S}]+|[\p{P}\p{S}]+$/gu, '');
27
+ }
28
+ /** Normalize to lowercase alphanumerics only (for palindrome / anagram). */
29
+ function alnumLower(text) {
30
+ return chars(text)
31
+ .filter((ch) => /[\p{L}\p{N}]/u.test(ch))
32
+ .map((ch) => ch.toLowerCase());
33
+ }
34
+ export function analyzeText(text) {
35
+ const cps = chars(text);
36
+ let letters = 0;
37
+ let uppercase = 0;
38
+ let lowercase = 0;
39
+ let vowels = 0;
40
+ let consonants = 0;
41
+ let digits = 0;
42
+ let punctuation = 0;
43
+ let whitespace = 0;
44
+ let spaces = 0;
45
+ let other = 0;
46
+ const freq = new Map();
47
+ for (const ch of cps) {
48
+ if (/\s/u.test(ch)) {
49
+ whitespace++;
50
+ if (ch === ' ')
51
+ spaces++;
52
+ }
53
+ else if (/\p{L}/u.test(ch)) {
54
+ letters++;
55
+ if (/\p{Lu}/u.test(ch))
56
+ uppercase++;
57
+ else if (/\p{Ll}/u.test(ch))
58
+ lowercase++;
59
+ if (/[a-z]/i.test(ch)) {
60
+ const lower = ch.toLowerCase();
61
+ freq.set(lower, (freq.get(lower) ?? 0) + 1);
62
+ if (VOWELS.has(lower))
63
+ vowels++;
64
+ else
65
+ consonants++;
66
+ }
67
+ }
68
+ else if (/\p{Nd}/u.test(ch)) {
69
+ digits++;
70
+ }
71
+ else if (/[\p{P}\p{S}]/u.test(ch)) {
72
+ punctuation++;
73
+ }
74
+ else {
75
+ other++;
76
+ }
77
+ }
78
+ const tokens = tokenize(text);
79
+ const lengths = tokens.map((t) => chars(t).length);
80
+ const cleaned = tokens.map((t) => trimWordPunct(t).toLowerCase()).filter(Boolean);
81
+ const uniq = new Set(cleaned);
82
+ const wordFreqMap = new Map();
83
+ for (const w of cleaned)
84
+ wordFreqMap.set(w, (wordFreqMap.get(w) ?? 0) + 1);
85
+ const wordFrequency = [...wordFreqMap.entries()]
86
+ .map(([word, count]) => ({ word, count }))
87
+ .sort((a, b) => b.count - a.count || a.word.localeCompare(b.word))
88
+ .slice(0, WORD_FREQUENCY_TOP);
89
+ const sentences = (text.match(/[.!?]+(?=\s|$)/gu) ?? []).length;
90
+ const lines = text === '' ? 0 : text.split('\n').length;
91
+ const paragraphs = text.split(/\n\s*\n/).map((p) => p.trim()).filter(Boolean).length;
92
+ const longestWord = tokens.reduce((a, b) => (chars(b).length > chars(a).length ? b : a), '');
93
+ const shortestWord = tokens.length
94
+ ? tokens.reduce((a, b) => (chars(b).length < chars(a).length ? b : a))
95
+ : '';
96
+ const averageWordLength = lengths.length
97
+ ? Math.round((lengths.reduce((a, b) => a + b, 0) / lengths.length) * 10) / 10
98
+ : 0;
99
+ const letterFrequency = [...freq.entries()]
100
+ .map(([letter, count]) => ({ letter, count }))
101
+ .sort((a, b) => b.count - a.count || a.letter.localeCompare(b.letter));
102
+ const reversed = cps.slice().reverse().join('');
103
+ const normalized = alnumLower(text);
104
+ const isPalindrome = normalized.length > 0 &&
105
+ normalized.join('') === normalized.slice().reverse().join('');
106
+ return {
107
+ characters: cps.length,
108
+ charactersNoSpaces: cps.length - spaces,
109
+ charactersNoWhitespace: cps.length - whitespace,
110
+ letters,
111
+ uppercase,
112
+ lowercase,
113
+ vowels,
114
+ consonants,
115
+ digits,
116
+ punctuation,
117
+ whitespace,
118
+ spaces,
119
+ other,
120
+ words: tokens.length,
121
+ uniqueWords: uniq.size,
122
+ sentences,
123
+ lines,
124
+ paragraphs,
125
+ longestWord,
126
+ shortestWord,
127
+ averageWordLength,
128
+ letterFrequency,
129
+ wordFrequency,
130
+ reversed,
131
+ isPalindrome,
132
+ };
133
+ }
134
+ function escapeRegExp(s) {
135
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
136
+ }
137
+ /**
138
+ * Count occurrences of a substring.
139
+ * - Default: both overlapping and non-overlapping counts (they differ for
140
+ * self-overlapping needles like "aa").
141
+ * - wholeWord: count only whole-word matches (\b boundaries); overlapping and
142
+ * non-overlapping are equal in that mode.
143
+ */
144
+ export function countOccurrences(text, needle, caseSensitive = false, wholeWord = false) {
145
+ if (needle === '') {
146
+ return { needle, caseSensitive, wholeWord, overlapping: 0, nonOverlapping: 0 };
147
+ }
148
+ if (wholeWord) {
149
+ const flags = caseSensitive ? 'gu' : 'giu';
150
+ const re = new RegExp(`\\b${escapeRegExp(needle)}\\b`, flags);
151
+ const n = (text.match(re) ?? []).length;
152
+ return { needle, caseSensitive, wholeWord, overlapping: n, nonOverlapping: n };
153
+ }
154
+ const hay = caseSensitive ? text : text.toLowerCase();
155
+ const sub = caseSensitive ? needle : needle.toLowerCase();
156
+ let overlapping = 0;
157
+ for (let i = hay.indexOf(sub); i !== -1; i = hay.indexOf(sub, i + 1))
158
+ overlapping++;
159
+ let nonOverlapping = 0;
160
+ for (let i = hay.indexOf(sub); i !== -1; i = hay.indexOf(sub, i + sub.length))
161
+ nonOverlapping++;
162
+ return { needle, caseSensitive, wholeWord, overlapping, nonOverlapping };
163
+ }
164
+ /** 1-indexed code-point positions where a substring starts (overlapping). */
165
+ export function findPositions(text, needle, caseSensitive = false) {
166
+ if (needle === '')
167
+ return [];
168
+ const hay = caseSensitive ? text : text.toLowerCase();
169
+ const sub = caseSensitive ? needle : needle.toLowerCase();
170
+ const positions = [];
171
+ for (let i = hay.indexOf(sub); i !== -1; i = hay.indexOf(sub, i + 1)) {
172
+ // Convert UTF-16 index to 1-indexed code-point position.
173
+ positions.push([...hay.slice(0, i)].length + 1);
174
+ }
175
+ return positions;
176
+ }
177
+ /** Resolve a 1-indexed position, supporting negatives (-1 = last). */
178
+ function resolveIndex(n, len) {
179
+ const idx = n < 0 ? len + n + 1 : n;
180
+ return idx >= 1 && idx <= len ? idx : null;
181
+ }
182
+ /** Nth word (whitespace-separated), 1-indexed; negative counts from the end. */
183
+ export function nthWord(text, n) {
184
+ const tokens = tokenize(text);
185
+ const idx = resolveIndex(n, tokens.length);
186
+ return idx === null ? null : tokens[idx - 1];
187
+ }
188
+ /** Nth character (code point), 1-indexed; negative counts from the end. */
189
+ export function nthChar(text, n) {
190
+ const cps = chars(text);
191
+ const idx = resolveIndex(n, cps.length);
192
+ return idx === null ? null : cps[idx - 1];
193
+ }
194
+ /** Are two strings anagrams? Ignores case, spaces, and punctuation. */
195
+ export function areAnagrams(a, b) {
196
+ const na = alnumLower(a).sort().join('');
197
+ const nb = alnumLower(b).sort().join('');
198
+ return { isAnagram: na.length > 0 && na === nb, normalizedA: na, normalizedB: nb };
199
+ }
200
+ //# sourceMappingURL=text-analysis.js.map