gipity 1.0.365 → 1.0.374
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/dist/banner.js +3 -1
- package/dist/commands/add.js +2 -2
- package/dist/commands/agent.js +3 -5
- package/dist/commands/approval.js +3 -3
- package/dist/commands/audit.js +2 -2
- package/dist/commands/chat.js +4 -4
- package/dist/commands/claude.js +8 -9
- package/dist/commands/credits.js +1 -1
- package/dist/commands/db.js +7 -6
- package/dist/commands/deploy.js +5 -8
- package/dist/commands/doctor.js +11 -13
- package/dist/commands/domain.js +18 -15
- package/dist/commands/email.js +0 -4
- package/dist/commands/fn.js +2 -2
- package/dist/commands/generate.js +57 -5
- package/dist/commands/job.js +6 -6
- package/dist/commands/location.js +7 -7
- package/dist/commands/login.js +2 -16
- package/dist/commands/logout.js +2 -3
- package/dist/commands/logs.js +1 -1
- package/dist/commands/page-eval.js +6 -4
- package/dist/commands/page-fetch.js +136 -0
- package/dist/commands/page-inspect.js +29 -27
- package/dist/commands/page-screenshot.js +17 -18
- package/dist/commands/page-test.js +8 -8
- package/dist/commands/page.js +6 -3
- package/dist/commands/plan.js +4 -4
- package/dist/commands/push.js +2 -6
- package/dist/commands/realtime.js +7 -9
- package/dist/commands/relay-install.js +18 -21
- package/dist/commands/relay.js +29 -31
- package/dist/commands/sandbox.js +16 -3
- package/dist/commands/service.js +1 -3
- package/dist/commands/status.js +2 -2
- package/dist/commands/sync.js +4 -1
- package/dist/commands/test.js +7 -13
- package/dist/commands/text.js +10 -10
- package/dist/commands/uninstall.js +20 -42
- package/dist/commands/update.js +0 -2
- package/dist/commands/upload.js +4 -4
- package/dist/commands/workflow.js +1 -2
- package/dist/helpers/output.js +45 -7
- package/dist/index.js +4 -0
- package/dist/knowledge.js +19 -4
- package/dist/progress.js +60 -0
- package/dist/project-setup.js +5 -1
- package/dist/provider-docs.js +7 -7
- package/dist/setup.js +20 -7
- package/dist/sync.js +16 -6
- package/dist/updater/shim.js +18 -4
- package/dist/upload.js +6 -0
- package/package.json +5 -4
package/dist/commands/upload.js
CHANGED
|
@@ -78,7 +78,7 @@ export const uploadCommand = new Command('upload')
|
|
|
78
78
|
const totalBytes = planned.reduce((s, f) => s + f.size, 0);
|
|
79
79
|
console.log(`Plan: ${planned.length} file${planned.length > 1 ? 's' : ''}, ${formatSize(totalBytes)}`);
|
|
80
80
|
for (const f of planned) {
|
|
81
|
-
console.log(
|
|
81
|
+
console.log(`${f.localPath} ${dim('→')} ${f.virtualPath} (${formatSize(f.size)})`);
|
|
82
82
|
}
|
|
83
83
|
if (opts.dryRun) {
|
|
84
84
|
console.log('\n--dry-run: skipping all network calls.');
|
|
@@ -100,15 +100,15 @@ export const uploadCommand = new Command('upload')
|
|
|
100
100
|
const result = await uploadOneFile(config.projectGuid, f.localPath, f.virtualPath, uploadOpts);
|
|
101
101
|
if (result.status === 'skipped') {
|
|
102
102
|
skipped++;
|
|
103
|
-
console.log(
|
|
103
|
+
console.log(`${dim('skip')} ${f.virtualPath} (already current)`);
|
|
104
104
|
}
|
|
105
105
|
else if (result.status === 'resumed') {
|
|
106
106
|
resumed++;
|
|
107
|
-
console.log(
|
|
107
|
+
console.log(`${dim('resumed')} ${f.virtualPath} v${result.version}`);
|
|
108
108
|
}
|
|
109
109
|
else {
|
|
110
110
|
uploaded++;
|
|
111
|
-
console.log(
|
|
111
|
+
console.log(`${dim('uploaded')} ${f.virtualPath} v${result.version}`);
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
catch (err) {
|
|
@@ -10,7 +10,6 @@ async function listWorkflows(opts) {
|
|
|
10
10
|
return;
|
|
11
11
|
}
|
|
12
12
|
if (res.meta) {
|
|
13
|
-
console.log('');
|
|
14
13
|
console.log(`Active workflows: ${res.meta.activeCount}/${res.meta.activeLimit}`);
|
|
15
14
|
}
|
|
16
15
|
printList(res.data, opts, 'No workflows.', w => {
|
|
@@ -51,7 +50,7 @@ workflowCommand
|
|
|
51
50
|
if (w.steps && w.steps.length > 0) {
|
|
52
51
|
console.log(`Steps:`);
|
|
53
52
|
for (const s of w.steps) {
|
|
54
|
-
console.log(
|
|
53
|
+
console.log(`${s.step_order}. ${s.name}${s.model ? ` [${s.model}]` : ''}`);
|
|
55
54
|
}
|
|
56
55
|
}
|
|
57
56
|
}
|
package/dist/helpers/output.js
CHANGED
|
@@ -1,7 +1,47 @@
|
|
|
1
|
+
/** Whether the in-flight command opened a non-JSON output frame (leading blank
|
|
2
|
+
* printed, trailing blank still owed). Module-level so the process-exit handler
|
|
3
|
+
* can close a frame even when a command ends via process.exit() and so skips
|
|
4
|
+
* the postAction hook. */
|
|
5
|
+
let frameOpen = false;
|
|
1
6
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
7
|
+
* Bracket every human (non-JSON) command's stdout with exactly one leading and
|
|
8
|
+
* one trailing blank line, so output is visually separated from the shell
|
|
9
|
+
* prompt and consistent across commands. JSON output is left untouched so it
|
|
10
|
+
* stays pipe/parse-clean.
|
|
11
|
+
*
|
|
12
|
+
* Centralizing the frame here is what lets individual commands stop printing
|
|
13
|
+
* their own leading/trailing blank lines (and stops them doubling up at the
|
|
14
|
+
* boundaries). Call once on the root program; Commander runs these lifecycle
|
|
15
|
+
* hooks for the actual subcommand action too.
|
|
4
16
|
*/
|
|
17
|
+
export function installOutputFrame(program) {
|
|
18
|
+
// Only decorate a real terminal. When stdout is piped or redirected (a relay
|
|
19
|
+
// capturing stream-json, `| less`, tests), leave it byte-clean - same policy
|
|
20
|
+
// colors.ts uses for ANSI. This keeps headless `claude -p` stdout empty.
|
|
21
|
+
if (!process.stdout.isTTY)
|
|
22
|
+
return;
|
|
23
|
+
program.hook('preAction', (_thisCommand, actionCommand) => {
|
|
24
|
+
const opts = actionCommand.optsWithGlobals
|
|
25
|
+
? actionCommand.optsWithGlobals()
|
|
26
|
+
: actionCommand.opts();
|
|
27
|
+
if (opts.json)
|
|
28
|
+
return; // never decorate machine output
|
|
29
|
+
process.stdout.write('\n');
|
|
30
|
+
frameOpen = true;
|
|
31
|
+
});
|
|
32
|
+
program.hook('postAction', () => {
|
|
33
|
+
if (frameOpen) {
|
|
34
|
+
process.stdout.write('\n');
|
|
35
|
+
frameOpen = false;
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
// Commands that finish via process.exit() never reach postAction; close the
|
|
39
|
+
// frame from the exit handler instead (sync write, fires on every exit path).
|
|
40
|
+
process.on('exit', () => {
|
|
41
|
+
if (frameOpen)
|
|
42
|
+
process.stdout.write('\n');
|
|
43
|
+
});
|
|
44
|
+
}
|
|
5
45
|
/**
|
|
6
46
|
* Print data as JSON or formatted text.
|
|
7
47
|
* Handles the ubiquitous `if (opts.json) { ... } else { ... }` pattern.
|
|
@@ -14,15 +54,14 @@ export function printOutput(data, opts, formatter) {
|
|
|
14
54
|
console.log(formatter(data));
|
|
15
55
|
}
|
|
16
56
|
}
|
|
17
|
-
/** Print a one-line
|
|
57
|
+
/** Print a one-line result message (text mode only). The surrounding blank
|
|
58
|
+
* lines come from the central output frame, not from here. */
|
|
18
59
|
export function printResult(text, opts, jsonData) {
|
|
19
60
|
if (opts.json) {
|
|
20
61
|
console.log(JSON.stringify(jsonData ?? { success: true }));
|
|
21
62
|
return;
|
|
22
63
|
}
|
|
23
|
-
console.log('');
|
|
24
64
|
console.log(text);
|
|
25
|
-
console.log('');
|
|
26
65
|
}
|
|
27
66
|
/**
|
|
28
67
|
* Print a list with JSON mode, empty state, and per-item formatting.
|
|
@@ -33,7 +72,7 @@ export function printList(data, opts, emptyMsg, formatter, header) {
|
|
|
33
72
|
console.log(JSON.stringify(data));
|
|
34
73
|
return;
|
|
35
74
|
}
|
|
36
|
-
|
|
75
|
+
// Surrounding blank lines come from the central output frame.
|
|
37
76
|
if (data.length === 0) {
|
|
38
77
|
console.log(emptyMsg);
|
|
39
78
|
}
|
|
@@ -48,6 +87,5 @@ export function printList(data, opts, emptyMsg, formatter, header) {
|
|
|
48
87
|
console.log(formatter(item));
|
|
49
88
|
}
|
|
50
89
|
}
|
|
51
|
-
console.log('');
|
|
52
90
|
}
|
|
53
91
|
//# sourceMappingURL=output.js.map
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import { fileURLToPath } from 'url';
|
|
|
5
5
|
import { dirname, resolve } from 'path';
|
|
6
6
|
import { setApiBaseOverride } from './config.js';
|
|
7
7
|
import { setAutoConfirm } from './utils.js';
|
|
8
|
+
import { installOutputFrame } from './helpers/output.js';
|
|
8
9
|
import { GIPITY_TAGLINE } from './knowledge.js';
|
|
9
10
|
import { getAuth, getTimeRemaining, isExpired } from './auth.js';
|
|
10
11
|
import { loginCommand } from './commands/login.js';
|
|
@@ -130,6 +131,9 @@ program.hook('preAction', () => {
|
|
|
130
131
|
if (globalOpts.yes)
|
|
131
132
|
setAutoConfirm(true);
|
|
132
133
|
});
|
|
134
|
+
// Bracket non-JSON command output with leading/trailing blank lines centrally,
|
|
135
|
+
// so commands never hand-roll their own boundary spacing.
|
|
136
|
+
installOutputFrame(program);
|
|
133
137
|
// ── Custom top-level help: version banner + grouped commands ────────────
|
|
134
138
|
program.configureHelp({
|
|
135
139
|
formatHelp(cmd, helper) {
|
package/dist/knowledge.js
CHANGED
|
@@ -40,7 +40,7 @@ Prefer the cheapest option that works - CLI and sandbox are instant and free, ap
|
|
|
40
40
|
|
|
41
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\`.
|
|
42
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.
|
|
43
|
-
3. App services - runtime HTTP endpoints your deployed app calls directly at \`https://a.gipity.ai/api/<PROJECT_GUID>/services/*\`. Available: LLM, TTS, image, sound, music, transcribe, video, file upload, realtime, location. Load the matching skill (\`app-llm\`, \`app-tts\`, etc.) before writing service code - they have the schemas, auth pattern, and common-mistake guards. For one-off generation during development, prefer \`gipity generate <image|video
|
|
43
|
+
3. App services - runtime HTTP endpoints your deployed app calls directly at \`https://a.gipity.ai/api/<PROJECT_GUID>/services/*\`. Available: LLM, TTS, image, sound, music, transcribe, video, file upload, realtime, location. Load the matching skill (\`app-llm\`, \`app-tts\`, etc.) before writing service code - they have the schemas, auth pattern, and common-mistake guards. For one-off generation during development, prefer \`gipity generate <image|video|speech|music>\` or \`gipity chat\`.
|
|
44
44
|
4. Delegate to Gip (\`gipity chat "<task>"\`) - only when the work genuinely needs agent reasoning or a tool not in the CLI, sandbox, or app services. Required for: Twitter/X search, Gmail, calendar, push notifications, video understanding, audio source isolation, cross-model second opinions, multi-step orchestration. Don't use \`gipity chat\` for anything the sandbox can do - it's slower and burns tokens.
|
|
45
45
|
|
|
46
46
|
You are the developer. Write files in this directory - they auto-sync to Gipity via hooks. Don't run \`npm install\`, \`npm start\`, \`node\`, or \`python\` locally; there is no local runtime. Code runs in the Gipity sandbox.
|
|
@@ -49,6 +49,20 @@ You are the developer. Write files in this directory - they auto-sync to Gipity
|
|
|
49
49
|
|
|
50
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.
|
|
51
51
|
|
|
52
|
+
## Gipity is opinionated - build on its stack
|
|
53
|
+
|
|
54
|
+
Gipity is an opinionated platform with its own best-practice stack, and that stack is the one you use - whatever tools the user names. The platform layer is fixed:
|
|
55
|
+
|
|
56
|
+
- **Frontend**: plain HTML + CSS + vanilla ES modules from a Gipity template. No React, Next, Vue, Svelte, or any build-step framework.
|
|
57
|
+
- **Backend**: Gipity serverless functions (\`functions/<name>.js\`). No Express, Next API routes, Django, Rails.
|
|
58
|
+
- **Database**: Gipity DB (Postgres) with raw SQL via the function \`db\` API. No MS SQL Server, MySQL, MongoDB, Firebase, or an ORM (Prisma/Drizzle/Sequelize).
|
|
59
|
+
- **Styling**: the template's CSS (Water.css + the Gipity theme). No Tailwind or other build-time CSS frameworks.
|
|
60
|
+
- **Hosting, auth, file storage, realtime, and the generative services** are first-party (see above).
|
|
61
|
+
|
|
62
|
+
When a user asks for a foreign stack ("build it in React", "use MS SQL Server", "set up Firebase auth"), don't silently comply and don't argue the app down. Build it the Gipity way and reassure them: Gipity has its own opinionated stack and best practices, it's what makes apps here fast to build and deploy, and you'll use it to make their app great. Say it briefly and warmly, then get building - the result satisfies the *intent* behind the request (a great hiking app, a working CRM) without the named technology.
|
|
63
|
+
|
|
64
|
+
The one exception is app-level libraries the user imports into their own \`src/\` code - Three.js, Rapier, Phaser, MediaPipe, a charting or animation library. Those are fine. The opinionation is about the *platform* layer (framework, backend, database, styling system, hosting, auth, services), not every npm package.
|
|
65
|
+
|
|
52
66
|
## When to add a template
|
|
53
67
|
|
|
54
68
|
The full rule and definition of done are injected at the top of every session context. In short: if the user asks you to build something deployable (web app, game, API), run \`gipity add <template>\` first (default \`web-simple\`); if it's a one-off task (analysis, PDFs, data work), use \`gipity sandbox run\` instead. To add a reusable building block to an existing app (e.g. multiplayer), \`gipity add <kit>\`.
|
|
@@ -83,9 +97,9 @@ App services skills (load before calling \`/services/*\` endpoints):
|
|
|
83
97
|
- \`app-image\` - providers, sizes, aspect ratios
|
|
84
98
|
- \`app-llm\` - chat completions, streaming, image input
|
|
85
99
|
- \`app-location\` - user location & reverse geocoding for deployed apps (first-party - no third-party geocoder)
|
|
86
|
-
- \`app-realtime\` -
|
|
100
|
+
- \`app-realtime\` - Gipity Realtime rooms, relay vs state
|
|
87
101
|
- \`app-tts\` - voices, multi-speaker, languages
|
|
88
|
-
- \`app-video\` -
|
|
102
|
+
- \`app-video\` - Gipity Video: models, aspect, resolution
|
|
89
103
|
|
|
90
104
|
App development skills:
|
|
91
105
|
- \`app-debugging\` - debug a deployed app: page inspect/eval, screenshots, function logs
|
|
@@ -106,7 +120,8 @@ export const DEFINITION_OF_DONE = `## Definition of done (build tasks)
|
|
|
106
120
|
1. \`gipity deploy dev\` succeeds and you have a live URL.
|
|
107
121
|
2. \`gipity page inspect <url>\` returns no console errors and the page loads (HTTP 200, no blank screen).
|
|
108
122
|
3. For apps with functions: \`gipity test\` passes.
|
|
109
|
-
4.
|
|
123
|
+
4. Non-rendered files the task called for (\`llms.txt\`, \`AGENTS.md\`, \`SKILL.md\`, \`robots.txt\`, served JSON, etc.): \`page inspect\` only sees rendered HTML, so verify them with \`gipity page fetch <url> <files...>\`. It flags any that 404 or come back as the static-host shell (a missing file is served as \`index.html\` with a 200, so a bare status check would pass) and checks each \`content-type\`.
|
|
124
|
+
5. You told the user the live URL.
|
|
110
125
|
|
|
111
126
|
If any step fails, fix it before claiming done - do not report success on a broken deploy.`;
|
|
112
127
|
export const GIPITY_TAGLINE = `The full-stack platform tuned for AI agents.`;
|
package/dist/progress.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// ── Gipity CLI Progress Reporter ────────────────────────────────────────
|
|
2
|
+
// One central place for long-running terminal feedback, so commands don't
|
|
3
|
+
// each reinvent status lines. Two channels:
|
|
4
|
+
//
|
|
5
|
+
// phase(msg) - a discrete step with no measurable size
|
|
6
|
+
// (scanning, hashing). Prints one committed line.
|
|
7
|
+
// transfer(label, n, tot) - a determinate byte transfer. Renders a single
|
|
8
|
+
// in-place bar that updates as bytes move.
|
|
9
|
+
//
|
|
10
|
+
// On a non-TTY (piped output, hook-driven sync, headless -p) the reporter is a
|
|
11
|
+
// silent no-op - no `\r` spam in logs. Colors come from ./colors so the bar
|
|
12
|
+
// matches the rest of the CLI (orange fill + percentage).
|
|
13
|
+
import { brand, brandBold, muted, dim } from './colors.js';
|
|
14
|
+
import { formatSize } from './utils.js';
|
|
15
|
+
const CLEAR_TO_EOL = '\x1b[K';
|
|
16
|
+
const BAR_WIDTH = 18;
|
|
17
|
+
const RENDER_THROTTLE_MS = 60;
|
|
18
|
+
class TerminalProgress {
|
|
19
|
+
/** True while an in-place transfer line is on screen and not yet committed. */
|
|
20
|
+
liveOpen = false;
|
|
21
|
+
lastRenderAt = 0;
|
|
22
|
+
phase(message) {
|
|
23
|
+
this.commitLive();
|
|
24
|
+
process.stdout.write(` ${muted(message)}\n`);
|
|
25
|
+
}
|
|
26
|
+
transfer(label, doneBytes, totalBytes) {
|
|
27
|
+
const finished = totalBytes > 0 && doneBytes >= totalBytes;
|
|
28
|
+
// Throttle mid-flight redraws; always paint the first and final frames.
|
|
29
|
+
const now = Date.now();
|
|
30
|
+
if (this.liveOpen && !finished && now - this.lastRenderAt < RENDER_THROTTLE_MS)
|
|
31
|
+
return;
|
|
32
|
+
this.lastRenderAt = now;
|
|
33
|
+
this.liveOpen = true;
|
|
34
|
+
process.stdout.write('\r' + this.frame(label, doneBytes, totalBytes) + CLEAR_TO_EOL);
|
|
35
|
+
if (finished)
|
|
36
|
+
this.commitLive();
|
|
37
|
+
}
|
|
38
|
+
finish() {
|
|
39
|
+
this.commitLive();
|
|
40
|
+
}
|
|
41
|
+
commitLive() {
|
|
42
|
+
if (!this.liveOpen)
|
|
43
|
+
return;
|
|
44
|
+
process.stdout.write('\n');
|
|
45
|
+
this.liveOpen = false;
|
|
46
|
+
}
|
|
47
|
+
frame(label, done, total) {
|
|
48
|
+
const pct = total > 0 ? Math.min(100, Math.floor((done / total) * 100)) : 100;
|
|
49
|
+
const filled = Math.round((pct / 100) * BAR_WIDTH);
|
|
50
|
+
const bar = brand('█'.repeat(filled)) + dim('░'.repeat(BAR_WIDTH - filled));
|
|
51
|
+
const sizes = muted(`${formatSize(done)} / ${formatSize(total)}`);
|
|
52
|
+
return ` ${muted(label)} ${bar} ${brandBold(`${pct}%`)} ${sizes}`;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const NOOP = { phase() { }, transfer() { }, finish() { } };
|
|
56
|
+
/** A reporter that draws on a TTY and stays silent otherwise. */
|
|
57
|
+
export function createProgressReporter() {
|
|
58
|
+
return process.stdout.isTTY ? new TerminalProgress() : NOOP;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=progress.js.map
|
package/dist/project-setup.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { clearConfigCache, saveConfigAt, getApiBaseOverride } from './config.js';
|
|
8
8
|
import { sync } from './sync.js';
|
|
9
|
+
import { createProgressReporter } from './progress.js';
|
|
9
10
|
import { setupClaudeHooks, setupGitignore, SUPPORTED_TOOLS, DEFAULT_SYNC_IGNORE } from './setup.js';
|
|
10
11
|
import { substituteDir } from './template-vars.js';
|
|
11
12
|
import { muted } from './colors.js';
|
|
@@ -49,7 +50,10 @@ export async function finalizeLocalProject(opts) {
|
|
|
49
50
|
}
|
|
50
51
|
let applied = 0;
|
|
51
52
|
try {
|
|
52
|
-
const result = await sync({
|
|
53
|
+
const result = await sync({
|
|
54
|
+
interactive: opts.interactive ?? false,
|
|
55
|
+
progress: createProgressReporter(),
|
|
56
|
+
});
|
|
53
57
|
applied = result.applied;
|
|
54
58
|
}
|
|
55
59
|
catch (err) {
|
package/dist/provider-docs.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Source: platform/server/src/config/constants/provider-docs.ts
|
|
6
6
|
* Run `just sync-docs` to refresh from platform.
|
|
7
7
|
*/
|
|
8
|
-
export const GEMINI_LLM_MODELS_DOC = `gemini-
|
|
8
|
+
export const GEMINI_LLM_MODELS_DOC = `gemini-3.5-flash (Gemini 3.5 Flash, $1.5/$9 per 1M tok, 1049K ctx), gemini-3.1-pro-preview (Gemini 3.1 Pro, $2/$12 per 1M tok, 1049K ctx), gemini-3.1-flash-lite (Gemini 3.1 Flash-Lite, $0.25/$1.5 per 1M tok, 1049K ctx), gemini-3-flash-preview (Gemini 3 Flash, $0.5/$3 per 1M tok, 1049K ctx), gemini-2.5-pro (Gemini 2.5 Pro, $1.25/$10 per 1M tok, 1049K ctx), gemini-2.5-flash (Gemini 2.5 Flash, $0.3/$2.5 per 1M tok, 1049K ctx), gemini-2.5-flash-lite (Gemini 2.5 Flash-Lite, $0.1/$0.4 per 1M tok, 1049K ctx)`;
|
|
9
9
|
export const GEMINI_TTS_VOICES = [
|
|
10
10
|
'Zephyr',
|
|
11
11
|
'Puck',
|
|
@@ -42,17 +42,17 @@ export const GEMINI_TTS_VOICES_DOC = `Zephyr, Puck, Charon, Kore, Fenrir, Leda,
|
|
|
42
42
|
export const GEMINI_TTS_VOICES_SHORT = `Kore, Puck, Zephyr, Charon, Fenrir, Leda, Orus, Aoede, and 22 more`;
|
|
43
43
|
export const IMAGE_GEMINI_ASPECT_RATIOS = `1:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:3, 4:5, 5:4, 21:9`;
|
|
44
44
|
export const IMAGE_GEMINI_SIZES = `512, 1K, 2K, 4K`;
|
|
45
|
-
export const IMAGE_MODELS_DOC = `openai: gpt-image-1. bfl: flux-2-pro, flux-2-flex, flux-2-max, flux-dev. gemini: gemini-2.5-flash-image, gemini-3.1-flash-image
|
|
46
|
-
export const IMAGE_PROVIDERS_BULLET = `- **OpenAI**: \`gpt-image-1\`
|
|
45
|
+
export const IMAGE_MODELS_DOC = `openai: gpt-image-2, gpt-image-1.5. bfl: flux-2-pro, flux-2-flex, flux-2-max, flux-dev. gemini: gemini-2.5-flash-image, gemini-3.1-flash-image, gemini-3-pro-image`;
|
|
46
|
+
export const IMAGE_PROVIDERS_BULLET = `- **OpenAI**: \`gpt-image-2, gpt-image-1.5\`
|
|
47
47
|
- **BFL/Flux**: \`flux-2-pro, flux-2-flex, flux-2-max, flux-dev\`
|
|
48
|
-
- **Gemini/Nano Banana**: \`gemini-2.5-flash-image, gemini-3.1-flash-image
|
|
48
|
+
- **Gemini/Nano Banana**: \`gemini-2.5-flash-image, gemini-3.1-flash-image, gemini-3-pro-image\``;
|
|
49
49
|
export const IMAGE_PROVIDERS_LIST = `openai, bfl, gemini`;
|
|
50
50
|
export const IMAGE_PROVIDER_DESCRIPTIONS = {
|
|
51
|
-
'openai': `OpenAI (gpt-image-1)`,
|
|
51
|
+
'openai': `OpenAI (gpt-image-2, gpt-image-1.5)`,
|
|
52
52
|
'bfl': `BFL/Flux (flux-2-pro, flux-2-flex, flux-2-max, flux-dev)`,
|
|
53
|
-
'gemini': `Gemini/Nano Banana (gemini-2.5-flash-image, gemini-3.1-flash-image
|
|
53
|
+
'gemini': `Gemini/Nano Banana (gemini-2.5-flash-image, gemini-3.1-flash-image, gemini-3-pro-image)`,
|
|
54
54
|
};
|
|
55
|
-
export const LLM_DEFAULT_MODELS_DOC = `OpenAI: gpt-5-mini (
|
|
55
|
+
export const LLM_DEFAULT_MODELS_DOC = `OpenAI: gpt-4.1-nano (cheapest), gpt-5.4-mini (cheap reasoning). Anthropic: claude-haiku-4-5 (cheapest). Gemini: gemini-2.5-flash-lite (cheapest, 1M context)`;
|
|
56
56
|
export const LLM_PROVIDERS_LIST = `anthropic, openai, gemini`;
|
|
57
57
|
export const OPENAI_TTS_VOICES_DOC = `alloy, ash, ballad, coral, echo, fable, nova, onyx, sage, shimmer, verse`;
|
|
58
58
|
export const TRANSCRIBE_PROVIDERS_DOC = `elevenlabs (default, Scribe v2), openai (GPT-4o Transcribe), gemini (Gemini 2.5 Flash - cheapest, multilingual)`;
|
package/dist/setup.js
CHANGED
|
@@ -22,9 +22,22 @@ export { SKILLS_CONTENT };
|
|
|
22
22
|
* in knowledge.ts and is CLI-version-dependent - syncing it would churn on
|
|
23
23
|
* every CLI upgrade. `.gipity.json`, `.gipity/`, and `.claude/` are per-
|
|
24
24
|
* workstation configuration. */
|
|
25
|
+
/** Relative path of each per-tool primer file we generate. Single source of
|
|
26
|
+
* truth: both {@link DEFAULT_SYNC_IGNORE} and the `setup*Md` writers read from
|
|
27
|
+
* here, so adding a tool can't silently leak its primer into project sync.
|
|
28
|
+
* Every primer is a CLI-version-generated client-side artifact (regenerated
|
|
29
|
+
* from knowledge.ts each session), not project content - syncing one churns on
|
|
30
|
+
* every CLI upgrade, so all of them are sync-ignored. */
|
|
31
|
+
export const PRIMER_FILES = {
|
|
32
|
+
claude: 'CLAUDE.md',
|
|
33
|
+
codex: 'AGENTS.md',
|
|
34
|
+
gemini: 'GEMINI.md',
|
|
35
|
+
copilot: '.github/copilot-instructions.md',
|
|
36
|
+
cursor: '.cursor/rules/gipity.mdc',
|
|
37
|
+
};
|
|
25
38
|
export const DEFAULT_SYNC_IGNORE = [
|
|
26
|
-
'node_modules', '.git', '.gipity.json', '.gipity/', '.claude/',
|
|
27
|
-
|
|
39
|
+
'node_modules', '.git', '.gipity.json', '.gipity/', '.claude/', '.gitignore',
|
|
40
|
+
...Object.values(PRIMER_FILES),
|
|
28
41
|
];
|
|
29
42
|
/** True if `name` (a top-level dir entry) is a workstation artifact that
|
|
30
43
|
* should be excluded from sync, file counts, and collision checks.
|
|
@@ -264,24 +277,24 @@ function writeSkillsFile(relPath, wrap) {
|
|
|
264
277
|
writeFileSync(path, next);
|
|
265
278
|
}
|
|
266
279
|
export function setupClaudeMd() {
|
|
267
|
-
writeSkillsFile(
|
|
280
|
+
writeSkillsFile(PRIMER_FILES.claude);
|
|
268
281
|
}
|
|
269
282
|
export function setupAgentsMd() {
|
|
270
|
-
writeSkillsFile(
|
|
283
|
+
writeSkillsFile(PRIMER_FILES.codex);
|
|
271
284
|
}
|
|
272
285
|
/** Gemini CLI auto-discovers GEMINI.md in the working directory. */
|
|
273
286
|
export function setupGeminiMd() {
|
|
274
|
-
writeSkillsFile(
|
|
287
|
+
writeSkillsFile(PRIMER_FILES.gemini);
|
|
275
288
|
}
|
|
276
289
|
/** GitHub Copilot CLI (and Copilot in VS Code) auto-discovers
|
|
277
290
|
* `.github/copilot-instructions.md`. */
|
|
278
291
|
export function setupCopilotMd() {
|
|
279
|
-
writeSkillsFile(
|
|
292
|
+
writeSkillsFile(PRIMER_FILES.copilot);
|
|
280
293
|
}
|
|
281
294
|
/** Cursor reads rule files from `.cursor/rules/`. The `.mdc` format wants
|
|
282
295
|
* YAML frontmatter; `alwaysApply: true` makes it load on every chat. */
|
|
283
296
|
export function setupCursorMd() {
|
|
284
|
-
writeSkillsFile(
|
|
297
|
+
writeSkillsFile(PRIMER_FILES.cursor, (block) => `---\ndescription: Gipity platform integration - CLI, sandbox, app services\nalwaysApply: true\n---\n\n${block}`);
|
|
285
298
|
}
|
|
286
299
|
/** All supported coding-tool primers and the function that writes each.
|
|
287
300
|
* Order matters for help-text rendering and the `all` expansion. */
|
package/dist/sync.js
CHANGED
|
@@ -478,11 +478,11 @@ async function syncInner(projectGuid, root, ignore, opts, interactive) {
|
|
|
478
478
|
// Shadow `config` locally so the rest of the function keeps its original
|
|
479
479
|
// shape. The two fields we actually use are the ones we took as args.
|
|
480
480
|
const config = { projectGuid, ignore };
|
|
481
|
-
const
|
|
481
|
+
const p = opts.progress;
|
|
482
482
|
const baseline = readBaseline(projectGuid);
|
|
483
|
-
|
|
483
|
+
p?.phase('Scanning local files…');
|
|
484
484
|
const local = walkLocal(root, ignore, baseline.files);
|
|
485
|
-
|
|
485
|
+
p?.phase('Checking Gipity for changes…');
|
|
486
486
|
const remote = await fetchRemote(projectGuid);
|
|
487
487
|
// Hash everything we might classify ambiguously. Any local path also on
|
|
488
488
|
// remote (and the remote has a hash) needs a local hash so size-match-but-
|
|
@@ -497,7 +497,7 @@ async function syncInner(projectGuid, root, ignore, opts, interactive) {
|
|
|
497
497
|
needHash.push(path);
|
|
498
498
|
}
|
|
499
499
|
if (needHash.length)
|
|
500
|
-
|
|
500
|
+
p?.phase(`Hashing ${needHash.length} file${needHash.length === 1 ? '' : 's'}…`);
|
|
501
501
|
await ensureLocalHashes(root, local, needHash);
|
|
502
502
|
const planned = plan(local, remote, baseline.files);
|
|
503
503
|
if (opts.plan) {
|
|
@@ -519,7 +519,7 @@ async function syncInner(projectGuid, root, ignore, opts, interactive) {
|
|
|
519
519
|
const downloadedBytes = new Map();
|
|
520
520
|
const needsBulkDownload = plannedToApply.some(a => a.kind === 'download' || a.kind === 'conflict');
|
|
521
521
|
if (needsBulkDownload) {
|
|
522
|
-
|
|
522
|
+
p?.phase('Downloading updates from Gipity…');
|
|
523
523
|
try {
|
|
524
524
|
const all = await downloadAll(config.projectGuid);
|
|
525
525
|
for (const a of plannedToApply) {
|
|
@@ -604,8 +604,16 @@ async function syncInner(projectGuid, root, ignore, opts, interactive) {
|
|
|
604
604
|
applied++;
|
|
605
605
|
}
|
|
606
606
|
// Uploads: bounded concurrency. On 409, rewrite as a conflict inline.
|
|
607
|
+
// A single byte bar tracks the whole batch (workers share the counter; JS is
|
|
608
|
+
// single-threaded so the += is race-free).
|
|
609
|
+
const uploadLabel = `Uploading ${uploadQueue.length} file${uploadQueue.length === 1 ? '' : 's'}`;
|
|
610
|
+
const totalUploadBytes = uploadQueue.reduce((sum, a) => sum + (a.localSize ?? 0), 0);
|
|
611
|
+
let sentBytes = 0;
|
|
607
612
|
if (uploadQueue.length)
|
|
608
|
-
|
|
613
|
+
p?.transfer(uploadLabel, 0, totalUploadBytes);
|
|
614
|
+
const onBytes = p
|
|
615
|
+
? (delta) => { sentBytes += delta; p.transfer(uploadLabel, sentBytes, totalUploadBytes); }
|
|
616
|
+
: undefined;
|
|
609
617
|
let cursor = 0;
|
|
610
618
|
const workers = [];
|
|
611
619
|
for (let w = 0; w < Math.min(UPLOAD_CONCURRENCY, uploadQueue.length); w++) {
|
|
@@ -619,6 +627,7 @@ async function syncInner(projectGuid, root, ignore, opts, interactive) {
|
|
|
619
627
|
try {
|
|
620
628
|
const result = await uploadOneFile(config.projectGuid, full, a.path, {
|
|
621
629
|
expectedServerVersion: a.expectedServerVersion,
|
|
630
|
+
onBytes,
|
|
622
631
|
});
|
|
623
632
|
const stat = statSync(full);
|
|
624
633
|
const { sha256 } = await hashFile(full);
|
|
@@ -712,6 +721,7 @@ async function syncInner(projectGuid, root, ignore, opts, interactive) {
|
|
|
712
721
|
cleanupEmptyDirs(root, config.ignore);
|
|
713
722
|
baseline.lastFullSync = new Date().toISOString();
|
|
714
723
|
writeBaseline(baseline);
|
|
724
|
+
p?.finish();
|
|
715
725
|
return {
|
|
716
726
|
plan: planned,
|
|
717
727
|
applied,
|
package/dist/updater/shim.js
CHANGED
|
@@ -2,13 +2,23 @@
|
|
|
2
2
|
// Thin launcher. Resolves the user-local install at ~/.gipity/local/, exec's
|
|
3
3
|
// it, and kicks off a detached background updater. Modeled on Claude Code.
|
|
4
4
|
import { spawn, spawnSync } from 'child_process';
|
|
5
|
-
import { readFileSync } from 'fs';
|
|
5
|
+
import { existsSync, readFileSync } from 'fs';
|
|
6
6
|
import { fileURLToPath } from 'url';
|
|
7
7
|
import { dirname, resolve, join } from 'path';
|
|
8
8
|
import { LOCAL_ENTRY } from './state.js';
|
|
9
9
|
import { isBootstrapped, bootstrap } from './bootstrap.js';
|
|
10
10
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
11
|
-
const
|
|
11
|
+
const pkgRoot = resolve(__dirname, '..', '..');
|
|
12
|
+
const shimPkg = JSON.parse(readFileSync(join(pkgRoot, 'package.json'), 'utf-8'));
|
|
13
|
+
// Dev-link detection. Published tarballs ship `dist/**` only (see package.json
|
|
14
|
+
// `files`), so a sibling `src/` means `gipity` was `npm link`ed from a source
|
|
15
|
+
// checkout. In that case run THIS checkout's own dist and skip the bootstrap +
|
|
16
|
+
// background updater entirely - otherwise the shim would defer to the last
|
|
17
|
+
// PUBLISHED build in ~/.gipity/local/ and silently shadow your local changes.
|
|
18
|
+
// Nothing persistent is written, so `just cli-unlink` (npm unlink) is the only
|
|
19
|
+
// cleanup needed: once `gipity` no longer resolves to this checkout, dev mode
|
|
20
|
+
// stops applying on its own.
|
|
21
|
+
const isDevLink = existsSync(join(pkgRoot, 'src'));
|
|
12
22
|
function startBackgroundUpdater() {
|
|
13
23
|
const checkScript = join(__dirname, 'check.js');
|
|
14
24
|
try {
|
|
@@ -30,8 +40,9 @@ function execLocal() {
|
|
|
30
40
|
process.exit(res.status ?? 1);
|
|
31
41
|
}
|
|
32
42
|
function execSelf() {
|
|
33
|
-
//
|
|
34
|
-
//
|
|
43
|
+
// Run our own dist/index.js (this checkout/install), bypassing the local
|
|
44
|
+
// bootstrapped copy. Used for dev links and as the bootstrap-failure fallback
|
|
45
|
+
// so the user is never blocked (they can retry via `gipity update --force`).
|
|
35
46
|
const ownEntry = resolve(__dirname, '..', 'index.js');
|
|
36
47
|
const args = process.argv.slice(2);
|
|
37
48
|
const res = spawnSync(process.execPath, [ownEntry, ...args], {
|
|
@@ -51,6 +62,9 @@ const isLoud = rawArgs.length === 0 ||
|
|
|
51
62
|
firstArg === '--version' ||
|
|
52
63
|
firstArg === '-v' ||
|
|
53
64
|
firstArg === 'version';
|
|
65
|
+
// Dev link: run this checkout's own build, no bootstrap, no auto-update.
|
|
66
|
+
if (isDevLink)
|
|
67
|
+
execSelf();
|
|
54
68
|
if (!isBootstrapped()) {
|
|
55
69
|
const ok = bootstrap(shimPkg.version, !isLoud);
|
|
56
70
|
if (!ok)
|
package/dist/upload.js
CHANGED
|
@@ -132,6 +132,7 @@ export async function uploadOneFile(projectGuid, localPath, virtualPath, opts =
|
|
|
132
132
|
const stream = createReadStream(localPath);
|
|
133
133
|
return putToPresignedUrl(data.url, stream, size, data.headers?.['Content-Type'] ?? mime);
|
|
134
134
|
});
|
|
135
|
+
opts.onBytes?.(size);
|
|
135
136
|
completeBody.etag = etag;
|
|
136
137
|
let comp;
|
|
137
138
|
try {
|
|
@@ -162,6 +163,10 @@ export async function uploadOneFile(projectGuid, localPath, virtualPath, opts =
|
|
|
162
163
|
const completed = [];
|
|
163
164
|
for (const p of alreadyDone)
|
|
164
165
|
completed.push(p);
|
|
166
|
+
// On resume, count the parts the server already has so the progress total
|
|
167
|
+
// still reaches 100% (capped at size for the short final part).
|
|
168
|
+
if (alreadyDone.length)
|
|
169
|
+
opts.onBytes?.(Math.min(alreadyDone.length * partSize, size));
|
|
165
170
|
const partConcurrency = opts.partConcurrency ?? MULTIPART_PART_CONCURRENCY;
|
|
166
171
|
let cursor = 0;
|
|
167
172
|
const workers = [];
|
|
@@ -176,6 +181,7 @@ export async function uploadOneFile(projectGuid, localPath, virtualPath, opts =
|
|
|
176
181
|
const end = Math.min(start + partSize - 1, size - 1);
|
|
177
182
|
const body = await readRange(localPath, start, end);
|
|
178
183
|
const etag = await withRetry(`part ${part.partNumber}`, () => putToPresignedUrl(part.url, body, body.length));
|
|
184
|
+
opts.onBytes?.(body.length);
|
|
179
185
|
completed.push({ part_number: part.partNumber, etag });
|
|
180
186
|
}
|
|
181
187
|
})());
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gipity",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.374",
|
|
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
6
|
"gipity": "dist/updater/shim.js",
|
|
@@ -12,8 +12,9 @@
|
|
|
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-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"
|
|
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__/progress.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 dist/__tests__/cli-e2e-sandbox-live.test.js dist/__tests__/cli-e2e-page-fetch-live.test.js",
|
|
17
|
+
"test:e2e:sandbox": "tsc && GIPITY_E2E=1 node --test --test-timeout=180000 dist/__tests__/cli-e2e-sandbox-live.test.js"
|
|
17
18
|
},
|
|
18
19
|
"dependencies": {
|
|
19
20
|
"commander": "^13.0.0",
|
|
@@ -22,7 +23,7 @@
|
|
|
22
23
|
"devDependencies": {
|
|
23
24
|
"@types/node": "^20.0.0",
|
|
24
25
|
"@types/tar-stream": "^3.1.4",
|
|
25
|
-
"typescript": "
|
|
26
|
+
"typescript": "5.9.3"
|
|
26
27
|
},
|
|
27
28
|
"engines": {
|
|
28
29
|
"node": ">=18"
|