@gowelle/stint-agent 1.2.32 → 1.2.34
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/{StatusDashboard-LF6THHHE.js → StatusDashboard-6H3FWITW.js} +2 -2
- package/dist/api-TC3OYN5R.js +7 -0
- package/dist/{chunk-6WYXA4IS.js → chunk-BKJMUBZE.js} +13 -6
- package/dist/{chunk-JFKHNWBC.js → chunk-L4S6LLKQ.js} +45 -19
- package/dist/{chunk-FHPSIVFK.js → chunk-NEUK7ZZY.js} +2 -2
- package/dist/{chunk-HCOIO2ND.js → chunk-UB56ZQNI.js} +1 -1
- package/dist/daemon/runner.js +4 -4
- package/dist/index.js +139 -44
- package/package.json +1 -1
- package/dist/api-MYPJRJLZ.js +0 -7
|
@@ -2,10 +2,10 @@ import {
|
|
|
2
2
|
gitService,
|
|
3
3
|
projectService,
|
|
4
4
|
validatePidFile
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-UB56ZQNI.js";
|
|
6
6
|
import {
|
|
7
7
|
authService
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-BKJMUBZE.js";
|
|
9
9
|
|
|
10
10
|
// src/components/StatusDashboard.tsx
|
|
11
11
|
import { useState, useEffect } from "react";
|
|
@@ -180,6 +180,13 @@ var ERROR_LOG = path.join(LOG_DIR, "error.log");
|
|
|
180
180
|
var MAX_LOG_SIZE = 10 * 1024 * 1024;
|
|
181
181
|
var MAX_LOG_FILES = 7;
|
|
182
182
|
var Logger = class {
|
|
183
|
+
consoleEnabled = true;
|
|
184
|
+
disableConsole() {
|
|
185
|
+
this.consoleEnabled = false;
|
|
186
|
+
}
|
|
187
|
+
enableConsole() {
|
|
188
|
+
this.consoleEnabled = true;
|
|
189
|
+
}
|
|
183
190
|
ensureLogDir() {
|
|
184
191
|
if (!fs.existsSync(LOG_DIR)) {
|
|
185
192
|
fs.mkdirSync(LOG_DIR, { recursive: true });
|
|
@@ -212,17 +219,17 @@ var Logger = class {
|
|
|
212
219
|
}
|
|
213
220
|
info(category, message) {
|
|
214
221
|
this.writeLog("INFO", category, message, AGENT_LOG);
|
|
215
|
-
console.log(`\u2139 [${category}] ${message}`);
|
|
222
|
+
if (this.consoleEnabled) console.log(`\u2139 [${category}] ${message}`);
|
|
216
223
|
}
|
|
217
224
|
warn(category, message) {
|
|
218
225
|
this.writeLog("WARN", category, message, AGENT_LOG);
|
|
219
|
-
console.warn(`\u26A0 [${category}] ${message}`);
|
|
226
|
+
if (this.consoleEnabled) console.warn(`\u26A0 [${category}] ${message}`);
|
|
220
227
|
}
|
|
221
228
|
error(category, message, error) {
|
|
222
229
|
const fullMessage = error ? `${message}: ${error.message}` : message;
|
|
223
230
|
this.writeLog("ERROR", category, fullMessage, ERROR_LOG);
|
|
224
231
|
this.writeLog("ERROR", category, fullMessage, AGENT_LOG);
|
|
225
|
-
console.error(`\u2716 [${category}] ${fullMessage}`);
|
|
232
|
+
if (this.consoleEnabled) console.error(`\u2716 [${category}] ${fullMessage}`);
|
|
226
233
|
if (error?.stack) {
|
|
227
234
|
this.writeLog("ERROR", category, error.stack, ERROR_LOG);
|
|
228
235
|
}
|
|
@@ -230,12 +237,12 @@ var Logger = class {
|
|
|
230
237
|
debug(category, message) {
|
|
231
238
|
if (process.env.DEBUG) {
|
|
232
239
|
this.writeLog("DEBUG", category, message, AGENT_LOG);
|
|
233
|
-
console.debug(`\u{1F41B} [${category}] ${message}`);
|
|
240
|
+
if (this.consoleEnabled) console.debug(`\u{1F41B} [${category}] ${message}`);
|
|
234
241
|
}
|
|
235
242
|
}
|
|
236
243
|
success(category, message) {
|
|
237
244
|
this.writeLog("INFO", category, message, AGENT_LOG);
|
|
238
|
-
console.log(`\u2713 [${category}] ${message}`);
|
|
245
|
+
if (this.consoleEnabled) console.log(`\u2713 [${category}] ${message}`);
|
|
239
246
|
}
|
|
240
247
|
};
|
|
241
248
|
var logger = new Logger();
|
|
@@ -308,7 +315,7 @@ var AuthServiceImpl = class {
|
|
|
308
315
|
return null;
|
|
309
316
|
}
|
|
310
317
|
try {
|
|
311
|
-
const { apiService } = await import("./api-
|
|
318
|
+
const { apiService } = await import("./api-TC3OYN5R.js");
|
|
312
319
|
const user = await apiService.getCurrentUser();
|
|
313
320
|
logger.info("auth", `Token validated for user: ${user.email}`);
|
|
314
321
|
return user;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
apiService
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-NEUK7ZZY.js";
|
|
4
4
|
import {
|
|
5
5
|
gitService,
|
|
6
6
|
projectService
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-UB56ZQNI.js";
|
|
8
8
|
import {
|
|
9
9
|
authService,
|
|
10
10
|
config,
|
|
11
11
|
logger
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-BKJMUBZE.js";
|
|
13
13
|
|
|
14
14
|
// src/utils/notify.ts
|
|
15
15
|
import notifier from "node-notifier";
|
|
@@ -519,6 +519,7 @@ var WebSocketServiceImpl = class {
|
|
|
519
519
|
maxReconnectAttempts = 10;
|
|
520
520
|
reconnectTimer = null;
|
|
521
521
|
isManualDisconnect = false;
|
|
522
|
+
currentPusherClient = null;
|
|
522
523
|
// Event handlers
|
|
523
524
|
commitApprovedHandlers = [];
|
|
524
525
|
commitPendingHandlers = [];
|
|
@@ -532,10 +533,12 @@ var WebSocketServiceImpl = class {
|
|
|
532
533
|
* @throws Error if connection fails or no auth token available
|
|
533
534
|
*/
|
|
534
535
|
async connect() {
|
|
536
|
+
this.currentPusherClient = null;
|
|
535
537
|
if (this.echo) {
|
|
536
538
|
logger.debug("websocket", "Closing existing connection before reconnecting...");
|
|
537
539
|
this.echo.disconnect();
|
|
538
540
|
this.echo = null;
|
|
541
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
539
542
|
}
|
|
540
543
|
try {
|
|
541
544
|
const token = await authService.getToken();
|
|
@@ -625,40 +628,54 @@ var WebSocketServiceImpl = class {
|
|
|
625
628
|
client: pusherClient
|
|
626
629
|
});
|
|
627
630
|
this.echo = echoInstance;
|
|
631
|
+
this.currentPusherClient = pusherClient;
|
|
628
632
|
logger.info("websocket", "Echo instance created, setting up connection handlers...");
|
|
629
633
|
return new Promise((resolve, reject) => {
|
|
634
|
+
let isSettled = false;
|
|
635
|
+
const safeResolve = () => {
|
|
636
|
+
if (!isSettled) {
|
|
637
|
+
isSettled = true;
|
|
638
|
+
resolve();
|
|
639
|
+
}
|
|
640
|
+
};
|
|
641
|
+
const safeReject = (error) => {
|
|
642
|
+
if (!isSettled) {
|
|
643
|
+
isSettled = true;
|
|
644
|
+
reject(error);
|
|
645
|
+
}
|
|
646
|
+
};
|
|
630
647
|
if (pusherClient.connection.state === "connected") {
|
|
631
648
|
logger.success("websocket", "\u2705 Already connected to Broadcaster");
|
|
632
649
|
writeStatus({ connected: true });
|
|
633
650
|
this.reconnectAttempts = 0;
|
|
634
651
|
this.isManualDisconnect = false;
|
|
635
|
-
|
|
652
|
+
safeResolve();
|
|
636
653
|
return;
|
|
637
654
|
}
|
|
638
655
|
const connectionTimeout = setTimeout(() => {
|
|
639
|
-
if (this.
|
|
656
|
+
if (this.currentPusherClient !== pusherClient) return;
|
|
640
657
|
const state = pusherClient.connection.state || "unknown";
|
|
641
658
|
logger.error("websocket", `Connection timeout after 30s (state: ${state})`);
|
|
642
659
|
if (state !== "connected") {
|
|
643
|
-
|
|
660
|
+
safeReject(new Error(`Connection timeout - stuck in state: ${state}`));
|
|
644
661
|
}
|
|
645
662
|
}, 3e4);
|
|
646
663
|
pusherClient.connection.bind("state_change", (states) => {
|
|
647
|
-
if (this.
|
|
664
|
+
if (this.currentPusherClient === pusherClient) {
|
|
648
665
|
logger.info("websocket", `Connection state: ${states.previous} -> ${states.current}`);
|
|
649
666
|
}
|
|
650
667
|
});
|
|
651
668
|
pusherClient.connection.bind("connected", () => {
|
|
652
|
-
if (this.
|
|
669
|
+
if (this.currentPusherClient !== pusherClient) return;
|
|
653
670
|
clearTimeout(connectionTimeout);
|
|
654
671
|
logger.success("websocket", "\u2705 Connected to Broadcaster via Sanctum");
|
|
655
672
|
writeStatus({ connected: true });
|
|
656
673
|
this.reconnectAttempts = 0;
|
|
657
674
|
this.isManualDisconnect = false;
|
|
658
|
-
|
|
675
|
+
safeResolve();
|
|
659
676
|
});
|
|
660
677
|
pusherClient.connection.bind("error", (error) => {
|
|
661
|
-
if (this.
|
|
678
|
+
if (this.currentPusherClient !== pusherClient) return;
|
|
662
679
|
clearTimeout(connectionTimeout);
|
|
663
680
|
const errorMessage = error instanceof Error ? error.message : JSON.stringify(error) || "Unknown connection error";
|
|
664
681
|
logger.error("websocket", `WebSocket error: ${errorMessage}`);
|
|
@@ -667,28 +684,31 @@ var WebSocketServiceImpl = class {
|
|
|
667
684
|
this.handleDisconnect();
|
|
668
685
|
}
|
|
669
686
|
if (pusherClient.connection.state === "failed") {
|
|
670
|
-
|
|
687
|
+
safeReject(new Error(errorMessage));
|
|
671
688
|
}
|
|
672
689
|
});
|
|
673
690
|
pusherClient.connection.bind("disconnected", () => {
|
|
674
|
-
if (this.
|
|
691
|
+
if (this.currentPusherClient !== pusherClient) {
|
|
692
|
+
logger.debug("websocket", "Ignoring disconnected event from previous connection attempt");
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
675
695
|
logger.warn("websocket", "WebSocket disconnected");
|
|
676
696
|
writeStatus({ connected: false });
|
|
677
697
|
this.handleDisconnect();
|
|
678
|
-
|
|
698
|
+
safeReject(new Error("WebSocket disconnected during connection"));
|
|
679
699
|
});
|
|
680
700
|
pusherClient.connection.bind("failed", () => {
|
|
681
|
-
if (this.
|
|
701
|
+
if (this.currentPusherClient !== pusherClient) return;
|
|
682
702
|
clearTimeout(connectionTimeout);
|
|
683
703
|
logger.error("websocket", "WebSocket connection failed");
|
|
684
704
|
this.handleDisconnect();
|
|
685
|
-
|
|
705
|
+
safeReject(new Error("WebSocket connection failed"));
|
|
686
706
|
});
|
|
687
707
|
pusherClient.connection.bind("unavailable", () => {
|
|
688
|
-
if (this.
|
|
708
|
+
if (this.currentPusherClient !== pusherClient) return;
|
|
689
709
|
logger.warn("websocket", "WebSocket connection unavailable, attempting auto-reconnect");
|
|
690
710
|
writeStatus({ connected: false });
|
|
691
|
-
|
|
711
|
+
safeReject(new Error("WebSocket connection unavailable"));
|
|
692
712
|
});
|
|
693
713
|
});
|
|
694
714
|
} catch (error) {
|
|
@@ -706,6 +726,7 @@ var WebSocketServiceImpl = class {
|
|
|
706
726
|
clearTimeout(this.reconnectTimer);
|
|
707
727
|
this.reconnectTimer = null;
|
|
708
728
|
}
|
|
729
|
+
this.currentPusherClient = null;
|
|
709
730
|
if (this.echo) {
|
|
710
731
|
if (this.userId) {
|
|
711
732
|
this.echo.leave(`user.${this.userId}`);
|
|
@@ -747,7 +768,7 @@ var WebSocketServiceImpl = class {
|
|
|
747
768
|
if (commit.has_large_files) {
|
|
748
769
|
try {
|
|
749
770
|
logger.info("websocket", `Commit ${commit.id} marked as large, fetching full details...`);
|
|
750
|
-
const { apiService: apiService2 } = await import("./api-
|
|
771
|
+
const { apiService: apiService2 } = await import("./api-TC3OYN5R.js");
|
|
751
772
|
const fullCommit = await apiService2.getCommit(commit.id);
|
|
752
773
|
commit = {
|
|
753
774
|
...commit,
|
|
@@ -833,7 +854,12 @@ var WebSocketServiceImpl = class {
|
|
|
833
854
|
await this.subscribeToUserChannel(this.userId);
|
|
834
855
|
}
|
|
835
856
|
} catch (error) {
|
|
836
|
-
|
|
857
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
858
|
+
if (errorMessage.includes("disconnected during connection")) {
|
|
859
|
+
logger.debug("websocket", "Connection disconnected during reconnection attempt, will retry");
|
|
860
|
+
} else {
|
|
861
|
+
logger.error("websocket", "Reconnection failed", error);
|
|
862
|
+
}
|
|
837
863
|
}
|
|
838
864
|
}, delay);
|
|
839
865
|
} else {
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
authService,
|
|
3
3
|
config,
|
|
4
4
|
logger
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-BKJMUBZE.js";
|
|
6
6
|
|
|
7
7
|
// src/utils/circuit-breaker.ts
|
|
8
8
|
var CircuitBreaker = class {
|
|
@@ -98,7 +98,7 @@ var CircuitBreaker = class {
|
|
|
98
98
|
};
|
|
99
99
|
|
|
100
100
|
// src/services/api.ts
|
|
101
|
-
var AGENT_VERSION = "1.2.
|
|
101
|
+
var AGENT_VERSION = "1.2.34";
|
|
102
102
|
var ApiServiceImpl = class {
|
|
103
103
|
sessionId = null;
|
|
104
104
|
circuitBreaker = new CircuitBreaker({
|
package/dist/daemon/runner.js
CHANGED
|
@@ -3,20 +3,20 @@ import {
|
|
|
3
3
|
commitQueue,
|
|
4
4
|
notify,
|
|
5
5
|
websocketService
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-L4S6LLKQ.js";
|
|
7
7
|
import {
|
|
8
8
|
apiService
|
|
9
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-NEUK7ZZY.js";
|
|
10
10
|
import {
|
|
11
11
|
gitService,
|
|
12
12
|
projectService,
|
|
13
13
|
removePidFile,
|
|
14
14
|
writePidFile
|
|
15
|
-
} from "../chunk-
|
|
15
|
+
} from "../chunk-UB56ZQNI.js";
|
|
16
16
|
import {
|
|
17
17
|
authService,
|
|
18
18
|
logger
|
|
19
|
-
} from "../chunk-
|
|
19
|
+
} from "../chunk-BKJMUBZE.js";
|
|
20
20
|
|
|
21
21
|
// src/daemon/runner.ts
|
|
22
22
|
import "dotenv/config";
|
package/dist/index.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
commitQueue,
|
|
4
4
|
websocketService
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-L4S6LLKQ.js";
|
|
6
6
|
import {
|
|
7
7
|
apiService
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-NEUK7ZZY.js";
|
|
9
9
|
import {
|
|
10
10
|
getPidFilePath,
|
|
11
11
|
gitService,
|
|
@@ -14,14 +14,14 @@ import {
|
|
|
14
14
|
projectService,
|
|
15
15
|
spawnDetached,
|
|
16
16
|
validatePidFile
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-UB56ZQNI.js";
|
|
18
18
|
import {
|
|
19
19
|
__commonJS,
|
|
20
20
|
__toESM,
|
|
21
21
|
authService,
|
|
22
22
|
config,
|
|
23
23
|
logger
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-BKJMUBZE.js";
|
|
25
25
|
|
|
26
26
|
// node_modules/semver/internal/constants.js
|
|
27
27
|
var require_constants = __commonJS({
|
|
@@ -2341,26 +2341,52 @@ function registerLogoutCommand(program2) {
|
|
|
2341
2341
|
import ora3 from "ora";
|
|
2342
2342
|
import chalk3 from "chalk";
|
|
2343
2343
|
function registerWhoamiCommand(program2) {
|
|
2344
|
-
program2.command("whoami").description("Show current user and machine information").action(async () => {
|
|
2345
|
-
|
|
2344
|
+
program2.command("whoami").description("Show current user and machine information").option("-j, --json", "Output in JSON format").action(async (options) => {
|
|
2345
|
+
if (options.json) logger.disableConsole();
|
|
2346
|
+
const spinner = options.json ? null : ora3("Checking authentication...").start();
|
|
2346
2347
|
try {
|
|
2347
2348
|
const token = await authService.getToken();
|
|
2348
2349
|
if (!token) {
|
|
2349
|
-
|
|
2350
|
+
if (options.json) {
|
|
2351
|
+
console.log(JSON.stringify({ authenticated: false }));
|
|
2352
|
+
return;
|
|
2353
|
+
}
|
|
2354
|
+
if (spinner) spinner.info("Not logged in");
|
|
2350
2355
|
console.log(chalk3.yellow("\n\u26A0 You are not logged in."));
|
|
2351
2356
|
console.log(chalk3.gray('Run "stint login" to authenticate.\n'));
|
|
2352
2357
|
return;
|
|
2353
2358
|
}
|
|
2354
|
-
spinner.text = "Validating credentials...";
|
|
2359
|
+
if (spinner) spinner.text = "Validating credentials...";
|
|
2355
2360
|
const user = await authService.validateToken();
|
|
2356
2361
|
if (!user) {
|
|
2357
|
-
|
|
2362
|
+
if (options.json) {
|
|
2363
|
+
console.log(JSON.stringify({ authenticated: false, error: "Token invalid" }));
|
|
2364
|
+
await authService.clearToken();
|
|
2365
|
+
return;
|
|
2366
|
+
}
|
|
2367
|
+
if (spinner) spinner.fail("Authentication invalid");
|
|
2358
2368
|
console.log(chalk3.red("\n\u2716 Your authentication token is invalid or expired."));
|
|
2359
2369
|
console.log(chalk3.gray('Run "stint login" to re-authenticate.\n'));
|
|
2360
2370
|
await authService.clearToken();
|
|
2361
2371
|
return;
|
|
2362
2372
|
}
|
|
2363
|
-
|
|
2373
|
+
if (options.json) {
|
|
2374
|
+
logger.disableConsole();
|
|
2375
|
+
console.log(JSON.stringify({
|
|
2376
|
+
authenticated: true,
|
|
2377
|
+
user: {
|
|
2378
|
+
name: user.name,
|
|
2379
|
+
email: user.email,
|
|
2380
|
+
id: user.id
|
|
2381
|
+
},
|
|
2382
|
+
machine: {
|
|
2383
|
+
name: authService.getMachineName(),
|
|
2384
|
+
id: authService.getMachineId()
|
|
2385
|
+
}
|
|
2386
|
+
}, null, 2));
|
|
2387
|
+
return;
|
|
2388
|
+
}
|
|
2389
|
+
if (spinner) spinner.succeed("Authenticated");
|
|
2364
2390
|
console.log(chalk3.blue("\n\u{1F464} User Information:"));
|
|
2365
2391
|
console.log(chalk3.gray("\u2500".repeat(50)));
|
|
2366
2392
|
console.log(`${chalk3.bold("Name:")} ${user.name}`);
|
|
@@ -2373,10 +2399,14 @@ function registerWhoamiCommand(program2) {
|
|
|
2373
2399
|
console.log();
|
|
2374
2400
|
logger.info("whoami", `User: ${user.email}, Machine: ${authService.getMachineName()}`);
|
|
2375
2401
|
} catch (error) {
|
|
2376
|
-
spinner.fail("Failed to retrieve information");
|
|
2402
|
+
if (spinner) spinner.fail("Failed to retrieve information");
|
|
2377
2403
|
logger.error("whoami", "Command failed", error);
|
|
2378
|
-
|
|
2404
|
+
if (options.json) {
|
|
2405
|
+
console.error(JSON.stringify({ error: error.message }));
|
|
2406
|
+
} else {
|
|
2407
|
+
console.error(chalk3.red(`
|
|
2379
2408
|
\u2716 Error: ${error.message}`));
|
|
2409
|
+
}
|
|
2380
2410
|
process.exit(1);
|
|
2381
2411
|
}
|
|
2382
2412
|
});
|
|
@@ -2546,13 +2576,14 @@ import process4 from "process";
|
|
|
2546
2576
|
import path2 from "path";
|
|
2547
2577
|
import os from "os";
|
|
2548
2578
|
function registerStatusCommand(program2) {
|
|
2549
|
-
program2.command("status").description("Show linked project and connection status").option("-d, --dashboard", "Launch interactive TUI dashboard").action(async (options) => {
|
|
2579
|
+
program2.command("status").description("Show linked project and connection status").option("-d, --dashboard", "Launch interactive TUI dashboard").option("-j, --json", "Output in JSON format").action(async (options) => {
|
|
2580
|
+
if (options.json) logger.disableConsole();
|
|
2550
2581
|
const cwd = process4.cwd();
|
|
2551
|
-
if (options.dashboard) {
|
|
2582
|
+
if (options.dashboard && !options.json) {
|
|
2552
2583
|
try {
|
|
2553
2584
|
const { render } = await import("ink");
|
|
2554
2585
|
const { createElement } = await import("react");
|
|
2555
|
-
const { StatusDashboard } = await import("./StatusDashboard-
|
|
2586
|
+
const { StatusDashboard } = await import("./StatusDashboard-6H3FWITW.js");
|
|
2556
2587
|
render(createElement(StatusDashboard, { cwd }));
|
|
2557
2588
|
return;
|
|
2558
2589
|
} catch (error) {
|
|
@@ -2560,11 +2591,63 @@ function registerStatusCommand(program2) {
|
|
|
2560
2591
|
process4.exit(1);
|
|
2561
2592
|
}
|
|
2562
2593
|
}
|
|
2563
|
-
const spinner = ora6("Gathering status...").start();
|
|
2594
|
+
const spinner = options.json ? null : ora6("Gathering status...").start();
|
|
2564
2595
|
try {
|
|
2565
2596
|
const linkedProject = await projectService.getLinkedProject(cwd);
|
|
2566
2597
|
const user = await authService.validateToken();
|
|
2567
|
-
|
|
2598
|
+
const isRepo = await gitService.isRepo(cwd);
|
|
2599
|
+
let repoInfo = null;
|
|
2600
|
+
if (isRepo) {
|
|
2601
|
+
try {
|
|
2602
|
+
repoInfo = await gitService.getRepoInfo(cwd);
|
|
2603
|
+
} catch {
|
|
2604
|
+
}
|
|
2605
|
+
}
|
|
2606
|
+
const { valid, pid } = validatePidFile();
|
|
2607
|
+
if (options.json) {
|
|
2608
|
+
logger.disableConsole();
|
|
2609
|
+
const statusOutput = {
|
|
2610
|
+
project: linkedProject ? {
|
|
2611
|
+
id: linkedProject.projectId,
|
|
2612
|
+
linkedAt: linkedProject.linkedAt
|
|
2613
|
+
} : null,
|
|
2614
|
+
authentication: user ? {
|
|
2615
|
+
authenticated: true,
|
|
2616
|
+
user: {
|
|
2617
|
+
name: user.name,
|
|
2618
|
+
email: user.email,
|
|
2619
|
+
id: user.id
|
|
2620
|
+
},
|
|
2621
|
+
machine: {
|
|
2622
|
+
name: authService.getMachineName(),
|
|
2623
|
+
id: authService.getMachineId()
|
|
2624
|
+
}
|
|
2625
|
+
} : {
|
|
2626
|
+
authenticated: false
|
|
2627
|
+
},
|
|
2628
|
+
git: isRepo && repoInfo ? {
|
|
2629
|
+
isRepo: true,
|
|
2630
|
+
branch: repoInfo.currentBranch,
|
|
2631
|
+
remote: repoInfo.remoteUrl,
|
|
2632
|
+
lastCommit: {
|
|
2633
|
+
sha: repoInfo.lastCommitSha,
|
|
2634
|
+
message: repoInfo.lastCommitMessage,
|
|
2635
|
+
date: repoInfo.lastCommitDate
|
|
2636
|
+
},
|
|
2637
|
+
status: repoInfo.status
|
|
2638
|
+
} : {
|
|
2639
|
+
isRepo: !!isRepo
|
|
2640
|
+
},
|
|
2641
|
+
daemon: {
|
|
2642
|
+
running: valid && !!pid,
|
|
2643
|
+
pid: pid || null,
|
|
2644
|
+
logFile: path2.join(os.homedir(), ".config", "stint", "logs", "daemon.log")
|
|
2645
|
+
}
|
|
2646
|
+
};
|
|
2647
|
+
console.log(JSON.stringify(statusOutput, null, 2));
|
|
2648
|
+
return;
|
|
2649
|
+
}
|
|
2650
|
+
if (spinner) spinner.stop();
|
|
2568
2651
|
console.log(chalk6.blue("\n\u{1F4E6} Project Status:"));
|
|
2569
2652
|
console.log(chalk6.gray("\u2500".repeat(50)));
|
|
2570
2653
|
if (linkedProject) {
|
|
@@ -2577,26 +2660,28 @@ function registerStatusCommand(program2) {
|
|
|
2577
2660
|
}
|
|
2578
2661
|
console.log(chalk6.blue("\n\u{1F4C2} Git Repository:"));
|
|
2579
2662
|
console.log(chalk6.gray("\u2500".repeat(50)));
|
|
2580
|
-
const isRepo = await gitService.isRepo(cwd);
|
|
2581
2663
|
if (isRepo) {
|
|
2582
2664
|
try {
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2665
|
+
if (repoInfo) {
|
|
2666
|
+
console.log(`${chalk6.bold("Branch:")} ${chalk6.cyan(repoInfo.currentBranch)}`);
|
|
2667
|
+
console.log(`${chalk6.bold("Remote:")} ${repoInfo.remoteUrl || chalk6.gray("None")}`);
|
|
2668
|
+
console.log(`${chalk6.bold("Last Commit:")} ${repoInfo.lastCommitSha.substring(0, 7)} - ${repoInfo.lastCommitMessage}`);
|
|
2669
|
+
console.log(`${chalk6.bold("Commit Date:")} ${new Date(repoInfo.lastCommitDate).toLocaleString()}`);
|
|
2670
|
+
const { staged, unstaged, untracked, ahead, behind } = repoInfo.status;
|
|
2671
|
+
const totalChanges = staged.length + unstaged.length + untracked.length;
|
|
2672
|
+
if (totalChanges > 0) {
|
|
2673
|
+
console.log(`${chalk6.bold("Changes:")} ${chalk6.yellow(`${totalChanges} file(s)`)}`);
|
|
2674
|
+
if (staged.length > 0) console.log(` ${chalk6.green("Staged:")} ${staged.length}`);
|
|
2675
|
+
if (unstaged.length > 0) console.log(` ${chalk6.yellow("Unstaged:")} ${unstaged.length}`);
|
|
2676
|
+
if (untracked.length > 0) console.log(` ${chalk6.gray("Untracked:")} ${untracked.length}`);
|
|
2677
|
+
} else {
|
|
2678
|
+
console.log(`${chalk6.bold("Changes:")} ${chalk6.green("Clean working tree")}`);
|
|
2679
|
+
}
|
|
2680
|
+
if (ahead > 0 || behind > 0) {
|
|
2681
|
+
console.log(`${chalk6.bold("Sync Status:")} ${ahead > 0 ? chalk6.yellow(`\u2191${ahead}`) : ""} ${behind > 0 ? chalk6.yellow(`\u2193${behind}`) : ""}`);
|
|
2682
|
+
}
|
|
2595
2683
|
} else {
|
|
2596
|
-
console.log(
|
|
2597
|
-
}
|
|
2598
|
-
if (ahead > 0 || behind > 0) {
|
|
2599
|
-
console.log(`${chalk6.bold("Sync Status:")} ${ahead > 0 ? chalk6.yellow(`\u2191${ahead}`) : ""} ${behind > 0 ? chalk6.yellow(`\u2193${behind}`) : ""}`);
|
|
2684
|
+
console.log(chalk6.red("Error reading repository information"));
|
|
2600
2685
|
}
|
|
2601
2686
|
} catch {
|
|
2602
2687
|
console.log(chalk6.red("Error reading repository information"));
|
|
@@ -2616,7 +2701,6 @@ function registerStatusCommand(program2) {
|
|
|
2616
2701
|
}
|
|
2617
2702
|
console.log(chalk6.blue("\n\u2699\uFE0F Daemon:"));
|
|
2618
2703
|
console.log(chalk6.gray("\u2500".repeat(50)));
|
|
2619
|
-
const { valid, pid } = validatePidFile();
|
|
2620
2704
|
if (valid && pid) {
|
|
2621
2705
|
console.log(`${chalk6.bold("Status:")} ${chalk6.green("\u2713 Running")}`);
|
|
2622
2706
|
console.log(`${chalk6.bold("PID:")} ${pid}`);
|
|
@@ -2628,7 +2712,7 @@ function registerStatusCommand(program2) {
|
|
|
2628
2712
|
console.log();
|
|
2629
2713
|
logger.info("status", "Status command executed");
|
|
2630
2714
|
} catch (error) {
|
|
2631
|
-
spinner.fail("Failed to get status");
|
|
2715
|
+
if (spinner) spinner.fail("Failed to get status");
|
|
2632
2716
|
logger.error("status", "Status command failed", error);
|
|
2633
2717
|
console.error(chalk6.red(`
|
|
2634
2718
|
\u2716 Error: ${error.message}
|
|
@@ -3160,20 +3244,30 @@ import chalk9 from "chalk";
|
|
|
3160
3244
|
import { confirm as confirm2 } from "@inquirer/prompts";
|
|
3161
3245
|
import process6 from "process";
|
|
3162
3246
|
function registerCommitCommands(program2) {
|
|
3163
|
-
program2.command("commits").description("List pending commits for the current project").action(async () => {
|
|
3164
|
-
|
|
3247
|
+
program2.command("commits").description("List pending commits for the current project").option("-j, --json", "Output in JSON format").action(async (options) => {
|
|
3248
|
+
if (options.json) logger.disableConsole();
|
|
3249
|
+
const spinner = options.json ? null : ora9("Loading pending commits...").start();
|
|
3165
3250
|
try {
|
|
3166
3251
|
const cwd = process6.cwd();
|
|
3167
3252
|
const linkedProject = await projectService.getLinkedProject(cwd);
|
|
3168
3253
|
if (!linkedProject) {
|
|
3169
|
-
|
|
3254
|
+
if (options.json) {
|
|
3255
|
+
console.error(JSON.stringify({ error: "Not linked to a project", code: "NOT_LINKED" }));
|
|
3256
|
+
process6.exit(1);
|
|
3257
|
+
}
|
|
3258
|
+
if (spinner) spinner.fail("Not linked");
|
|
3170
3259
|
console.log(chalk9.yellow("\n\u26A0 This directory is not linked to any project."));
|
|
3171
3260
|
console.log(chalk9.gray('Run "stint link" first to link this directory.\n'));
|
|
3172
3261
|
process6.exit(1);
|
|
3173
3262
|
}
|
|
3174
|
-
spinner.text = "Fetching pending commits...";
|
|
3263
|
+
if (spinner) spinner.text = "Fetching pending commits...";
|
|
3175
3264
|
const commits = await apiService.getPendingCommits(linkedProject.projectId);
|
|
3176
|
-
|
|
3265
|
+
if (options.json) {
|
|
3266
|
+
logger.disableConsole();
|
|
3267
|
+
console.log(JSON.stringify(commits, null, 2));
|
|
3268
|
+
return;
|
|
3269
|
+
}
|
|
3270
|
+
if (spinner) spinner.stop();
|
|
3177
3271
|
if (commits.length === 0) {
|
|
3178
3272
|
console.log(chalk9.blue("\n\u{1F4CB} No pending commits\n"));
|
|
3179
3273
|
console.log(chalk9.gray("All commits have been executed.\n"));
|
|
@@ -3194,9 +3288,10 @@ function registerCommitCommands(program2) {
|
|
|
3194
3288
|
console.log(chalk9.gray('\nRun "stint commit <id>" to execute a specific commit.\n'));
|
|
3195
3289
|
logger.info("commits", `Listed ${commits.length} pending commits`);
|
|
3196
3290
|
} catch (error) {
|
|
3197
|
-
spinner.fail("Failed to fetch commits");
|
|
3291
|
+
if (spinner) spinner.fail("Failed to fetch commits");
|
|
3292
|
+
else if (options.json) console.error(JSON.stringify({ error: error.message }));
|
|
3198
3293
|
logger.error("commits", "Failed to fetch commits", error);
|
|
3199
|
-
console.error(chalk9.red(`
|
|
3294
|
+
if (!options.json) console.error(chalk9.red(`
|
|
3200
3295
|
\u2716 Error: ${error.message}
|
|
3201
3296
|
`));
|
|
3202
3297
|
process6.exit(1);
|
|
@@ -4356,7 +4451,7 @@ ${chalk14.bold("Config file:")} ${chalk14.cyan(configPath)}
|
|
|
4356
4451
|
}
|
|
4357
4452
|
|
|
4358
4453
|
// src/index.ts
|
|
4359
|
-
var AGENT_VERSION = "1.2.
|
|
4454
|
+
var AGENT_VERSION = "1.2.34";
|
|
4360
4455
|
var program = new Command();
|
|
4361
4456
|
program.name("stint").description("Stint Agent - Local daemon for Stint Project Assistant").version(AGENT_VERSION, "-v, --version", "output the current version").addHelpText("after", `
|
|
4362
4457
|
${chalk15.bold("Examples:")}
|
package/package.json
CHANGED