gipity 1.0.306 → 1.0.329

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 (256) hide show
  1. package/README.md +16 -13
  2. package/dist/__tests__/adopt-cwd.test.d.ts +1 -0
  3. package/dist/__tests__/adopt-cwd.test.js +176 -0
  4. package/dist/__tests__/adopt-cwd.test.js.map +1 -0
  5. package/dist/__tests__/claude-noninteractive.test.js +1 -1
  6. package/dist/__tests__/cli-cmd-agent.test.d.ts +1 -0
  7. package/dist/__tests__/cli-cmd-agent.test.js +76 -0
  8. package/dist/__tests__/cli-cmd-agent.test.js.map +1 -0
  9. package/dist/__tests__/cli-cmd-approval.test.d.ts +1 -0
  10. package/dist/__tests__/cli-cmd-approval.test.js +47 -0
  11. package/dist/__tests__/cli-cmd-approval.test.js.map +1 -0
  12. package/dist/__tests__/cli-cmd-audit.test.d.ts +1 -0
  13. package/dist/__tests__/cli-cmd-audit.test.js +33 -0
  14. package/dist/__tests__/cli-cmd-audit.test.js.map +1 -0
  15. package/dist/__tests__/cli-cmd-chat.test.d.ts +1 -0
  16. package/dist/__tests__/cli-cmd-chat.test.js +63 -0
  17. package/dist/__tests__/cli-cmd-chat.test.js.map +1 -0
  18. package/dist/__tests__/cli-cmd-credits.test.d.ts +1 -0
  19. package/dist/__tests__/cli-cmd-credits.test.js +66 -0
  20. package/dist/__tests__/cli-cmd-credits.test.js.map +1 -0
  21. package/dist/__tests__/cli-cmd-db.test.d.ts +1 -0
  22. package/dist/__tests__/cli-cmd-db.test.js +95 -0
  23. package/dist/__tests__/cli-cmd-db.test.js.map +1 -0
  24. package/dist/__tests__/cli-cmd-deploy.test.d.ts +1 -0
  25. package/dist/__tests__/cli-cmd-deploy.test.js +53 -0
  26. package/dist/__tests__/cli-cmd-deploy.test.js.map +1 -0
  27. package/dist/__tests__/cli-cmd-domain.test.d.ts +1 -0
  28. package/dist/__tests__/cli-cmd-domain.test.js +73 -0
  29. package/dist/__tests__/cli-cmd-domain.test.js.map +1 -0
  30. package/dist/__tests__/cli-cmd-email.test.d.ts +1 -0
  31. package/dist/__tests__/cli-cmd-email.test.js +31 -0
  32. package/dist/__tests__/cli-cmd-email.test.js.map +1 -0
  33. package/dist/__tests__/cli-cmd-file.test.d.ts +1 -0
  34. package/dist/__tests__/cli-cmd-file.test.js +86 -0
  35. package/dist/__tests__/cli-cmd-file.test.js.map +1 -0
  36. package/dist/__tests__/cli-cmd-fn.test.d.ts +1 -0
  37. package/dist/__tests__/cli-cmd-fn.test.js +50 -0
  38. package/dist/__tests__/cli-cmd-fn.test.js.map +1 -0
  39. package/dist/__tests__/cli-cmd-generate.test.d.ts +1 -0
  40. package/dist/__tests__/cli-cmd-generate.test.js +46 -0
  41. package/dist/__tests__/cli-cmd-generate.test.js.map +1 -0
  42. package/dist/__tests__/cli-cmd-gmail.test.d.ts +1 -0
  43. package/dist/__tests__/cli-cmd-gmail.test.js +49 -0
  44. package/dist/__tests__/cli-cmd-gmail.test.js.map +1 -0
  45. package/dist/__tests__/cli-cmd-info.test.d.ts +1 -0
  46. package/dist/__tests__/cli-cmd-info.test.js +52 -0
  47. package/dist/__tests__/cli-cmd-info.test.js.map +1 -0
  48. package/dist/__tests__/cli-cmd-location.test.d.ts +1 -0
  49. package/dist/__tests__/cli-cmd-location.test.js +58 -0
  50. package/dist/__tests__/cli-cmd-location.test.js.map +1 -0
  51. package/dist/__tests__/cli-cmd-login.test.d.ts +1 -0
  52. package/dist/__tests__/cli-cmd-login.test.js +41 -0
  53. package/dist/__tests__/cli-cmd-login.test.js.map +1 -0
  54. package/dist/__tests__/cli-cmd-logout.test.d.ts +1 -0
  55. package/dist/__tests__/cli-cmd-logout.test.js +20 -0
  56. package/dist/__tests__/cli-cmd-logout.test.js.map +1 -0
  57. package/dist/__tests__/cli-cmd-logs.test.d.ts +1 -0
  58. package/dist/__tests__/cli-cmd-logs.test.js +40 -0
  59. package/dist/__tests__/cli-cmd-logs.test.js.map +1 -0
  60. package/dist/__tests__/cli-cmd-memory.test.d.ts +1 -0
  61. package/dist/__tests__/cli-cmd-memory.test.js +58 -0
  62. package/dist/__tests__/cli-cmd-memory.test.js.map +1 -0
  63. package/dist/__tests__/cli-cmd-page-inspect.test.d.ts +1 -0
  64. package/dist/__tests__/cli-cmd-page-inspect.test.js +47 -0
  65. package/dist/__tests__/cli-cmd-page-inspect.test.js.map +1 -0
  66. package/dist/__tests__/cli-cmd-plan.test.d.ts +1 -0
  67. package/dist/__tests__/cli-cmd-plan.test.js +81 -0
  68. package/dist/__tests__/cli-cmd-plan.test.js.map +1 -0
  69. package/dist/__tests__/cli-cmd-project.test.d.ts +1 -0
  70. package/dist/__tests__/cli-cmd-project.test.js +61 -0
  71. package/dist/__tests__/cli-cmd-project.test.js.map +1 -0
  72. package/dist/__tests__/cli-cmd-rbac.test.d.ts +1 -0
  73. package/dist/__tests__/cli-cmd-rbac.test.js +39 -0
  74. package/dist/__tests__/cli-cmd-rbac.test.js.map +1 -0
  75. package/dist/__tests__/cli-cmd-records.test.d.ts +1 -0
  76. package/dist/__tests__/cli-cmd-records.test.js +67 -0
  77. package/dist/__tests__/cli-cmd-records.test.js.map +1 -0
  78. package/dist/__tests__/cli-cmd-relay.test.d.ts +1 -0
  79. package/dist/__tests__/cli-cmd-relay.test.js +100 -0
  80. package/dist/__tests__/cli-cmd-relay.test.js.map +1 -0
  81. package/dist/__tests__/cli-cmd-sandbox.test.d.ts +1 -0
  82. package/dist/__tests__/cli-cmd-sandbox.test.js +46 -0
  83. package/dist/__tests__/cli-cmd-sandbox.test.js.map +1 -0
  84. package/dist/__tests__/cli-cmd-scaffold.test.d.ts +1 -0
  85. package/dist/__tests__/cli-cmd-scaffold.test.js +30 -0
  86. package/dist/__tests__/cli-cmd-scaffold.test.js.map +1 -0
  87. package/dist/__tests__/cli-cmd-skill.test.d.ts +1 -0
  88. package/dist/__tests__/cli-cmd-skill.test.js +40 -0
  89. package/dist/__tests__/cli-cmd-skill.test.js.map +1 -0
  90. package/dist/__tests__/cli-cmd-test.test.d.ts +1 -0
  91. package/dist/__tests__/cli-cmd-test.test.js +58 -0
  92. package/dist/__tests__/cli-cmd-test.test.js.map +1 -0
  93. package/dist/__tests__/cli-cmd-workflow.test.d.ts +1 -0
  94. package/dist/__tests__/cli-cmd-workflow.test.js +84 -0
  95. package/dist/__tests__/cli-cmd-workflow.test.js.map +1 -0
  96. package/dist/__tests__/cli-e2e-live.test.js +3 -3
  97. package/dist/__tests__/helpers/mock-server.d.ts +52 -0
  98. package/dist/__tests__/helpers/mock-server.js +86 -0
  99. package/dist/__tests__/helpers/mock-server.js.map +1 -0
  100. package/dist/__tests__/helpers/spawn-cli.d.ts +1 -1
  101. package/dist/__tests__/helpers/spawn-cli.js +2 -2
  102. package/dist/__tests__/helpers/test-home.d.ts +22 -0
  103. package/dist/__tests__/helpers/test-home.js +35 -0
  104. package/dist/__tests__/helpers/test-home.js.map +1 -0
  105. package/dist/__tests__/prompts.test.js +3 -3
  106. package/dist/__tests__/push-cas.test.js +2 -2
  107. package/dist/__tests__/relay-bridge-abort.test.js +2 -2
  108. package/dist/__tests__/relay-daemon.test.js +5 -5
  109. package/dist/__tests__/relay-ingest-contract.test.js +2 -2
  110. package/dist/__tests__/relay-installers.test.js +4 -4
  111. package/dist/__tests__/relay-state.test.js +1 -1
  112. package/dist/__tests__/stream-json.test.js +2 -2
  113. package/dist/__tests__/sync-apply.test.js +7 -7
  114. package/dist/__tests__/sync-lock.test.js +4 -4
  115. package/dist/__tests__/sync.test.js +2 -2
  116. package/dist/__tests__/updater.test.js +1 -1
  117. package/dist/adopt-cwd.d.ts +2 -2
  118. package/dist/adopt-cwd.js +9 -9
  119. package/dist/api.d.ts +1 -1
  120. package/dist/api.js +1 -1
  121. package/dist/auth.js +1 -1
  122. package/dist/banner.js +43 -31
  123. package/dist/banner.js.map +1 -1
  124. package/dist/capture/sources/claude-code.d.ts +2 -2
  125. package/dist/capture/sources/claude-code.js +4 -4
  126. package/dist/colors.js +1 -1
  127. package/dist/commands/agent.js +18 -22
  128. package/dist/commands/agent.js.map +1 -1
  129. package/dist/commands/api.js +1 -1
  130. package/dist/commands/approval.d.ts +2 -0
  131. package/dist/commands/approval.js +117 -0
  132. package/dist/commands/approval.js.map +1 -0
  133. package/dist/commands/chat.js +40 -2
  134. package/dist/commands/chat.js.map +1 -1
  135. package/dist/commands/claude.js +19 -19
  136. package/dist/commands/claude.js.map +1 -1
  137. package/dist/commands/credits.js +4 -4
  138. package/dist/commands/credits.js.map +1 -1
  139. package/dist/commands/db.js +9 -6
  140. package/dist/commands/db.js.map +1 -1
  141. package/dist/commands/deploy.js +2 -2
  142. package/dist/commands/deploy.js.map +1 -1
  143. package/dist/commands/doctor.js +2 -2
  144. package/dist/commands/doctor.js.map +1 -1
  145. package/dist/commands/domain.js +2 -2
  146. package/dist/commands/email.js +30 -5
  147. package/dist/commands/email.js.map +1 -1
  148. package/dist/commands/file.js +11 -21
  149. package/dist/commands/file.js.map +1 -1
  150. package/dist/commands/fn.js +2 -2
  151. package/dist/commands/fn.js.map +1 -1
  152. package/dist/commands/generate.js +2 -2
  153. package/dist/commands/generate.js.map +1 -1
  154. package/dist/commands/gmail.d.ts +2 -0
  155. package/dist/commands/gmail.js +85 -0
  156. package/dist/commands/gmail.js.map +1 -0
  157. package/dist/commands/init.js +2 -2
  158. package/dist/commands/init.js.map +1 -1
  159. package/dist/commands/location.js +1 -1
  160. package/dist/commands/location.js.map +1 -1
  161. package/dist/commands/login.js +27 -13
  162. package/dist/commands/login.js.map +1 -1
  163. package/dist/commands/logout.js +7 -4
  164. package/dist/commands/logout.js.map +1 -1
  165. package/dist/commands/logs.js +3 -3
  166. package/dist/commands/logs.js.map +1 -1
  167. package/dist/commands/memory.js +8 -18
  168. package/dist/commands/memory.js.map +1 -1
  169. package/dist/commands/page-inspect.js +5 -4
  170. package/dist/commands/page-inspect.js.map +1 -1
  171. package/dist/commands/page-screenshot.js +3 -3
  172. package/dist/commands/page-screenshot.js.map +1 -1
  173. package/dist/commands/plan.d.ts +2 -0
  174. package/dist/commands/plan.js +93 -0
  175. package/dist/commands/plan.js.map +1 -0
  176. package/dist/commands/project.js +11 -26
  177. package/dist/commands/project.js.map +1 -1
  178. package/dist/commands/push.js +6 -2
  179. package/dist/commands/push.js.map +1 -1
  180. package/dist/commands/rbac.js +7 -7
  181. package/dist/commands/rbac.js.map +1 -1
  182. package/dist/commands/records.js +10 -8
  183. package/dist/commands/records.js.map +1 -1
  184. package/dist/commands/relay-install.d.ts +2 -2
  185. package/dist/commands/relay-install.js +2 -2
  186. package/dist/commands/relay-install.js.map +1 -1
  187. package/dist/commands/relay.d.ts +1 -1
  188. package/dist/commands/relay.js +15 -15
  189. package/dist/commands/relay.js.map +1 -1
  190. package/dist/commands/sandbox.js +3 -3
  191. package/dist/commands/sandbox.js.map +1 -1
  192. package/dist/commands/scaffold.js +16 -8
  193. package/dist/commands/scaffold.js.map +1 -1
  194. package/dist/commands/skill.d.ts +2 -0
  195. package/dist/commands/skill.js +45 -0
  196. package/dist/commands/skill.js.map +1 -0
  197. package/dist/commands/skills.js +3 -3
  198. package/dist/commands/skills.js.map +1 -1
  199. package/dist/commands/status.js +2 -2
  200. package/dist/commands/status.js.map +1 -1
  201. package/dist/commands/sync.js +1 -1
  202. package/dist/commands/sync.js.map +1 -1
  203. package/dist/commands/test.js +5 -5
  204. package/dist/commands/test.js.map +1 -1
  205. package/dist/commands/uninstall.d.ts +2 -2
  206. package/dist/commands/uninstall.js +7 -7
  207. package/dist/commands/uninstall.js.map +1 -1
  208. package/dist/commands/update.js +4 -1
  209. package/dist/commands/update.js.map +1 -1
  210. package/dist/commands/upload.js +2 -2
  211. package/dist/commands/upload.js.map +1 -1
  212. package/dist/commands/workflow.js +51 -22
  213. package/dist/commands/workflow.js.map +1 -1
  214. package/dist/config.js +3 -3
  215. package/dist/help-skills.js +1 -1
  216. package/dist/helpers/command.d.ts +1 -1
  217. package/dist/helpers/command.js +1 -1
  218. package/dist/helpers/index.d.ts +2 -2
  219. package/dist/helpers/index.js +2 -2
  220. package/dist/helpers/index.js.map +1 -1
  221. package/dist/helpers/output.d.ts +5 -1
  222. package/dist/helpers/output.js +15 -2
  223. package/dist/helpers/output.js.map +1 -1
  224. package/dist/helpers/sync.d.ts +1 -1
  225. package/dist/helpers/sync.js +1 -1
  226. package/dist/hooks/capture-runner.d.ts +2 -2
  227. package/dist/hooks/capture-runner.js +7 -7
  228. package/dist/index.js +13 -10
  229. package/dist/index.js.map +1 -1
  230. package/dist/project-setup.js +2 -2
  231. package/dist/prompts.d.ts +14 -12
  232. package/dist/prompts.js +53 -44
  233. package/dist/prompts.js.map +1 -1
  234. package/dist/provider-docs.d.ts +4 -4
  235. package/dist/provider-docs.js +6 -6
  236. package/dist/provider-docs.js.map +1 -1
  237. package/dist/relay/daemon.d.ts +1 -1
  238. package/dist/relay/daemon.js +75 -37
  239. package/dist/relay/daemon.js.map +1 -1
  240. package/dist/relay/installers.d.ts +1 -1
  241. package/dist/relay/installers.js +11 -11
  242. package/dist/relay/onboarding.js +6 -6
  243. package/dist/relay/state.d.ts +1 -1
  244. package/dist/relay/state.js +6 -6
  245. package/dist/relay/stream-json.d.ts +3 -3
  246. package/dist/relay/stream-json.js +4 -4
  247. package/dist/setup.d.ts +5 -5
  248. package/dist/setup.js +10 -10
  249. package/dist/sync.js +11 -11
  250. package/dist/updater/bootstrap.d.ts +1 -1
  251. package/dist/updater/bootstrap.js +2 -2
  252. package/dist/updater/shim.js +1 -1
  253. package/dist/upload.js +3 -3
  254. package/dist/utils.d.ts +3 -3
  255. package/dist/utils.js +4 -4
  256. package/package.json +3 -3
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # Gipity CLI
2
2
 
3
- Most AI tools give you a chatbot. We gave ours a computer.
3
+ The agent-tuned platform where AI-built apps live.
4
4
 
5
- [Gipity](https://gipity.ai) is an AI agent with 90+ tools and a full cloud platform — app hosting, databases, file storage, deployment, workflows, code execution, and more. Use it standalone or plug it into Claude Code to give your local agent cloud superpowers.
5
+ [Gipity](https://gipity.ai) is the platform: hosting, databases, file storage, deployment, workflows, code execution, and monitoring. Agent-tuned from scaffold to deploy. Use standalone, or pair with Claude Code to give your local agent cloud superpowers. Any model, any infra, always your code.
6
6
 
7
- This CLI connects [Claude Code](https://claude.ai/claude-code) to Gipity's cloud platform databases, deployment, browser testing, image gen, and 50+ other capabilities your local agent doesn't have. It also syncs files so Claude Code and the Gipity web agent share the same project.
7
+ This CLI connects [Claude Code](https://claude.ai/claude-code) to Gipity's cloud platform - databases, deployment, browser testing, image gen, and 50+ other capabilities your local agent doesn't have. It also syncs files so Claude Code and the Gipity web agent share the same project.
8
8
 
9
9
  ## Getting Started
10
10
 
@@ -16,7 +16,7 @@ You need **Node.js 18+** (which includes npm) and **Claude Code**.
16
16
  # macOS
17
17
  brew install node
18
18
 
19
- # Windows download the installer from https://nodejs.org
19
+ # Windows - download the installer from https://nodejs.org
20
20
 
21
21
  # Linux (Ubuntu/Debian)
22
22
  curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt install -y nodejs
@@ -32,7 +32,7 @@ That's it. `claude` walks you through login, project setup, and launches Claude
32
32
 
33
33
  ## Updates
34
34
 
35
- The CLI auto-updates in the background. After your one-time `npm install -g gipity`, every run silently checks npm for a new version and installs it into `~/.gipity/local/` no sudo, no re-running install commands. The new version takes effect on your next invocation.
35
+ The CLI auto-updates in the background. After your one-time `npm install -g gipity`, every run silently checks npm for a new version and installs it into `~/.gipity/local/` - no sudo, no re-running install commands. The new version takes effect on your next invocation.
36
36
 
37
37
  ```bash
38
38
  gipity doctor # show install version, last update check, opt-out status
@@ -75,7 +75,7 @@ That's it. You'll see:
75
75
 
76
76
  If you're already logged in, it skips straight to project setup. If you already have a project in the current directory, it skips straight to launching Claude Code.
77
77
 
78
- Projects live in `~/GipityProjects/{project-slug}/` created automatically on first use. Any extra flags (like `--dangerously-skip-permissions`, `--model opus`, etc.) get passed through to Claude.
78
+ Projects live in `~/GipityProjects/{project-slug}/` - created automatically on first use. Any extra flags (like `--dangerously-skip-permissions`, `--model opus`, etc.) get passed through to Claude.
79
79
 
80
80
  ### The manual way
81
81
 
@@ -93,11 +93,11 @@ claude
93
93
 
94
94
  This is the good part. When you run `gipity init` in a project, it sets up two hooks in `.claude/settings.json`:
95
95
 
96
- **Auto-push** Every time Claude Code writes or edits a file, it gets pushed to Gipity in the background. No extra steps.
96
+ **Auto-push** - Every time Claude Code writes or edits a file, it gets pushed to Gipity in the background. No extra steps.
97
97
 
98
- **Auto-pull** Before each turn, Claude Code pulls any changes that happened remotely (like if your Gipity agent built something via chat). Claude sees what changed and can pick up where things left off.
98
+ **Auto-pull** - Before each turn, Claude Code pulls any changes that happened remotely (like if your Gipity agent built something via chat). Claude sees what changed and can pick up where things left off.
99
99
 
100
- That means Claude Code and your Gipity agent share the same files, same project, same context. You get the best of both Claude Code for hands-on coding, Gipity for autonomous agent work.
100
+ That means Claude Code and your Gipity agent share the same files, same project, same context. You get the best of both - Claude Code for hands-on coding, Gipity for autonomous agent work.
101
101
 
102
102
  ### What gets set up
103
103
 
@@ -122,7 +122,7 @@ gipity sync down # Pull remote changes
122
122
 
123
123
  | Command | What it does |
124
124
  |---------|-------------|
125
- | `gipity claude` | Log in, pick a project, and launch Claude Code all in one |
125
+ | `gipity claude` | Log in, pick a project, and launch Claude Code - all in one |
126
126
  | `gipity login` | Authenticate with email + verification code |
127
127
  | `gipity init` | Set up a Gipity project and configure Claude Code |
128
128
  | `gipity status` | Show project, agent, and auth info |
@@ -135,6 +135,7 @@ gipity sync down # Pull remote changes
135
135
  | `gipity sandbox run <code>` | Execute code in a sandboxed container |
136
136
  | `gipity project` | List, create, switch, or delete projects |
137
137
  | `gipity agent` | List, create, switch, or configure agents |
138
+ | `gipity approval` | List, create, answer, or cancel pending approvals |
138
139
  | `gipity workflow` | Manage and trigger automated workflows |
139
140
  | `gipity file` | Browse remote files (ls, cat, tree) |
140
141
  | `gipity scaffold [title]` | Create app structure (`--type web`, `--type 2d-game`, or `--type 3d-world`) |
@@ -146,9 +147,11 @@ gipity sync down # Pull remote changes
146
147
  | `gipity rbac` | Manage RBAC policies |
147
148
  | `gipity audit` | Query audit logs |
148
149
  | `gipity credits` | Check your balance and usage |
149
- | `gipity skills` | List and manage agent skills |
150
+ | `gipity skill` | List and manage agent skills |
151
+ | `gipity chat [list\|rename\|archive\|delete]` | Manage chats (or `gipity chat <message>` to send) |
152
+ | `gipity gmail [send\|reply\|search\|read]` | Send/read via your own Gmail (different from `gipity email`) |
150
153
  | `gipity domain` | Manage custom domains for deployed apps |
151
- | `gipity email` | Send emails via your agent |
154
+ | `gipity email [send]` | Send emails from the platform (gipity@gipity.ai) |
152
155
  | `gipity generate` | Generate images, audio, or video via your agent |
153
156
  | `gipity logout` | Sign out and clear local tokens |
154
157
 
@@ -253,7 +256,7 @@ Your login tokens. Created by `gipity login`. Tokens auto-refresh so you shouldn
253
256
 
254
257
  ## Questions?
255
258
 
256
- Reach out anytime steve@gipity.ai
259
+ Reach out anytime - steve@gipity.ai
257
260
 
258
261
  This is early and moving fast. If something's broken or confusing, I want to hear about it.
259
262
 
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,176 @@
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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adopt-cwd.test.js","sourceRoot":"","sources":["../../src/__tests__/adopt-cwd.test.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * `gipity claude -p "msg"` / `--print` non-interactive passthrough mode.
2
+ * `gipity claude -p "msg"` / `--print` - non-interactive passthrough mode.
3
3
  *
4
4
  * Exercises the early-exit preconditions (must be logged in + must have a
5
5
  * project in cwd) since the success path shells out to `claude` which isn't
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,76 @@
1
+ import { test, before, after } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { runCliAsync } from './helpers/spawn-cli.js';
4
+ import { startMockServer } from './helpers/mock-server.js';
5
+ import { makeAuthedHome, makeProjectDir } from './helpers/test-home.js';
6
+ let mock;
7
+ let home;
8
+ const AGENT_A = { short_guid: 'a_AgentA0n0', name: 'Alice', is_default: 1, model_preference: 'claude-sonnet-4-6', temperature: 0.7, voice_id: null, voice_provider: null, created_at: '2026-01-01T00:00:00Z' };
9
+ const AGENT_B = { short_guid: 'a_AgentB0n0', name: 'Bob', is_default: 0, model_preference: null, temperature: null, voice_id: null, voice_provider: null, created_at: '2026-02-01T00:00:00Z' };
10
+ before(async () => {
11
+ mock = await startMockServer();
12
+ home = makeAuthedHome();
13
+ });
14
+ after(async () => { await mock.stop(); });
15
+ /** Each test gets a fresh project dir so config writes (e.g. agent switch) don't bleed. */
16
+ function inProject(args, agentGuid = AGENT_A.short_guid) {
17
+ const projectDir = makeProjectDir({ apiBase: mock.apiBase, agentGuid });
18
+ return runCliAsync(['--api-base', mock.apiBase, ...args], { env: { HOME: home }, cwd: projectDir });
19
+ }
20
+ test('gipity agent (bare) lists agents and stars the active one', async () => {
21
+ mock.reset();
22
+ mock.on('GET /agents', { body: { data: [AGENT_A, AGENT_B] } });
23
+ const r = await inProject(['agent']);
24
+ assert.equal(r.status, 0, r.stderr);
25
+ assert.match(r.stdout, /Alice/);
26
+ assert.match(r.stdout, /Bob/);
27
+ assert.doesNotMatch(r.stdout, /undefined/);
28
+ });
29
+ test('gipity agent <name> switches to that agent', async () => {
30
+ mock.reset();
31
+ mock.on('GET /agents', { body: { data: [AGENT_A, AGENT_B] } });
32
+ const r = await inProject(['agent', 'Bob']);
33
+ assert.equal(r.status, 0, r.stderr);
34
+ assert.match(r.stdout, /Switched to Bob/);
35
+ });
36
+ test('gipity agent create <name> POSTs and prints created message', async () => {
37
+ mock.reset();
38
+ mock.on('POST /agents', { status: 201, body: { data: { ...AGENT_B, name: 'Carol', short_guid: 'a_NewCarol00' } } });
39
+ const r = await inProject(['agent', 'create', 'Carol']);
40
+ assert.equal(r.status, 0, r.stderr);
41
+ assert.match(r.stdout, /Created "Carol"/);
42
+ assert.doesNotMatch(r.stdout, /undefined/);
43
+ });
44
+ test('gipity agent set model sends PUT with the value', async () => {
45
+ mock.reset();
46
+ mock.on('PUT /agents/a_AgentA0n0', { body: { data: AGENT_A } });
47
+ const r = await inProject(['agent', 'set', 'model', 'claude-opus-4-7']);
48
+ assert.equal(r.status, 0, r.stderr);
49
+ assert.match(r.stdout, /Set model = claude-opus-4-7/);
50
+ });
51
+ test('gipity agent rename sends PUT and prints renamed line', async () => {
52
+ mock.reset();
53
+ mock.on('PUT /agents/a_AgentA0n0', { body: { data: AGENT_A } });
54
+ const r = await inProject(['agent', 'rename', 'Alicia']);
55
+ assert.equal(r.status, 0, r.stderr);
56
+ assert.match(r.stdout, /Renamed.*Alicia/);
57
+ });
58
+ test('gipity agent info shows name + model + created date', async () => {
59
+ mock.reset();
60
+ mock.on('GET /agents/a_AgentA0n0', { body: { data: AGENT_A } });
61
+ const r = await inProject(['agent', 'info']);
62
+ assert.equal(r.status, 0, r.stderr);
63
+ assert.match(r.stdout, /Name:\s+Alice/);
64
+ assert.match(r.stdout, /Model:\s+claude-sonnet-4-6/);
65
+ assert.doesNotMatch(r.stdout, /undefined/);
66
+ });
67
+ test('gipity agent delete --yes calls DELETE and prints deleted line', async () => {
68
+ mock.reset();
69
+ mock.on('GET /agents', { body: { data: [AGENT_A, AGENT_B] } });
70
+ mock.on('DELETE /agents/a_AgentB0n0', { body: { data: { deleted: true } } });
71
+ // delete prompts for confirmation; pass --yes via the global flag
72
+ const r = await inProject(['--yes', 'agent', 'delete', 'Bob']);
73
+ assert.equal(r.status, 0, r.stderr);
74
+ assert.match(r.stdout, /Deleted "Bob"/);
75
+ });
76
+ //# sourceMappingURL=cli-cmd-agent.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-cmd-agent.test.js","sourceRoot":"","sources":["../../src/__tests__/cli-cmd-agent.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAc,MAAM,0BAA0B,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExE,IAAI,IAAgB,CAAC;AACrB,IAAI,IAAY,CAAC;AAEjB,MAAM,OAAO,GAAG,EAAE,UAAU,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,WAAW,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,UAAU,EAAE,sBAAsB,EAAE,CAAC;AAC/M,MAAM,OAAO,GAAG,EAAE,UAAU,EAAE,aAAa,EAAE,IAAI,EAAE,KAAK,EAAI,UAAU,EAAE,CAAC,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,UAAU,EAAE,sBAAsB,EAAE,CAAC;AAEjM,MAAM,CAAC,KAAK,IAAI,EAAE;IAChB,IAAI,GAAG,MAAM,eAAe,EAAE,CAAC;IAC/B,IAAI,GAAG,cAAc,EAAE,CAAC;AAC1B,CAAC,CAAC,CAAC;AAEH,KAAK,CAAC,KAAK,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAE1C,2FAA2F;AAC3F,SAAS,SAAS,CAAC,IAAc,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU;IAC/D,MAAM,UAAU,GAAG,cAAc,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;IACxE,OAAO,WAAW,CAAC,CAAC,YAAY,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC;AACtG,CAAC;AAED,IAAI,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;IAC3E,IAAI,CAAC,KAAK,EAAE,CAAC;IACb,IAAI,CAAC,EAAE,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;IAC/D,MAAM,CAAC,GAAG,MAAM,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACrC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC9B,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAC7C,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;IAC5D,IAAI,CAAC,KAAK,EAAE,CAAC;IACb,IAAI,CAAC,EAAE,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;IAC/D,MAAM,CAAC,GAAG,MAAM,SAAS,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;IAC5C,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;AAC5C,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;IAC7E,IAAI,CAAC,KAAK,EAAE,CAAC;IACb,IAAI,CAAC,EAAE,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC,CAAC;IACpH,MAAM,CAAC,GAAG,MAAM,SAAS,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;IACxD,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAC1C,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAC7C,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;IACjE,IAAI,CAAC,KAAK,EAAE,CAAC;IACb,IAAI,CAAC,EAAE,CAAC,yBAAyB,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;IAChE,MAAM,CAAC,GAAG,MAAM,SAAS,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC;IACxE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,6BAA6B,CAAC,CAAC;AACxD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;IACvE,IAAI,CAAC,KAAK,EAAE,CAAC;IACb,IAAI,CAAC,EAAE,CAAC,yBAAyB,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;IAChE,MAAM,CAAC,GAAG,MAAM,SAAS,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;IACzD,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;AAC5C,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;IACrE,IAAI,CAAC,KAAK,EAAE,CAAC;IACb,IAAI,CAAC,EAAE,CAAC,yBAAyB,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;IAChE,MAAM,CAAC,GAAG,MAAM,SAAS,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7C,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACxC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,4BAA4B,CAAC,CAAC;IACrD,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAC7C,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;IAChF,IAAI,CAAC,KAAK,EAAE,CAAC;IACb,IAAI,CAAC,EAAE,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;IAC/D,IAAI,CAAC,EAAE,CAAC,4BAA4B,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IAC7E,kEAAkE;IAClE,MAAM,CAAC,GAAG,MAAM,SAAS,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;IAC/D,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;AAC1C,CAAC,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,47 @@
1
+ import { test, before, after } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { runCliAsync } from './helpers/spawn-cli.js';
4
+ import { startMockServer } from './helpers/mock-server.js';
5
+ import { makeAuthedHome } from './helpers/test-home.js';
6
+ let mock;
7
+ let home;
8
+ before(async () => { mock = await startMockServer(); home = makeAuthedHome(); });
9
+ after(async () => { await mock.stop(); });
10
+ function run(args) {
11
+ return runCliAsync(['--api-base', mock.apiBase, ...args], { env: { HOME: home } });
12
+ }
13
+ test('gipity approval list shows pending approvals with status', async () => {
14
+ mock.reset();
15
+ mock.on('GET /approvals', { body: { data: [
16
+ { guid: 'ap_Approv001', title: 'Deploy to prod?', status: 'pending', response_type: 'yes_no', choices: null, created_at: new Date(Date.now() - 5 * 60_000).toISOString() },
17
+ ] } });
18
+ const r = await run(['approval', 'list']);
19
+ assert.equal(r.status, 0, r.stderr);
20
+ assert.match(r.stdout, /ap_Approv001/);
21
+ assert.match(r.stdout, /Deploy to prod\?/);
22
+ assert.match(r.stdout, /pending/);
23
+ assert.doesNotMatch(r.stdout, /undefined/);
24
+ });
25
+ test('gipity approval create POSTs and prints created guid', async () => {
26
+ mock.reset();
27
+ mock.on('POST /approvals', { status: 201, body: { data: { guid: 'ap_NewApprov0' } } });
28
+ const r = await run(['approval', 'create', 'Test', 'approval']);
29
+ assert.equal(r.status, 0, r.stderr);
30
+ assert.match(r.stdout, /Created ap_NewApprov0/);
31
+ });
32
+ test('gipity approval answer a (approve) resolves a yes_no approval', async () => {
33
+ mock.reset();
34
+ mock.on('GET /approvals/ap_Approv001', { body: { data: { response_type: 'yes_no', choices: null } } });
35
+ mock.on('POST /approvals/ap_Approv001/resolve', { body: { data: { resolved: true } } });
36
+ const r = await run(['approval', 'answer', 'ap_Approv001', 'a']);
37
+ assert.equal(r.status, 0, r.stderr);
38
+ assert.match(r.stdout, /Approved/);
39
+ });
40
+ test('gipity approval cancel <guid> POSTs cancel + prints cancelled', async () => {
41
+ mock.reset();
42
+ mock.on('POST /approvals/ap_Approv001/cancel', { body: { data: { cancelled: true } } });
43
+ const r = await run(['approval', 'cancel', 'ap_Approv001']);
44
+ assert.equal(r.status, 0, r.stderr);
45
+ assert.match(r.stdout, /Cancelled ap_Approv001/);
46
+ });
47
+ //# sourceMappingURL=cli-cmd-approval.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-cmd-approval.test.js","sourceRoot":"","sources":["../../src/__tests__/cli-cmd-approval.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,33 @@
1
+ import { test, before, after } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { runCliAsync } from './helpers/spawn-cli.js';
4
+ import { startMockServer } from './helpers/mock-server.js';
5
+ import { makeAuthedHome, makeProjectDir } from './helpers/test-home.js';
6
+ let mock;
7
+ let home;
8
+ before(async () => { mock = await startMockServer(); home = makeAuthedHome(); });
9
+ after(async () => { await mock.stop(); });
10
+ function fresh(args) {
11
+ const d = makeProjectDir({ apiBase: mock.apiBase });
12
+ return runCliAsync(['--api-base', mock.apiBase, ...args], { env: { HOME: home }, cwd: d });
13
+ }
14
+ test('gipity audit list shows events with timestamp + type', async () => {
15
+ mock.reset();
16
+ mock.on('GET /projects/p_TestProj/audit', { body: { data: [
17
+ { event_type: 'record.create', action: 'create', entity_type: 'incidents', entity_id: '42', created_at: '2026-05-01T10:00:00Z' },
18
+ { event_type: 'record.delete', action: 'delete', entity_type: 'incidents', entity_id: '7', created_at: '2026-05-02T10:00:00Z' },
19
+ ] } });
20
+ const r = await fresh(['audit', 'list']);
21
+ assert.equal(r.status, 0, r.stderr);
22
+ assert.match(r.stdout, /record\.create/);
23
+ assert.match(r.stdout, /incidents:42/);
24
+ assert.doesNotMatch(r.stdout, /undefined/);
25
+ });
26
+ test('gipity audit count prints "N events"', async () => {
27
+ mock.reset();
28
+ mock.on('GET /projects/p_TestProj/audit/count', { body: { data: { count: 137 } } });
29
+ const r = await fresh(['audit', 'count']);
30
+ assert.equal(r.status, 0, r.stderr);
31
+ assert.match(r.stdout, /137 events/);
32
+ });
33
+ //# sourceMappingURL=cli-cmd-audit.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-cmd-audit.test.js","sourceRoot":"","sources":["../../src/__tests__/cli-cmd-audit.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAc,MAAM,0BAA0B,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExE,IAAI,IAAgB,CAAC;AACrB,IAAI,IAAY,CAAC;AAEjB,MAAM,CAAC,KAAK,IAAI,EAAE,GAAG,IAAI,GAAG,MAAM,eAAe,EAAE,CAAC,CAAC,IAAI,GAAG,cAAc,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AACjF,KAAK,CAAC,KAAK,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAE1C,SAAS,KAAK,CAAC,IAAc;IAC3B,MAAM,CAAC,GAAG,cAAc,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IACpD,OAAO,WAAW,CAAC,CAAC,YAAY,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;AAC7F,CAAC;AAED,IAAI,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;IACtE,IAAI,CAAC,KAAK,EAAE,CAAC;IACb,IAAI,CAAC,EAAE,CAAC,gCAAgC,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE;gBACxD,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,sBAAsB,EAAE;gBAChI,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,EAAG,UAAU,EAAE,sBAAsB,EAAE;aACjI,EAAE,EAAE,CAAC,CAAC;IACP,MAAM,CAAC,GAAG,MAAM,KAAK,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IACzC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACzC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACvC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAC7C,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;IACtD,IAAI,CAAC,KAAK,EAAE,CAAC;IACb,IAAI,CAAC,EAAE,CAAC,sCAAsC,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;IACpF,MAAM,CAAC,GAAG,MAAM,KAAK,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1C,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;AACvC,CAAC,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,63 @@
1
+ import { test, before, after } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { runCliAsync } from './helpers/spawn-cli.js';
4
+ import { startMockServer } from './helpers/mock-server.js';
5
+ import { makeAuthedHome, makeProjectDir } from './helpers/test-home.js';
6
+ let mock;
7
+ let home;
8
+ before(async () => { mock = await startMockServer(); home = makeAuthedHome(); });
9
+ after(async () => { await mock.stop(); });
10
+ function fresh(args) {
11
+ const d = makeProjectDir({ apiBase: mock.apiBase });
12
+ return runCliAsync(['--api-base', mock.apiBase, ...args], { env: { HOME: home }, cwd: d });
13
+ }
14
+ test('gipity chat <message> posts and prints agent response', async () => {
15
+ mock.reset();
16
+ mock.on('POST /conversations', { body: { data: {
17
+ content: 'Hello back!',
18
+ conversationGuid: 'c_NewConv001',
19
+ messageGuid: 'm_New000000',
20
+ model: 'claude-sonnet-4-6',
21
+ inputTokens: 10, outputTokens: 5, costUsd: 0.0001,
22
+ filesChanged: false,
23
+ toolsUsed: [],
24
+ } } });
25
+ const r = await fresh(['chat', 'Hi there']);
26
+ assert.equal(r.status, 0, r.stderr);
27
+ assert.match(r.stdout, /Hello back!/);
28
+ assert.doesNotMatch(r.stdout, /undefined/);
29
+ });
30
+ test('gipity chat list shows recent conversations', async () => {
31
+ mock.reset();
32
+ mock.on('GET /conversations', { body: { data: [
33
+ { short_guid: 'c_Conv00001', title: 'Bug triage', updated_at: '2026-05-01T00:00:00Z' },
34
+ { short_guid: 'c_Conv00002', title: null, updated_at: '2026-04-01T00:00:00Z' },
35
+ ] } });
36
+ const r = await fresh(['chat', 'list']);
37
+ assert.equal(r.status, 0, r.stderr);
38
+ assert.match(r.stdout, /c_Conv00001/);
39
+ assert.match(r.stdout, /Bug triage/);
40
+ assert.match(r.stdout, /\(untitled\)/);
41
+ });
42
+ test('gipity chat rename <guid> <title> sends PUT and prints renamed', async () => {
43
+ mock.reset();
44
+ mock.on('PUT /conversations/c_Conv00001', { body: { data: { renamed: true } } });
45
+ const r = await fresh(['chat', 'rename', 'c_Conv00001', 'New', 'title']);
46
+ assert.equal(r.status, 0, r.stderr);
47
+ assert.match(r.stdout, /Renamed c_Conv00001/);
48
+ });
49
+ test('gipity chat archive <guid> sends PUT', async () => {
50
+ mock.reset();
51
+ mock.on('PUT /conversations/c_Conv00001', { body: { data: { archived: true } } });
52
+ const r = await fresh(['chat', 'archive', 'c_Conv00001']);
53
+ assert.equal(r.status, 0, r.stderr);
54
+ assert.match(r.stdout, /Archived c_Conv00001/);
55
+ });
56
+ test('gipity chat delete <guid> sends DELETE', async () => {
57
+ mock.reset();
58
+ mock.on('DELETE /conversations/c_Conv00001', { body: { data: { deleted: true } } });
59
+ const r = await fresh(['chat', 'delete', 'c_Conv00001']);
60
+ assert.equal(r.status, 0, r.stderr);
61
+ assert.match(r.stdout, /Deleted c_Conv00001/);
62
+ });
63
+ //# sourceMappingURL=cli-cmd-chat.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-cmd-chat.test.js","sourceRoot":"","sources":["../../src/__tests__/cli-cmd-chat.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};