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
|
@@ -8,7 +8,7 @@ import { planFor, UnsupportedPlatformError } from '../relay/installers.js';
|
|
|
8
8
|
function requirePaired() {
|
|
9
9
|
const device = state.getDevice();
|
|
10
10
|
if (!device) {
|
|
11
|
-
console.error(
|
|
11
|
+
console.error(`${clrError('No paired device.')} Run ${bold('gipity claude')} to pair this machine.`);
|
|
12
12
|
process.exit(1);
|
|
13
13
|
}
|
|
14
14
|
return device;
|
|
@@ -48,40 +48,37 @@ export function registerInstallCommands(relayCommand) {
|
|
|
48
48
|
}
|
|
49
49
|
catch (err) {
|
|
50
50
|
if (err instanceof UnsupportedPlatformError) {
|
|
51
|
-
console.error(
|
|
52
|
-
console.error(
|
|
51
|
+
console.error(clrError(err.message));
|
|
52
|
+
console.error(muted('Supported on macOS, Linux, and Windows.'));
|
|
53
53
|
}
|
|
54
54
|
else
|
|
55
55
|
throw err;
|
|
56
56
|
process.exit(1);
|
|
57
57
|
}
|
|
58
|
-
console.log('');
|
|
59
|
-
console.log(
|
|
60
|
-
console.log(` ${bold('File:')} ${plan.path}`);
|
|
61
|
-
console.log('');
|
|
58
|
+
console.log(`${bold('Install plan:')} ${plan.summary}`);
|
|
59
|
+
console.log(`${bold('File:')} ${plan.path}`);
|
|
62
60
|
if (opts.print) {
|
|
61
|
+
console.log('');
|
|
63
62
|
console.log(`${dim('--- file content ---')}`);
|
|
64
63
|
console.log(plan.content);
|
|
65
64
|
console.log(`${dim('--- enable: ---')}`);
|
|
66
65
|
console.log(plan.enableDisplay);
|
|
67
|
-
console.log('');
|
|
68
66
|
return;
|
|
69
67
|
}
|
|
70
|
-
if (!(await confirm('
|
|
71
|
-
console.log(
|
|
68
|
+
if (!(await confirm('Write the file and enable the service now?'))) {
|
|
69
|
+
console.log(muted('Cancelled. (Use --print to preview without installing.)'));
|
|
72
70
|
return;
|
|
73
71
|
}
|
|
74
72
|
mkdirSync(dirname(plan.path), { recursive: true });
|
|
75
73
|
writeFileSync(plan.path, plan.content);
|
|
76
|
-
console.log(
|
|
74
|
+
console.log(success(`Wrote ${plan.path}`));
|
|
77
75
|
if (!runArgvSequence(plan.enableCmds, { failFast: true })) {
|
|
78
|
-
console.error(
|
|
76
|
+
console.error(clrError(`Couldn't enable autostart. Try manually: ${plan.enableDisplay}`));
|
|
79
77
|
process.exit(1);
|
|
80
78
|
}
|
|
81
|
-
console.log('');
|
|
82
|
-
console.log(`
|
|
83
|
-
console.log(
|
|
84
|
-
console.log(` ${dim(`Tail logs: gipity relay log`)}`);
|
|
79
|
+
console.log(success('Background service installed and started.'));
|
|
80
|
+
console.log(muted(`Check status: ${plan.statusDisplay}`));
|
|
81
|
+
console.log(muted(`Tail logs: gipity relay log`));
|
|
85
82
|
});
|
|
86
83
|
relayCommand
|
|
87
84
|
.command('autostart <on|off>')
|
|
@@ -89,7 +86,7 @@ export function registerInstallCommands(relayCommand) {
|
|
|
89
86
|
.action(async (mode) => {
|
|
90
87
|
const want = mode.toLowerCase();
|
|
91
88
|
if (want !== 'on' && want !== 'off') {
|
|
92
|
-
console.error(
|
|
89
|
+
console.error(clrError('Usage: gipity relay autostart <on|off>'));
|
|
93
90
|
process.exit(1);
|
|
94
91
|
}
|
|
95
92
|
let plan;
|
|
@@ -98,7 +95,7 @@ export function registerInstallCommands(relayCommand) {
|
|
|
98
95
|
}
|
|
99
96
|
catch (err) {
|
|
100
97
|
if (err instanceof UnsupportedPlatformError) {
|
|
101
|
-
console.error(
|
|
98
|
+
console.error(clrError(err.message));
|
|
102
99
|
process.exit(1);
|
|
103
100
|
}
|
|
104
101
|
else
|
|
@@ -106,14 +103,14 @@ export function registerInstallCommands(relayCommand) {
|
|
|
106
103
|
}
|
|
107
104
|
const cmds = want === 'on' ? plan.enableCmds : plan.disableCmds;
|
|
108
105
|
const display = want === 'on' ? plan.enableDisplay : plan.disableDisplay;
|
|
109
|
-
console.log(
|
|
106
|
+
console.log(`${info('Running:')} ${dim(display)}`);
|
|
110
107
|
// Disable is best-effort (the task may already be stopped); enable is fail-fast.
|
|
111
108
|
const ok = runArgvSequence(cmds, { failFast: want === 'on' });
|
|
112
109
|
if (!ok && want === 'on') {
|
|
113
|
-
console.error(
|
|
110
|
+
console.error(clrError('Command failed.'));
|
|
114
111
|
process.exit(1);
|
|
115
112
|
}
|
|
116
|
-
console.log(
|
|
113
|
+
console.log(success(`Autostart ${want}.`));
|
|
117
114
|
});
|
|
118
115
|
}
|
|
119
116
|
//# sourceMappingURL=relay-install.js.map
|
package/dist/commands/relay.js
CHANGED
|
@@ -10,7 +10,7 @@ import { existsSync, readFileSync, unlinkSync } from 'fs';
|
|
|
10
10
|
import { spawn } from 'child_process';
|
|
11
11
|
import { post } from '../api.js';
|
|
12
12
|
import { confirm } from '../utils.js';
|
|
13
|
-
import { bold, brand,
|
|
13
|
+
import { bold, brand, success, error as clrError, muted, } from '../colors.js';
|
|
14
14
|
import * as state from '../relay/state.js';
|
|
15
15
|
import * as daemon from '../relay/daemon.js';
|
|
16
16
|
import { registerInstallCommands } from './relay-install.js';
|
|
@@ -32,16 +32,14 @@ relayCommand
|
|
|
32
32
|
console.log(JSON.stringify(safe, null, 2));
|
|
33
33
|
return;
|
|
34
34
|
}
|
|
35
|
-
console.log('');
|
|
36
35
|
if (!s.device) {
|
|
37
|
-
console.log(
|
|
36
|
+
console.log(`${muted('No paired device.')} Run ${brand('gipity claude')} to pair this machine.`);
|
|
38
37
|
return;
|
|
39
38
|
}
|
|
40
|
-
console.log(
|
|
41
|
-
console.log(
|
|
42
|
-
console.log(
|
|
43
|
-
console.log(
|
|
44
|
-
console.log('');
|
|
39
|
+
console.log(`${bold('Device:')} ${brand(s.device.name)} ${muted(`(${s.device.guid})`)}`);
|
|
40
|
+
console.log(`${bold('Platform:')} ${s.device.platform}`);
|
|
41
|
+
console.log(`${bold('Paired:')} ${s.device.paired_at}`);
|
|
42
|
+
console.log(`${bold('Paused:')} ${s.paused ? 'yes' : 'no'}`);
|
|
45
43
|
});
|
|
46
44
|
// ─── gipity relay run ──────────────────────────────────────────────────
|
|
47
45
|
relayCommand
|
|
@@ -64,12 +62,12 @@ relayCommand
|
|
|
64
62
|
.action(async (opts) => {
|
|
65
63
|
const pidPath = state.getDaemonPidPath();
|
|
66
64
|
if (!existsSync(pidPath)) {
|
|
67
|
-
console.log(
|
|
65
|
+
console.log(muted('Background service isn\'t running.'));
|
|
68
66
|
return;
|
|
69
67
|
}
|
|
70
68
|
const pid = parseInt(readFileSync(pidPath, 'utf-8').trim(), 10);
|
|
71
69
|
if (!pid || isNaN(pid)) {
|
|
72
|
-
console.error(
|
|
70
|
+
console.error(clrError('PID file is empty or malformed.'));
|
|
73
71
|
process.exit(1);
|
|
74
72
|
}
|
|
75
73
|
try {
|
|
@@ -77,14 +75,14 @@ relayCommand
|
|
|
77
75
|
}
|
|
78
76
|
catch (err) {
|
|
79
77
|
if (err?.code === 'ESRCH') {
|
|
80
|
-
console.log(
|
|
78
|
+
console.log(muted(`PID ${pid} not running - cleaning up stale PID file.`));
|
|
81
79
|
try {
|
|
82
80
|
unlinkSync(pidPath);
|
|
83
81
|
}
|
|
84
82
|
catch { /* ignore */ }
|
|
85
83
|
return;
|
|
86
84
|
}
|
|
87
|
-
console.error(
|
|
85
|
+
console.error(clrError(`Could not signal PID ${pid}: ${err?.message || err}`));
|
|
88
86
|
process.exit(1);
|
|
89
87
|
}
|
|
90
88
|
// Wait up to 5s for clean shutdown.
|
|
@@ -110,15 +108,15 @@ relayCommand
|
|
|
110
108
|
process.kill(pid, 'SIGKILL');
|
|
111
109
|
}
|
|
112
110
|
catch { /* ignore */ }
|
|
113
|
-
console.log(
|
|
111
|
+
console.log(success('Background service force-stopped.'));
|
|
114
112
|
}
|
|
115
113
|
else {
|
|
116
|
-
console.error(
|
|
114
|
+
console.error(clrError(`Didn't shut down cleanly after 5s. Retry with --force to stop it.`));
|
|
117
115
|
process.exit(1);
|
|
118
116
|
}
|
|
119
117
|
}
|
|
120
118
|
else {
|
|
121
|
-
console.log(
|
|
119
|
+
console.log(success('Background service stopped.'));
|
|
122
120
|
}
|
|
123
121
|
});
|
|
124
122
|
// ─── gipity relay pause / resume ───────────────────────────────────────
|
|
@@ -128,7 +126,7 @@ relayCommand
|
|
|
128
126
|
.action(() => {
|
|
129
127
|
requirePaired();
|
|
130
128
|
state.setPaused(true);
|
|
131
|
-
console.log(
|
|
129
|
+
console.log(`${success('Paused.')} ${muted('Run `gipity relay resume` to accept commands again.')}`);
|
|
132
130
|
});
|
|
133
131
|
relayCommand
|
|
134
132
|
.command('resume')
|
|
@@ -136,7 +134,7 @@ relayCommand
|
|
|
136
134
|
.action(() => {
|
|
137
135
|
requirePaired();
|
|
138
136
|
state.setPaused(false);
|
|
139
|
-
console.log(
|
|
137
|
+
console.log(success('Resumed.'));
|
|
140
138
|
});
|
|
141
139
|
// ─── gipity relay rename <name> ────────────────────────────────────────
|
|
142
140
|
relayCommand
|
|
@@ -146,7 +144,7 @@ relayCommand
|
|
|
146
144
|
const device = requirePaired();
|
|
147
145
|
const name = newName.trim();
|
|
148
146
|
if (!name || name.length > 100) {
|
|
149
|
-
console.error(
|
|
147
|
+
console.error(clrError('Device name must be 1–100 non-whitespace characters.'));
|
|
150
148
|
process.exit(1);
|
|
151
149
|
}
|
|
152
150
|
try {
|
|
@@ -154,14 +152,14 @@ relayCommand
|
|
|
154
152
|
await post(`/remote-devices/${encodeURIComponent(device.guid)}/rename`, { name });
|
|
155
153
|
}
|
|
156
154
|
catch (err) {
|
|
157
|
-
console.error(
|
|
155
|
+
console.error(clrError(`Rename failed: ${err?.message || err}`));
|
|
158
156
|
if (err?.statusCode === 401) {
|
|
159
|
-
console.error(
|
|
157
|
+
console.error(muted('Run `gipity login` first - rename requires your user auth.'));
|
|
160
158
|
}
|
|
161
159
|
process.exit(1);
|
|
162
160
|
}
|
|
163
161
|
state.setDevice({ ...device, name });
|
|
164
|
-
console.log(
|
|
162
|
+
console.log(success(`Renamed to ${bold(name)}.`));
|
|
165
163
|
});
|
|
166
164
|
// ─── gipity relay revoke ───────────────────────────────────────────────
|
|
167
165
|
relayCommand
|
|
@@ -169,8 +167,8 @@ relayCommand
|
|
|
169
167
|
.description('Revoke and forget this device')
|
|
170
168
|
.action(async () => {
|
|
171
169
|
const device = requirePaired();
|
|
172
|
-
if (!(await confirm(`
|
|
173
|
-
console.log(
|
|
170
|
+
if (!(await confirm(`Revoke ${bold(device.name)} (${device.guid})?`))) {
|
|
171
|
+
console.log(muted('Cancelled.'));
|
|
174
172
|
return;
|
|
175
173
|
}
|
|
176
174
|
try {
|
|
@@ -179,12 +177,12 @@ relayCommand
|
|
|
179
177
|
catch (err) {
|
|
180
178
|
// Even if the server call fails, drop local state - a stale token is
|
|
181
179
|
// worse than double-revoking. Warn loudly though.
|
|
182
|
-
console.error(
|
|
183
|
-
console.error(
|
|
180
|
+
console.error(clrError(`Server revoke failed: ${err?.message || err}`));
|
|
181
|
+
console.error(muted('Local token cleared anyway. Visit the web CLI to confirm the server-side revoke.'));
|
|
184
182
|
}
|
|
185
183
|
state.clearDevice();
|
|
186
|
-
console.log(
|
|
187
|
-
console.log(
|
|
184
|
+
console.log(success('Device revoked + local state cleared.'));
|
|
185
|
+
console.log(muted('Any running background service will notice and exit within ~30s.'));
|
|
188
186
|
});
|
|
189
187
|
// ─── gipity relay log ──────────────────────────────────────────────────
|
|
190
188
|
relayCommand
|
|
@@ -195,7 +193,7 @@ relayCommand
|
|
|
195
193
|
.action((opts) => {
|
|
196
194
|
const path = daemon.RELAY_LOG_PATH;
|
|
197
195
|
if (!existsSync(path)) {
|
|
198
|
-
console.log(
|
|
196
|
+
console.log(muted('No log file yet. Start the service with `gipity relay run` (or install it).'));
|
|
199
197
|
return;
|
|
200
198
|
}
|
|
201
199
|
const lines = parseInt(opts.lines, 10) || 100;
|
|
@@ -205,14 +203,14 @@ relayCommand
|
|
|
205
203
|
process.stdout.write(tail);
|
|
206
204
|
}
|
|
207
205
|
catch (err) {
|
|
208
|
-
console.error(
|
|
206
|
+
console.error(clrError(`Could not read log: ${err?.message || err}`));
|
|
209
207
|
process.exit(1);
|
|
210
208
|
}
|
|
211
209
|
if (opts.follow) {
|
|
212
210
|
// Defer real follow to `tail -f` - cross-platform fallback below.
|
|
213
211
|
const tailCmd = process.platform === 'win32' ? null : 'tail';
|
|
214
212
|
if (!tailCmd) {
|
|
215
|
-
console.error(
|
|
213
|
+
console.error(clrError('--follow is not supported on this platform yet.'));
|
|
216
214
|
process.exit(1);
|
|
217
215
|
}
|
|
218
216
|
const child = spawn(tailCmd, ['-f', '-n', '0', path], { stdio: 'inherit' });
|
|
@@ -226,7 +224,7 @@ registerInstallCommands(relayCommand);
|
|
|
226
224
|
function requirePaired() {
|
|
227
225
|
const device = state.getDevice();
|
|
228
226
|
if (!device) {
|
|
229
|
-
console.error(
|
|
227
|
+
console.error(`${clrError('No paired device.')} Run ${brand('gipity claude')} to pair this machine.`);
|
|
230
228
|
process.exit(1);
|
|
231
229
|
}
|
|
232
230
|
return device;
|
package/dist/commands/sandbox.js
CHANGED
|
@@ -2,6 +2,7 @@ import { Command } from 'commander';
|
|
|
2
2
|
import { dirname, relative } from 'path';
|
|
3
3
|
import { post } from '../api.js';
|
|
4
4
|
import { resolveProjectContext, getConfigPath } from '../config.js';
|
|
5
|
+
import { sync } from '../sync.js';
|
|
5
6
|
import { error as clrError, dim } from '../colors.js';
|
|
6
7
|
import { run } from '../helpers/index.js';
|
|
7
8
|
const LANG_MAP = {
|
|
@@ -41,6 +42,9 @@ file you write lands back in the project. No manual copy needed.
|
|
|
41
42
|
Use --input only for projects over the auto-mirror cap, or when you want
|
|
42
43
|
to restrict what the sandbox sees.
|
|
43
44
|
|
|
45
|
+
No network, and the toolset is fixed - pip/npm/apt installs won't work.
|
|
46
|
+
Use only preinstalled tools, or pull external inputs into the project first.
|
|
47
|
+
|
|
44
48
|
Examples:
|
|
45
49
|
|
|
46
50
|
# Auto-mirror: code sees the whole project at /work/
|
|
@@ -80,8 +84,17 @@ GCC/Rust).
|
|
|
80
84
|
input_files: opts.input,
|
|
81
85
|
cwd,
|
|
82
86
|
});
|
|
87
|
+
// Pull sandbox-written outputs down to the local cwd automatically. The
|
|
88
|
+
// server has already mirrored them into the project (VFS) and handed back
|
|
89
|
+
// the exact list, so honoring it here means files land locally without a
|
|
90
|
+
// manual `gipity sync` - same auto-pull contract `gipity chat` uses on its
|
|
91
|
+
// `filesChanged` flag. Skip in one-off mode (no local project to sync into).
|
|
92
|
+
const pulledLocal = !!(res.data.outputFiles?.length && getConfigPath());
|
|
93
|
+
if (pulledLocal) {
|
|
94
|
+
await sync({ interactive: false });
|
|
95
|
+
}
|
|
83
96
|
if (opts.json) {
|
|
84
|
-
console.log(JSON.stringify(res.data));
|
|
97
|
+
console.log(JSON.stringify({ ...res.data, filesSynced: pulledLocal }));
|
|
85
98
|
}
|
|
86
99
|
else {
|
|
87
100
|
if (res.data.autoMirrorSkipped) {
|
|
@@ -94,9 +107,9 @@ GCC/Rust).
|
|
|
94
107
|
if (res.data.timedOut)
|
|
95
108
|
console.error(`[Timed out after ${res.data.durationMs}ms]`);
|
|
96
109
|
if (res.data.outputFiles && res.data.outputFiles.length > 0) {
|
|
97
|
-
console.log(`\nOutput files saved to project:`);
|
|
110
|
+
console.log(`\nOutput files ${pulledLocal ? 'synced to this directory' : 'saved to project'}:`);
|
|
98
111
|
for (const f of res.data.outputFiles)
|
|
99
|
-
console.log(
|
|
112
|
+
console.log(`${f}`);
|
|
100
113
|
}
|
|
101
114
|
if (res.data.exitCode !== 0)
|
|
102
115
|
process.exit(res.data.exitCode);
|
package/dist/commands/service.js
CHANGED
|
@@ -27,14 +27,12 @@ serviceCommand
|
|
|
27
27
|
.action(() => run('Services', async () => {
|
|
28
28
|
requireConfig();
|
|
29
29
|
const width = SERVICES.reduce((m, s) => Math.max(m, s.name.length), 0);
|
|
30
|
-
console.log('');
|
|
31
30
|
console.log('Call one with `gipity service call <name> \'{"json":"body"}\'`');
|
|
32
31
|
console.log(muted('(GET endpoints like llm/models, tts/voices take --get and no body)'));
|
|
33
32
|
console.log('');
|
|
34
33
|
for (const s of SERVICES) {
|
|
35
|
-
console.log(
|
|
34
|
+
console.log(`${bold(s.name.padEnd(width))} ${muted(`[${s.method}] ${s.desc}`)}`);
|
|
36
35
|
}
|
|
37
|
-
console.log('');
|
|
38
36
|
}));
|
|
39
37
|
serviceCommand
|
|
40
38
|
.command('call <name> [body]')
|
package/dist/commands/status.js
CHANGED
|
@@ -86,8 +86,8 @@ export const statusCommand = new Command('status')
|
|
|
86
86
|
}
|
|
87
87
|
else {
|
|
88
88
|
console.log(`${muted('Hooks:')} ${warning(`missing/modified: ${hookCheck.missing.join(', ')}`)}`);
|
|
89
|
-
console.log(
|
|
90
|
-
console.log(
|
|
89
|
+
console.log(muted('Run `gipity status --repair-hooks` to re-install.'));
|
|
90
|
+
console.log(muted('Without these, web CLI dispatches can\'t show Claude Code output.'));
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
});
|
package/dist/commands/sync.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import { sync } from '../sync.js';
|
|
3
|
+
import { createProgressReporter } from '../progress.js';
|
|
3
4
|
import { error as clrError } from '../colors.js';
|
|
4
5
|
export const syncCommand = new Command('sync')
|
|
5
6
|
.description('Sync files')
|
|
@@ -8,7 +9,9 @@ export const syncCommand = new Command('sync')
|
|
|
8
9
|
.option('--json', 'Output as JSON')
|
|
9
10
|
.action(async (opts) => {
|
|
10
11
|
try {
|
|
11
|
-
|
|
12
|
+
// JSON mode stays machine-clean; otherwise show live progress on a TTY.
|
|
13
|
+
const progress = opts.json ? undefined : createProgressReporter();
|
|
14
|
+
const result = await sync({ plan: opts.plan, force: opts.force, progress });
|
|
12
15
|
if (opts.json) {
|
|
13
16
|
console.log(JSON.stringify(result));
|
|
14
17
|
}
|
package/dist/commands/test.js
CHANGED
|
@@ -86,7 +86,6 @@ export const testCommand = new Command('test')
|
|
|
86
86
|
const config = requireConfig();
|
|
87
87
|
await syncBeforeAction(opts);
|
|
88
88
|
if (!opts.json) {
|
|
89
|
-
console.log('');
|
|
90
89
|
console.log(bold(`Running tests: ${filterPath || 'all'}`));
|
|
91
90
|
console.log('');
|
|
92
91
|
}
|
|
@@ -98,7 +97,7 @@ export const testCommand = new Command('test')
|
|
|
98
97
|
});
|
|
99
98
|
const runGuid = kickoff.data.runGuid;
|
|
100
99
|
if (!opts.json) {
|
|
101
|
-
console.log(
|
|
100
|
+
console.log(muted(`Run: ${runGuid}`));
|
|
102
101
|
console.log('');
|
|
103
102
|
}
|
|
104
103
|
// Poll for results (streams results as they complete)
|
|
@@ -123,7 +122,6 @@ export const testCommand = new Command('test')
|
|
|
123
122
|
if (data.skipped > 0)
|
|
124
123
|
parts.push(muted(`${data.skipped} skipped`));
|
|
125
124
|
console.log(`${parts.join(', ')} ${muted(`(${data.durationMs}ms)`)}`);
|
|
126
|
-
console.log('');
|
|
127
125
|
if (data.failed > 0)
|
|
128
126
|
process.exit(1);
|
|
129
127
|
}));
|
|
@@ -150,24 +148,22 @@ testCommand
|
|
|
150
148
|
return;
|
|
151
149
|
}
|
|
152
150
|
const icon = data.status === 'running' ? muted('⧗') : data.status === 'passed' ? success('✓') : clrError('✗');
|
|
153
|
-
console.log(
|
|
154
|
-
console.log(` ${icon} ${bold(data.status)} - ${data.passed}/${data.total} passed`);
|
|
151
|
+
console.log(`${icon} ${bold(data.status)} - ${data.passed}/${data.total} passed`);
|
|
155
152
|
if (data.totalFiles > 0) {
|
|
156
|
-
console.log(
|
|
153
|
+
console.log(muted(`Files: ${data.completedFiles}/${data.totalFiles}`));
|
|
157
154
|
}
|
|
158
155
|
if (data.durationMs) {
|
|
159
|
-
console.log(
|
|
156
|
+
console.log(muted(`Duration: ${data.durationMs}ms`));
|
|
160
157
|
}
|
|
161
158
|
if (data.failed > 0) {
|
|
162
159
|
console.log('');
|
|
163
160
|
const failures = data.results.filter(r => r.status === 'failed');
|
|
164
161
|
for (const f of failures) {
|
|
165
|
-
console.log(
|
|
162
|
+
console.log(`${clrError('✗')} ${f.path}/${f.name}`);
|
|
166
163
|
if (f.error)
|
|
167
|
-
console.log(`
|
|
164
|
+
console.log(` ${clrError(f.error)}`);
|
|
168
165
|
}
|
|
169
166
|
}
|
|
170
|
-
console.log('');
|
|
171
167
|
}));
|
|
172
168
|
// ── History subcommand ─────────────────────────────────────────────────
|
|
173
169
|
testCommand
|
|
@@ -186,13 +182,11 @@ testCommand
|
|
|
186
182
|
console.log(muted('No test runs yet.'));
|
|
187
183
|
return;
|
|
188
184
|
}
|
|
189
|
-
console.log('');
|
|
190
185
|
console.log(bold('Test History'));
|
|
191
186
|
for (const entry of res.data) {
|
|
192
187
|
const icon = entry.status === 'passed' ? success('✓') : entry.status === 'running' ? muted('⧗') : clrError('✗');
|
|
193
188
|
const date = new Date(entry.started_at).toLocaleDateString('en-US', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' });
|
|
194
|
-
console.log(
|
|
189
|
+
console.log(`${icon} ${muted(date)} ${entry.passed}/${entry.total} passed ${muted(entry.run_guid)}`);
|
|
195
190
|
}
|
|
196
|
-
console.log('');
|
|
197
191
|
}));
|
|
198
192
|
//# sourceMappingURL=test.js.map
|
package/dist/commands/text.js
CHANGED
|
@@ -19,7 +19,7 @@ function resolveInput(args, opts) {
|
|
|
19
19
|
}
|
|
20
20
|
function formatProfile(a) {
|
|
21
21
|
const L = [];
|
|
22
|
-
const row = (label, val) => L.push(
|
|
22
|
+
const row = (label, val) => L.push(`${label.padEnd(22)}${val}`);
|
|
23
23
|
L.push(bold('Counts'));
|
|
24
24
|
row('Characters', a.characters);
|
|
25
25
|
row('Chars (no spaces)', a.charactersNoSpaces);
|
|
@@ -53,15 +53,15 @@ function formatProfile(a) {
|
|
|
53
53
|
const freq = a.letterFrequency
|
|
54
54
|
.map((f) => `${f.letter}:${f.count}`)
|
|
55
55
|
.join(' ');
|
|
56
|
-
L.push(
|
|
56
|
+
L.push(freq);
|
|
57
57
|
}
|
|
58
58
|
else {
|
|
59
|
-
L.push(dim('
|
|
59
|
+
L.push(dim('(no letters)'));
|
|
60
60
|
}
|
|
61
61
|
if (a.wordFrequency.length) {
|
|
62
62
|
L.push('');
|
|
63
63
|
L.push(bold('Top words'));
|
|
64
|
-
L.push(
|
|
64
|
+
L.push(a.wordFrequency.map((w) => `${w.word}:${w.count}`).join(' '));
|
|
65
65
|
}
|
|
66
66
|
L.push('');
|
|
67
67
|
L.push(bold('Other'));
|
|
@@ -99,7 +99,7 @@ const analyzeCommand = new Command('analyze')
|
|
|
99
99
|
const counts = r.wholeWord
|
|
100
100
|
? `${r.nonOverlapping}`
|
|
101
101
|
: `${r.nonOverlapping} non-overlapping, ${r.overlapping} overlapping`;
|
|
102
|
-
console.log(`
|
|
102
|
+
console.log(`"${r.needle}" (${mode}): ${counts}`);
|
|
103
103
|
return;
|
|
104
104
|
}
|
|
105
105
|
if (opts.find !== undefined) {
|
|
@@ -107,29 +107,29 @@ const analyzeCommand = new Command('analyze')
|
|
|
107
107
|
if (opts.json)
|
|
108
108
|
return void console.log(JSON.stringify({ needle: opts.find, positions }));
|
|
109
109
|
console.log(positions.length
|
|
110
|
-
? `
|
|
111
|
-
: dim(`
|
|
110
|
+
? `"${opts.find}" at: ${positions.join(', ')}`
|
|
111
|
+
: dim(`"${opts.find}" not found`));
|
|
112
112
|
return;
|
|
113
113
|
}
|
|
114
114
|
if (opts.anagram !== undefined) {
|
|
115
115
|
const r = areAnagrams(text, opts.anagram);
|
|
116
116
|
if (opts.json)
|
|
117
117
|
return void console.log(JSON.stringify(r));
|
|
118
|
-
console.log(
|
|
118
|
+
console.log(`${r.isAnagram ? 'yes' : 'no'} - anagram of "${opts.anagram}"`);
|
|
119
119
|
return;
|
|
120
120
|
}
|
|
121
121
|
if (opts.word !== undefined) {
|
|
122
122
|
const w = nthWord(text, opts.word);
|
|
123
123
|
if (opts.json)
|
|
124
124
|
return void console.log(JSON.stringify({ word: w, n: opts.word }));
|
|
125
|
-
console.log(w === null ? dim('
|
|
125
|
+
console.log(w === null ? dim('(out of range)') : `${w}`);
|
|
126
126
|
return;
|
|
127
127
|
}
|
|
128
128
|
if (opts.char !== undefined) {
|
|
129
129
|
const c = nthChar(text, opts.char);
|
|
130
130
|
if (opts.json)
|
|
131
131
|
return void console.log(JSON.stringify({ char: c, n: opts.char }));
|
|
132
|
-
console.log(c === null ? dim('
|
|
132
|
+
console.log(c === null ? dim('(out of range)') : `${c}`);
|
|
133
133
|
return;
|
|
134
134
|
}
|
|
135
135
|
const analysis = analyzeText(text);
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `gipity uninstall` - true reset. Stops the relay daemon, removes the
|
|
3
3
|
* platform autostart service, revokes the device on the server (best-effort),
|
|
4
|
-
* and wipes ~/.gipity/.
|
|
4
|
+
* and wipes ~/.gipity/. Never touches ~/GipityProjects/ - your local
|
|
5
|
+
* project trees are yours to keep or remove yourself.
|
|
5
6
|
*
|
|
6
7
|
* Does not touch the npm-installed shim - the user removes that separately
|
|
7
8
|
* via `npm uninstall -g gipity`.
|
|
@@ -91,76 +92,53 @@ async function revokeDeviceBestEffort() {
|
|
|
91
92
|
export const uninstallCommand = new Command('uninstall')
|
|
92
93
|
.description('Uninstall Gipity')
|
|
93
94
|
.option('--yes', 'Skip confirmation prompts')
|
|
94
|
-
.option('--purge-projects', 'Also delete ~/GipityProjects/ (your local project trees)')
|
|
95
95
|
.action(async (opts) => {
|
|
96
96
|
const autoYes = opts.yes || getAutoConfirm();
|
|
97
97
|
const gipityDir = join(homedir(), '.gipity');
|
|
98
|
-
|
|
98
|
+
console.log(`${bold('Gipity uninstall')} - this will:`);
|
|
99
|
+
console.log(`• Stop the running relay daemon (if any)`);
|
|
100
|
+
console.log(`• Remove the OS autostart service (launchd / systemd / Task Scheduler)`);
|
|
101
|
+
console.log(`• Revoke this device on the server (best-effort)`);
|
|
102
|
+
console.log(`• Delete ${gipityDir}/`);
|
|
99
103
|
console.log('');
|
|
100
|
-
console.log(
|
|
101
|
-
console.log(` • Stop the running relay daemon (if any)`);
|
|
102
|
-
console.log(` • Remove the OS autostart service (launchd / systemd / Task Scheduler)`);
|
|
103
|
-
console.log(` • Revoke this device on the server (best-effort)`);
|
|
104
|
-
console.log(` • Delete ${gipityDir}/`);
|
|
105
|
-
console.log('');
|
|
106
|
-
console.log(` ${dim('It will NOT remove the `gipity` binary. Run `npm uninstall -g gipity` afterward if you want that too.')}`);
|
|
104
|
+
console.log(`${dim('It will NOT remove the `gipity` binary. Run `npm uninstall -g gipity` afterward if you want that too.')}`);
|
|
107
105
|
console.log('');
|
|
108
106
|
if (!autoYes) {
|
|
109
|
-
const ok = await confirm('
|
|
107
|
+
const ok = await confirm('Proceed?');
|
|
110
108
|
if (!ok) {
|
|
111
|
-
console.log(
|
|
109
|
+
console.log(`${muted('Cancelled.')}`);
|
|
112
110
|
return;
|
|
113
111
|
}
|
|
114
112
|
}
|
|
115
113
|
// 1. Stop daemon.
|
|
116
114
|
await stopDaemon();
|
|
117
|
-
console.log(
|
|
115
|
+
console.log(`${success('Daemon stopped.')}`);
|
|
118
116
|
// 2. Remove OS service.
|
|
119
117
|
const svc = removeServiceUnit();
|
|
120
118
|
if (svc.ran && svc.ok)
|
|
121
|
-
console.log(
|
|
119
|
+
console.log(`${success('Autostart service removed.')} ${svc.note ? dim(`(${svc.note})`) : ''}`);
|
|
122
120
|
else if (svc.ran)
|
|
123
|
-
console.log(
|
|
121
|
+
console.log(`${muted('Autostart service not installed or already gone.')}`);
|
|
124
122
|
else
|
|
125
|
-
console.log(
|
|
123
|
+
console.log(`${muted(svc.note ?? 'Autostart skipped.')}`);
|
|
126
124
|
// 3. Revoke device on server.
|
|
127
125
|
await revokeDeviceBestEffort();
|
|
128
|
-
console.log(
|
|
126
|
+
console.log(`${success('Device revoked on server (or was already revoked).')}`);
|
|
129
127
|
// 4. Wipe ~/.gipity/.
|
|
130
128
|
if (existsSync(gipityDir)) {
|
|
131
129
|
try {
|
|
132
130
|
rmSync(gipityDir, { recursive: true, force: true });
|
|
133
|
-
console.log(
|
|
131
|
+
console.log(`${success(`Removed ${gipityDir}/`)}`);
|
|
134
132
|
}
|
|
135
133
|
catch (err) {
|
|
136
|
-
console.error(
|
|
134
|
+
console.error(`${clrError(`Could not remove ${gipityDir}: ${err?.message || err}`)}`);
|
|
137
135
|
}
|
|
138
136
|
}
|
|
139
137
|
else {
|
|
140
|
-
console.log(
|
|
138
|
+
console.log(`${muted(`${gipityDir}/ already gone.`)}`);
|
|
141
139
|
}
|
|
142
|
-
// 5. Offer to wipe ~/GipityProjects/.
|
|
143
|
-
if (existsSync(projectsDir)) {
|
|
144
|
-
let alsoPurge = opts.purgeProjects === true;
|
|
145
|
-
if (!alsoPurge && !autoYes) {
|
|
146
|
-
alsoPurge = await confirm(` Also delete ${projectsDir}/ (your local project trees)?`);
|
|
147
|
-
}
|
|
148
|
-
if (alsoPurge) {
|
|
149
|
-
try {
|
|
150
|
-
rmSync(projectsDir, { recursive: true, force: true });
|
|
151
|
-
console.log(` ${success(`Removed ${projectsDir}/`)}`);
|
|
152
|
-
}
|
|
153
|
-
catch (err) {
|
|
154
|
-
console.error(` ${clrError(`Could not remove ${projectsDir}: ${err?.message || err}`)}`);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
else {
|
|
158
|
-
console.log(` ${muted(`Kept ${projectsDir}/ (projects still live in the cloud).`)}`);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
console.log('');
|
|
162
|
-
console.log(` ${success('Uninstall complete.')} ${dim('Run')} ${brand('npm uninstall -g gipity')} ${dim('to remove the binary too.')}`);
|
|
163
|
-
console.log(` ${dim('Then run')} ${brand('hash -r')} ${dim('(or open a new shell) so bash forgets the old binary path.')}`);
|
|
164
140
|
console.log('');
|
|
141
|
+
console.log(`${success('Uninstall complete.')} ${dim('Run')} ${brand('npm uninstall -g gipity')} ${dim('to remove the binary too.')}`);
|
|
142
|
+
console.log(`${dim('Then run')} ${brand('hash -r')} ${dim('(or open a new shell) so bash forgets the old binary path.')}`);
|
|
165
143
|
});
|
|
166
144
|
//# sourceMappingURL=uninstall.js.map
|
package/dist/commands/update.js
CHANGED
|
@@ -4,7 +4,6 @@ import { success, warning, info, dim } from '../colors.js';
|
|
|
4
4
|
export const updateCommand = new Command('update')
|
|
5
5
|
.description('Update the CLI')
|
|
6
6
|
.action(async () => {
|
|
7
|
-
console.log('');
|
|
8
7
|
console.log(info('Checking for updates...'));
|
|
9
8
|
const result = await runCheck({ force: true, verbose: true });
|
|
10
9
|
console.log('');
|
|
@@ -18,6 +17,5 @@ export const updateCommand = new Command('update')
|
|
|
18
17
|
else {
|
|
19
18
|
console.log(warning(`No update applied: ${result.reason}`));
|
|
20
19
|
}
|
|
21
|
-
console.log('');
|
|
22
20
|
});
|
|
23
21
|
//# sourceMappingURL=update.js.map
|