gipity 1.0.48
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.
- package/LICENSE +21 -0
- package/README.md +234 -0
- package/dist/__tests__/config.test.d.ts +1 -0
- package/dist/__tests__/config.test.js +31 -0
- package/dist/__tests__/config.test.js.map +1 -0
- package/dist/__tests__/sync.test.d.ts +1 -0
- package/dist/__tests__/sync.test.js +89 -0
- package/dist/__tests__/sync.test.js.map +1 -0
- package/dist/__tests__/utils.test.d.ts +1 -0
- package/dist/__tests__/utils.test.js +69 -0
- package/dist/__tests__/utils.test.js.map +1 -0
- package/dist/api.d.ts +13 -0
- package/dist/api.js +85 -0
- package/dist/api.js.map +1 -0
- package/dist/auth.d.ts +12 -0
- package/dist/auth.js +90 -0
- package/dist/auth.js.map +1 -0
- package/dist/coding-guidelines.d.ts +9 -0
- package/dist/coding-guidelines.js +52 -0
- package/dist/coding-guidelines.js.map +1 -0
- package/dist/commands/agent.d.ts +2 -0
- package/dist/commands/agent.js +164 -0
- package/dist/commands/agent.js.map +1 -0
- package/dist/commands/api.d.ts +2 -0
- package/dist/commands/api.js +137 -0
- package/dist/commands/api.js.map +1 -0
- package/dist/commands/audit.d.ts +2 -0
- package/dist/commands/audit.js +70 -0
- package/dist/commands/audit.js.map +1 -0
- package/dist/commands/browser.d.ts +2 -0
- package/dist/commands/browser.js +88 -0
- package/dist/commands/browser.js.map +1 -0
- package/dist/commands/chat.d.ts +2 -0
- package/dist/commands/chat.js +68 -0
- package/dist/commands/chat.js.map +1 -0
- package/dist/commands/checkpoint.d.ts +2 -0
- package/dist/commands/checkpoint.js +67 -0
- package/dist/commands/checkpoint.js.map +1 -0
- package/dist/commands/credits.d.ts +2 -0
- package/dist/commands/credits.js +57 -0
- package/dist/commands/credits.js.map +1 -0
- package/dist/commands/db.d.ts +2 -0
- package/dist/commands/db.js +102 -0
- package/dist/commands/db.js.map +1 -0
- package/dist/commands/deploy.d.ts +2 -0
- package/dist/commands/deploy.js +49 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/file.d.ts +2 -0
- package/dist/commands/file.js +85 -0
- package/dist/commands/file.js.map +1 -0
- package/dist/commands/fn.d.ts +2 -0
- package/dist/commands/fn.js +87 -0
- package/dist/commands/fn.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.js +107 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/login.d.ts +2 -0
- package/dist/commands/login.js +62 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.d.ts +2 -0
- package/dist/commands/logout.js +14 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/logs.d.ts +2 -0
- package/dist/commands/logs.js +39 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/memory.d.ts +2 -0
- package/dist/commands/memory.js +114 -0
- package/dist/commands/memory.js.map +1 -0
- package/dist/commands/project.d.ts +2 -0
- package/dist/commands/project.js +132 -0
- package/dist/commands/project.js.map +1 -0
- package/dist/commands/push.d.ts +2 -0
- package/dist/commands/push.js +34 -0
- package/dist/commands/push.js.map +1 -0
- package/dist/commands/rbac.d.ts +2 -0
- package/dist/commands/rbac.js +89 -0
- package/dist/commands/rbac.js.map +1 -0
- package/dist/commands/records.d.ts +2 -0
- package/dist/commands/records.js +131 -0
- package/dist/commands/records.js.map +1 -0
- package/dist/commands/sandbox.d.ts +2 -0
- package/dist/commands/sandbox.js +53 -0
- package/dist/commands/sandbox.js.map +1 -0
- package/dist/commands/scaffold.d.ts +2 -0
- package/dist/commands/scaffold.js +38 -0
- package/dist/commands/scaffold.js.map +1 -0
- package/dist/commands/start-cc.d.ts +2 -0
- package/dist/commands/start-cc.js +201 -0
- package/dist/commands/start-cc.js.map +1 -0
- package/dist/commands/status.d.ts +2 -0
- package/dist/commands/status.js +43 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/sync.d.ts +2 -0
- package/dist/commands/sync.js +42 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/workflow.d.ts +2 -0
- package/dist/commands/workflow.js +163 -0
- package/dist/commands/workflow.js.map +1 -0
- package/dist/config.d.ts +15 -0
- package/dist/config.js +76 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +65 -0
- package/dist/index.js.map +1 -0
- package/dist/setup.d.ts +23 -0
- package/dist/setup.js +168 -0
- package/dist/setup.js.map +1 -0
- package/dist/sync.d.ts +34 -0
- package/dist/sync.js +234 -0
- package/dist/sync.js.map +1 -0
- package/dist/utils.d.ts +10 -0
- package/dist/utils.js +57 -0
- package/dist/utils.js.map +1 -0
- package/hooks/post-write.sh +17 -0
- package/hooks/pre-turn.sh +20 -0
- package/package.json +29 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Gipity
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
# Gipity CLI
|
|
2
|
+
|
|
3
|
+
Connect AI coding agents to the Gipity platform. Built for [Claude Code](https://claude.ai/claude-code) and works great from your terminal too.
|
|
4
|
+
|
|
5
|
+
Gipity gives your AI agent a persistent workspace with file storage, databases, code execution, deployment, memory, workflows, and more. This CLI is the bridge.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g @gipity/cli
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Requires Node 18+.
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
One command. It walks you through login, project setup, and drops you into Claude Code.
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
gipity start-cc --dangerously-skip-permissions
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
That's it. You'll see:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
Welcome to Gipity
|
|
27
|
+
─────────────────
|
|
28
|
+
|
|
29
|
+
Email: you@example.com
|
|
30
|
+
Check your email for a 6-digit code.
|
|
31
|
+
|
|
32
|
+
Code: 482910
|
|
33
|
+
Authenticated as you@example.com
|
|
34
|
+
|
|
35
|
+
Your projects:
|
|
36
|
+
1. my-website (my-website)
|
|
37
|
+
2. Create new project
|
|
38
|
+
|
|
39
|
+
Choose (1-2): 2
|
|
40
|
+
Project name [project01]: cool-app
|
|
41
|
+
Creating "cool-app"...
|
|
42
|
+
Created.
|
|
43
|
+
|
|
44
|
+
Launching Claude Code...
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
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.
|
|
48
|
+
|
|
49
|
+
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.
|
|
50
|
+
|
|
51
|
+
### The manual way
|
|
52
|
+
|
|
53
|
+
If you prefer to do things step by step:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
gipity login --email you@example.com
|
|
57
|
+
gipity login --code 123456
|
|
58
|
+
cd my-project
|
|
59
|
+
gipity init
|
|
60
|
+
claude
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Claude Code Integration
|
|
64
|
+
|
|
65
|
+
This is the good part. When you run `gipity init` in a project, it sets up two hooks in `.claude/settings.json`:
|
|
66
|
+
|
|
67
|
+
**Auto-push** — Every time Claude Code writes or edits a file, it gets pushed to Gipity in the background. No extra steps.
|
|
68
|
+
|
|
69
|
+
**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.
|
|
70
|
+
|
|
71
|
+
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.
|
|
72
|
+
|
|
73
|
+
### What gets set up
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
.gipity.json # Project config (which project, which agent)
|
|
77
|
+
.gipity/ # Local sync state (gitignored)
|
|
78
|
+
.claude/settings.json # Hooks for auto-push and auto-pull
|
|
79
|
+
CLAUDE.md # Gipity commands reference for Claude Code
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Manual sync
|
|
83
|
+
|
|
84
|
+
If you ever need to sync manually:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
gipity sync check # See what's different
|
|
88
|
+
gipity sync up # Push local changes
|
|
89
|
+
gipity sync down # Pull remote changes
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Commands
|
|
93
|
+
|
|
94
|
+
| Command | What it does |
|
|
95
|
+
|---------|-------------|
|
|
96
|
+
| `gipity start-cc` | Log in, pick a project, and launch Claude Code — all in one |
|
|
97
|
+
| `gipity login` | Authenticate with email + verification code |
|
|
98
|
+
| `gipity init` | Set up a Gipity project and configure Claude Code |
|
|
99
|
+
| `gipity status` | Show project, agent, and auth info |
|
|
100
|
+
| `gipity sync` | Sync files between local and Gipity |
|
|
101
|
+
| `gipity push <file>` | Push a single file |
|
|
102
|
+
| `gipity deploy [dev\|prod]` | Deploy your project to the web |
|
|
103
|
+
| `gipity chat <message>` | Send a message to your Gipity agent |
|
|
104
|
+
| `gipity db` | Query, list, or create project databases |
|
|
105
|
+
| `gipity memory` | Read/write agent and project memory |
|
|
106
|
+
| `gipity sandbox run <code>` | Execute code in a sandboxed container |
|
|
107
|
+
| `gipity api` | Define and manage API procedures |
|
|
108
|
+
| `gipity project` | List, create, switch, or delete projects |
|
|
109
|
+
| `gipity agent` | List, create, switch, or configure agents |
|
|
110
|
+
| `gipity workflow` | Manage and trigger automated workflows |
|
|
111
|
+
| `gipity file` | Browse remote files (ls, cat, tree) |
|
|
112
|
+
| `gipity scaffold [title]` | Create web app structure (HTML, CSS, JS, favicons) |
|
|
113
|
+
| `gipity checkpoint` | List or restore file snapshots (undo) |
|
|
114
|
+
| `gipity logs fn <name>` | View function execution logs |
|
|
115
|
+
| `gipity browser <url>` | Inspect a URL: console errors, performance, failed resources |
|
|
116
|
+
| `gipity records` | Query and manage Records API tables |
|
|
117
|
+
| `gipity fn` | Manage and call sandboxed functions |
|
|
118
|
+
| `gipity rbac` | Manage RBAC policies |
|
|
119
|
+
| `gipity audit` | Query audit logs |
|
|
120
|
+
| `gipity credits` | Check your balance and usage |
|
|
121
|
+
|
|
122
|
+
Every command supports `--json` for scripted/programmatic use.
|
|
123
|
+
|
|
124
|
+
### deploy
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
gipity deploy # Deploy to dev (dev.gipity.ai)
|
|
128
|
+
gipity deploy prod # Deploy to production (app.gipity.ai)
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Your project gets a live URL at `https://dev.gipity.ai/{account}/{project}/`.
|
|
132
|
+
|
|
133
|
+
### chat
|
|
134
|
+
|
|
135
|
+
Talk to your Gipity agent from the terminal. If the agent creates or modifies files, they sync back automatically.
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
gipity chat "Build me a landing page"
|
|
139
|
+
gipity chat "Add a contact form" --new # Start a fresh conversation
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### db
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
gipity db list
|
|
146
|
+
gipity db query "SELECT * FROM users LIMIT 10"
|
|
147
|
+
gipity db query "SELECT * FROM orders" --database my_app_db
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### memory
|
|
151
|
+
|
|
152
|
+
Agent memory persists across all conversations. Project memory is scoped to one project.
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
gipity memory list
|
|
156
|
+
gipity memory read preferences
|
|
157
|
+
gipity memory write api_keys "stripe: sk_live_..."
|
|
158
|
+
gipity memory write design_notes "use dark theme" --project
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### sandbox
|
|
162
|
+
|
|
163
|
+
Run code in a sandboxed Docker container with no network access. JavaScript, Python, and Bash.
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
gipity sandbox run "console.log('Hello')"
|
|
167
|
+
gipity sandbox run "import pandas; print(pandas.__version__)" --lang py
|
|
168
|
+
gipity sandbox run "echo hello" --lang bash
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### api
|
|
172
|
+
|
|
173
|
+
Define SQL-backed API endpoints that your deployed apps can call.
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
gipity api list
|
|
177
|
+
gipity api define get_users --sql "SELECT * FROM users" --database mydb --auth public
|
|
178
|
+
gipity api define create_post --sql @queries/create_post.sql --database mydb --method write
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### workflow
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
gipity workflow # List workflows
|
|
185
|
+
gipity workflow run daily_report # Trigger manually
|
|
186
|
+
gipity workflow enable daily_report # Turn on cron schedule
|
|
187
|
+
gipity workflow runs daily_report # View recent runs
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### agent
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
gipity agent # List agents
|
|
194
|
+
gipity agent create "Research Bot" # Create a new agent
|
|
195
|
+
gipity agent set model claude-opus # Change the model
|
|
196
|
+
gipity agent "Research Bot" # Switch active agent
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### project
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
gipity project # List projects
|
|
203
|
+
gipity project create "My App" # Create new project
|
|
204
|
+
gipity project my-app # Switch active project
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Project Config
|
|
208
|
+
|
|
209
|
+
### `.gipity.json`
|
|
210
|
+
|
|
211
|
+
Created by `gipity init`. Links your local directory to a Gipity project.
|
|
212
|
+
|
|
213
|
+
```json
|
|
214
|
+
{
|
|
215
|
+
"projectGuid": "prj-a1b2c3d4",
|
|
216
|
+
"projectSlug": "my-app",
|
|
217
|
+
"accountSlug": "steve",
|
|
218
|
+
"agentGuid": "agt-x1y2z3w4",
|
|
219
|
+
"apiBase": "https://a.gipity.ai",
|
|
220
|
+
"ignore": ["node_modules", ".git", "dist", ".env"]
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### `~/.gipity/auth.json`
|
|
225
|
+
|
|
226
|
+
Your login tokens. Created by `gipity login`. Tokens auto-refresh so you shouldn't need to log in again unless you've been away for a week.
|
|
227
|
+
|
|
228
|
+
## Questions?
|
|
229
|
+
|
|
230
|
+
Reach out anytime — steve@gipity.ai
|
|
231
|
+
|
|
232
|
+
This is early and moving fast. If something's broken or confusing, I want to hear about it.
|
|
233
|
+
|
|
234
|
+
-- Steve Iverson
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { describe, it } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { shouldIgnore } from '../config.js';
|
|
4
|
+
describe('shouldIgnore', () => {
|
|
5
|
+
const patterns = ['node_modules', '.git', '.gipity.json', '.gipity/', '.claude/', '*.log'];
|
|
6
|
+
it('ignores exact match', () => {
|
|
7
|
+
assert.equal(shouldIgnore('.gipity.json', patterns), true);
|
|
8
|
+
});
|
|
9
|
+
it('ignores directory name anywhere in path', () => {
|
|
10
|
+
assert.equal(shouldIgnore('node_modules', patterns), true);
|
|
11
|
+
assert.equal(shouldIgnore('src/node_modules/foo.js', patterns), true);
|
|
12
|
+
assert.equal(shouldIgnore('.git', patterns), true);
|
|
13
|
+
});
|
|
14
|
+
it('ignores prefix match with trailing slash', () => {
|
|
15
|
+
assert.equal(shouldIgnore('.gipity/sync-state.json', patterns), true);
|
|
16
|
+
assert.equal(shouldIgnore('.claude/settings.json', patterns), true);
|
|
17
|
+
});
|
|
18
|
+
it('ignores extension match', () => {
|
|
19
|
+
assert.equal(shouldIgnore('app.log', patterns), true);
|
|
20
|
+
assert.equal(shouldIgnore('logs/error.log', patterns), true);
|
|
21
|
+
});
|
|
22
|
+
it('does not ignore non-matching paths', () => {
|
|
23
|
+
assert.equal(shouldIgnore('src/index.ts', patterns), false);
|
|
24
|
+
assert.equal(shouldIgnore('package.json', patterns), false);
|
|
25
|
+
assert.equal(shouldIgnore('README.md', patterns), false);
|
|
26
|
+
});
|
|
27
|
+
it('handles empty patterns', () => {
|
|
28
|
+
assert.equal(shouldIgnore('anything.ts', []), false);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
//# sourceMappingURL=config.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.test.js","sourceRoot":"","sources":["../../src/__tests__/config.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,MAAM,QAAQ,GAAG,CAAC,cAAc,EAAE,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IAE3F,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,cAAc,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,cAAc,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC;QAC3D,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,yBAAyB,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC;QACtE,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,yBAAyB,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC;QACtE,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,uBAAuB,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACjC,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC;QACtD,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,gBAAgB,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,cAAc,EAAE,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC;QAC5D,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,cAAc,EAAE,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC;QAC5D,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,WAAW,EAAE,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAChC,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,aAAa,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { describe, it } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { diffManifest, formatDiff } from '../sync.js';
|
|
4
|
+
const remoteFiles = [
|
|
5
|
+
{ path: 'src/index.html', size: 500, modified: '2024-01-01', type: 'file', guid: 'f1' },
|
|
6
|
+
{ path: 'src/app.js', size: 1200, modified: '2024-01-01', type: 'file', guid: 'f2' },
|
|
7
|
+
{ path: 'src/styles.css', size: 300, modified: '2024-01-01', type: 'file', guid: 'f3' },
|
|
8
|
+
{ path: 'src/', size: 0, modified: '2024-01-01', type: 'directory', guid: 'd1' },
|
|
9
|
+
];
|
|
10
|
+
describe('diffManifest — down', () => {
|
|
11
|
+
it('detects added files (remote has, local lacks)', () => {
|
|
12
|
+
const local = new Map();
|
|
13
|
+
const changes = diffManifest(remoteFiles, local, 'down');
|
|
14
|
+
const added = changes.filter(c => c.type === 'added');
|
|
15
|
+
assert.equal(added.length, 3);
|
|
16
|
+
});
|
|
17
|
+
it('detects modified files (size mismatch)', () => {
|
|
18
|
+
const local = new Map([
|
|
19
|
+
['src/index.html', { size: 999, modified: '2024-01-01' }],
|
|
20
|
+
['src/app.js', { size: 1200, modified: '2024-01-01' }],
|
|
21
|
+
['src/styles.css', { size: 300, modified: '2024-01-01' }],
|
|
22
|
+
]);
|
|
23
|
+
const changes = diffManifest(remoteFiles, local, 'down');
|
|
24
|
+
assert.equal(changes.length, 1);
|
|
25
|
+
assert.equal(changes[0].type, 'modified');
|
|
26
|
+
assert.equal(changes[0].path, 'src/index.html');
|
|
27
|
+
});
|
|
28
|
+
it('detects deleted files (local has, remote lacks)', () => {
|
|
29
|
+
const local = new Map([
|
|
30
|
+
['src/index.html', { size: 500, modified: '2024-01-01' }],
|
|
31
|
+
['src/app.js', { size: 1200, modified: '2024-01-01' }],
|
|
32
|
+
['src/styles.css', { size: 300, modified: '2024-01-01' }],
|
|
33
|
+
['src/old.js', { size: 100, modified: '2024-01-01' }],
|
|
34
|
+
]);
|
|
35
|
+
const changes = diffManifest(remoteFiles, local, 'down');
|
|
36
|
+
const deleted = changes.filter(c => c.type === 'deleted');
|
|
37
|
+
assert.equal(deleted.length, 1);
|
|
38
|
+
assert.equal(deleted[0].path, 'src/old.js');
|
|
39
|
+
});
|
|
40
|
+
it('returns empty when in sync', () => {
|
|
41
|
+
const local = new Map([
|
|
42
|
+
['src/index.html', { size: 500, modified: '2024-01-01' }],
|
|
43
|
+
['src/app.js', { size: 1200, modified: '2024-01-01' }],
|
|
44
|
+
['src/styles.css', { size: 300, modified: '2024-01-01' }],
|
|
45
|
+
]);
|
|
46
|
+
const changes = diffManifest(remoteFiles, local, 'down');
|
|
47
|
+
assert.equal(changes.length, 0);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
describe('diffManifest — up', () => {
|
|
51
|
+
it('detects locally added files', () => {
|
|
52
|
+
const local = new Map([
|
|
53
|
+
['src/index.html', { size: 500, modified: '2024-01-01' }],
|
|
54
|
+
['src/app.js', { size: 1200, modified: '2024-01-01' }],
|
|
55
|
+
['src/styles.css', { size: 300, modified: '2024-01-01' }],
|
|
56
|
+
['src/new.js', { size: 200, modified: '2024-01-01' }],
|
|
57
|
+
]);
|
|
58
|
+
const changes = diffManifest(remoteFiles, local, 'up');
|
|
59
|
+
const added = changes.filter(c => c.type === 'added');
|
|
60
|
+
assert.equal(added.length, 1);
|
|
61
|
+
assert.equal(added[0].path, 'src/new.js');
|
|
62
|
+
});
|
|
63
|
+
it('detects locally deleted files', () => {
|
|
64
|
+
const local = new Map([
|
|
65
|
+
['src/index.html', { size: 500, modified: '2024-01-01' }],
|
|
66
|
+
]);
|
|
67
|
+
const changes = diffManifest(remoteFiles, local, 'up');
|
|
68
|
+
const deleted = changes.filter(c => c.type === 'deleted');
|
|
69
|
+
assert.equal(deleted.length, 2); // app.js and styles.css
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
describe('formatDiff', () => {
|
|
73
|
+
it('returns no changes message when empty', () => {
|
|
74
|
+
assert.equal(formatDiff([], 'down'), 'No changes detected.');
|
|
75
|
+
});
|
|
76
|
+
it('formats changes with counts', () => {
|
|
77
|
+
const changes = [
|
|
78
|
+
{ type: 'added', path: 'src/new.js', remoteSize: 100 },
|
|
79
|
+
{ type: 'modified', path: 'src/app.js', localSize: 1000, remoteSize: 1200 },
|
|
80
|
+
{ type: 'deleted', path: 'src/old.js', localSize: 50 },
|
|
81
|
+
];
|
|
82
|
+
const output = formatDiff(changes, 'down');
|
|
83
|
+
assert.ok(output.includes('3 changes'));
|
|
84
|
+
assert.ok(output.includes('+ src/new.js'));
|
|
85
|
+
assert.ok(output.includes('~ src/app.js'));
|
|
86
|
+
assert.ok(output.includes('- src/old.js'));
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
//# sourceMappingURL=sync.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.test.js","sourceRoot":"","sources":["../../src/__tests__/sync.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { describe, it } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { decodeJwtExp, isBinaryFile, formatSize, formatAge } from '../utils.js';
|
|
4
|
+
describe('decodeJwtExp', () => {
|
|
5
|
+
it('extracts exp from a valid JWT', () => {
|
|
6
|
+
// Header: {"alg":"HS256"}, Payload: {"exp":1700000000}, Signature: fake
|
|
7
|
+
const header = Buffer.from('{"alg":"HS256"}').toString('base64url');
|
|
8
|
+
const payload = Buffer.from('{"exp":1700000000}').toString('base64url');
|
|
9
|
+
const token = `${header}.${payload}.fakesig`;
|
|
10
|
+
assert.equal(decodeJwtExp(token), 1700000000);
|
|
11
|
+
});
|
|
12
|
+
it('returns null for malformed token', () => {
|
|
13
|
+
assert.equal(decodeJwtExp('not.a.jwt'), null);
|
|
14
|
+
assert.equal(decodeJwtExp(''), null);
|
|
15
|
+
assert.equal(decodeJwtExp('onlyone'), null);
|
|
16
|
+
});
|
|
17
|
+
it('returns null when exp is missing', () => {
|
|
18
|
+
const header = Buffer.from('{"alg":"HS256"}').toString('base64url');
|
|
19
|
+
const payload = Buffer.from('{"sub":"user"}').toString('base64url');
|
|
20
|
+
const token = `${header}.${payload}.fakesig`;
|
|
21
|
+
assert.equal(decodeJwtExp(token), null);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
describe('isBinaryFile', () => {
|
|
25
|
+
it('detects binary files (null bytes)', () => {
|
|
26
|
+
const buf = Buffer.from([0x48, 0x65, 0x00, 0x6c, 0x6f]);
|
|
27
|
+
assert.equal(isBinaryFile(buf), true);
|
|
28
|
+
});
|
|
29
|
+
it('detects text files', () => {
|
|
30
|
+
const buf = Buffer.from('Hello, world!', 'utf-8');
|
|
31
|
+
assert.equal(isBinaryFile(buf), false);
|
|
32
|
+
});
|
|
33
|
+
it('handles empty buffer', () => {
|
|
34
|
+
assert.equal(isBinaryFile(Buffer.alloc(0)), false);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
describe('formatSize', () => {
|
|
38
|
+
it('formats bytes', () => {
|
|
39
|
+
assert.equal(formatSize(0), '0 B');
|
|
40
|
+
assert.equal(formatSize(512), '512 B');
|
|
41
|
+
assert.equal(formatSize(1023), '1023 B');
|
|
42
|
+
});
|
|
43
|
+
it('formats kilobytes', () => {
|
|
44
|
+
assert.equal(formatSize(1024), '1.0 KB');
|
|
45
|
+
assert.equal(formatSize(1536), '1.5 KB');
|
|
46
|
+
});
|
|
47
|
+
it('formats megabytes', () => {
|
|
48
|
+
assert.equal(formatSize(1048576), '1.0 MB');
|
|
49
|
+
assert.equal(formatSize(2621440), '2.5 MB');
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
describe('formatAge', () => {
|
|
53
|
+
it('returns "just now" for recent timestamps', () => {
|
|
54
|
+
assert.equal(formatAge(new Date().toISOString()), 'just now');
|
|
55
|
+
});
|
|
56
|
+
it('returns minutes ago', () => {
|
|
57
|
+
const fiveMinAgo = new Date(Date.now() - 5 * 60 * 1000).toISOString();
|
|
58
|
+
assert.equal(formatAge(fiveMinAgo), '5m ago');
|
|
59
|
+
});
|
|
60
|
+
it('returns hours ago', () => {
|
|
61
|
+
const threeHoursAgo = new Date(Date.now() - 3 * 60 * 60 * 1000).toISOString();
|
|
62
|
+
assert.equal(formatAge(threeHoursAgo), '3h ago');
|
|
63
|
+
});
|
|
64
|
+
it('returns days ago', () => {
|
|
65
|
+
const twoDaysAgo = new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString();
|
|
66
|
+
assert.equal(formatAge(twoDaysAgo), '2d ago');
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
//# sourceMappingURL=utils.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.test.js","sourceRoot":"","sources":["../../src/__tests__/utils.test.ts"],"names":[],"mappings":"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"}
|
package/dist/api.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare class ApiError extends Error {
|
|
2
|
+
statusCode: number;
|
|
3
|
+
code: string;
|
|
4
|
+
constructor(statusCode: number, code: string, message: string);
|
|
5
|
+
}
|
|
6
|
+
export declare function get<T>(path: string): Promise<T>;
|
|
7
|
+
export declare function post<T>(path: string, body?: unknown): Promise<T>;
|
|
8
|
+
export declare function put<T>(path: string, body?: unknown): Promise<T>;
|
|
9
|
+
export declare function del<T>(path: string, body?: unknown): Promise<T>;
|
|
10
|
+
/** Send a message via the conversation API, reusing or creating a conversation. Returns content string. */
|
|
11
|
+
export declare function sendMessage(message: string): Promise<string>;
|
|
12
|
+
/** Unauthenticated request (for login/verify) */
|
|
13
|
+
export declare function publicPost<T>(path: string, body: unknown): Promise<T>;
|
package/dist/api.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { getAuth, refreshTokenIfNeeded } from './auth.js';
|
|
2
|
+
import { getConfig, requireConfig, saveConfig } from './config.js';
|
|
3
|
+
export class ApiError extends Error {
|
|
4
|
+
statusCode;
|
|
5
|
+
code;
|
|
6
|
+
constructor(statusCode, code, message) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.statusCode = statusCode;
|
|
9
|
+
this.code = code;
|
|
10
|
+
this.name = 'ApiError';
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
async function getHeaders() {
|
|
14
|
+
await refreshTokenIfNeeded();
|
|
15
|
+
const auth = getAuth();
|
|
16
|
+
if (!auth)
|
|
17
|
+
throw new Error('Not authenticated. Run: gipity login');
|
|
18
|
+
return {
|
|
19
|
+
'Authorization': `Bearer ${auth.accessToken}`,
|
|
20
|
+
'Content-Type': 'application/json',
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function baseUrl() {
|
|
24
|
+
const config = getConfig();
|
|
25
|
+
return config?.apiBase || 'https://a.gipity.ai';
|
|
26
|
+
}
|
|
27
|
+
async function request(method, path, body) {
|
|
28
|
+
const headers = await getHeaders();
|
|
29
|
+
const url = `${baseUrl()}${path}`;
|
|
30
|
+
const res = await fetch(url, {
|
|
31
|
+
method,
|
|
32
|
+
headers,
|
|
33
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
34
|
+
});
|
|
35
|
+
if (!res.ok) {
|
|
36
|
+
const json = await res.json().catch(() => ({ error: { code: 'UNKNOWN', message: res.statusText } }));
|
|
37
|
+
const err = json.error || { code: 'UNKNOWN', message: res.statusText };
|
|
38
|
+
throw new ApiError(res.status, err.code, err.message);
|
|
39
|
+
}
|
|
40
|
+
return res.json();
|
|
41
|
+
}
|
|
42
|
+
export function get(path) {
|
|
43
|
+
return request('GET', path);
|
|
44
|
+
}
|
|
45
|
+
export function post(path, body) {
|
|
46
|
+
return request('POST', path, body);
|
|
47
|
+
}
|
|
48
|
+
export function put(path, body) {
|
|
49
|
+
return request('PUT', path, body);
|
|
50
|
+
}
|
|
51
|
+
export function del(path, body) {
|
|
52
|
+
return request('DELETE', path, body);
|
|
53
|
+
}
|
|
54
|
+
/** Send a message via the conversation API, reusing or creating a conversation. Returns content string. */
|
|
55
|
+
export async function sendMessage(message) {
|
|
56
|
+
const config = requireConfig();
|
|
57
|
+
const useExisting = !!config.conversationGuid;
|
|
58
|
+
const endpoint = useExisting
|
|
59
|
+
? `/conversations/${config.conversationGuid}/messages`
|
|
60
|
+
: '/conversations';
|
|
61
|
+
const body = useExisting
|
|
62
|
+
? { content: message }
|
|
63
|
+
: { agentGuid: config.agentGuid, content: message, projectGuid: config.projectGuid };
|
|
64
|
+
const res = await post(endpoint, body);
|
|
65
|
+
if (res.data.conversationGuid !== config.conversationGuid) {
|
|
66
|
+
saveConfig({ ...config, conversationGuid: res.data.conversationGuid });
|
|
67
|
+
}
|
|
68
|
+
return res.data.content;
|
|
69
|
+
}
|
|
70
|
+
/** Unauthenticated request (for login/verify) */
|
|
71
|
+
export async function publicPost(path, body) {
|
|
72
|
+
const url = `${baseUrl()}${path}`;
|
|
73
|
+
const res = await fetch(url, {
|
|
74
|
+
method: 'POST',
|
|
75
|
+
headers: { 'Content-Type': 'application/json' },
|
|
76
|
+
body: JSON.stringify(body),
|
|
77
|
+
});
|
|
78
|
+
if (!res.ok) {
|
|
79
|
+
const json = await res.json().catch(() => ({ error: { code: 'UNKNOWN', message: res.statusText } }));
|
|
80
|
+
const err = json.error || { code: 'UNKNOWN', message: res.statusText };
|
|
81
|
+
throw new ApiError(res.status, err.code, err.message);
|
|
82
|
+
}
|
|
83
|
+
return res.json();
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=api.js.map
|
package/dist/api.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface AuthData {
|
|
2
|
+
accessToken: string;
|
|
3
|
+
refreshToken: string;
|
|
4
|
+
email: string;
|
|
5
|
+
expiresAt: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function getAuth(): AuthData | null;
|
|
8
|
+
export declare function saveAuth(data: AuthData): void;
|
|
9
|
+
export declare function clearAuth(): void;
|
|
10
|
+
export declare function isExpired(): boolean;
|
|
11
|
+
export declare function getTimeRemaining(): string;
|
|
12
|
+
export declare function refreshTokenIfNeeded(): Promise<void>;
|