gipity 1.0.356 → 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/capture/sources/claude-code.js +76 -11
- package/dist/commands/add.js +45 -28
- 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 +73 -18
- 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 +48 -7
- package/dist/commands/page-fetch.js +136 -0
- package/dist/commands/page-inspect.js +59 -29
- package/dist/commands/page-screenshot.js +51 -41
- package/dist/commands/page-test.js +86 -0
- package/dist/commands/page.js +8 -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 +54 -0
- package/dist/commands/skill.js +2 -1
- 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 +148 -0
- 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 +11 -16
- package/dist/config.js +8 -1
- package/dist/help-skills.js +1 -0
- package/dist/helpers/output.js +52 -8
- package/dist/helpers/text-analysis.js +200 -0
- package/dist/hooks/capture-runner.js +32 -8
- package/dist/index.js +35 -2
- package/dist/knowledge.js +32 -7
- package/dist/progress.js +60 -0
- package/dist/project-setup.js +5 -1
- package/dist/provider-docs.js +7 -7
- package/dist/relay/daemon.js +11 -1
- package/dist/relay/stream-json.js +45 -8
- package/dist/setup.js +38 -11
- package/dist/sync.js +30 -8
- package/dist/updater/shim.js +18 -4
- package/dist/upload.js +6 -0
- package/package.json +5 -4
package/dist/banner.js
CHANGED
|
@@ -191,7 +191,9 @@ function renderBox(opts, outerW, bodyLines) {
|
|
|
191
191
|
for (const row of bodyLines)
|
|
192
192
|
lines.push(row);
|
|
193
193
|
lines.push(border('╰') + border('─'.repeat(innerW)) + border('╯'));
|
|
194
|
-
|
|
194
|
+
// Leading blank comes from the central output frame; keep the trailing one
|
|
195
|
+
// (it separates the banner from the picker/output that follows).
|
|
196
|
+
console.log(lines.join('\n') + '\n');
|
|
195
197
|
}
|
|
196
198
|
// ── Narrow layout (single panel, egg only) ────────────────────────────
|
|
197
199
|
function printNarrow(opts, outerW) {
|
|
@@ -24,6 +24,25 @@
|
|
|
24
24
|
* so retried POSTs are deduplicated by the partial unique index on
|
|
25
25
|
* messages(conversation_id, source_uuid).
|
|
26
26
|
*/
|
|
27
|
+
/** Pull token usage + model + stop_reason off an assistant `message` object.
|
|
28
|
+
* Same shape in the transcript JSONL and the stream-json assistant event, so
|
|
29
|
+
* both capture paths share this. Only includes keys that are actually present
|
|
30
|
+
* (so they spread cleanly onto an assistant entry without writing nulls).
|
|
31
|
+
* Cost is NOT here — it doesn't exist per-message; only the stream `result`
|
|
32
|
+
* footer reports a session total. */
|
|
33
|
+
export function usageFields(msg) {
|
|
34
|
+
const out = {};
|
|
35
|
+
const u = msg?.usage;
|
|
36
|
+
if (u && typeof u.input_tokens === 'number')
|
|
37
|
+
out.input_tokens = u.input_tokens;
|
|
38
|
+
if (u && typeof u.output_tokens === 'number')
|
|
39
|
+
out.output_tokens = u.output_tokens;
|
|
40
|
+
if (typeof msg?.model === 'string')
|
|
41
|
+
out.model = msg.model;
|
|
42
|
+
if (typeof msg?.stop_reason === 'string')
|
|
43
|
+
out.stop_reason = msg.stop_reason;
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
27
46
|
/** Extract joined `{type:'text', text}` blocks into a single string.
|
|
28
47
|
* The full blocks array is emitted separately so the client can render
|
|
29
48
|
* text + tool_use in the agent's original narrative order. */
|
|
@@ -37,8 +56,38 @@ function joinText(content) {
|
|
|
37
56
|
}
|
|
38
57
|
return parts.join('\n');
|
|
39
58
|
}
|
|
40
|
-
/**
|
|
41
|
-
|
|
59
|
+
/** Stamp a unique `source_uuid` on every entry parsed from one transcript line.
|
|
60
|
+
*
|
|
61
|
+
* One transcript line yields many entries (an assistant line emits its text
|
|
62
|
+
* entry PLUS one tool_use entry per tool call). The server dedupes ingest on
|
|
63
|
+
* the partial unique index messages(conversation_id, source_uuid) with
|
|
64
|
+
* ON CONFLICT DO NOTHING. If all siblings shared the bare `line.uuid`, the
|
|
65
|
+
* first entry (the assistant text) would claim the row and every subsequent
|
|
66
|
+
* tool_use would be silently dropped - leaving the later tool_result to land
|
|
67
|
+
* as a name-less stub. That bug made 100% of terminal-session tool calls lose
|
|
68
|
+
* their tool_name.
|
|
69
|
+
*
|
|
70
|
+
* The primary entry keeps the bare line uuid (so it still dedupes against rows
|
|
71
|
+
* written before this fix); each sibling gets a deterministic `#N` suffix.
|
|
72
|
+
* Determinism matters: a retried POST re-parses the same line in the same
|
|
73
|
+
* order, producing identical suffixes, so dedup still collapses retries. */
|
|
74
|
+
function stampEntries(entries, lineUuid, lineTs) {
|
|
75
|
+
return entries.map((e, i) => ({
|
|
76
|
+
...e,
|
|
77
|
+
source_uuid: i === 0 ? lineUuid : `${lineUuid}#${i}`,
|
|
78
|
+
...(lineTs ? { ts: lineTs } : {}),
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
/** Map a single parsed transcript line to zero or more ingest entries.
|
|
82
|
+
*
|
|
83
|
+
* `toolNames` (optional) is a per-transcript `tool_use_id → tool_name`
|
|
84
|
+
* map threaded across lines by `parseTranscript`: an assistant line
|
|
85
|
+
* records each tool call's name into it, and the later user line that
|
|
86
|
+
* carries the paired `tool_result` reads the name back out. This lets
|
|
87
|
+
* the server denormalize `tool_name` onto the tool row even when the
|
|
88
|
+
* result lands as a stub (the tool_use row missing/deduped). The
|
|
89
|
+
* `tool_result` block itself never carries the name. */
|
|
90
|
+
export function transcriptLineToEntries(line, toolNames) {
|
|
42
91
|
if (!line || typeof line !== 'object')
|
|
43
92
|
return [];
|
|
44
93
|
if (typeof line.type !== 'string')
|
|
@@ -54,13 +103,14 @@ export function transcriptLineToEntries(line) {
|
|
|
54
103
|
if (line.toolUseResult && !line.message)
|
|
55
104
|
return [];
|
|
56
105
|
const srcUuid = line.uuid;
|
|
106
|
+
const lineTs = typeof line.timestamp === 'string' ? line.timestamp : undefined;
|
|
57
107
|
const msg = line.message ?? {};
|
|
58
108
|
if (line.type === 'user') {
|
|
59
109
|
const content = msg.content;
|
|
60
110
|
if (typeof content === 'string') {
|
|
61
111
|
if (!content)
|
|
62
112
|
return [];
|
|
63
|
-
return [{ kind: 'prompt', prompt: content,
|
|
113
|
+
return stampEntries([{ kind: 'prompt', prompt: content }], srcUuid, lineTs);
|
|
64
114
|
}
|
|
65
115
|
if (Array.isArray(content)) {
|
|
66
116
|
const out = [];
|
|
@@ -69,18 +119,18 @@ export function transcriptLineToEntries(line) {
|
|
|
69
119
|
out.push({
|
|
70
120
|
kind: 'tool_result',
|
|
71
121
|
tool_use_id: b.tool_use_id,
|
|
122
|
+
tool_name: toolNames?.get(b.tool_use_id),
|
|
72
123
|
content: b.content ?? null,
|
|
73
124
|
is_error: Boolean(b.is_error),
|
|
74
|
-
source_uuid: srcUuid,
|
|
75
125
|
});
|
|
76
126
|
}
|
|
77
127
|
else if (b?.type === 'text' && typeof b.text === 'string' && b.text) {
|
|
78
128
|
// A user message with raw text blocks (rare - first-turn preamble
|
|
79
129
|
// is sometimes split this way). Treat like a prompt.
|
|
80
|
-
out.push({ kind: 'prompt', prompt: b.text
|
|
130
|
+
out.push({ kind: 'prompt', prompt: b.text });
|
|
81
131
|
}
|
|
82
132
|
}
|
|
83
|
-
return out;
|
|
133
|
+
return stampEntries(out, srcUuid, lineTs);
|
|
84
134
|
}
|
|
85
135
|
return [];
|
|
86
136
|
}
|
|
@@ -89,20 +139,21 @@ export function transcriptLineToEntries(line) {
|
|
|
89
139
|
const text = joinText(content);
|
|
90
140
|
const out = [];
|
|
91
141
|
if (text || content.length) {
|
|
92
|
-
out.push({ kind: 'assistant', text, blocks: content,
|
|
142
|
+
out.push({ kind: 'assistant', text, blocks: content, ...usageFields(msg) });
|
|
93
143
|
}
|
|
94
144
|
for (const block of content) {
|
|
95
145
|
if (block?.type === 'tool_use' && typeof block.id === 'string') {
|
|
146
|
+
const toolName = typeof block.name === 'string' ? block.name : 'tool';
|
|
147
|
+
toolNames?.set(block.id, toolName);
|
|
96
148
|
out.push({
|
|
97
149
|
kind: 'tool_use',
|
|
98
150
|
tool_use_id: block.id,
|
|
99
|
-
tool_name:
|
|
151
|
+
tool_name: toolName,
|
|
100
152
|
tool_input: block.input ?? null,
|
|
101
|
-
source_uuid: srcUuid,
|
|
102
153
|
});
|
|
103
154
|
}
|
|
104
155
|
}
|
|
105
|
-
return out;
|
|
156
|
+
return stampEntries(out, srcUuid, lineTs);
|
|
106
157
|
}
|
|
107
158
|
// Other envelope types (system notes, hook-emitted, …) - not captured.
|
|
108
159
|
return [];
|
|
@@ -120,6 +171,11 @@ export function parseTranscript(content, afterUuid) {
|
|
|
120
171
|
let seenWatermark = afterUuid === null;
|
|
121
172
|
let lastUuid = afterUuid;
|
|
122
173
|
const out = [];
|
|
174
|
+
// tool_use_id → tool_name, accumulated across lines so a later
|
|
175
|
+
// tool_result can be denormalized with its tool's name. Built from the
|
|
176
|
+
// whole file (including pre-watermark lines) so a result whose tool_use
|
|
177
|
+
// was forwarded in an earlier sweep still resolves its name.
|
|
178
|
+
const toolNames = new Map();
|
|
123
179
|
for (const raw of content.split('\n')) {
|
|
124
180
|
const line = raw.trim();
|
|
125
181
|
if (!line)
|
|
@@ -131,12 +187,21 @@ export function parseTranscript(content, afterUuid) {
|
|
|
131
187
|
catch {
|
|
132
188
|
continue;
|
|
133
189
|
}
|
|
190
|
+
// Record tool names from every assistant line we scan, even before the
|
|
191
|
+
// watermark - the map is read-only side state, it doesn't emit entries.
|
|
134
192
|
if (!seenWatermark) {
|
|
193
|
+
if (Array.isArray(parsed?.message?.content)) {
|
|
194
|
+
for (const block of parsed.message.content) {
|
|
195
|
+
if (block?.type === 'tool_use' && typeof block.id === 'string') {
|
|
196
|
+
toolNames.set(block.id, typeof block.name === 'string' ? block.name : 'tool');
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
135
200
|
if (parsed?.uuid === afterUuid)
|
|
136
201
|
seenWatermark = true;
|
|
137
202
|
continue;
|
|
138
203
|
}
|
|
139
|
-
const entries = transcriptLineToEntries(parsed);
|
|
204
|
+
const entries = transcriptLineToEntries(parsed, toolNames);
|
|
140
205
|
if (entries.length) {
|
|
141
206
|
for (const e of entries)
|
|
142
207
|
out.push(e);
|
package/dist/commands/add.js
CHANGED
|
@@ -7,35 +7,38 @@ import { requireConfig } from '../config.js';
|
|
|
7
7
|
import { sync } from '../sync.js';
|
|
8
8
|
import { success, muted, bold } from '../colors.js';
|
|
9
9
|
import { run } from '../helpers/index.js';
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const
|
|
10
|
+
const STARTERS = [
|
|
11
|
+
{ key: 'web-fullstack', hint: 'backend API + database (weather-by-zip demo)' },
|
|
12
|
+
{ key: 'web-vision-cam', hint: 'fullscreen camera app with on-device vision (MediaPipe)' },
|
|
13
|
+
{ key: '2d-game', hint: '2D games with Phaser 3 - platformer, arcade, puzzle' },
|
|
14
|
+
{ key: '3d-world', hint: 'playable 3D multiplayer rocket-launcher demo' },
|
|
15
|
+
{ key: 'api', hint: 'pure API backend, no frontend' },
|
|
16
|
+
];
|
|
17
|
+
const BLANK = [
|
|
18
|
+
{ key: 'web-simple', hint: 'static frontend-only site - pages, dashboards, simple games' },
|
|
19
|
+
{ key: '3d-engine', hint: '3D multiplayer wiring - Three.js + Rapier + Gipity Realtime' },
|
|
20
|
+
];
|
|
18
21
|
const HIDDEN = [{ key: 'app-itsm', hint: 'IT service management / helpdesk / ticketing' }];
|
|
19
22
|
const KITS = [
|
|
20
23
|
{ key: 'realtime', hint: 'multiplayer / presence / shared state' },
|
|
21
24
|
{ key: 'web-vision-mediapipe', hint: 'browser camera vision - gesture, pose, object detection' },
|
|
25
|
+
{ key: 'i18n', hint: 'multi-language web apps - language picker, RTL, translations' },
|
|
22
26
|
];
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
console.log('');
|
|
27
|
+
// The catalog block, rendered once and reused by the full help output
|
|
28
|
+
// (`gipity add` / `gipity add --help`) and the bare listing (`gipity add
|
|
29
|
+
// --list`) so they can never drift. Three sections, one entry per line, keys
|
|
30
|
+
// column-aligned. No leading/trailing blank lines - callers add surrounding
|
|
31
|
+
// whitespace.
|
|
32
|
+
function catalogText() {
|
|
33
|
+
const width = Math.max(...[...STARTERS, ...BLANK, ...KITS].map(e => e.key.length));
|
|
34
|
+
const row = (e) => ` ${e.key.padEnd(width)} ${muted(e.hint)}`;
|
|
35
|
+
const section = (title, blurb, entries) => [`${bold(title)} ${muted('- ' + blurb)}`, ...entries.map(row)].join('\n');
|
|
36
|
+
return [
|
|
37
|
+
'Names to pass to `gipity add <name>`:',
|
|
38
|
+
section('Templates (working demos)', 'complete apps to run, then extend or replace', STARTERS),
|
|
39
|
+
section('Templates (blank wiring)', 'minimal framework setup - build your app on top', BLANK),
|
|
40
|
+
section('Kits', 'building blocks to add into an app you already scaffolded', KITS),
|
|
41
|
+
].join('\n\n');
|
|
39
42
|
}
|
|
40
43
|
// ─── Local-path payload mode ────────────────────────────────────────────────
|
|
41
44
|
//
|
|
@@ -136,14 +139,28 @@ function buildLocalPayload(rootDir) {
|
|
|
136
139
|
}
|
|
137
140
|
export const addCommand = new Command('add')
|
|
138
141
|
.description('Add a template (scaffold an app) or a kit (reusable building block) to the project. Pass ./path/to/dir to install a local template directly.')
|
|
139
|
-
.argument('[name]', 'Template/kit key, OR a local directory path (./, ~/, or /abs). Omit
|
|
142
|
+
.argument('[name]', 'Template/kit key, OR a local directory path (./, ~/, or /abs). Omit for help; use --list for just the catalog.')
|
|
140
143
|
.option('--title <title>', 'App title - templates only (defaults to project name)')
|
|
141
144
|
.option('--description <desc>', 'App description for meta tags - templates only')
|
|
142
145
|
.option('--force', 'Templates only: overwrite any colliding files')
|
|
146
|
+
.option('--list', 'List the template/kit catalog and exit')
|
|
143
147
|
.option('--json', 'Output as JSON')
|
|
144
|
-
.
|
|
148
|
+
.addHelpText('after', () => catalogText() + '\n\n'
|
|
149
|
+
+ muted('Local path gipity add ./dir (or ~/path, /abs) - template or kit, auto-detected'))
|
|
150
|
+
.action((name, opts, command) => run('Add', async () => {
|
|
151
|
+
// `--list` is a bare catalog dump; no project/config needed.
|
|
152
|
+
if (opts.list) {
|
|
153
|
+
if (opts.json) {
|
|
154
|
+
console.log(JSON.stringify({ templates: { starters: STARTERS, blank: BLANK }, kits: KITS }));
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
console.log(catalogText());
|
|
158
|
+
}
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
// No name = show the full help (usage + options + catalog), same as --help.
|
|
145
162
|
if (!name) {
|
|
146
|
-
|
|
163
|
+
command.outputHelp();
|
|
147
164
|
return;
|
|
148
165
|
}
|
|
149
166
|
const config = requireConfig();
|
|
@@ -190,7 +207,7 @@ export const addCommand = new Command('add')
|
|
|
190
207
|
console.log(success(`Scaffolded "${data.title}" (${data.type}) - ${data.files.length} files:`));
|
|
191
208
|
}
|
|
192
209
|
for (const f of data.files)
|
|
193
|
-
console.log(
|
|
210
|
+
console.log(`${f}`);
|
|
194
211
|
if (data.notes?.length) {
|
|
195
212
|
console.log('');
|
|
196
213
|
for (const n of data.notes)
|
package/dist/commands/agent.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import { get, post, put, del } from '../api.js';
|
|
3
3
|
import { requireConfig, saveConfig } from '../config.js';
|
|
4
|
-
import { error as clrError } from '../colors.js';
|
|
4
|
+
import { error as clrError, success } from '../colors.js';
|
|
5
5
|
import { run, printList, printResult } from '../helpers/index.js';
|
|
6
6
|
import { confirm } from '../utils.js';
|
|
7
7
|
export const agentCommand = new Command('agent')
|
|
@@ -51,11 +51,9 @@ agentCommand
|
|
|
51
51
|
console.log(JSON.stringify(res.data));
|
|
52
52
|
}
|
|
53
53
|
else {
|
|
54
|
-
console.log(
|
|
55
|
-
console.log(`Created "${res.data.name}" (${res.data.short_guid})`);
|
|
54
|
+
console.log(success(`Created "${res.data.name}" (${res.data.short_guid})`));
|
|
56
55
|
if (opts.switch)
|
|
57
56
|
console.log('Switched.');
|
|
58
|
-
console.log('');
|
|
59
57
|
}
|
|
60
58
|
}));
|
|
61
59
|
agentCommand
|
|
@@ -114,7 +112,7 @@ agentCommand
|
|
|
114
112
|
const res = await get('/agents');
|
|
115
113
|
const match = res.data.find(a => a.name === name || a.short_guid === name);
|
|
116
114
|
if (!match) {
|
|
117
|
-
console.error(`Agent "${name}" not found.`);
|
|
115
|
+
console.error(clrError(`Agent "${name}" not found.`));
|
|
118
116
|
process.exit(1);
|
|
119
117
|
}
|
|
120
118
|
if (!await confirm(`Delete agent "${match.name}"?`)) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import { get, post } from '../api.js';
|
|
3
|
-
import { muted } from '../colors.js';
|
|
3
|
+
import { muted, success } from '../colors.js';
|
|
4
4
|
import { run, printList, printResult } from '../helpers/index.js';
|
|
5
5
|
function timeAgo(dateStr) {
|
|
6
6
|
const diffMs = Date.now() - new Date(dateStr).getTime();
|
|
@@ -53,7 +53,7 @@ approvalCommand
|
|
|
53
53
|
if (opts.expiresIn)
|
|
54
54
|
body.expires_in_minutes = Number(opts.expiresIn);
|
|
55
55
|
const res = await post('/approvals', body);
|
|
56
|
-
printResult(`Created ${res.data.guid}
|
|
56
|
+
printResult(success(`Created ${res.data.guid}.`), opts, res.data);
|
|
57
57
|
}));
|
|
58
58
|
approvalCommand
|
|
59
59
|
.command('answer <guid> [selection...]')
|
|
@@ -112,6 +112,6 @@ approvalCommand
|
|
|
112
112
|
throw new Error('Expected approval guid like ap_xxxxxxxx');
|
|
113
113
|
}
|
|
114
114
|
await post(`/approvals/${guid}/cancel`, {});
|
|
115
|
-
printResult(`Cancelled ${guid}
|
|
115
|
+
printResult(success(`Cancelled ${guid}.`), opts, { guid, cancelled: true });
|
|
116
116
|
}));
|
|
117
117
|
//# sourceMappingURL=approval.js.map
|
package/dist/commands/audit.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import { get } from '../api.js';
|
|
3
3
|
import { requireConfig } from '../config.js';
|
|
4
|
-
import { muted } from '../colors.js';
|
|
4
|
+
import { muted, brand } from '../colors.js';
|
|
5
5
|
import { run, printList } from '../helpers/index.js';
|
|
6
6
|
export const auditCommand = new Command('audit')
|
|
7
7
|
.description('Query audit logs');
|
|
@@ -47,6 +47,6 @@ auditCommand
|
|
|
47
47
|
if (opts.entity)
|
|
48
48
|
params.set('entity_type', opts.entity);
|
|
49
49
|
const res = await get(`/projects/${config.projectGuid}/audit/count?${params}`);
|
|
50
|
-
console.log(opts.json ? JSON.stringify(res.data) : `${res.data.count} events`);
|
|
50
|
+
console.log(opts.json ? JSON.stringify(res.data) : `${brand(String(res.data.count))} events`);
|
|
51
51
|
}));
|
|
52
52
|
//# sourceMappingURL=audit.js.map
|
package/dist/commands/chat.js
CHANGED
|
@@ -2,7 +2,7 @@ import { Command } from 'commander';
|
|
|
2
2
|
import { get, post, put, del } from '../api.js';
|
|
3
3
|
import { resolveProjectContext, saveConfig } from '../config.js';
|
|
4
4
|
import { sync } from '../sync.js';
|
|
5
|
-
import { error as clrError, muted } from '../colors.js';
|
|
5
|
+
import { error as clrError, muted, success } from '../colors.js';
|
|
6
6
|
import { run, printList, printResult } from '../helpers/index.js';
|
|
7
7
|
export const chatCommand = new Command('chat')
|
|
8
8
|
.description('Send a message to your agent')
|
|
@@ -95,7 +95,7 @@ chatCommand
|
|
|
95
95
|
.action((guid, titleParts, opts) => run('Rename', async () => {
|
|
96
96
|
const title = titleParts.join(' ');
|
|
97
97
|
await put(`/conversations/${guid}`, { title });
|
|
98
|
-
printResult(`Renamed ${guid} → "${title}"
|
|
98
|
+
printResult(success(`Renamed ${guid} → "${title}".`), opts, { guid, title });
|
|
99
99
|
}));
|
|
100
100
|
chatCommand
|
|
101
101
|
.command('archive <guid>')
|
|
@@ -103,7 +103,7 @@ chatCommand
|
|
|
103
103
|
.option('--json', 'Output as JSON')
|
|
104
104
|
.action((guid, opts) => run('Archive', async () => {
|
|
105
105
|
await put(`/conversations/${guid}`, { archive: true });
|
|
106
|
-
printResult(`Archived ${guid}
|
|
106
|
+
printResult(success(`Archived ${guid}.`), opts, { guid, archived: true });
|
|
107
107
|
}));
|
|
108
108
|
chatCommand
|
|
109
109
|
.command('delete <guid>')
|
|
@@ -111,6 +111,6 @@ chatCommand
|
|
|
111
111
|
.option('--json', 'Output as JSON')
|
|
112
112
|
.action((guid, opts) => run('Delete', async () => {
|
|
113
113
|
await del(`/conversations/${guid}`);
|
|
114
|
-
printResult(`Deleted ${guid}
|
|
114
|
+
printResult(success(`Deleted ${guid}.`), opts, { guid, deleted: true });
|
|
115
115
|
}));
|
|
116
116
|
//# sourceMappingURL=chat.js.map
|
package/dist/commands/claude.js
CHANGED
|
@@ -27,6 +27,7 @@ import * as relayState from '../relay/state.js';
|
|
|
27
27
|
import { maybeOfferRelayOn, ensureDaemonRunning } from '../relay/onboarding.js';
|
|
28
28
|
import { prompt, promptBoxed, pickOne, decodeJwtExp, confirm } from '../utils.js';
|
|
29
29
|
import { brand, bold, info, success, error as clrError, muted } from '../colors.js';
|
|
30
|
+
import { createProgressReporter } from '../progress.js';
|
|
30
31
|
import { printBanner } from '../banner.js';
|
|
31
32
|
import { scanForAdoption, isLikelyEmpty, canAdoptCwd, formatCwdLabel, formatBytes, adoptCurrentDir, ADOPT_THRESHOLDS, } from '../adopt-cwd.js';
|
|
32
33
|
const __clDir = dirname(fileURLToPath(import.meta.url));
|
|
@@ -297,12 +298,10 @@ export const claudeCommand = new Command('claude')
|
|
|
297
298
|
// ── Step 2: Project ───────────────────────────────────────────────
|
|
298
299
|
let initialPrompt = '';
|
|
299
300
|
let headlessNewProject = false;
|
|
300
|
-
//
|
|
301
|
-
// sync of a large tree no longer reads as a hang.
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
console.log(` ${muted(msg)}`);
|
|
305
|
-
};
|
|
301
|
+
// One reporter for the (otherwise silent) sync phases + upload bar, so a
|
|
302
|
+
// long sync of a large tree no longer reads as a hang. Stays silent in
|
|
303
|
+
// headless (-p) runs to keep machine-readable output clean.
|
|
304
|
+
const syncProgress = nonInteractive ? undefined : createProgressReporter();
|
|
306
305
|
let existing = getConfig();
|
|
307
306
|
let forceAdoptCwd = false;
|
|
308
307
|
// Ambiguity guard: a `.gipity.json` inherited from an ANCESTOR directory
|
|
@@ -394,7 +393,7 @@ export const claudeCommand = new Command('claude')
|
|
|
394
393
|
});
|
|
395
394
|
console.log(`\n Using ${projectDir}`);
|
|
396
395
|
try {
|
|
397
|
-
const result = await sync({ interactive: !nonInteractive,
|
|
396
|
+
const result = await sync({ interactive: !nonInteractive, progress: syncProgress });
|
|
398
397
|
if (result.applied > 0) {
|
|
399
398
|
console.log(` Synced ${result.applied} change${result.applied > 1 ? 's' : ''} with Gipity.`);
|
|
400
399
|
}
|
|
@@ -462,7 +461,7 @@ export const claudeCommand = new Command('claude')
|
|
|
462
461
|
}
|
|
463
462
|
if (doSync) {
|
|
464
463
|
try {
|
|
465
|
-
const result = await sync({ interactive: !nonInteractive,
|
|
464
|
+
const result = await sync({ interactive: !nonInteractive, progress: syncProgress });
|
|
466
465
|
if (result.applied > 0) {
|
|
467
466
|
console.log(` Synced ${result.applied} change${result.applied > 1 ? 's' : ''} with Gipity.`);
|
|
468
467
|
}
|
|
@@ -588,7 +587,7 @@ export const claudeCommand = new Command('claude')
|
|
|
588
587
|
console.log(`\n Using ${projectDir}`);
|
|
589
588
|
// Unified sync - push and pull resolved via three-way merge (non-fatal)
|
|
590
589
|
try {
|
|
591
|
-
const result = await sync({ interactive: !nonInteractive,
|
|
590
|
+
const result = await sync({ interactive: !nonInteractive, progress: syncProgress });
|
|
592
591
|
if (result.applied > 0) {
|
|
593
592
|
console.log(` Synced ${result.applied} change${result.applied > 1 ? 's' : ''} with Gipity.`);
|
|
594
593
|
}
|
package/dist/commands/credits.js
CHANGED
|
@@ -28,7 +28,7 @@ export const creditsCommand = new Command('credits')
|
|
|
28
28
|
if (res.data.balances.length > 0) {
|
|
29
29
|
for (const b of res.data.balances) {
|
|
30
30
|
const exp = new Date(b.expiresAt).toLocaleDateString();
|
|
31
|
-
console.log(
|
|
31
|
+
console.log(`${b.source}: ${b.creditsRemaining.toLocaleString()} ${muted(`expires ${exp}`)}`);
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
}
|
package/dist/commands/db.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import { get, post, sendMessage } from '../api.js';
|
|
3
3
|
import { requireConfig } from '../config.js';
|
|
4
|
-
import { error as clrError } from '../colors.js';
|
|
4
|
+
import { error as clrError, success } from '../colors.js';
|
|
5
5
|
import { run, printList } from '../helpers/index.js';
|
|
6
6
|
import { confirm } from '../utils.js';
|
|
7
7
|
export const dbCommand = new Command('db')
|
|
@@ -62,12 +62,10 @@ dbCommand
|
|
|
62
62
|
console.log(JSON.stringify(res.data));
|
|
63
63
|
return;
|
|
64
64
|
}
|
|
65
|
-
console.log('');
|
|
66
65
|
console.log(`Databases: ${count}/${limit}`);
|
|
67
66
|
console.log('');
|
|
68
67
|
if (databases.length === 0) {
|
|
69
68
|
console.log('No databases.');
|
|
70
|
-
console.log('');
|
|
71
69
|
return;
|
|
72
70
|
}
|
|
73
71
|
// Group by project
|
|
@@ -78,13 +76,16 @@ dbCommand
|
|
|
78
76
|
grouped.set(key, []);
|
|
79
77
|
grouped.get(key).push(db);
|
|
80
78
|
}
|
|
79
|
+
let first = true;
|
|
81
80
|
for (const [projectGuid, dbs] of grouped) {
|
|
81
|
+
if (!first)
|
|
82
|
+
console.log('');
|
|
83
|
+
first = false;
|
|
82
84
|
const label = dbs[0].projectSlug || dbs[0].projectName || projectGuid;
|
|
83
85
|
console.log(label);
|
|
84
86
|
for (const db of dbs) {
|
|
85
|
-
console.log(
|
|
87
|
+
console.log(`${db.friendlyName}`);
|
|
86
88
|
}
|
|
87
|
-
console.log();
|
|
88
89
|
}
|
|
89
90
|
}
|
|
90
91
|
else {
|
|
@@ -143,7 +144,7 @@ dbCommand
|
|
|
143
144
|
console.log(JSON.stringify({ success: true }));
|
|
144
145
|
}
|
|
145
146
|
else {
|
|
146
|
-
console.log(`Dropped database '${name}'.`);
|
|
147
|
+
console.log(success(`Dropped database '${name}'.`));
|
|
147
148
|
}
|
|
148
149
|
}));
|
|
149
150
|
//# sourceMappingURL=db.js.map
|
package/dist/commands/deploy.js
CHANGED
|
@@ -31,8 +31,6 @@ export const deployCommand = new Command('deploy')
|
|
|
31
31
|
}
|
|
32
32
|
const config = requireConfig();
|
|
33
33
|
await syncBeforeAction(opts);
|
|
34
|
-
if (!opts.json)
|
|
35
|
-
console.log('');
|
|
36
34
|
// Call server - pipeline runs entirely server-side
|
|
37
35
|
const res = await post(`/projects/${config.projectGuid}/deploy`, {
|
|
38
36
|
target,
|
|
@@ -52,26 +50,26 @@ export const deployCommand = new Command('deploy')
|
|
|
52
50
|
console.log(muted('─'.repeat(40)));
|
|
53
51
|
if (d.phases && d.phases.length > 0) {
|
|
54
52
|
for (const phase of d.phases) {
|
|
55
|
-
console.log(
|
|
53
|
+
console.log(`${statusIcon(phase.status)} ${bold(phase.name)}: ${phase.summary}`);
|
|
56
54
|
}
|
|
57
55
|
}
|
|
58
56
|
else {
|
|
59
57
|
// Fallback for simple deploys without phases
|
|
60
58
|
const size = formatSize(d.totalBytes);
|
|
61
|
-
console.log(
|
|
59
|
+
console.log(`${success('✓')} ${d.fileCount} files (${size}) → ${success(d.url)}`);
|
|
62
60
|
}
|
|
63
61
|
if (d.customDomains?.length) {
|
|
64
|
-
console.log(
|
|
62
|
+
console.log(`${muted('Also:')} ${d.customDomains.join(', ')}`);
|
|
65
63
|
}
|
|
66
64
|
if (d.warning) {
|
|
67
|
-
console.log(
|
|
65
|
+
console.log(`${warning(d.warning)}`);
|
|
68
66
|
}
|
|
69
67
|
// Show example curl commands for public endpoints
|
|
70
68
|
if (d.examples && d.examples.length > 0) {
|
|
71
69
|
console.log('');
|
|
72
70
|
console.log(bold('Test your endpoints:'));
|
|
73
71
|
for (const ex of d.examples) {
|
|
74
|
-
console.log(
|
|
72
|
+
console.log(`${muted(ex)}`);
|
|
75
73
|
}
|
|
76
74
|
}
|
|
77
75
|
console.log(muted('─'.repeat(40)));
|
|
@@ -83,6 +81,5 @@ export const deployCommand = new Command('deploy')
|
|
|
83
81
|
else {
|
|
84
82
|
console.log(success(`✓ Deployed to ${target}`) + muted(` (${d.elapsedMs}ms)`));
|
|
85
83
|
}
|
|
86
|
-
console.log('');
|
|
87
84
|
}));
|
|
88
85
|
//# sourceMappingURL=deploy.js.map
|
package/dist/commands/doctor.js
CHANGED
|
@@ -46,22 +46,20 @@ export const doctorCommand = new Command('doctor')
|
|
|
46
46
|
const dis = updatesDisabled();
|
|
47
47
|
const local = localVersion();
|
|
48
48
|
const localOk = existsSync(LOCAL_ENTRY);
|
|
49
|
-
console.log('');
|
|
50
49
|
console.log(bold('Gipity CLI - doctor'));
|
|
51
50
|
console.log('');
|
|
52
|
-
console.log(
|
|
53
|
-
console.log(
|
|
54
|
-
console.log(
|
|
55
|
-
console.log('');
|
|
56
|
-
console.log(` ${muted('auto-updates ')} ${dis.disabled ? warning(`disabled (${dis.reason})`) : success('enabled')}`);
|
|
57
|
-
console.log(` ${muted('settings file ')} ${existsSync(SETTINGS_FILE) ? SETTINGS_FILE : dim('(default)')} autoUpdates=${settings.autoUpdates}`);
|
|
58
|
-
console.log(` ${muted('last check ')} ${rel(state.lastCheckAt)}`);
|
|
59
|
-
console.log(` ${muted('last error ')} ${state.lastError ? clrError(state.lastError) : dim('none')}`);
|
|
60
|
-
console.log(` ${muted('state file ')} ${existsSync(STATE_FILE) ? STATE_FILE : dim('(none yet)')}`);
|
|
61
|
-
console.log(` ${muted('update log ')} ${existsSync(UPDATE_LOG) ? `${UPDATE_LOG} (${statSync(UPDATE_LOG).size} bytes)` : dim('(none yet)')}`);
|
|
51
|
+
console.log(`${muted('shim version ')} ${shimVersion()}`);
|
|
52
|
+
console.log(`${muted('local version ')} ${local ?? dim('not installed')} ${localOk ? success('✓') : warning('(running from shim fallback)')}`);
|
|
53
|
+
console.log(`${muted('local install ')} ${LOCAL_PKG_DIR}`);
|
|
62
54
|
console.log('');
|
|
63
|
-
console.log(
|
|
64
|
-
console.log(
|
|
55
|
+
console.log(`${muted('auto-updates ')} ${dis.disabled ? warning(`disabled (${dis.reason})`) : success('enabled')}`);
|
|
56
|
+
console.log(`${muted('settings file ')} ${existsSync(SETTINGS_FILE) ? SETTINGS_FILE : dim('(default)')} autoUpdates=${settings.autoUpdates}`);
|
|
57
|
+
console.log(`${muted('last check ')} ${rel(state.lastCheckAt)}`);
|
|
58
|
+
console.log(`${muted('last error ')} ${state.lastError ? clrError(state.lastError) : dim('none')}`);
|
|
59
|
+
console.log(`${muted('state file ')} ${existsSync(STATE_FILE) ? STATE_FILE : dim('(none yet)')}`);
|
|
60
|
+
console.log(`${muted('update log ')} ${existsSync(UPDATE_LOG) ? `${UPDATE_LOG} (${statSync(UPDATE_LOG).size} bytes)` : dim('(none yet)')}`);
|
|
65
61
|
console.log('');
|
|
62
|
+
console.log(dim('Force an update with: gipity update'));
|
|
63
|
+
console.log(dim('Disable auto-update: export DISABLE_AUTOUPDATER=1 (or set autoUpdates: false in settings.json)'));
|
|
66
64
|
});
|
|
67
65
|
//# sourceMappingURL=doctor.js.map
|