gemkit-cli 0.2.3 → 0.3.1

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 +90 -59
  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,102 @@
1
+ /**
2
+ * Logging service for GemKit CLI
3
+ */
4
+ import { brand } from '../utils/colors.js';
5
+ const LOG_LEVELS = {
6
+ debug: 0,
7
+ info: 1,
8
+ warn: 2,
9
+ error: 3,
10
+ silent: 4,
11
+ };
12
+ let config = {
13
+ level: 'info',
14
+ verbose: false,
15
+ json: false,
16
+ };
17
+ export function configureLogger(options) {
18
+ config = { ...config, ...options };
19
+ }
20
+ function shouldLog(level) {
21
+ return LOG_LEVELS[level] >= LOG_LEVELS[config.level];
22
+ }
23
+ export function debug(message, data) {
24
+ if (!shouldLog('debug'))
25
+ return;
26
+ if (config.json) {
27
+ console.log(JSON.stringify({ level: 'debug', message, data }));
28
+ }
29
+ else {
30
+ console.log(brand.dim(`[DEBUG] ${message}`));
31
+ if (data && config.verbose) {
32
+ console.log(brand.dim(JSON.stringify(data, null, 2)));
33
+ }
34
+ }
35
+ }
36
+ export function info(message, data) {
37
+ if (!shouldLog('info'))
38
+ return;
39
+ if (config.json) {
40
+ console.log(JSON.stringify({ level: 'info', message, data }));
41
+ }
42
+ else {
43
+ console.log(`${brand.info('ℹ')} ${message}`);
44
+ if (data && config.verbose) {
45
+ console.log(JSON.stringify(data, null, 2));
46
+ }
47
+ }
48
+ }
49
+ export function success(message, data) {
50
+ if (!shouldLog('info'))
51
+ return;
52
+ if (config.json) {
53
+ console.log(JSON.stringify({ level: 'success', message, data }));
54
+ }
55
+ else {
56
+ console.log(`${brand.success('✓')} ${message}`);
57
+ }
58
+ }
59
+ export function warn(message, data) {
60
+ if (!shouldLog('warn'))
61
+ return;
62
+ if (config.json) {
63
+ console.log(JSON.stringify({ level: 'warn', message, data }));
64
+ }
65
+ else {
66
+ console.log(`${brand.warn('⚠')} ${message}`);
67
+ }
68
+ }
69
+ export function error(message, data) {
70
+ if (!shouldLog('error'))
71
+ return;
72
+ if (config.json) {
73
+ console.error(JSON.stringify({ level: 'error', message, data }));
74
+ }
75
+ else {
76
+ console.error(`${brand.error('✗')} ${message}`);
77
+ if (data && config.verbose) {
78
+ console.error(JSON.stringify(data, null, 2));
79
+ }
80
+ }
81
+ }
82
+ export function table(data) {
83
+ if (config.json) {
84
+ console.log(JSON.stringify(data));
85
+ }
86
+ else {
87
+ console.table(data);
88
+ }
89
+ }
90
+ export function json(data) {
91
+ console.log(JSON.stringify(data, null, 2));
92
+ }
93
+ export const logger = {
94
+ debug,
95
+ info,
96
+ success,
97
+ warn,
98
+ error,
99
+ table,
100
+ json,
101
+ configure: configureLogger,
102
+ };
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Elevator Music Player - Cross-platform background audio for long-running processes
3
+ * Supports: Windows (PowerShell), Mac (afplay), Linux (aplay/paplay)
4
+ */
5
+ export interface ElevatorMusicOptions {
6
+ audioFile?: string;
7
+ loop?: boolean;
8
+ volume?: number;
9
+ }
10
+ export declare class ElevatorMusic {
11
+ private audioFile;
12
+ private loop;
13
+ private volume;
14
+ private process;
15
+ private isPlaying;
16
+ private loopInterval;
17
+ private hasLock;
18
+ private lockRefreshInterval;
19
+ private triedFallback;
20
+ constructor(options?: ElevatorMusicOptions);
21
+ /**
22
+ * Try to acquire the global music lock
23
+ */
24
+ private tryAcquireLock;
25
+ /**
26
+ * Try to take over a potentially stale lock
27
+ */
28
+ private tryTakeStaleLock;
29
+ /**
30
+ * Refresh the lock timestamp
31
+ */
32
+ private refreshLock;
33
+ /**
34
+ * Release the global music lock
35
+ */
36
+ private releaseLock;
37
+ /**
38
+ * Get default audio file path
39
+ */
40
+ private getDefaultAudioFile;
41
+ /**
42
+ * Get platform-specific play command
43
+ */
44
+ private getPlayCommand;
45
+ /**
46
+ * Start playing music
47
+ */
48
+ start(options?: {
49
+ force?: boolean;
50
+ }): boolean;
51
+ /**
52
+ * Internal loop handler
53
+ */
54
+ private playLoop;
55
+ /**
56
+ * Stop playing music
57
+ */
58
+ stop(): void;
59
+ /**
60
+ * Check if currently playing
61
+ */
62
+ get playing(): boolean;
63
+ /**
64
+ * Static method to check if any instance is currently playing
65
+ */
66
+ static isAnyPlaying(): boolean;
67
+ }
@@ -0,0 +1,290 @@
1
+ /**
2
+ * Elevator Music Player - Cross-platform background audio for long-running processes
3
+ * Supports: Windows (PowerShell), Mac (afplay), Linux (aplay/paplay)
4
+ */
5
+ import { spawn, exec } from 'child_process';
6
+ import { existsSync, readFileSync, writeFileSync, unlinkSync } from 'fs';
7
+ import { join } from 'path';
8
+ import { tmpdir, platform } from 'os';
9
+ // Global lock file path for cross-process coordination
10
+ const LOCK_FILE = join(tmpdir(), 'elevator-music.lock');
11
+ const LOCK_STALE_MS = 30000; // Consider lock stale after 30 seconds
12
+ export class ElevatorMusic {
13
+ audioFile;
14
+ loop;
15
+ volume;
16
+ process = null;
17
+ isPlaying = false;
18
+ loopInterval = null;
19
+ hasLock = false;
20
+ lockRefreshInterval = null;
21
+ triedFallback = false;
22
+ constructor(options = {}) {
23
+ this.audioFile = options.audioFile || this.getDefaultAudioFile();
24
+ this.loop = options.loop !== false; // Default to looping
25
+ this.volume = options.volume || 0.5; // 0.0 to 1.0
26
+ }
27
+ /**
28
+ * Try to acquire the global music lock
29
+ */
30
+ tryAcquireLock() {
31
+ const lockData = {
32
+ pid: process.pid,
33
+ timestamp: Date.now()
34
+ };
35
+ try {
36
+ writeFileSync(LOCK_FILE, JSON.stringify(lockData), { flag: 'wx' });
37
+ this.hasLock = true;
38
+ this.lockRefreshInterval = setInterval(() => {
39
+ this.refreshLock();
40
+ }, LOCK_STALE_MS / 3);
41
+ return true;
42
+ }
43
+ catch (err) {
44
+ if (err.code === 'EEXIST') {
45
+ return this.tryTakeStaleLock(lockData);
46
+ }
47
+ return false;
48
+ }
49
+ }
50
+ /**
51
+ * Try to take over a potentially stale lock
52
+ */
53
+ tryTakeStaleLock(newLockData) {
54
+ try {
55
+ const existingLock = JSON.parse(readFileSync(LOCK_FILE, 'utf8'));
56
+ const lockAge = Date.now() - existingLock.timestamp;
57
+ if (lockAge < LOCK_STALE_MS && existingLock.pid !== process.pid) {
58
+ try {
59
+ process.kill(existingLock.pid, 0);
60
+ return false;
61
+ }
62
+ catch {
63
+ // Process doesn't exist, lock is stale
64
+ }
65
+ }
66
+ unlinkSync(LOCK_FILE);
67
+ try {
68
+ writeFileSync(LOCK_FILE, JSON.stringify(newLockData), { flag: 'wx' });
69
+ this.hasLock = true;
70
+ this.lockRefreshInterval = setInterval(() => {
71
+ this.refreshLock();
72
+ }, LOCK_STALE_MS / 3);
73
+ return true;
74
+ }
75
+ catch {
76
+ return false;
77
+ }
78
+ }
79
+ catch {
80
+ return false;
81
+ }
82
+ }
83
+ /**
84
+ * Refresh the lock timestamp
85
+ */
86
+ refreshLock() {
87
+ if (!this.hasLock)
88
+ return;
89
+ try {
90
+ const lockData = {
91
+ pid: process.pid,
92
+ timestamp: Date.now()
93
+ };
94
+ writeFileSync(LOCK_FILE, JSON.stringify(lockData), { flag: 'w' });
95
+ }
96
+ catch {
97
+ // Ignore refresh errors
98
+ }
99
+ }
100
+ /**
101
+ * Release the global music lock
102
+ */
103
+ releaseLock() {
104
+ if (this.lockRefreshInterval) {
105
+ clearInterval(this.lockRefreshInterval);
106
+ this.lockRefreshInterval = null;
107
+ }
108
+ if (!this.hasLock)
109
+ return;
110
+ try {
111
+ if (existsSync(LOCK_FILE)) {
112
+ const lockData = JSON.parse(readFileSync(LOCK_FILE, 'utf8'));
113
+ if (lockData.pid === process.pid) {
114
+ unlinkSync(LOCK_FILE);
115
+ }
116
+ }
117
+ }
118
+ catch {
119
+ // Ignore cleanup errors
120
+ }
121
+ this.hasLock = false;
122
+ }
123
+ /**
124
+ * Get default audio file path
125
+ */
126
+ getDefaultAudioFile() {
127
+ // Check common locations for audio file
128
+ const searchPaths = [
129
+ join(process.cwd(), '.gemini', 'extensions', 'spawn-agent', 'assets', 'golden-coast-melody.wav'),
130
+ join(process.cwd(), '.gemini', 'assets', 'elevator_music.wav'),
131
+ join(process.cwd(), 'assets', 'elevator_music.wav'),
132
+ ];
133
+ for (const p of searchPaths) {
134
+ if (existsSync(p)) {
135
+ return p;
136
+ }
137
+ }
138
+ return null;
139
+ }
140
+ /**
141
+ * Get platform-specific play command
142
+ */
143
+ getPlayCommand() {
144
+ if (!this.audioFile)
145
+ return null;
146
+ const plat = platform();
147
+ switch (plat) {
148
+ case 'win32':
149
+ return {
150
+ command: 'powershell',
151
+ args: [
152
+ '-NoProfile',
153
+ '-Command',
154
+ `$player = New-Object System.Media.SoundPlayer '${this.audioFile}'; $player.PlaySync()`
155
+ ],
156
+ shell: false
157
+ };
158
+ case 'darwin':
159
+ return {
160
+ command: 'afplay',
161
+ args: ['-v', String(this.volume), this.audioFile],
162
+ shell: false
163
+ };
164
+ case 'linux':
165
+ return {
166
+ command: 'paplay',
167
+ args: ['--volume', String(Math.round(this.volume * 65536)), this.audioFile],
168
+ shell: false,
169
+ fallback: {
170
+ command: 'aplay',
171
+ args: ['-q', this.audioFile],
172
+ shell: false
173
+ }
174
+ };
175
+ default:
176
+ return null;
177
+ }
178
+ }
179
+ /**
180
+ * Start playing music
181
+ */
182
+ start(options = {}) {
183
+ if (!this.audioFile) {
184
+ return false;
185
+ }
186
+ if (!existsSync(this.audioFile)) {
187
+ return false;
188
+ }
189
+ if (this.isPlaying) {
190
+ return true;
191
+ }
192
+ if (!options.force && !this.tryAcquireLock()) {
193
+ return false;
194
+ }
195
+ const playConfig = this.getPlayCommand();
196
+ if (!playConfig) {
197
+ this.releaseLock();
198
+ return false;
199
+ }
200
+ this.isPlaying = true;
201
+ this.playLoop(playConfig);
202
+ return true;
203
+ }
204
+ /**
205
+ * Internal loop handler
206
+ */
207
+ playLoop(playConfig) {
208
+ if (!this.isPlaying)
209
+ return;
210
+ const startPlay = (config) => {
211
+ this.process = spawn(config.command, config.args, {
212
+ stdio: ['ignore', 'ignore', 'pipe'],
213
+ windowsHide: true,
214
+ shell: config.shell
215
+ });
216
+ this.process.stderr?.on('data', () => {
217
+ if (config.fallback && !this.triedFallback) {
218
+ this.triedFallback = true;
219
+ this.process?.kill();
220
+ startPlay(config.fallback);
221
+ }
222
+ });
223
+ this.process.on('close', () => {
224
+ if (this.isPlaying && this.loop) {
225
+ this.loopInterval = setTimeout(() => {
226
+ this.playLoop(playConfig);
227
+ }, 100);
228
+ }
229
+ });
230
+ this.process.on('error', () => {
231
+ if (config.fallback && !this.triedFallback) {
232
+ this.triedFallback = true;
233
+ startPlay(config.fallback);
234
+ }
235
+ });
236
+ };
237
+ startPlay(playConfig);
238
+ }
239
+ /**
240
+ * Stop playing music
241
+ */
242
+ stop() {
243
+ this.isPlaying = false;
244
+ if (this.loopInterval) {
245
+ clearTimeout(this.loopInterval);
246
+ this.loopInterval = null;
247
+ }
248
+ if (this.process) {
249
+ if (platform() === 'win32') {
250
+ exec(`taskkill /pid ${this.process.pid} /T /F`, { windowsHide: true });
251
+ }
252
+ else {
253
+ this.process.kill('SIGTERM');
254
+ }
255
+ this.process = null;
256
+ }
257
+ this.releaseLock();
258
+ }
259
+ /**
260
+ * Check if currently playing
261
+ */
262
+ get playing() {
263
+ return this.isPlaying;
264
+ }
265
+ /**
266
+ * Static method to check if any instance is currently playing
267
+ */
268
+ static isAnyPlaying() {
269
+ try {
270
+ if (!existsSync(LOCK_FILE)) {
271
+ return false;
272
+ }
273
+ const lockData = JSON.parse(readFileSync(LOCK_FILE, 'utf8'));
274
+ const lockAge = Date.now() - lockData.timestamp;
275
+ if (lockAge >= LOCK_STALE_MS) {
276
+ return false;
277
+ }
278
+ try {
279
+ process.kill(lockData.pid, 0);
280
+ return true;
281
+ }
282
+ catch {
283
+ return false;
284
+ }
285
+ }
286
+ catch {
287
+ return false;
288
+ }
289
+ }
290
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * NPM Registry service - Check package versions
3
+ */
4
+ export interface NpmPackageInfo {
5
+ name: string;
6
+ version: string;
7
+ description?: string;
8
+ publishedAt?: string;
9
+ }
10
+ /**
11
+ * Get latest version of a package from npm registry
12
+ */
13
+ export declare function getLatestNpmVersion(packageName: string): Promise<NpmPackageInfo | null>;
14
+ /**
15
+ * Compare two semver versions
16
+ * Returns: 1 if a > b, -1 if a < b, 0 if equal
17
+ */
18
+ export declare function compareVersions(a: string, b: string): number;
19
+ /**
20
+ * Check if update is available
21
+ */
22
+ export declare function isUpdateAvailable(current: string, latest: string): boolean;
@@ -0,0 +1,65 @@
1
+ /**
2
+ * NPM Registry service - Check package versions
3
+ */
4
+ import { getCache, setCache } from '../domains/cache/manager.js';
5
+ const NPM_REGISTRY = 'https://registry.npmjs.org';
6
+ const CACHE_KEY = 'npm-version';
7
+ const CACHE_TTL = 3600; // 1 hour
8
+ /**
9
+ * Get latest version of a package from npm registry
10
+ */
11
+ export async function getLatestNpmVersion(packageName) {
12
+ const cacheKey = `${CACHE_KEY}-${packageName}`;
13
+ // Check cache first
14
+ const cached = getCache(cacheKey);
15
+ if (cached) {
16
+ return cached;
17
+ }
18
+ try {
19
+ const response = await fetch(`${NPM_REGISTRY}/${packageName}/latest`, {
20
+ headers: {
21
+ 'Accept': 'application/json',
22
+ 'User-Agent': 'gemkit-cli',
23
+ },
24
+ });
25
+ if (!response.ok) {
26
+ return null;
27
+ }
28
+ const data = await response.json();
29
+ const info = {
30
+ name: data.name,
31
+ version: data.version,
32
+ description: data.description,
33
+ publishedAt: data.time?.[data.version],
34
+ };
35
+ // Cache result
36
+ setCache(cacheKey, info, CACHE_TTL);
37
+ return info;
38
+ }
39
+ catch {
40
+ return null;
41
+ }
42
+ }
43
+ /**
44
+ * Compare two semver versions
45
+ * Returns: 1 if a > b, -1 if a < b, 0 if equal
46
+ */
47
+ export function compareVersions(a, b) {
48
+ const partsA = a.replace(/^v/, '').split('.').map(Number);
49
+ const partsB = b.replace(/^v/, '').split('.').map(Number);
50
+ for (let i = 0; i < Math.max(partsA.length, partsB.length); i++) {
51
+ const numA = partsA[i] || 0;
52
+ const numB = partsB[i] || 0;
53
+ if (numA > numB)
54
+ return 1;
55
+ if (numA < numB)
56
+ return -1;
57
+ }
58
+ return 0;
59
+ }
60
+ /**
61
+ * Check if update is available
62
+ */
63
+ export function isUpdateAvailable(current, latest) {
64
+ return compareVersions(latest, current) > 0;
65
+ }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * PTY Client - Sends commands to the PTY server
3
+ * Ported from claude-pty-wrapper/client.js
4
+ */
5
+ import type { PtyExchange, PtyServerStatus, PtySendResponse, PtyCompleteResponse, PtyPendingResponse } from '../domains/agent/pty-types.js';
6
+ export declare class PtyClient {
7
+ private port;
8
+ private host;
9
+ constructor(port?: number, host?: string);
10
+ /**
11
+ * Send command to server and get response
12
+ */
13
+ sendCommand(command: string): Promise<string>;
14
+ /**
15
+ * Check if server is running
16
+ */
17
+ isServerRunning(): Promise<boolean>;
18
+ /**
19
+ * Get server status
20
+ */
21
+ status(): Promise<PtyServerStatus>;
22
+ /**
23
+ * Send prompt to session
24
+ */
25
+ send(prompt: string): Promise<PtySendResponse>;
26
+ /**
27
+ * Wait for completion
28
+ */
29
+ waitForCompletion(timeout?: number): Promise<boolean>;
30
+ /**
31
+ * Check if response is complete
32
+ */
33
+ complete(): Promise<PtyCompleteResponse>;
34
+ /**
35
+ * Get structured exchange output
36
+ */
37
+ exchange(): Promise<PtyExchange>;
38
+ /**
39
+ * Check for pending tool confirmations
40
+ */
41
+ pending(): Promise<PtyPendingResponse>;
42
+ /**
43
+ * Read raw output
44
+ */
45
+ read(lines?: number): Promise<string>;
46
+ /**
47
+ * Get exchange history
48
+ */
49
+ history(): Promise<{
50
+ provider: string;
51
+ count: number;
52
+ exchanges: PtyExchange[];
53
+ }>;
54
+ /**
55
+ * Clear exchange history
56
+ */
57
+ clearHistory(): Promise<void>;
58
+ /**
59
+ * Stop the server
60
+ */
61
+ stop(): Promise<void>;
62
+ /**
63
+ * Sleep helper
64
+ */
65
+ private sleep;
66
+ }