gemkit-cli 0.2.2 → 0.3.0
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/README.md +152 -5
- package/dist/commands/agent/index.d.ts +9 -0
- package/dist/commands/agent/index.js +1329 -0
- package/dist/commands/cache/index.d.ts +5 -0
- package/dist/commands/cache/index.js +43 -0
- package/dist/commands/catalog/index.d.ts +2 -0
- package/dist/commands/catalog/index.js +57 -0
- package/dist/commands/config/index.d.ts +7 -0
- package/dist/commands/config/index.js +122 -0
- package/dist/commands/convert/index.d.ts +8 -0
- package/dist/commands/convert/index.js +391 -0
- package/dist/commands/doctor/index.d.ts +2 -0
- package/dist/commands/doctor/index.js +243 -0
- package/dist/commands/extension/index.d.ts +5 -0
- package/dist/commands/extension/index.js +52 -0
- package/dist/commands/index.d.ts +5 -0
- package/dist/commands/index.js +37 -0
- package/dist/commands/init/index.d.ts +6 -0
- package/dist/commands/init/index.js +345 -0
- package/dist/commands/new/index.d.ts +5 -0
- package/dist/commands/new/index.js +49 -0
- package/dist/commands/office/index.d.ts +5 -0
- package/dist/commands/office/index.js +283 -0
- package/dist/commands/paste/index.d.ts +10 -0
- package/dist/commands/paste/index.js +533 -0
- package/dist/commands/plan/index.d.ts +8 -0
- package/dist/commands/plan/index.js +247 -0
- package/dist/commands/session/index.d.ts +8 -0
- package/dist/commands/session/index.js +289 -0
- package/dist/commands/tokens/index.d.ts +6 -0
- package/dist/commands/tokens/index.js +148 -0
- package/dist/commands/update/index.d.ts +26 -0
- package/dist/commands/update/index.js +199 -0
- package/dist/commands/versions/index.d.ts +5 -0
- package/dist/commands/versions/index.js +39 -0
- package/dist/domains/agent/index.d.ts +8 -0
- package/dist/domains/agent/index.js +8 -0
- package/dist/domains/agent/mappings.d.ts +32 -0
- package/dist/domains/agent/mappings.js +164 -0
- package/dist/domains/agent/profile.d.ts +26 -0
- package/dist/domains/agent/profile.js +225 -0
- package/dist/domains/agent/pty-context.d.ts +11 -0
- package/dist/domains/agent/pty-context.js +83 -0
- package/dist/domains/agent/pty-providers.d.ts +18 -0
- package/dist/domains/agent/pty-providers.js +66 -0
- package/dist/domains/agent/pty-session.d.ts +33 -0
- package/dist/domains/agent/pty-session.js +82 -0
- package/dist/domains/agent/pty-types.d.ts +127 -0
- package/dist/domains/agent/pty-types.js +4 -0
- package/dist/domains/agent/search.d.ts +45 -0
- package/dist/domains/agent/search.js +614 -0
- package/dist/domains/agent/types.d.ts +78 -0
- package/dist/domains/agent/types.js +5 -0
- package/dist/domains/agent-office/documents-scanner.d.ts +9 -0
- package/dist/domains/agent-office/documents-scanner.js +143 -0
- package/dist/domains/agent-office/event-emitter.d.ts +43 -0
- package/dist/domains/agent-office/event-emitter.js +86 -0
- package/dist/domains/agent-office/file-watcher.d.ts +40 -0
- package/dist/domains/agent-office/file-watcher.js +173 -0
- package/dist/domains/agent-office/icons.d.ts +11 -0
- package/dist/domains/agent-office/icons.js +36 -0
- package/dist/domains/agent-office/index.d.ts +12 -0
- package/dist/domains/agent-office/index.js +20 -0
- package/dist/domains/agent-office/renderer/web/assets.d.ts +11 -0
- package/dist/domains/agent-office/renderer/web/assets.js +3419 -0
- package/dist/domains/agent-office/renderer/web/server.d.ts +42 -0
- package/dist/domains/agent-office/renderer/web/server.js +228 -0
- package/dist/domains/agent-office/renderer/web.d.ts +30 -0
- package/dist/domains/agent-office/renderer/web.js +111 -0
- package/dist/domains/agent-office/session-bridge.d.ts +23 -0
- package/dist/domains/agent-office/session-bridge.js +171 -0
- package/dist/domains/agent-office/state-machine.d.ts +5 -0
- package/dist/domains/agent-office/state-machine.js +82 -0
- package/dist/domains/agent-office/types.d.ts +91 -0
- package/dist/domains/agent-office/types.js +4 -0
- package/dist/domains/cache/index.d.ts +1 -0
- package/dist/domains/cache/index.js +1 -0
- package/dist/domains/cache/manager.d.ts +22 -0
- package/dist/domains/cache/manager.js +84 -0
- package/dist/domains/config/index.d.ts +5 -0
- package/dist/domains/config/index.js +5 -0
- package/dist/domains/config/manager.d.ts +24 -0
- package/dist/domains/config/manager.js +85 -0
- package/dist/domains/config/schema.d.ts +17 -0
- package/dist/domains/config/schema.js +96 -0
- package/dist/domains/convert/converter.d.ts +78 -0
- package/dist/domains/convert/converter.js +471 -0
- package/dist/domains/convert/index.d.ts +5 -0
- package/dist/domains/convert/index.js +5 -0
- package/dist/domains/convert/types.d.ts +88 -0
- package/dist/domains/convert/types.js +18 -0
- package/dist/domains/github/download.d.ts +12 -0
- package/dist/domains/github/download.js +51 -0
- package/dist/domains/github/index.d.ts +2 -0
- package/dist/domains/github/index.js +2 -0
- package/dist/domains/github/releases.d.ts +16 -0
- package/dist/domains/github/releases.js +68 -0
- package/dist/domains/installation/conflict.d.ts +13 -0
- package/dist/domains/installation/conflict.js +38 -0
- package/dist/domains/installation/file-sync.d.ts +16 -0
- package/dist/domains/installation/file-sync.js +77 -0
- package/dist/domains/installation/index.d.ts +3 -0
- package/dist/domains/installation/index.js +3 -0
- package/dist/domains/installation/metadata.d.ts +20 -0
- package/dist/domains/installation/metadata.js +52 -0
- package/dist/domains/plan/index.d.ts +2 -0
- package/dist/domains/plan/index.js +2 -0
- package/dist/domains/plan/resolver.d.ts +24 -0
- package/dist/domains/plan/resolver.js +164 -0
- package/dist/domains/plan/types.d.ts +13 -0
- package/dist/domains/plan/types.js +4 -0
- package/dist/domains/session/env.d.ts +51 -0
- package/dist/domains/session/env.js +118 -0
- package/dist/domains/session/index.d.ts +8 -0
- package/dist/domains/session/index.js +8 -0
- package/dist/domains/session/manager.d.ts +56 -0
- package/dist/domains/session/manager.js +205 -0
- package/dist/domains/session/paths.d.ts +6 -0
- package/dist/domains/session/paths.js +6 -0
- package/dist/domains/session/types.d.ts +121 -0
- package/dist/domains/session/types.js +5 -0
- package/dist/domains/session/writer.d.ts +82 -0
- package/dist/domains/session/writer.js +431 -0
- package/dist/domains/tokens/index.d.ts +5 -0
- package/dist/domains/tokens/index.js +5 -0
- package/dist/domains/tokens/pricing.d.ts +38 -0
- package/dist/domains/tokens/pricing.js +129 -0
- package/dist/domains/tokens/scanner.d.ts +42 -0
- package/dist/domains/tokens/scanner.js +168 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +86 -57
- package/dist/services/aipty.d.ts +76 -0
- package/dist/services/aipty.js +276 -0
- package/dist/services/archive.d.ts +22 -0
- package/dist/services/archive.js +53 -0
- package/dist/services/auto-update.d.ts +26 -0
- package/dist/services/auto-update.js +117 -0
- package/dist/services/hash.d.ts +36 -0
- package/dist/services/hash.js +63 -0
- package/dist/services/logger.d.ts +28 -0
- package/dist/services/logger.js +102 -0
- package/dist/services/music.d.ts +67 -0
- package/dist/services/music.js +290 -0
- package/dist/services/npm.d.ts +22 -0
- package/dist/services/npm.js +65 -0
- package/dist/services/pty-client.d.ts +66 -0
- package/dist/services/pty-client.js +154 -0
- package/dist/services/pty-server.d.ts +102 -0
- package/dist/services/pty-server.js +613 -0
- package/dist/types/index.d.ts +155 -0
- package/dist/types/index.js +4 -0
- package/dist/utils/colors.d.ts +43 -0
- package/dist/utils/colors.js +98 -0
- package/dist/utils/errors.d.ts +24 -0
- package/dist/utils/errors.js +56 -0
- package/dist/utils/paths.d.ts +46 -0
- package/dist/utils/paths.js +89 -0
- package/dist/utils/platform.d.ts +11 -0
- package/dist/utils/platform.js +31 -0
- package/package.json +55 -54
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan command - list, status, create, set, info
|
|
3
|
+
* Replaces: gk-set-active-plan.cjs (set), get_plan_info.js (info)
|
|
4
|
+
*
|
|
5
|
+
* Subcommands organized with custom help display.
|
|
6
|
+
*/
|
|
7
|
+
import { listPlans, createPlan, setActivePlan, getPlanInfo } from '../../domains/plan/index.js';
|
|
8
|
+
import { getActivePlan, getActiveGkSessionId, readEnv } from '../../domains/session/env.js';
|
|
9
|
+
import { logger } from '../../services/logger.js';
|
|
10
|
+
import { brand, ui, pc } from '../../utils/colors.js';
|
|
11
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
12
|
+
// HELP FUNCTIONS
|
|
13
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
14
|
+
function showMainHelp() {
|
|
15
|
+
console.log();
|
|
16
|
+
console.log(pc.bold(brand.geminiPurple('Plan Management')));
|
|
17
|
+
console.log();
|
|
18
|
+
console.log('Usage:');
|
|
19
|
+
console.log(` ${brand.primary('gk plan')} <subcommand> [options]`);
|
|
20
|
+
console.log();
|
|
21
|
+
console.log('Subcommands:');
|
|
22
|
+
console.log(` ${brand.primary('list')} List all plans (default)`);
|
|
23
|
+
console.log(` ${brand.primary('status')} Show active plan status`);
|
|
24
|
+
console.log(` ${brand.primary('create')} <name> Create new plan`);
|
|
25
|
+
console.log(` ${brand.primary('set')} <name> Set active plan`);
|
|
26
|
+
console.log(` ${brand.primary('info')} Get plan info from .env`);
|
|
27
|
+
console.log();
|
|
28
|
+
console.log('Options:');
|
|
29
|
+
console.log(` ${brand.dim('--json')} Output as JSON`);
|
|
30
|
+
console.log(` ${brand.dim('-a, --active')} [info] Show only ACTIVE_PLAN value`);
|
|
31
|
+
console.log(` ${brand.dim('-s, --suggested')} [info] Show only SUGGESTED_PLAN value`);
|
|
32
|
+
console.log(` ${brand.dim('-f, --format')} [info] Show only PLAN_DATE_FORMAT value`);
|
|
33
|
+
console.log();
|
|
34
|
+
console.log('Examples:');
|
|
35
|
+
console.log(` ${brand.dim('gk plan list')}`);
|
|
36
|
+
console.log(` ${brand.dim('gk plan create my-feature')}`);
|
|
37
|
+
console.log(` ${brand.dim('gk plan set my-feature')}`);
|
|
38
|
+
console.log(` ${brand.dim('gk plan info --active')}`);
|
|
39
|
+
console.log();
|
|
40
|
+
}
|
|
41
|
+
export function registerPlanCommand(cli) {
|
|
42
|
+
cli
|
|
43
|
+
.command('plan [subcommand] [name]', 'Plan management (list, status, create, set, info)')
|
|
44
|
+
.alias('p')
|
|
45
|
+
.option('--json', '[all] Output as JSON')
|
|
46
|
+
.option('-a, --active', '[info] Show only ACTIVE_PLAN value')
|
|
47
|
+
.option('-s, --suggested', '[info] Show only SUGGESTED_PLAN value')
|
|
48
|
+
.option('-f, --format', '[info] Show only PLAN_DATE_FORMAT value')
|
|
49
|
+
.action(async (subcommand, name, options) => {
|
|
50
|
+
const sub = subcommand || 'list';
|
|
51
|
+
switch (sub) {
|
|
52
|
+
case 'list':
|
|
53
|
+
await handleList(options);
|
|
54
|
+
break;
|
|
55
|
+
case 'status':
|
|
56
|
+
await handleStatus(options);
|
|
57
|
+
break;
|
|
58
|
+
case 'create':
|
|
59
|
+
if (!name) {
|
|
60
|
+
console.log();
|
|
61
|
+
logger.error('Plan name required');
|
|
62
|
+
console.log(brand.dim('Usage: gk plan create <name>'));
|
|
63
|
+
console.log();
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
await handleCreate(name);
|
|
67
|
+
break;
|
|
68
|
+
case 'set':
|
|
69
|
+
if (!name) {
|
|
70
|
+
console.log();
|
|
71
|
+
logger.error('Plan name required');
|
|
72
|
+
console.log(brand.dim('Usage: gk plan set <name>'));
|
|
73
|
+
console.log();
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
await handleSet(name);
|
|
77
|
+
break;
|
|
78
|
+
case 'info':
|
|
79
|
+
await handleInfo(options);
|
|
80
|
+
break;
|
|
81
|
+
default:
|
|
82
|
+
showMainHelp();
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
async function handleList(options) {
|
|
87
|
+
const plans = listPlans();
|
|
88
|
+
if (options.json) {
|
|
89
|
+
console.log(JSON.stringify(plans, null, 2));
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
console.log();
|
|
93
|
+
console.log(pc.bold(brand.geminiPurple('Project Plans')));
|
|
94
|
+
console.log();
|
|
95
|
+
if (plans.length === 0) {
|
|
96
|
+
logger.info('No plans found. Create one with "gk plan create <name>".');
|
|
97
|
+
console.log();
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
for (const p of plans) {
|
|
101
|
+
const icon = p.isActive ? brand.success('→') : brand.dim('○');
|
|
102
|
+
const activeMarker = p.isActive ? brand.success(' (active)') : '';
|
|
103
|
+
console.log(` ${icon} ${brand.primary(p.name)}${activeMarker}`);
|
|
104
|
+
console.log(` ${brand.dim('Created:')} ${brand.dim(new Date(p.createdAt).toLocaleDateString())}`);
|
|
105
|
+
}
|
|
106
|
+
console.log();
|
|
107
|
+
}
|
|
108
|
+
async function handleStatus(options) {
|
|
109
|
+
const activeName = getActivePlan();
|
|
110
|
+
if (!activeName) {
|
|
111
|
+
if (options.json) {
|
|
112
|
+
console.log(JSON.stringify({ active: false }, null, 2));
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
console.log();
|
|
116
|
+
logger.info('No active plan set.');
|
|
117
|
+
console.log();
|
|
118
|
+
}
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const info = getPlanInfo(activeName);
|
|
122
|
+
if (options.json) {
|
|
123
|
+
console.log(JSON.stringify(info, null, 2));
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
console.log();
|
|
127
|
+
console.log(ui.line());
|
|
128
|
+
console.log(pc.bold(brand.geminiPurple('Active Plan')));
|
|
129
|
+
console.log(ui.line());
|
|
130
|
+
console.log();
|
|
131
|
+
console.log(` ${brand.primary(activeName)}`);
|
|
132
|
+
console.log();
|
|
133
|
+
}
|
|
134
|
+
async function handleCreate(name) {
|
|
135
|
+
try {
|
|
136
|
+
const newPlan = createPlan(name);
|
|
137
|
+
console.log();
|
|
138
|
+
logger.success(`Plan created: ${brand.primary(name)}`);
|
|
139
|
+
logger.info(`Path: ${brand.dim(newPlan.path)}`);
|
|
140
|
+
// Auto-activate
|
|
141
|
+
setActivePlan(name);
|
|
142
|
+
logger.info('Set as active plan.');
|
|
143
|
+
console.log();
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
console.log();
|
|
147
|
+
logger.error(`Failed to create plan: ${error instanceof Error ? error.message : String(error)}`);
|
|
148
|
+
console.log();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
async function handleSet(name) {
|
|
152
|
+
const plans = listPlans();
|
|
153
|
+
const exists = plans.some(p => p.name === name);
|
|
154
|
+
if (!exists) {
|
|
155
|
+
console.log();
|
|
156
|
+
logger.error(`Plan not found: ${name}`);
|
|
157
|
+
console.log();
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const success = setActivePlan(name);
|
|
161
|
+
if (!success) {
|
|
162
|
+
console.log();
|
|
163
|
+
logger.error('Failed to update session or env file');
|
|
164
|
+
console.log();
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
// Get session info for display
|
|
168
|
+
const gkSessionId = getActiveGkSessionId();
|
|
169
|
+
console.log();
|
|
170
|
+
if (gkSessionId) {
|
|
171
|
+
logger.success(`Session ${gkSessionId.slice(0, 20)}...: activePlan set to: ${brand.primary(name)}`);
|
|
172
|
+
}
|
|
173
|
+
logger.info(`Environment updated: ACTIVE_PLAN = ${name}`);
|
|
174
|
+
console.log();
|
|
175
|
+
logger.success(`Active plan set to: ${brand.primary(name)}`);
|
|
176
|
+
console.log();
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Handle plan info - Get plan information from .env
|
|
180
|
+
* Replaces: get_plan_info.js
|
|
181
|
+
*/
|
|
182
|
+
async function handleInfo(options) {
|
|
183
|
+
const env = readEnv();
|
|
184
|
+
const info = {
|
|
185
|
+
activePlan: env.ACTIVE_PLAN || null,
|
|
186
|
+
suggestedPlan: env.SUGGESTED_PLAN || null,
|
|
187
|
+
planDateFormat: env.PLAN_DATE_FORMAT || null,
|
|
188
|
+
gkSessionId: env.ACTIVE_GK_SESSION_ID || null,
|
|
189
|
+
projectDir: env.PROJECT_DIR || null
|
|
190
|
+
};
|
|
191
|
+
// Handle single-field requests
|
|
192
|
+
if (options.active) {
|
|
193
|
+
if (options.json) {
|
|
194
|
+
console.log(JSON.stringify({ activePlan: info.activePlan }));
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
console.log(info.activePlan || '');
|
|
198
|
+
}
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (options.suggested) {
|
|
202
|
+
if (options.json) {
|
|
203
|
+
console.log(JSON.stringify({ suggestedPlan: info.suggestedPlan }));
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
console.log(info.suggestedPlan || '');
|
|
207
|
+
}
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
if (options.format) {
|
|
211
|
+
if (options.json) {
|
|
212
|
+
console.log(JSON.stringify({ planDateFormat: info.planDateFormat }));
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
console.log(info.planDateFormat || '');
|
|
216
|
+
}
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
// Full output
|
|
220
|
+
if (options.json) {
|
|
221
|
+
console.log(JSON.stringify({
|
|
222
|
+
activePlan: info.activePlan,
|
|
223
|
+
suggestedPlan: info.suggestedPlan,
|
|
224
|
+
planDateFormat: info.planDateFormat,
|
|
225
|
+
context: {
|
|
226
|
+
gkSessionId: info.gkSessionId,
|
|
227
|
+
projectDir: info.projectDir
|
|
228
|
+
}
|
|
229
|
+
}, null, 2));
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
console.log();
|
|
233
|
+
console.log(ui.line());
|
|
234
|
+
console.log(pc.bold(brand.geminiPurple('Plan Information')));
|
|
235
|
+
console.log(ui.line());
|
|
236
|
+
console.log();
|
|
237
|
+
console.log(` ${brand.dim('Active Plan:')} ${info.activePlan || brand.dim('(not set)')}`);
|
|
238
|
+
console.log(` ${brand.dim('Suggested Plan:')} ${info.suggestedPlan || brand.dim('(not set)')}`);
|
|
239
|
+
console.log(` ${brand.dim('Date Format:')} ${info.planDateFormat || brand.dim('(not set)')}`);
|
|
240
|
+
console.log();
|
|
241
|
+
console.log(ui.line());
|
|
242
|
+
const shortSession = info.gkSessionId ? info.gkSessionId.substring(0, 25) + '...' : brand.dim('(no session)');
|
|
243
|
+
console.log(` ${brand.dim('Session:')} ${shortSession}`);
|
|
244
|
+
console.log(` ${brand.dim('Project:')} ${info.projectDir || brand.dim('(unknown)')}`);
|
|
245
|
+
console.log();
|
|
246
|
+
}
|
|
247
|
+
}
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session command - status, list, info, agents, init
|
|
3
|
+
* Replaces: gk-init.cjs (init subcommand)
|
|
4
|
+
*
|
|
5
|
+
* Subcommands organized with custom help display.
|
|
6
|
+
*/
|
|
7
|
+
import { getSession, listSessions, getMetrics, getActiveGkSessionId, getProjectDir, readEnv, initializeNonGeminiSession, addAgent, parseGkSessionId, getTerminalPid } from '../../domains/session/index.js';
|
|
8
|
+
import { logger } from '../../services/logger.js';
|
|
9
|
+
import { brand, ui, pc } from '../../utils/colors.js';
|
|
10
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
11
|
+
// HELP FUNCTIONS
|
|
12
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
13
|
+
function showMainHelp() {
|
|
14
|
+
console.log();
|
|
15
|
+
console.log(pc.bold(brand.geminiPurple('Session Management')));
|
|
16
|
+
console.log();
|
|
17
|
+
console.log('Usage:');
|
|
18
|
+
console.log(` ${brand.primary('gk session')} <subcommand> [options]`);
|
|
19
|
+
console.log();
|
|
20
|
+
console.log('Subcommands:');
|
|
21
|
+
console.log(` ${brand.primary('status')} Show active session (default)`);
|
|
22
|
+
console.log(` ${brand.primary('list')} List recent sessions`);
|
|
23
|
+
console.log(` ${brand.primary('info')} <id> Show session details`);
|
|
24
|
+
console.log(` ${brand.primary('agents')} [id] List agents in session`);
|
|
25
|
+
console.log(` ${brand.primary('init')} [app] Initialize new session`);
|
|
26
|
+
console.log();
|
|
27
|
+
console.log('Options:');
|
|
28
|
+
console.log(` ${brand.dim('--json')} Output as JSON`);
|
|
29
|
+
console.log(` ${brand.dim('-n, --limit <n>')} Number of results for list (default: 10)`);
|
|
30
|
+
console.log();
|
|
31
|
+
console.log('Examples:');
|
|
32
|
+
console.log(` ${brand.dim('gk session status')}`);
|
|
33
|
+
console.log(` ${brand.dim('gk session list -n 20')}`);
|
|
34
|
+
console.log(` ${brand.dim('gk session info abc123')}`);
|
|
35
|
+
console.log(` ${brand.dim('gk session agents')}`);
|
|
36
|
+
console.log(` ${brand.dim('gk session init myapp')}`);
|
|
37
|
+
console.log();
|
|
38
|
+
}
|
|
39
|
+
export function registerSessionCommand(cli) {
|
|
40
|
+
cli
|
|
41
|
+
.command('session [subcommand] [id]', 'Session management (status, list, info, agents, init)')
|
|
42
|
+
.alias('s')
|
|
43
|
+
.option('--json', '[all] Output as JSON')
|
|
44
|
+
.option('-n, --limit <n>', '[list] Number of results', { default: 10 })
|
|
45
|
+
.action(async (subcommand, id, options) => {
|
|
46
|
+
const sub = subcommand || 'status';
|
|
47
|
+
switch (sub) {
|
|
48
|
+
case 'status':
|
|
49
|
+
await handleStatus(options);
|
|
50
|
+
break;
|
|
51
|
+
case 'list':
|
|
52
|
+
await handleList(options);
|
|
53
|
+
break;
|
|
54
|
+
case 'info':
|
|
55
|
+
if (!id) {
|
|
56
|
+
console.log();
|
|
57
|
+
logger.error('Session ID required');
|
|
58
|
+
console.log(brand.dim('Usage: gk session info <id>'));
|
|
59
|
+
console.log();
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
await handleInfo(id, options);
|
|
63
|
+
break;
|
|
64
|
+
case 'agents':
|
|
65
|
+
await handleAgents(id, options);
|
|
66
|
+
break;
|
|
67
|
+
case 'init':
|
|
68
|
+
await handleInit(id || 'app', options);
|
|
69
|
+
break;
|
|
70
|
+
default:
|
|
71
|
+
showMainHelp();
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
async function handleStatus(options) {
|
|
76
|
+
const env = readEnv();
|
|
77
|
+
const projectDir = getProjectDir();
|
|
78
|
+
const gkSessionId = env.ACTIVE_GK_SESSION_ID;
|
|
79
|
+
if (!gkSessionId) {
|
|
80
|
+
if (options.json) {
|
|
81
|
+
console.log(JSON.stringify({ active: false, projectDir }, null, 2));
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
console.log();
|
|
85
|
+
logger.info('No active GemKit session.');
|
|
86
|
+
console.log(brand.dim(` Project: ${projectDir}`));
|
|
87
|
+
console.log();
|
|
88
|
+
}
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const session = getSession(projectDir, gkSessionId);
|
|
92
|
+
if (options.json) {
|
|
93
|
+
console.log(JSON.stringify(session || { active: false, gkSessionId }, null, 2));
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (!session) {
|
|
97
|
+
console.log();
|
|
98
|
+
logger.warn(`Session ID in .env but file not found: ${gkSessionId}`);
|
|
99
|
+
console.log(brand.dim(` Project: ${projectDir}`));
|
|
100
|
+
console.log();
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const metrics = getMetrics(projectDir, gkSessionId);
|
|
104
|
+
const mainAgent = session.agents?.find(a => a.agentType === 'Main Agent');
|
|
105
|
+
const status = mainAgent?.status || 'active';
|
|
106
|
+
console.log();
|
|
107
|
+
console.log(pc.bold(brand.geminiPurple('Active Session')));
|
|
108
|
+
console.log(ui.line());
|
|
109
|
+
console.log();
|
|
110
|
+
console.log(` ${brand.dim('GK Session ID:')} ${brand.primary(session.gkSessionId)}`);
|
|
111
|
+
console.log(` ${brand.dim('Gemini Session ID:')} ${session.geminiSessionId || brand.dim('N/A')}`);
|
|
112
|
+
console.log(` ${brand.dim('Project Dir:')} ${session.projectDir}`);
|
|
113
|
+
console.log(` ${brand.dim('App Name:')} ${session.appName}`);
|
|
114
|
+
console.log(` ${brand.dim('PID:')} ${session.pid}`);
|
|
115
|
+
console.log(` ${brand.dim('Status:')} ${ui.statusIcon(status)} ${status}`);
|
|
116
|
+
console.log(` ${brand.dim('Started:')} ${session.initTimestamp}`);
|
|
117
|
+
if (session.activePlan) {
|
|
118
|
+
console.log(` ${brand.dim('Active Plan:')} ${brand.primary(session.activePlan)}`);
|
|
119
|
+
}
|
|
120
|
+
console.log();
|
|
121
|
+
console.log(` ${brand.dim('Agents:')} ${metrics.total} total (${metrics.mainAgents} main, ${metrics.subAgents} sub)`);
|
|
122
|
+
console.log(` ${brand.success(String(metrics.completed))} completed, ${brand.error(String(metrics.failed))} failed, ${metrics.active} active`);
|
|
123
|
+
console.log();
|
|
124
|
+
}
|
|
125
|
+
async function handleList(options) {
|
|
126
|
+
const projectDir = getProjectDir();
|
|
127
|
+
const sessions = listSessions(projectDir, { limit: options.limit });
|
|
128
|
+
if (options.json) {
|
|
129
|
+
console.log(JSON.stringify(sessions, null, 2));
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
console.log();
|
|
133
|
+
console.log(pc.bold(brand.geminiPurple('Recent Sessions')));
|
|
134
|
+
console.log(brand.dim(` Project: ${projectDir}`));
|
|
135
|
+
console.log();
|
|
136
|
+
if (sessions.length === 0) {
|
|
137
|
+
logger.info(' No sessions found.');
|
|
138
|
+
console.log();
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
for (const s of sessions) {
|
|
142
|
+
const date = new Date(s.initTimestamp).toLocaleString();
|
|
143
|
+
const mainAgent = s.agents?.find(a => a.agentType === 'Main Agent');
|
|
144
|
+
const status = mainAgent?.status || 'active';
|
|
145
|
+
const shortId = s.gkSessionId.length > 25 ? s.gkSessionId.slice(0, 25) + '...' : s.gkSessionId;
|
|
146
|
+
console.log(` ${ui.statusIcon(status)} ${brand.primary(shortId)} ${brand.dim(date)}`);
|
|
147
|
+
if (s.activePlan) {
|
|
148
|
+
console.log(` ${brand.dim('Plan:')} ${s.activePlan}`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
console.log();
|
|
152
|
+
console.log(brand.dim(` Showing ${sessions.length} sessions (limit: ${options.limit})`));
|
|
153
|
+
console.log();
|
|
154
|
+
}
|
|
155
|
+
async function handleInfo(id, options) {
|
|
156
|
+
const projectDir = getProjectDir();
|
|
157
|
+
const session = getSession(projectDir, id);
|
|
158
|
+
if (!session) {
|
|
159
|
+
console.log();
|
|
160
|
+
logger.error(`Session not found: ${id}`);
|
|
161
|
+
console.log(brand.dim(` Looked in: ~/.gemkit/projects/${projectDir}/`));
|
|
162
|
+
console.log();
|
|
163
|
+
process.exit(1);
|
|
164
|
+
}
|
|
165
|
+
if (options.json) {
|
|
166
|
+
console.log(JSON.stringify(session, null, 2));
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
console.log();
|
|
170
|
+
console.log(pc.bold(brand.geminiPurple(`Session: ${session.gkSessionId}`)));
|
|
171
|
+
console.log(ui.line());
|
|
172
|
+
console.log();
|
|
173
|
+
console.log(JSON.stringify(session, null, 2));
|
|
174
|
+
console.log();
|
|
175
|
+
}
|
|
176
|
+
async function handleAgents(id, options) {
|
|
177
|
+
const projectDir = getProjectDir();
|
|
178
|
+
const sessionId = id || getActiveGkSessionId();
|
|
179
|
+
if (!sessionId) {
|
|
180
|
+
console.log();
|
|
181
|
+
logger.error('No session ID provided and no active session found.');
|
|
182
|
+
console.log();
|
|
183
|
+
process.exit(1);
|
|
184
|
+
}
|
|
185
|
+
const session = getSession(projectDir, sessionId);
|
|
186
|
+
if (!session) {
|
|
187
|
+
console.log();
|
|
188
|
+
logger.error(`Session not found: ${sessionId}`);
|
|
189
|
+
console.log();
|
|
190
|
+
process.exit(1);
|
|
191
|
+
}
|
|
192
|
+
const agents = session.agents || [];
|
|
193
|
+
if (options.json) {
|
|
194
|
+
console.log(JSON.stringify(agents, null, 2));
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
const shortId = sessionId.length > 30 ? sessionId.slice(0, 30) + '...' : sessionId;
|
|
198
|
+
console.log();
|
|
199
|
+
console.log(pc.bold(brand.geminiPurple(`Agents in Session`)));
|
|
200
|
+
console.log(brand.dim(` ${shortId}`));
|
|
201
|
+
console.log();
|
|
202
|
+
if (agents.length === 0) {
|
|
203
|
+
logger.info(' No agents in this session.');
|
|
204
|
+
console.log();
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
for (let i = 0; i < agents.length; i++) {
|
|
208
|
+
const a = agents[i];
|
|
209
|
+
const role = a.agentRole || 'unknown';
|
|
210
|
+
const model = a.model || 'default';
|
|
211
|
+
const type = a.agentType === 'Main Agent' ? brand.primary('MAIN') : brand.dim('SUB');
|
|
212
|
+
console.log(` ${ui.statusIcon(a.status)} [${type}] ${brand.primary(role)} ${brand.dim(`(${model})`)}`);
|
|
213
|
+
if (a.prompt) {
|
|
214
|
+
const shortPrompt = a.prompt.length > 60 ? a.prompt.slice(0, 60) + '...' : a.prompt;
|
|
215
|
+
console.log(` ${brand.dim('Prompt:')} ${shortPrompt}`);
|
|
216
|
+
}
|
|
217
|
+
if (a.tokenUsage) {
|
|
218
|
+
console.log(` ${brand.dim('Tokens:')} ${a.tokenUsage.total.toLocaleString()} total`);
|
|
219
|
+
}
|
|
220
|
+
if (a.geminiSessionId) {
|
|
221
|
+
console.log(` ${brand.dim('Gemini ID:')} ${a.geminiSessionId.slice(0, 8)}...`);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
console.log();
|
|
225
|
+
console.log(brand.dim(` Total: ${agents.length} agents`));
|
|
226
|
+
console.log();
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Handle session init - Initialize a non-Gemini GemKit session
|
|
230
|
+
* Replaces: gk-init.cjs
|
|
231
|
+
*/
|
|
232
|
+
async function handleInit(appName, options) {
|
|
233
|
+
const env = readEnv();
|
|
234
|
+
const existingSessionId = env.ACTIVE_GK_SESSION_ID;
|
|
235
|
+
if (existingSessionId) {
|
|
236
|
+
// Parse PID from existing session ID
|
|
237
|
+
const parsed = parseGkSessionId(existingSessionId);
|
|
238
|
+
const projectDir = getProjectDir();
|
|
239
|
+
if (parsed) {
|
|
240
|
+
// Get current terminal PID to compare
|
|
241
|
+
const currentTerminalPid = getTerminalPid();
|
|
242
|
+
// Check if session exists and has same PID (same terminal)
|
|
243
|
+
const existingSession = getSession(projectDir, existingSessionId);
|
|
244
|
+
if (existingSession && parsed.pid === currentTerminalPid) {
|
|
245
|
+
// Session already exists for this terminal
|
|
246
|
+
if (options.json) {
|
|
247
|
+
console.log(JSON.stringify({
|
|
248
|
+
status: 'existing',
|
|
249
|
+
gkSessionId: existingSessionId,
|
|
250
|
+
pid: parsed.pid
|
|
251
|
+
}, null, 2));
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
console.log();
|
|
255
|
+
logger.info(`GemKit session already active: ${brand.primary(existingSessionId.slice(0, 30) + '...')}`);
|
|
256
|
+
console.log(brand.dim(` PID: ${parsed.pid}`));
|
|
257
|
+
console.log();
|
|
258
|
+
}
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
// Initialize new non-Gemini session
|
|
264
|
+
const { session, gkSessionId, pid, projectDir } = initializeNonGeminiSession(appName);
|
|
265
|
+
// Add main agent entry to session
|
|
266
|
+
addAgent(projectDir, gkSessionId, {
|
|
267
|
+
gkSessionId: gkSessionId,
|
|
268
|
+
pid: pid,
|
|
269
|
+
geminiSessionId: null,
|
|
270
|
+
parentGkSessionId: null,
|
|
271
|
+
agentRole: 'main',
|
|
272
|
+
prompt: null,
|
|
273
|
+
model: null
|
|
274
|
+
});
|
|
275
|
+
if (options.json) {
|
|
276
|
+
console.log(JSON.stringify({
|
|
277
|
+
status: 'initialized',
|
|
278
|
+
gkSessionId: gkSessionId,
|
|
279
|
+
pid: pid,
|
|
280
|
+
projectDir: projectDir
|
|
281
|
+
}, null, 2));
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
console.log();
|
|
285
|
+
logger.success(`GemKit session initialized: ${brand.primary(gkSessionId.slice(0, 30) + '...')}`);
|
|
286
|
+
console.log(brand.dim(` PID: ${pid}`));
|
|
287
|
+
console.log();
|
|
288
|
+
}
|
|
289
|
+
}
|