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
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
3
  * Internal hook runner - invoked by Claude Code's lifecycle hooks
4
- * (SessionStart, Stop, SubagentStop, SessionEnd) to mirror a terminal
5
- * `gipity claude` session into the Gipity server so the web CLI can
6
- * display it read-only.
4
+ * (SessionStart, Stop, SubagentStop, SessionEnd, and a throttled
5
+ * PostToolUse for mid-run flushing) to mirror a terminal `gipity claude`
6
+ * session into the Gipity server so the web CLI can display it read-only.
7
7
  *
8
8
  * Not a user-facing `gipity` subcommand by design: users never invoke
9
9
  * this directly. `setupClaudeHooks` wires up hook entries that call
@@ -12,7 +12,7 @@
12
12
  * Usage:
13
13
  * node capture-runner.js <source> <event>
14
14
  * source: 'claude-code' (today) | future: 'codex', …
15
- * event: 'session-start' | 'stop' | 'subagent-stop' | 'session-end'
15
+ * event: 'session-start' | 'stop' | 'subagent-stop' | 'session-end' | 'post-tool-use'
16
16
  *
17
17
  * Graceful no-ops (exit 0 silently):
18
18
  * - GIPITY_CONVERSATION_GUID env var unset (hook fired from a bare
@@ -29,6 +29,13 @@ import { deviceFetch } from '../relay/device-http.js';
29
29
  import { parseTranscript, } from '../capture/sources/claude-code.js';
30
30
  const CAPTURE_DIR = join(homedir(), '.gipity', 'capture-state');
31
31
  const INGEST_BATCH_MAX = 100; // server caps at 200; stay comfortably under
32
+ // PostToolUse fires after every tool call. We flush on it so a session that is
33
+ // killed/crashes mid-run (e.g. a long headless `gipity claude -p` build that
34
+ // hits a timeout) still has its transcript in the DB - Stop/SessionEnd only
35
+ // fire on a CLEAN exit, so without this an interrupted run loses EVERYTHING.
36
+ // Throttled to one flush per this interval to bound the cost of re-scanning a
37
+ // growing transcript on every tool call; a kill then loses at most this much tail.
38
+ const POST_TOOL_FLUSH_MS = 10_000;
32
39
  function statePath(convGuid) {
33
40
  return join(CAPTURE_DIR, `${convGuid}.json`);
34
41
  }
@@ -42,7 +49,10 @@ function readState(convGuid) {
42
49
  try {
43
50
  const raw = readFileSync(p, 'utf-8');
44
51
  const parsed = JSON.parse(raw);
45
- return { last_uuid: typeof parsed.last_uuid === 'string' ? parsed.last_uuid : null };
52
+ return {
53
+ last_uuid: typeof parsed.last_uuid === 'string' ? parsed.last_uuid : null,
54
+ last_flush_ms: typeof parsed.last_flush_ms === 'number' ? parsed.last_flush_ms : undefined,
55
+ };
46
56
  }
47
57
  catch {
48
58
  return null;
@@ -143,10 +153,17 @@ async function handleSessionStart(convGuid, hook) {
143
153
  }];
144
154
  await postEntries(convGuid, entries);
145
155
  }
146
- async function handleStopFamily(convGuid, hook, isSubagent) {
156
+ async function handleStopFamily(convGuid, hook, isSubagent, minIntervalMs = 0) {
147
157
  void isSubagent;
148
158
  if (!hook.transcript_path || !existsSync(hook.transcript_path))
149
159
  return;
160
+ // Throttle high-frequency callers (PostToolUse). Stop/SessionEnd pass
161
+ // minIntervalMs=0 so they always flush in full on a clean exit.
162
+ if (minIntervalMs > 0) {
163
+ const prev = readState(convGuid);
164
+ if (prev?.last_flush_ms && Date.now() - prev.last_flush_ms < minIntervalMs)
165
+ return;
166
+ }
150
167
  const release = acquireLock(convGuid);
151
168
  if (!release)
152
169
  return; // another hook instance is already flushing; it'll catch our lines
@@ -160,8 +177,10 @@ async function handleStopFamily(convGuid, hook, isSubagent) {
160
177
  result = parseTranscript(content, null);
161
178
  }
162
179
  const ok = await postEntries(convGuid, result.entries);
163
- if (ok && result.lastUuid) {
164
- writeState(convGuid, { last_uuid: result.lastUuid });
180
+ if (ok) {
181
+ // Stamp the flush time even when no new lines landed, so the throttle
182
+ // above measures from the last attempt. Keep the watermark if unchanged.
183
+ writeState(convGuid, { last_uuid: result.lastUuid ?? state.last_uuid, last_flush_ms: Date.now() });
165
184
  }
166
185
  }
167
186
  finally {
@@ -218,6 +237,11 @@ async function main() {
218
237
  case 'subagent-stop':
219
238
  await handleStopFamily(convGuid, hook, true);
220
239
  break;
240
+ case 'post-tool-use':
241
+ // Incremental mid-run flush so an interrupted session keeps its
242
+ // transcript (Stop/SessionEnd only fire on clean exit). Throttled.
243
+ await handleStopFamily(convGuid, hook, false, POST_TOOL_FLUSH_MS);
244
+ break;
221
245
  case 'session-end':
222
246
  await handleSessionEnd(convGuid, hook, source);
223
247
  break;
package/dist/index.js CHANGED
@@ -31,6 +31,7 @@ import { logsCommand } from './commands/logs.js';
31
31
  import { pageCommand } from './commands/page.js';
32
32
  import { recordsCommand } from './commands/records.js';
33
33
  import { fnCommand } from './commands/fn.js';
34
+ import { serviceCommand } from './commands/service.js';
34
35
  import { jobCommand } from './commands/job.js';
35
36
  import { rbacCommand } from './commands/rbac.js';
36
37
  import { auditCommand } from './commands/audit.js';
@@ -47,6 +48,7 @@ import { relayCommand } from './commands/relay.js';
47
48
  import { uninstallCommand } from './commands/uninstall.js';
48
49
  import { approvalCommand } from './commands/approval.js';
49
50
  import { gmailCommand } from './commands/gmail.js';
51
+ import { textCommand } from './commands/text.js';
50
52
  import { HELP_SKILL_MAP, fetchAndPrintSkill } from './help-skills.js';
51
53
  import { bold, dim, brand, muted, success } from './colors.js';
52
54
  import { normalizeAliases } from './flag-aliases.js';
@@ -90,13 +92,19 @@ function configureHelp(cmd) {
90
92
  });
91
93
  }
92
94
  const program = new Command();
95
+ // Global value-options (`--api-base <url>`) are only meaningful before the
96
+ // subcommand. Without this, commander interleaves program + subcommand option
97
+ // parsing and mis-reads a subcommand's `.requiredOption()` as missing when a
98
+ // global value-option precedes it (e.g. `gipity --api-base X workflow create
99
+ // --from Y`). enablePositionalOptions draws the boundary at the first command.
100
+ program.enablePositionalOptions();
93
101
  // ── Command groups (logical ordering within each) ──────────────────────
94
102
  const commonGroup = [skillCommand, projectCommand, addCommand, deployCommand];
95
103
  const connectGroup = [claudeCommand, relayCommand];
96
104
  const projectGroup = [domainCommand, statusCommand, initCommand];
97
105
  const filesGroup = [fileCommand, syncCommand, pushCommand, uploadCommand];
98
- const appBuildingGroup = [testCommand, fnCommand, jobCommand, dbCommand, logsCommand, workflowCommand, realtimeCommand, rbacCommand, auditCommand, recordsCommand];
99
- const utilitiesGroup = [pageCommand, sandboxCommand, generateCommand, emailCommand, gmailCommand, locationCommand];
106
+ const appBuildingGroup = [testCommand, fnCommand, serviceCommand, jobCommand, dbCommand, logsCommand, workflowCommand, realtimeCommand, rbacCommand, auditCommand, recordsCommand];
107
+ const utilitiesGroup = [pageCommand, sandboxCommand, generateCommand, emailCommand, gmailCommand, locationCommand, textCommand];
100
108
  const agentGroup = [chatCommand, memoryCommand, agentCommand, approvalCommand];
101
109
  const setupGroup = [loginCommand, logoutCommand, creditsCommand, planCommand, doctorCommand, updateCommand, uninstallCommand];
102
110
  const HELP_SECTIONS = [
@@ -170,6 +178,27 @@ for (const cmd of HELP_SECTIONS.flatMap(s => s.cmds)) {
170
178
  configureHelp(cmd);
171
179
  program.addCommand(cmd);
172
180
  }
181
+ // ── Malformed invocation → print the error AND the command's help inline ──
182
+ // When an agent guesses the wrong shape (excess args, unknown command/option,
183
+ // missing arg), don't make it run `--help` as a second trip: Commander fires
184
+ // error() on the offending (sub)command, so showHelpAfterError(true) appends
185
+ // that exact command's help, and a labeled header names the canonical help
186
+ // invocation. addCommand doesn't inherit these settings, so apply recursively.
187
+ function fullCommandName(cmd) {
188
+ const parts = [];
189
+ for (let c = cmd; c; c = c.parent)
190
+ parts.unshift(c.name());
191
+ return parts.join(' ');
192
+ }
193
+ function enableHelpAfterError(cmd) {
194
+ cmd.showHelpAfterError(true);
195
+ cmd.configureOutput({
196
+ outputError: (str, write) => write(`${str.replace(/\n+$/, '')}\n\nShowing \`${fullCommandName(cmd)} --help\`:\n`),
197
+ });
198
+ for (const sub of cmd.commands)
199
+ enableHelpAfterError(sub);
200
+ }
201
+ enableHelpAfterError(program);
173
202
  // Auto-fetch related skill docs when --help is run on mapped commands
174
203
  const argv = process.argv.slice(2);
175
204
  const hasHelp = argv.includes('--help') || argv.includes('-h');
package/dist/knowledge.js CHANGED
@@ -30,12 +30,13 @@ Kits are reusable building blocks added to an existing app, not whole templates
30
30
  - \`gipity add realtime\` - Multiplayer / presence / shared state - channels, host election, server-persisted sync. Engine-agnostic; works in any app.
31
31
  - \`gipity add web-vision-mediapipe\` - On-device camera vision - gesture recognition, body pose, object detection. Runs fully client-side via MediaPipe Tasks; no server, no upload. Web only.
32
32
  - \`gipity add chatbot\` - Drop-in chatbot - configurable persona, scope guardrails, static knowledge (20k budget), streaming responses. Headless engine + bubble widget; bring your own UI if you want. Works in any app.
33
- - \`gipity add audio-align\` - Audio + lyrics -> word-level timing JSON. Demucs vocal isolation + MMS_FA forced alignment, runs as a Modal L4 GPU job (~$0.01 per 3-min song). For karaoke captions, subtitling, language learning, dubbing alignment.`;
33
+ - \`gipity add audio-align\` - Audio + lyrics -> word-level timing JSON. Demucs vocal isolation + MMS_FA forced alignment, runs as a Modal L4 GPU job (~$0.01 per 3-min song). For karaoke captions, subtitling, language learning, dubbing alignment.
34
+ - \`gipity add i18n\` - Multi-language for web apps - language picker, locale persistence, RTL, plural/translation lookup. Scaffolds src/js/strings.js and wires it up; move your copy there and read it with t('key'). Web only.`;
34
35
  export const SKILLS_CONTENT = `# Gipity Integration
35
36
 
36
37
  Gipity is the cloud platform your project runs on - hosting, databases, deployment, file storage, code execution, workflows, and monitoring. Gip is the cloud agent that runs on Gipity.
37
38
 
38
- This session is connected to a Gipity project. Prefer the cheapest option that works - CLI and sandbox are instant and free, app services are runtime HTTP calls, \`gipity chat\` burns LLM tokens:
39
+ Prefer the cheapest option that works - CLI and sandbox are instant and free, app services are runtime HTTP calls, \`gipity chat\` burns LLM tokens:
39
40
 
40
41
  1. CLI commands (fast, no agent overhead). The \`gipity\` CLI covers add, deploy, db, fn, logs, browser, sync, memory, skill, and more. All commands support \`--json\`.
41
42
  2. Cloud sandbox via \`gipity sandbox run\` - Docker container with pre-installed tools for media (ffmpeg, ImageMagick, sox), documents (pandoc, LibreOffice), and data (pandas, matplotlib, sqlite3). Run \`gipity skill read sandbox-tools\` for the full toolkit. No network from inside the sandbox - fetch what you need before sending it in.
@@ -46,7 +47,7 @@ You are the developer. Write files in this directory - they auto-sync to Gipity
46
47
 
47
48
  ## Use first-party services before reaching outside
48
49
 
49
- Gipity ships its own services for things apps usually pull from a third party - auth, location and geocoding, LLM, image/audio/video generation, transcription, file uploads, realtime. Before you call an external API or add an npm package for one of these, run \`gipity skill list\` and look for a matching skill. First-party services need no API keys, cost less, and keep user data off third parties. Reach outside only when the catalog genuinely has no equivalent - and say so when you do.
50
+ Gipity ships first-party services for what apps usually pull from third parties - auth, location/geocoding, LLM, image/audio/video generation, transcription, file uploads, realtime. Before calling an external API or adding an npm package for one of these, check \`gipity skill list\` for a match. First-party services need no API keys, cost less, and keep data in-house. Reach outside only when the catalog has no equivalent - and say so when you do.
50
51
 
51
52
  ## When to add a template
52
53
 
@@ -54,11 +55,19 @@ The full rule and definition of done are injected at the top of every session co
54
55
 
55
56
  Build loop: \`gipity add\` → edit files → \`gipity deploy dev\` → \`gipity page inspect <url>\` → fix any errors → repeat until the definition of done is met.
56
57
 
58
+ Make your file changes and verify they landed, then run \`gipity deploy dev\` once. \`0 uploaded, N unchanged\` means nothing changed on disk - fix the files, don't re-run deploy or probe the environment.
59
+
60
+ Before telling the user the app is online, verify the source tree is consistent: no files named like \`* (conflict from *)*\`, and every package directory has its expected canonical entry file. If a conflict artifact exists, resolve it (keep one copy), re-deploy, and re-inspect before reporting done.
61
+
57
62
  ## CLI quick reference
58
63
 
59
64
  Key commands: \`gipity add <template|kit>\`, \`gipity deploy dev\`, \`gipity sandbox run\`, \`gipity page inspect <url>\`, \`gipity db query "SQL"\`, \`gipity fn call <name>\`, \`gipity logs fn <name>\`, \`gipity skill read <name>\`.
60
65
  Run \`gipity --help\` for the full list. Use \`--help\` on any command for details.
61
66
 
67
+ ## Tool output is complete and synchronous
68
+
69
+ Every tool call returns its full output with that call. There is no output buffer to flush. Never run no-op commands (echo, date, sleep, repeated reads) to "retrieve" or "flush" lagged output - if a result looks empty or delayed, treat it as the actual result and move on, or re-run the real command once.
70
+
62
71
  ## Files and sync
63
72
 
64
73
  Write files locally - hooks auto-push to Gipity on every save. Remote-generated files (images, audio from \`gipity chat\`) auto-pull. Use \`gipity sync\` if things get out of sync. Deletes are safe - use \`rollback\` with a datetime to undo, or \`file_version_restore\` for individual files.
@@ -85,6 +94,7 @@ App development skills:
85
94
  - \`jobs\` - long-running CPU + GPU compute jobs (Python / Node / bash)
86
95
  - \`realtime-scheduled-app\` - recipe: realtime presence/messages + DB function + scheduled poster, end-to-end
87
96
  - \`web-app-basics\` - coding guidelines, file structure, HTML/CSS/JS patterns
97
+ - \`web-ui-patterns\` - default Gipity look (theme tokens) + web UI recipes - feeds, copy-to-clipboard
88
98
 
89
99
  Kit skills (reusable building blocks - \`gipity add <kit>\`):
90
100
  - \`audio-align\` - the audio-align kit: forced alignment of audio + lyrics into word-level timing JSON
@@ -891,15 +891,25 @@ export async function spawnGipityClaude(args, cwd, d) {
891
891
  // as they arrive. That's the live-streaming path - every assistant
892
892
  // message and tool call appears in the web CLI within a second of
893
893
  // Claude emitting it.
894
+ // Per-dispatch tool_use_id → tool_name map so a `tool_result` event can
895
+ // be denormalized with its tool's name (the result block omits it).
896
+ const toolNames = new Map();
894
897
  const splitter = createLineSplitter((line) => {
895
898
  const evt = parseEvent(line, (reason, snippet) => {
896
899
  log('warn', 'stream-json parse skipped line', { id: d.short_guid, reason, snippet });
897
900
  });
898
901
  if (!evt)
899
902
  return;
900
- const entries = mapEventToEntries(evt);
903
+ const entries = mapEventToEntries(evt, toolNames);
901
904
  if (entries.length === 0)
902
905
  return;
906
+ // Stamp the read time as the event-time hint (event_at). Stream-json
907
+ // carries no per-event timestamp; the daemon reads events as Claude
908
+ // emits them, so receipt time is a close, per-event proxy - far
909
+ // better than the single flush-time created_at on the whole batch.
910
+ const ts = new Date().toISOString();
911
+ for (const e of entries)
912
+ e.ts = ts;
903
913
  // Fire-and-forget POST but tracked so the drain on exit can
904
914
  // `allSettled` the set before we claim the spawn is done.
905
915
  const p = postIngest(d.conversation_guid, entries)
@@ -62,8 +62,14 @@ function joinAssistantText(content) {
62
62
  * assistant event may yield one `assistant` entry AND one `tool_use`
63
63
  * entry per tool_use block within it (server persists each tool call
64
64
  * as its own `role='tool'` row, then updates it when the matching
65
- * `tool_result` arrives). */
66
- export function mapEventToEntries(evt) {
65
+ * `tool_result` arrives).
66
+ *
67
+ * `toolNames` (optional) is a per-dispatch `tool_use_id → tool_name`
68
+ * map threaded across events by the daemon: assistant events record
69
+ * each tool call's name, the later user event with the paired
70
+ * `tool_result` reads it back so the server can denormalize `tool_name`
71
+ * onto the tool row even when the result lands as a stub. */
72
+ export function mapEventToEntries(evt, toolNames) {
67
73
  const out = [];
68
74
  if (evt.type === 'system' && evt.subtype === 'init') {
69
75
  const s = evt;
@@ -76,14 +82,16 @@ export function mapEventToEntries(evt) {
76
82
  const content = Array.isArray(msg.content) ? msg.content : [];
77
83
  const text = joinAssistantText(content);
78
84
  if (text || content.length) {
79
- out.push({ kind: 'assistant', text, blocks: content });
85
+ out.push({ kind: 'assistant', text, blocks: content, ...usageFields(msg) });
80
86
  }
81
87
  for (const block of content) {
82
88
  if (block?.type === 'tool_use' && typeof block.id === 'string') {
89
+ const toolName = typeof block.name === 'string' ? block.name : 'tool';
90
+ toolNames?.set(block.id, toolName);
83
91
  out.push({
84
92
  kind: 'tool_use',
85
93
  tool_use_id: block.id,
86
- tool_name: typeof block.name === 'string' ? block.name : 'tool',
94
+ tool_name: toolName,
87
95
  tool_input: block.input ?? null,
88
96
  });
89
97
  }
@@ -98,6 +106,7 @@ export function mapEventToEntries(evt) {
98
106
  out.push({
99
107
  kind: 'tool_result',
100
108
  tool_use_id: block.tool_use_id,
109
+ tool_name: toolNames?.get(block.tool_use_id),
101
110
  content: block.content ?? null,
102
111
  is_error: Boolean(block.is_error),
103
112
  });
@@ -105,10 +114,38 @@ export function mapEventToEntries(evt) {
105
114
  }
106
115
  return out;
107
116
  }
108
- // `result` is the final footer. The daemon emits its own cosmetic
109
- // "Claude Code finished (Xs)" system marker anyway, so this event is
110
- // a no-op in the ingest stream. Kept here as a hook-point in case we
111
- // want to surface cost/usage later.
117
+ // `result` is the final footer a session-level total. Emit a `result`
118
+ // ingest entry carrying the cost so the server can record it on the
119
+ // conversation. (Per-turn tokens ride on the assistant entries above; cost is
120
+ // only ever here, and only on the stream path.)
121
+ if (evt.type === 'result') {
122
+ const r = evt;
123
+ if (typeof r.total_cost_usd === 'number' || typeof r.num_turns === 'number' || typeof r.duration_ms === 'number') {
124
+ out.push({
125
+ kind: 'result',
126
+ total_cost_usd: typeof r.total_cost_usd === 'number' ? r.total_cost_usd : undefined,
127
+ num_turns: typeof r.num_turns === 'number' ? r.num_turns : undefined,
128
+ duration_ms: typeof r.duration_ms === 'number' ? r.duration_ms : undefined,
129
+ });
130
+ }
131
+ return out;
132
+ }
133
+ return out;
134
+ }
135
+ /** Pull token usage + model + stop_reason off an assistant stream `message`.
136
+ * Same shape as the transcript path's `usageFields` (kept in sync; the two
137
+ * capture modules don't share a module). Cost is NOT per-message. */
138
+ function usageFields(msg) {
139
+ const out = {};
140
+ const u = msg?.usage;
141
+ if (u && typeof u.input_tokens === 'number')
142
+ out.input_tokens = u.input_tokens;
143
+ if (u && typeof u.output_tokens === 'number')
144
+ out.output_tokens = u.output_tokens;
145
+ if (typeof msg?.model === 'string')
146
+ out.model = msg.model;
147
+ if (typeof msg?.stop_reason === 'string')
148
+ out.stop_reason = msg.stop_reason;
112
149
  return out;
113
150
  }
114
151
  // ─── Line-buffered stream splitter ─────────────────────────────────────
package/dist/setup.js CHANGED
@@ -66,6 +66,7 @@ export const PERMISSIONS_SETTINGS = {
66
66
  'Bash(gipity file versions *)',
67
67
  'Bash(gipity records *)',
68
68
  'Bash(gipity fn *)',
69
+ 'Bash(gipity service *)',
69
70
  'Bash(gipity rbac *)',
70
71
  'Bash(gipity audit *)',
71
72
  'Bash(gipity generate *)',
@@ -93,9 +94,11 @@ export function resolveCaptureRunnerPath() {
93
94
  // 1. File-sync hooks (PreToolUse / PostToolUse / UserPromptSubmit):
94
95
  // installed unconditionally. Scaffold reminder + push/pull. Not
95
96
  // related to conversation capture.
96
- // 2. Capture hooks (SessionStart / Stop / SubagentStop / SessionEnd):
97
- // mirror a terminal Claude Code session into the Gipity DB so the
98
- // web CLI can display it read-only. Toggled by the `captureHooks`
97
+ // 2. Capture hooks (SessionStart / Stop / SubagentStop / SessionEnd, plus
98
+ // a throttled PostToolUse for mid-run flushing): mirror a terminal
99
+ // Claude Code session into the Gipity DB so the web CLI can display it
100
+ // read-only. The PostToolUse capture entry is merged alongside the
101
+ // file-sync one (see setupClaudeHooks). Toggled by the `captureHooks`
99
102
  // field in `.gipity.json` - default on.
100
103
  export const HOOKS_SETTINGS = {
101
104
  hooks: {
@@ -153,6 +156,11 @@ function buildCaptureHookEntries(source) {
153
156
  Stop: [{ hooks: [{ type: 'command', command: cmd('stop') }] }],
154
157
  SubagentStop: [{ hooks: [{ type: 'command', command: cmd('subagent-stop') }] }],
155
158
  SessionEnd: [{ hooks: [{ type: 'command', command: cmd('session-end') }] }],
159
+ // Mid-run incremental flush (matcher '' = every tool). Stop/SessionEnd only
160
+ // fire on a CLEAN exit, so without this a session that's killed/crashes mid-run
161
+ // (e.g. a long headless build that times out) loses its whole transcript. The
162
+ // runner throttles this so it's cheap. Merged alongside the file-sync PostToolUse.
163
+ PostToolUse: [{ matcher: '', hooks: [{ type: 'command', command: cmd('post-tool-use') }] }],
156
164
  };
157
165
  }
158
166
  export function setupClaudeHooks() {
@@ -173,7 +181,13 @@ export function setupClaudeHooks() {
173
181
  // feature for this project without affecting the file-sync hooks.
174
182
  const captureEnabled = getConfig()?.captureHooks !== false;
175
183
  const captureEntries = captureEnabled ? buildCaptureHookEntries('claude-code') : {};
176
- settings.hooks = { ...HOOKS_SETTINGS.hooks, ...captureEntries };
184
+ // Merge per-event arrays rather than spread-overwriting: capture and file-sync
185
+ // both register PostToolUse, and a plain spread would drop one of them.
186
+ const mergedHooks = { ...HOOKS_SETTINGS.hooks };
187
+ for (const [event, entries] of Object.entries(captureEntries)) {
188
+ mergedHooks[event] = [...(mergedHooks[event] ?? []), ...entries];
189
+ }
190
+ settings.hooks = mergedHooks;
177
191
  // Merge permissions (additive - preserve user's existing allows)
178
192
  const perms = settings.permissions || {};
179
193
  if (!perms.allow)
package/dist/sync.js CHANGED
@@ -302,8 +302,16 @@ export function plan(local, remote, baseline) {
302
302
  // unchanged × unchanged → noop
303
303
  if (lSide === 'unchanged' && rSide === 'unchanged')
304
304
  continue;
305
- // unchanged × modified → download
305
+ // unchanged × modified → download, but ONLY if the remote genuinely advanced.
306
+ // Guards a read-after-write race: right after a local write+push, the push can
307
+ // advance the local baseline to the new version while the remote tree API still
308
+ // serves the OLD bytes (stale read). That makes remote look "modified" vs an
309
+ // already-updated baseline, and a blind download would silently clobber the
310
+ // just-written local file with a stale older version. A real remote change
311
+ // always carries a strictly newer serverVersion; an equal/older one is stale.
306
312
  if (lSide === 'unchanged' && rSide === 'modified') {
313
+ if (B && R.serverVersion <= B.serverVersion)
314
+ continue;
307
315
  actions.push({ path, kind: 'download', remoteSize: R.size });
308
316
  continue;
309
317
  }
@@ -359,8 +367,12 @@ export function plan(local, remote, baseline) {
359
367
  actions.push({ path, kind: 'delete-remote', remoteSize: R.size, expectedServerVersion: B.serverVersion });
360
368
  continue;
361
369
  }
362
- // deleted × modified → remote wins, restore locally
370
+ // deleted × modified → remote wins, restore locally — but only if the remote
371
+ // actually advanced past the baseline. A stale (older/equal) remote read must
372
+ // not resurrect a file the user intentionally deleted.
363
373
  if (lSide === 'deleted' && rSide === 'modified') {
374
+ if (B && R.serverVersion <= B.serverVersion)
375
+ continue;
364
376
  actions.push({
365
377
  path, kind: 'download', remoteSize: R.size,
366
378
  reason: 'local deleted but remote modified - remote preserved',
package/package.json CHANGED
@@ -1,19 +1,19 @@
1
1
  {
2
2
  "name": "gipity",
3
- "version": "1.0.355",
3
+ "version": "1.0.365",
4
4
  "description": "The full-stack platform tuned for AI agents. Database, storage, auth, functions, deploy, and drop-in kits - all agent-tuned. Pair with Claude Code or use standalone.",
5
5
  "bin": {
6
- "gipity": "./dist/updater/shim.js",
7
- "gipcc": "./dist/gipcc.js",
8
- "gipccd": "./dist/gipccd.js"
6
+ "gipity": "dist/updater/shim.js",
7
+ "gipcc": "dist/gipcc.js",
8
+ "gipccd": "dist/gipccd.js"
9
9
  },
10
10
  "type": "module",
11
11
  "scripts": {
12
12
  "build": "tsc && chmod +x dist/index.js dist/gipcc.js dist/gipccd.js dist/updater/shim.js dist/updater/check.js",
13
13
  "dev": "tsc --watch",
14
14
  "test": "npm run test:smoke",
15
- "test:smoke": "tsc && node --test dist/__tests__/utils.test.js dist/__tests__/config.test.js dist/__tests__/sync.test.js dist/__tests__/sync-apply.test.js dist/__tests__/sync-lock.test.js dist/__tests__/push-cas.test.js dist/__tests__/upload.test.js dist/__tests__/updater.test.js dist/__tests__/cli-smoke.test.js dist/__tests__/claude-noninteractive.test.js dist/__tests__/claude-trust.test.js dist/__tests__/relay-state.test.js dist/__tests__/relay-daemon.test.js dist/__tests__/relay-installers.test.js dist/__tests__/relay-bridge-abort.test.js dist/__tests__/relay-redact.test.js dist/__tests__/relay-machine-id.test.js dist/__tests__/stream-json.test.js dist/__tests__/relay-ingest-contract.test.js dist/__tests__/prompts.test.js dist/__tests__/capture-transcript.test.js dist/__tests__/flag-aliases.test.js dist/__tests__/adopt-cwd.test.js dist/__tests__/cli-cmd-agent.test.js dist/__tests__/cli-cmd-approval.test.js dist/__tests__/cli-cmd-audit.test.js dist/__tests__/cli-cmd-chat.test.js dist/__tests__/cli-cmd-credits.test.js dist/__tests__/cli-cmd-db.test.js dist/__tests__/cli-cmd-deploy.test.js dist/__tests__/cli-cmd-domain.test.js dist/__tests__/cli-cmd-email.test.js dist/__tests__/cli-cmd-file.test.js dist/__tests__/cli-cmd-fn.test.js dist/__tests__/cli-cmd-job.test.js dist/__tests__/cli-cmd-generate.test.js dist/__tests__/cli-cmd-gmail.test.js dist/__tests__/cli-cmd-info.test.js dist/__tests__/cli-cmd-init.test.js dist/__tests__/cli-cmd-location.test.js dist/__tests__/cli-cmd-login.test.js dist/__tests__/cli-cmd-logout.test.js dist/__tests__/cli-cmd-logs.test.js dist/__tests__/cli-cmd-memory.test.js dist/__tests__/cli-cmd-page.test.js dist/__tests__/cli-cmd-plan.test.js dist/__tests__/cli-cmd-project.test.js dist/__tests__/cli-cmd-rbac.test.js dist/__tests__/cli-cmd-realtime.test.js dist/__tests__/cli-cmd-records.test.js dist/__tests__/cli-cmd-relay.test.js dist/__tests__/cli-cmd-sandbox.test.js dist/__tests__/cli-cmd-add.test.js dist/__tests__/cli-cmd-skill.test.js dist/__tests__/cli-cmd-test.test.js dist/__tests__/cli-cmd-workflow.test.js dist/__tests__/setup-skills-block.test.js",
16
- "test:e2e": "tsc && GIPITY_E2E=1 node --test --test-timeout=180000 dist/__tests__/cli-e2e-live.test.js"
15
+ "test:smoke": "tsc && node --test dist/__tests__/utils.test.js dist/__tests__/config.test.js dist/__tests__/sync.test.js dist/__tests__/sync-apply.test.js dist/__tests__/sync-lock.test.js dist/__tests__/push-cas.test.js dist/__tests__/upload.test.js dist/__tests__/updater.test.js dist/__tests__/cli-smoke.test.js dist/__tests__/claude-noninteractive.test.js dist/__tests__/claude-trust.test.js dist/__tests__/relay-state.test.js dist/__tests__/relay-daemon.test.js dist/__tests__/relay-installers.test.js dist/__tests__/relay-bridge-abort.test.js dist/__tests__/relay-redact.test.js dist/__tests__/relay-machine-id.test.js dist/__tests__/stream-json.test.js dist/__tests__/relay-ingest-contract.test.js dist/__tests__/prompts.test.js dist/__tests__/capture-transcript.test.js dist/__tests__/flag-aliases.test.js dist/__tests__/adopt-cwd.test.js dist/__tests__/cli-cmd-agent.test.js dist/__tests__/cli-cmd-approval.test.js dist/__tests__/cli-cmd-audit.test.js dist/__tests__/cli-cmd-chat.test.js dist/__tests__/cli-cmd-credits.test.js dist/__tests__/cli-cmd-db.test.js dist/__tests__/cli-cmd-deploy.test.js dist/__tests__/cli-cmd-domain.test.js dist/__tests__/cli-cmd-email.test.js dist/__tests__/cli-cmd-file.test.js dist/__tests__/cli-cmd-fn.test.js dist/__tests__/cli-cmd-service.test.js dist/__tests__/cli-cmd-job.test.js dist/__tests__/cli-cmd-generate.test.js dist/__tests__/cli-cmd-gmail.test.js dist/__tests__/cli-cmd-info.test.js dist/__tests__/cli-cmd-init.test.js dist/__tests__/cli-cmd-location.test.js dist/__tests__/cli-cmd-text.test.js dist/__tests__/cli-cmd-login.test.js dist/__tests__/cli-cmd-logout.test.js dist/__tests__/cli-cmd-logs.test.js dist/__tests__/cli-cmd-memory.test.js dist/__tests__/cli-cmd-page.test.js dist/__tests__/cli-cmd-plan.test.js dist/__tests__/cli-cmd-project.test.js dist/__tests__/cli-cmd-rbac.test.js dist/__tests__/cli-cmd-realtime.test.js dist/__tests__/cli-cmd-records.test.js dist/__tests__/cli-cmd-relay.test.js dist/__tests__/cli-cmd-sandbox.test.js dist/__tests__/cli-cmd-add.test.js dist/__tests__/cli-cmd-skill.test.js dist/__tests__/cli-cmd-test.test.js dist/__tests__/cli-cmd-workflow.test.js dist/__tests__/setup-skills-block.test.js dist/__tests__/setup-hooks.test.js",
16
+ "test:e2e": "tsc && GIPITY_E2E=1 node --test --test-timeout=180000 dist/__tests__/cli-e2e-live.test.js dist/__tests__/cli-e2e-services-media-live.test.js dist/__tests__/cli-e2e-workflow-live.test.js"
17
17
  },
18
18
  "dependencies": {
19
19
  "commander": "^13.0.0",
@@ -28,7 +28,8 @@
28
28
  "node": ">=18"
29
29
  },
30
30
  "files": [
31
- "dist",
31
+ "dist/**/*.js",
32
+ "!dist/__tests__/**",
32
33
  "hooks"
33
34
  ],
34
35
  "license": "MIT"
@@ -1 +0,0 @@
1
- export {};
@@ -1,176 +0,0 @@
1
- /**
2
- * Unit tests for the cwd-adoption helpers. Pure logic + small fs walks
3
- * inside tmp dirs - no network, no real platform state.
4
- */
5
- import { describe, it, before, after } from 'node:test';
6
- import assert from 'node:assert/strict';
7
- import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'fs';
8
- import { tmpdir, homedir } from 'os';
9
- import { join, sep } from 'path';
10
- import { scanForAdoption, isLikelyEmpty, canAdoptCwd, formatCwdLabel, formatBytes, } from '../adopt-cwd.js';
11
- let root;
12
- before(() => {
13
- root = mkdtempSync(join(tmpdir(), 'gipity-adopt-test-'));
14
- });
15
- after(() => {
16
- try {
17
- rmSync(root, { recursive: true, force: true });
18
- }
19
- catch { /* best effort */ }
20
- });
21
- function mkdir(p) {
22
- const full = join(root, p);
23
- mkdirSync(full, { recursive: true });
24
- return full;
25
- }
26
- function writeBytes(dir, name, n) {
27
- writeFileSync(join(dir, name), Buffer.alloc(n));
28
- }
29
- describe('scanForAdoption', () => {
30
- it('returns easy tier for a tiny project', () => {
31
- const d = mkdir('easy');
32
- writeBytes(d, 'a.txt', 10);
33
- writeBytes(d, 'b.txt', 10);
34
- const s = scanForAdoption(d);
35
- assert.equal(s.tier, 'easy');
36
- assert.equal(s.files, 2);
37
- assert.equal(s.bytes, 20);
38
- assert.equal(s.truncated, false);
39
- });
40
- it('handles a missing directory gracefully', () => {
41
- const s = scanForAdoption(join(root, 'no-such-dir'));
42
- assert.equal(s.tier, 'easy');
43
- assert.equal(s.files, 0);
44
- });
45
- it('walks nested directories', () => {
46
- const d = mkdir('nested');
47
- const sub = mkdir('nested/sub/sub2');
48
- writeBytes(d, 'top.txt', 1);
49
- writeBytes(sub, 'deep.txt', 2);
50
- const s = scanForAdoption(d);
51
- assert.equal(s.files, 2);
52
- assert.equal(s.bytes, 3);
53
- });
54
- it('returns moderate tier when over the easy file-count threshold', () => {
55
- const d = mkdir('moderate-files');
56
- for (let i = 0; i < 250; i++)
57
- writeBytes(d, `f${i}.txt`, 1);
58
- const s = scanForAdoption(d);
59
- assert.equal(s.tier, 'moderate');
60
- assert.equal(s.truncated, false);
61
- });
62
- it('returns refuse + truncated when over the refuse file-count threshold', () => {
63
- const d = mkdir('refuse-files');
64
- for (let i = 0; i < 2100; i++)
65
- writeBytes(d, `f${i}.txt`, 1);
66
- const s = scanForAdoption(d);
67
- assert.equal(s.tier, 'refuse');
68
- assert.equal(s.truncated, true);
69
- });
70
- it('skips sync-ignored entries (node_modules, .git)', () => {
71
- const d = mkdir('with-junk');
72
- writeBytes(d, 'real.txt', 1);
73
- const nm = mkdir('with-junk/node_modules');
74
- writeBytes(nm, 'should-not-count.txt', 999_999);
75
- const git = mkdir('with-junk/.git');
76
- writeBytes(git, 'also-skip.txt', 999_999);
77
- const s = scanForAdoption(d);
78
- assert.equal(s.files, 1);
79
- assert.equal(s.bytes, 1);
80
- });
81
- });
82
- describe('isLikelyEmpty', () => {
83
- it('true for a truly empty dir', () => {
84
- const d = mkdir('empty');
85
- assert.equal(isLikelyEmpty(d), true);
86
- });
87
- it('true for a dir with only sync-ignored entries', () => {
88
- const d = mkdir('only-junk');
89
- mkdir('only-junk/node_modules');
90
- mkdir('only-junk/.git');
91
- assert.equal(isLikelyEmpty(d), true);
92
- });
93
- it('false when there is any real file', () => {
94
- const d = mkdir('not-empty');
95
- writeBytes(d, 'hello.md', 1);
96
- assert.equal(isLikelyEmpty(d), false);
97
- });
98
- it('true when the dir does not exist', () => {
99
- assert.equal(isLikelyEmpty(join(root, 'ghost')), true);
100
- });
101
- });
102
- describe('canAdoptCwd', () => {
103
- it('refuses the filesystem root', () => {
104
- assert.equal(canAdoptCwd(sep), false);
105
- });
106
- it('refuses the user\'s home directory', () => {
107
- assert.equal(canAdoptCwd(homedir()), false);
108
- });
109
- it('refuses system dirs', () => {
110
- assert.equal(canAdoptCwd('/tmp'), false);
111
- assert.equal(canAdoptCwd('/etc'), false);
112
- assert.equal(canAdoptCwd('/usr'), false);
113
- });
114
- it('allows a subdirectory of /tmp', () => {
115
- const d = mkdir('allowed-subdir');
116
- assert.equal(canAdoptCwd(d), true);
117
- });
118
- it('refuses a workspace-parent (depth ≤1 below home with 3+ git children)', () => {
119
- // Simulate ~/Workspace/{a,b,c}/.git
120
- const ws = mkdtempSync(join(homedir(), 'gipity-adopt-ws-'));
121
- try {
122
- for (const sub of ['a', 'b', 'c']) {
123
- mkdirSync(join(ws, sub, '.git'), { recursive: true });
124
- }
125
- assert.equal(canAdoptCwd(ws), false);
126
- }
127
- finally {
128
- rmSync(ws, { recursive: true, force: true });
129
- }
130
- });
131
- it('allows a single-project dir even at depth ≤1 under home', () => {
132
- const single = mkdtempSync(join(homedir(), 'gipity-adopt-single-'));
133
- try {
134
- mkdirSync(join(single, '.git'), { recursive: true });
135
- assert.equal(canAdoptCwd(single), true);
136
- }
137
- finally {
138
- rmSync(single, { recursive: true, force: true });
139
- }
140
- });
141
- });
142
- describe('formatCwdLabel', () => {
143
- it('returns "~" for the home dir', () => {
144
- assert.equal(formatCwdLabel(homedir()), '~');
145
- });
146
- it('uses ~/tail when 1-2 segments deep in home', () => {
147
- assert.equal(formatCwdLabel(join(homedir(), 'Github')), '~/Github');
148
- assert.equal(formatCwdLabel(join(homedir(), 'Github', 'Gipity')), '~/Github/Gipity');
149
- });
150
- it('uses ~/…/last-2 when deeper in home', () => {
151
- const deep = join(homedir(), 'a', 'b', 'c', 'd');
152
- assert.equal(formatCwdLabel(deep), '~/…/c/d');
153
- });
154
- it('shows parent/this for non-home paths', () => {
155
- assert.equal(formatCwdLabel('/tmp/scratch'), 'tmp/scratch');
156
- });
157
- });
158
- describe('formatBytes', () => {
159
- it('B for sub-KB', () => {
160
- assert.equal(formatBytes(0), '0 B');
161
- assert.equal(formatBytes(512), '512 B');
162
- });
163
- it('KB for sub-MB', () => {
164
- assert.equal(formatBytes(1024), '1.0 KB');
165
- assert.equal(formatBytes(2048), '2.0 KB');
166
- });
167
- it('MB for sub-GB', () => {
168
- assert.equal(formatBytes(1024 * 1024), '1.0 MB');
169
- assert.equal(formatBytes(50 * 1024 * 1024), '50.0 MB');
170
- });
171
- it('GB for ≥ GB (fixes the "1024.0 MB" overflow at the refuse threshold)', () => {
172
- assert.equal(formatBytes(1024 * 1024 * 1024), '1.00 GB');
173
- assert.equal(formatBytes(2.5 * 1024 * 1024 * 1024), '2.50 GB');
174
- });
175
- });
176
- //# sourceMappingURL=adopt-cwd.test.js.map