gemkit-cli 0.2.3 → 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.
Files changed (160) hide show
  1. package/README.md +141 -7
  2. package/dist/commands/agent/index.d.ts +9 -0
  3. package/dist/commands/agent/index.js +1329 -0
  4. package/dist/commands/cache/index.d.ts +5 -0
  5. package/dist/commands/cache/index.js +43 -0
  6. package/dist/commands/catalog/index.d.ts +2 -0
  7. package/dist/commands/catalog/index.js +57 -0
  8. package/dist/commands/config/index.d.ts +7 -0
  9. package/dist/commands/config/index.js +122 -0
  10. package/dist/commands/convert/index.d.ts +8 -0
  11. package/dist/commands/convert/index.js +391 -0
  12. package/dist/commands/doctor/index.d.ts +2 -0
  13. package/dist/commands/doctor/index.js +243 -0
  14. package/dist/commands/extension/index.d.ts +5 -0
  15. package/dist/commands/extension/index.js +52 -0
  16. package/dist/commands/index.d.ts +5 -0
  17. package/dist/commands/index.js +37 -0
  18. package/dist/commands/init/index.d.ts +6 -0
  19. package/dist/commands/init/index.js +345 -0
  20. package/dist/commands/new/index.d.ts +5 -0
  21. package/dist/commands/new/index.js +49 -0
  22. package/dist/commands/office/index.d.ts +5 -0
  23. package/dist/commands/office/index.js +283 -0
  24. package/dist/commands/paste/index.d.ts +10 -0
  25. package/dist/commands/paste/index.js +533 -0
  26. package/dist/commands/plan/index.d.ts +8 -0
  27. package/dist/commands/plan/index.js +247 -0
  28. package/dist/commands/session/index.d.ts +8 -0
  29. package/dist/commands/session/index.js +289 -0
  30. package/dist/commands/tokens/index.d.ts +6 -0
  31. package/dist/commands/tokens/index.js +148 -0
  32. package/dist/commands/update/index.d.ts +26 -0
  33. package/dist/commands/update/index.js +199 -0
  34. package/dist/commands/versions/index.d.ts +5 -0
  35. package/dist/commands/versions/index.js +39 -0
  36. package/dist/domains/agent/index.d.ts +8 -0
  37. package/dist/domains/agent/index.js +8 -0
  38. package/dist/domains/agent/mappings.d.ts +32 -0
  39. package/dist/domains/agent/mappings.js +164 -0
  40. package/dist/domains/agent/profile.d.ts +26 -0
  41. package/dist/domains/agent/profile.js +225 -0
  42. package/dist/domains/agent/pty-context.d.ts +11 -0
  43. package/dist/domains/agent/pty-context.js +83 -0
  44. package/dist/domains/agent/pty-providers.d.ts +18 -0
  45. package/dist/domains/agent/pty-providers.js +66 -0
  46. package/dist/domains/agent/pty-session.d.ts +33 -0
  47. package/dist/domains/agent/pty-session.js +82 -0
  48. package/dist/domains/agent/pty-types.d.ts +127 -0
  49. package/dist/domains/agent/pty-types.js +4 -0
  50. package/dist/domains/agent/search.d.ts +45 -0
  51. package/dist/domains/agent/search.js +614 -0
  52. package/dist/domains/agent/types.d.ts +78 -0
  53. package/dist/domains/agent/types.js +5 -0
  54. package/dist/domains/agent-office/documents-scanner.d.ts +9 -0
  55. package/dist/domains/agent-office/documents-scanner.js +143 -0
  56. package/dist/domains/agent-office/event-emitter.d.ts +43 -0
  57. package/dist/domains/agent-office/event-emitter.js +86 -0
  58. package/dist/domains/agent-office/file-watcher.d.ts +40 -0
  59. package/dist/domains/agent-office/file-watcher.js +173 -0
  60. package/dist/domains/agent-office/icons.d.ts +11 -0
  61. package/dist/domains/agent-office/icons.js +36 -0
  62. package/dist/domains/agent-office/index.d.ts +12 -0
  63. package/dist/domains/agent-office/index.js +20 -0
  64. package/dist/domains/agent-office/renderer/web/assets.d.ts +11 -0
  65. package/dist/domains/agent-office/renderer/web/assets.js +3419 -0
  66. package/dist/domains/agent-office/renderer/web/server.d.ts +42 -0
  67. package/dist/domains/agent-office/renderer/web/server.js +228 -0
  68. package/dist/domains/agent-office/renderer/web.d.ts +30 -0
  69. package/dist/domains/agent-office/renderer/web.js +111 -0
  70. package/dist/domains/agent-office/session-bridge.d.ts +23 -0
  71. package/dist/domains/agent-office/session-bridge.js +171 -0
  72. package/dist/domains/agent-office/state-machine.d.ts +5 -0
  73. package/dist/domains/agent-office/state-machine.js +82 -0
  74. package/dist/domains/agent-office/types.d.ts +91 -0
  75. package/dist/domains/agent-office/types.js +4 -0
  76. package/dist/domains/cache/index.d.ts +1 -0
  77. package/dist/domains/cache/index.js +1 -0
  78. package/dist/domains/cache/manager.d.ts +22 -0
  79. package/dist/domains/cache/manager.js +84 -0
  80. package/dist/domains/config/index.d.ts +5 -0
  81. package/dist/domains/config/index.js +5 -0
  82. package/dist/domains/config/manager.d.ts +24 -0
  83. package/dist/domains/config/manager.js +85 -0
  84. package/dist/domains/config/schema.d.ts +17 -0
  85. package/dist/domains/config/schema.js +96 -0
  86. package/dist/domains/convert/converter.d.ts +78 -0
  87. package/dist/domains/convert/converter.js +471 -0
  88. package/dist/domains/convert/index.d.ts +5 -0
  89. package/dist/domains/convert/index.js +5 -0
  90. package/dist/domains/convert/types.d.ts +88 -0
  91. package/dist/domains/convert/types.js +18 -0
  92. package/dist/domains/github/download.d.ts +12 -0
  93. package/dist/domains/github/download.js +51 -0
  94. package/dist/domains/github/index.d.ts +2 -0
  95. package/dist/domains/github/index.js +2 -0
  96. package/dist/domains/github/releases.d.ts +16 -0
  97. package/dist/domains/github/releases.js +68 -0
  98. package/dist/domains/installation/conflict.d.ts +13 -0
  99. package/dist/domains/installation/conflict.js +38 -0
  100. package/dist/domains/installation/file-sync.d.ts +16 -0
  101. package/dist/domains/installation/file-sync.js +77 -0
  102. package/dist/domains/installation/index.d.ts +3 -0
  103. package/dist/domains/installation/index.js +3 -0
  104. package/dist/domains/installation/metadata.d.ts +20 -0
  105. package/dist/domains/installation/metadata.js +52 -0
  106. package/dist/domains/plan/index.d.ts +2 -0
  107. package/dist/domains/plan/index.js +2 -0
  108. package/dist/domains/plan/resolver.d.ts +24 -0
  109. package/dist/domains/plan/resolver.js +164 -0
  110. package/dist/domains/plan/types.d.ts +13 -0
  111. package/dist/domains/plan/types.js +4 -0
  112. package/dist/domains/session/env.d.ts +51 -0
  113. package/dist/domains/session/env.js +118 -0
  114. package/dist/domains/session/index.d.ts +8 -0
  115. package/dist/domains/session/index.js +8 -0
  116. package/dist/domains/session/manager.d.ts +56 -0
  117. package/dist/domains/session/manager.js +205 -0
  118. package/dist/domains/session/paths.d.ts +6 -0
  119. package/dist/domains/session/paths.js +6 -0
  120. package/dist/domains/session/types.d.ts +121 -0
  121. package/dist/domains/session/types.js +5 -0
  122. package/dist/domains/session/writer.d.ts +82 -0
  123. package/dist/domains/session/writer.js +431 -0
  124. package/dist/domains/tokens/index.d.ts +5 -0
  125. package/dist/domains/tokens/index.js +5 -0
  126. package/dist/domains/tokens/pricing.d.ts +38 -0
  127. package/dist/domains/tokens/pricing.js +129 -0
  128. package/dist/domains/tokens/scanner.d.ts +42 -0
  129. package/dist/domains/tokens/scanner.js +168 -0
  130. package/dist/index.d.ts +5 -0
  131. package/dist/index.js +87 -58
  132. package/dist/services/aipty.d.ts +76 -0
  133. package/dist/services/aipty.js +276 -0
  134. package/dist/services/archive.d.ts +22 -0
  135. package/dist/services/archive.js +53 -0
  136. package/dist/services/auto-update.d.ts +26 -0
  137. package/dist/services/auto-update.js +117 -0
  138. package/dist/services/hash.d.ts +36 -0
  139. package/dist/services/hash.js +63 -0
  140. package/dist/services/logger.d.ts +28 -0
  141. package/dist/services/logger.js +102 -0
  142. package/dist/services/music.d.ts +67 -0
  143. package/dist/services/music.js +290 -0
  144. package/dist/services/npm.d.ts +22 -0
  145. package/dist/services/npm.js +65 -0
  146. package/dist/services/pty-client.d.ts +66 -0
  147. package/dist/services/pty-client.js +154 -0
  148. package/dist/services/pty-server.d.ts +102 -0
  149. package/dist/services/pty-server.js +613 -0
  150. package/dist/types/index.d.ts +155 -0
  151. package/dist/types/index.js +4 -0
  152. package/dist/utils/colors.d.ts +43 -0
  153. package/dist/utils/colors.js +98 -0
  154. package/dist/utils/errors.d.ts +24 -0
  155. package/dist/utils/errors.js +56 -0
  156. package/dist/utils/paths.d.ts +46 -0
  157. package/dist/utils/paths.js +89 -0
  158. package/dist/utils/platform.d.ts +11 -0
  159. package/dist/utils/platform.js +31 -0
  160. 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,8 @@
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 type { CAC } from 'cac';
8
+ export declare function registerSessionCommand(cli: CAC): void;
@@ -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
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Tokens command - Session token usage analysis
3
+ * Matches token_stats.py --latest output format
4
+ */
5
+ import type { CAC } from 'cac';
6
+ export declare function registerTokensCommand(cli: CAC): void;