@gowelle/stint-agent 1.2.26 → 1.2.28
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-6BRCPQQO.js → StatusDashboard-BV7RHIIH.js} +2 -2
- package/dist/api-MEUGSQYO.js +7 -0
- package/dist/{chunk-CCMXVYVO.js → chunk-GLD7IU2F.js} +50 -19
- package/dist/{chunk-Z7ZSQCVR.js → chunk-JIRQHCFR.js} +1 -1
- package/dist/{chunk-ZHIGA6EY.js → chunk-RHWE22KH.js} +1 -1
- package/dist/{chunk-YXNR7UVV.js → chunk-UJBUIRQZ.js} +7 -4
- package/dist/daemon/runner.js +35 -9
- package/dist/index.js +6 -6
- package/package.json +1 -1
- package/dist/api-3Y72TBXG.js +0 -7
|
@@ -2,10 +2,10 @@ import {
|
|
|
2
2
|
gitService,
|
|
3
3
|
projectService,
|
|
4
4
|
validatePidFile
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-JIRQHCFR.js";
|
|
6
6
|
import {
|
|
7
7
|
authService
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-RHWE22KH.js";
|
|
9
9
|
|
|
10
10
|
// src/components/StatusDashboard.tsx
|
|
11
11
|
import { useState, useEffect } from "react";
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
apiService
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-UJBUIRQZ.js";
|
|
4
4
|
import {
|
|
5
5
|
gitService,
|
|
6
6
|
projectService
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-JIRQHCFR.js";
|
|
8
8
|
import {
|
|
9
9
|
authService,
|
|
10
10
|
config,
|
|
11
11
|
logger
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-RHWE22KH.js";
|
|
13
13
|
|
|
14
14
|
// src/utils/notify.ts
|
|
15
15
|
import notifier from "node-notifier";
|
|
@@ -561,6 +561,10 @@ var WebSocketServiceImpl = class {
|
|
|
561
561
|
forceTLS = true;
|
|
562
562
|
}
|
|
563
563
|
logger.info("websocket", `Connecting to ${wsHost}:${wsPort} with key ${reverbAppKey}...`);
|
|
564
|
+
if (typeof global.WebSocket === "undefined") {
|
|
565
|
+
const { WebSocket } = await import("ws");
|
|
566
|
+
global.WebSocket = WebSocket;
|
|
567
|
+
}
|
|
564
568
|
const pusherClient = new Pusher(reverbAppKey, {
|
|
565
569
|
wsHost,
|
|
566
570
|
wsPort,
|
|
@@ -569,6 +573,12 @@ var WebSocketServiceImpl = class {
|
|
|
569
573
|
disableStats: true,
|
|
570
574
|
cluster: "",
|
|
571
575
|
// Required but unused for Reverb
|
|
576
|
+
// Activity timeout: if no activity for this duration, Pusher sends a ping
|
|
577
|
+
activityTimeout: 6e4,
|
|
578
|
+
// 60 seconds (default is 120s)
|
|
579
|
+
// Pong timeout: wait this long for pong response before considering connection dead
|
|
580
|
+
pongTimeout: 3e4,
|
|
581
|
+
// 30 seconds (default is 30s)
|
|
572
582
|
authorizer: (channel) => ({
|
|
573
583
|
authorize: async (socketId, callback) => {
|
|
574
584
|
try {
|
|
@@ -599,7 +609,7 @@ var WebSocketServiceImpl = class {
|
|
|
599
609
|
}
|
|
600
610
|
})
|
|
601
611
|
});
|
|
602
|
-
|
|
612
|
+
const echoInstance = new Echo({
|
|
603
613
|
broadcaster: "reverb",
|
|
604
614
|
key: reverbAppKey,
|
|
605
615
|
wsHost,
|
|
@@ -616,21 +626,32 @@ var WebSocketServiceImpl = class {
|
|
|
616
626
|
},
|
|
617
627
|
client: pusherClient
|
|
618
628
|
});
|
|
629
|
+
this.echo = echoInstance;
|
|
619
630
|
logger.info("websocket", "Echo instance created, setting up connection handlers...");
|
|
620
631
|
return new Promise((resolve, reject) => {
|
|
621
|
-
if (
|
|
622
|
-
|
|
632
|
+
if (pusherClient.connection.state === "connected") {
|
|
633
|
+
logger.success("websocket", "\u2705 Already connected to Broadcaster");
|
|
634
|
+
writeStatus({ connected: true });
|
|
635
|
+
this.reconnectAttempts = 0;
|
|
636
|
+
this.isManualDisconnect = false;
|
|
637
|
+
resolve();
|
|
623
638
|
return;
|
|
624
639
|
}
|
|
625
640
|
const connectionTimeout = setTimeout(() => {
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
641
|
+
if (this.echo !== echoInstance) return;
|
|
642
|
+
const state = pusherClient.connection.state || "unknown";
|
|
643
|
+
logger.error("websocket", `Connection timeout after 30s (state: ${state})`);
|
|
644
|
+
if (state !== "connected") {
|
|
645
|
+
reject(new Error(`Connection timeout - stuck in state: ${state}`));
|
|
646
|
+
}
|
|
647
|
+
}, 3e4);
|
|
648
|
+
pusherClient.connection.bind("state_change", (states) => {
|
|
649
|
+
if (this.echo === echoInstance) {
|
|
650
|
+
logger.info("websocket", `Connection state: ${states.previous} -> ${states.current}`);
|
|
651
|
+
}
|
|
632
652
|
});
|
|
633
|
-
|
|
653
|
+
pusherClient.connection.bind("connected", () => {
|
|
654
|
+
if (this.echo !== echoInstance) return;
|
|
634
655
|
clearTimeout(connectionTimeout);
|
|
635
656
|
logger.success("websocket", "\u2705 Connected to Broadcaster via Sanctum");
|
|
636
657
|
writeStatus({ connected: true });
|
|
@@ -638,27 +659,37 @@ var WebSocketServiceImpl = class {
|
|
|
638
659
|
this.isManualDisconnect = false;
|
|
639
660
|
resolve();
|
|
640
661
|
});
|
|
641
|
-
|
|
662
|
+
pusherClient.connection.bind("error", (error) => {
|
|
663
|
+
if (this.echo !== echoInstance) return;
|
|
642
664
|
clearTimeout(connectionTimeout);
|
|
643
665
|
const errorMessage = error instanceof Error ? error.message : JSON.stringify(error) || "Unknown connection error";
|
|
644
666
|
logger.error("websocket", `WebSocket error: ${errorMessage}`);
|
|
645
|
-
if (error
|
|
667
|
+
if (error && typeof error === "object" && "data" in error && error.data?.code === 1006) {
|
|
646
668
|
logger.warn("websocket", "Detected abnormal closure (1006), ensuring reconnection...");
|
|
647
669
|
this.handleDisconnect();
|
|
648
670
|
}
|
|
649
|
-
|
|
671
|
+
if (pusherClient.connection.state === "failed") {
|
|
672
|
+
reject(new Error(errorMessage));
|
|
673
|
+
}
|
|
650
674
|
});
|
|
651
|
-
|
|
675
|
+
pusherClient.connection.bind("disconnected", () => {
|
|
676
|
+
if (this.echo !== echoInstance) return;
|
|
652
677
|
logger.warn("websocket", "WebSocket disconnected");
|
|
653
678
|
writeStatus({ connected: false });
|
|
654
679
|
this.handleDisconnect();
|
|
655
680
|
});
|
|
656
|
-
|
|
681
|
+
pusherClient.connection.bind("failed", () => {
|
|
682
|
+
if (this.echo !== echoInstance) return;
|
|
657
683
|
clearTimeout(connectionTimeout);
|
|
658
684
|
logger.error("websocket", "WebSocket connection failed");
|
|
659
685
|
this.handleDisconnect();
|
|
660
686
|
reject(new Error("WebSocket connection failed"));
|
|
661
687
|
});
|
|
688
|
+
pusherClient.connection.bind("unavailable", () => {
|
|
689
|
+
if (this.echo !== echoInstance) return;
|
|
690
|
+
logger.warn("websocket", "WebSocket connection unavailable, attempting auto-reconnect");
|
|
691
|
+
writeStatus({ connected: false });
|
|
692
|
+
});
|
|
662
693
|
});
|
|
663
694
|
} catch (error) {
|
|
664
695
|
logger.error("websocket", "Failed to connect", error);
|
|
@@ -716,7 +747,7 @@ var WebSocketServiceImpl = class {
|
|
|
716
747
|
if (commit.has_large_files) {
|
|
717
748
|
try {
|
|
718
749
|
logger.info("websocket", `Commit ${commit.id} marked as large, fetching full details...`);
|
|
719
|
-
const { apiService: apiService2 } = await import("./api-
|
|
750
|
+
const { apiService: apiService2 } = await import("./api-MEUGSQYO.js");
|
|
720
751
|
const fullCommit = await apiService2.getCommit(commit.id);
|
|
721
752
|
commit = {
|
|
722
753
|
...commit,
|
|
@@ -308,7 +308,7 @@ var AuthServiceImpl = class {
|
|
|
308
308
|
return null;
|
|
309
309
|
}
|
|
310
310
|
try {
|
|
311
|
-
const { apiService } = await import("./api-
|
|
311
|
+
const { apiService } = await import("./api-MEUGSQYO.js");
|
|
312
312
|
const user = await apiService.getCurrentUser();
|
|
313
313
|
logger.info("auth", `Token validated for user: ${user.email}`);
|
|
314
314
|
return user;
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
authService,
|
|
3
3
|
config,
|
|
4
4
|
logger
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-RHWE22KH.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.28";
|
|
102
102
|
var ApiServiceImpl = class {
|
|
103
103
|
sessionId = null;
|
|
104
104
|
circuitBreaker = new CircuitBreaker({
|
|
@@ -358,7 +358,7 @@ var ApiServiceImpl = class {
|
|
|
358
358
|
*/
|
|
359
359
|
async syncProject(projectId, data, changedFiles) {
|
|
360
360
|
logger.info("api", `Syncing project ${projectId}`);
|
|
361
|
-
|
|
361
|
+
return this.withRetry(async () => {
|
|
362
362
|
const payload = {
|
|
363
363
|
repo_path: data.repoPath,
|
|
364
364
|
remote_url: data.remoteUrl,
|
|
@@ -369,11 +369,14 @@ var ApiServiceImpl = class {
|
|
|
369
369
|
if (changedFiles && changedFiles.length > 0) {
|
|
370
370
|
payload.changed_files = changedFiles;
|
|
371
371
|
}
|
|
372
|
-
await this.request(`/api/agent/projects/${projectId}/sync`, {
|
|
372
|
+
const response = await this.request(`/api/agent/projects/${projectId}/sync`, {
|
|
373
373
|
method: "POST",
|
|
374
374
|
body: JSON.stringify(payload)
|
|
375
375
|
});
|
|
376
376
|
logger.success("api", `Project ${projectId} synced (${changedFiles?.length ?? 0} changed files)`);
|
|
377
|
+
return {
|
|
378
|
+
auto_sync: response.auto_sync
|
|
379
|
+
};
|
|
377
380
|
}, "Sync project");
|
|
378
381
|
}
|
|
379
382
|
/**
|
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-GLD7IU2F.js";
|
|
7
7
|
import {
|
|
8
8
|
apiService
|
|
9
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-UJBUIRQZ.js";
|
|
10
10
|
import {
|
|
11
11
|
gitService,
|
|
12
12
|
projectService,
|
|
13
13
|
removePidFile,
|
|
14
14
|
writePidFile
|
|
15
|
-
} from "../chunk-
|
|
15
|
+
} from "../chunk-JIRQHCFR.js";
|
|
16
16
|
import {
|
|
17
17
|
authService,
|
|
18
18
|
logger
|
|
19
|
-
} from "../chunk-
|
|
19
|
+
} from "../chunk-RHWE22KH.js";
|
|
20
20
|
|
|
21
21
|
// src/daemon/runner.ts
|
|
22
22
|
import "dotenv/config";
|
|
@@ -25,8 +25,8 @@ import "dotenv/config";
|
|
|
25
25
|
import fs from "fs";
|
|
26
26
|
var FileWatcher = class {
|
|
27
27
|
watchers = /* @__PURE__ */ new Map();
|
|
28
|
-
|
|
29
|
-
// 3 seconds
|
|
28
|
+
DEFAULT_DEBOUNCE_DELAY = 3e3;
|
|
29
|
+
// 3 seconds fallback
|
|
30
30
|
IGNORE_PATTERNS = [
|
|
31
31
|
".git",
|
|
32
32
|
"node_modules",
|
|
@@ -76,6 +76,11 @@ var FileWatcher = class {
|
|
|
76
76
|
return;
|
|
77
77
|
}
|
|
78
78
|
logger.debug("watcher", `File change detected: ${filenameStr} (${eventType}) in ${projectPath}`);
|
|
79
|
+
const watcherInfo = this.watchers.get(projectPath);
|
|
80
|
+
if (watcherInfo && !watcherInfo.enabled) {
|
|
81
|
+
logger.debug("watcher", `Auto-sync disabled for project ${projectId}, skipping sync`);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
79
84
|
this.debounceSync(projectPath, projectId);
|
|
80
85
|
});
|
|
81
86
|
watcher.on("error", (error) => {
|
|
@@ -91,7 +96,10 @@ var FileWatcher = class {
|
|
|
91
96
|
this.watchers.set(projectPath, {
|
|
92
97
|
watcher,
|
|
93
98
|
debounceTimer: null,
|
|
94
|
-
projectId
|
|
99
|
+
projectId,
|
|
100
|
+
debounceDelay: this.DEFAULT_DEBOUNCE_DELAY,
|
|
101
|
+
enabled: true
|
|
102
|
+
// Enabled by default until settings are fetched
|
|
95
103
|
});
|
|
96
104
|
logger.info("watcher", `Started watching: ${projectPath} (project: ${projectId})`);
|
|
97
105
|
} catch (error) {
|
|
@@ -147,7 +155,7 @@ var FileWatcher = class {
|
|
|
147
155
|
} finally {
|
|
148
156
|
watcherInfo.debounceTimer = null;
|
|
149
157
|
}
|
|
150
|
-
},
|
|
158
|
+
}, watcherInfo.debounceDelay);
|
|
151
159
|
}
|
|
152
160
|
/**
|
|
153
161
|
* Perform sync operation for a project
|
|
@@ -162,7 +170,10 @@ var FileWatcher = class {
|
|
|
162
170
|
}
|
|
163
171
|
const repoInfo = await gitService.getRepoInfo(projectPath);
|
|
164
172
|
const changedFiles = await gitService.getChangedFiles(projectPath);
|
|
165
|
-
await apiService.syncProject(projectId, repoInfo, changedFiles);
|
|
173
|
+
const response = await apiService.syncProject(projectId, repoInfo, changedFiles);
|
|
174
|
+
if (response.auto_sync) {
|
|
175
|
+
this.updateProjectSettings(projectId, response.auto_sync);
|
|
176
|
+
}
|
|
166
177
|
logger.success("watcher", `Synced project ${projectId}`);
|
|
167
178
|
let projectName = projectId;
|
|
168
179
|
try {
|
|
@@ -234,6 +245,18 @@ var FileWatcher = class {
|
|
|
234
245
|
logger.error("watcher", `Error removing watcher for ${projectPath}`, error);
|
|
235
246
|
}
|
|
236
247
|
}
|
|
248
|
+
/**
|
|
249
|
+
* Update auto-sync settings for a project
|
|
250
|
+
*/
|
|
251
|
+
updateProjectSettings(projectId, settings) {
|
|
252
|
+
for (const watcherInfo of this.watchers.values()) {
|
|
253
|
+
if (watcherInfo.projectId === projectId) {
|
|
254
|
+
watcherInfo.enabled = settings.enabled;
|
|
255
|
+
watcherInfo.debounceDelay = settings.interval * 1e3;
|
|
256
|
+
logger.debug("watcher", `Updated settings for project ${projectId}: enabled=${settings.enabled}, interval=${settings.interval}s`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
237
260
|
};
|
|
238
261
|
|
|
239
262
|
// src/daemon/index.ts
|
|
@@ -286,6 +309,9 @@ Project: ${project.name}`
|
|
|
286
309
|
});
|
|
287
310
|
websocketService.onProjectUpdated((project) => {
|
|
288
311
|
logger.info("daemon", `Project updated: ${project.id} - ${project.name}`);
|
|
312
|
+
if (project.settings?.auto_sync) {
|
|
313
|
+
fileWatcher.updateProjectSettings(project.id, project.settings.auto_sync);
|
|
314
|
+
}
|
|
289
315
|
notify({
|
|
290
316
|
title: "Project Updated",
|
|
291
317
|
message: project.name
|
package/dist/index.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
commitQueue,
|
|
4
4
|
websocketService
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-GLD7IU2F.js";
|
|
6
6
|
import {
|
|
7
7
|
apiService
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-UJBUIRQZ.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-JIRQHCFR.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-RHWE22KH.js";
|
|
25
25
|
|
|
26
26
|
// node_modules/semver/internal/constants.js
|
|
27
27
|
var require_constants = __commonJS({
|
|
@@ -2552,7 +2552,7 @@ function registerStatusCommand(program2) {
|
|
|
2552
2552
|
try {
|
|
2553
2553
|
const { render } = await import("ink");
|
|
2554
2554
|
const { createElement } = await import("react");
|
|
2555
|
-
const { StatusDashboard } = await import("./StatusDashboard-
|
|
2555
|
+
const { StatusDashboard } = await import("./StatusDashboard-BV7RHIIH.js");
|
|
2556
2556
|
render(createElement(StatusDashboard, { cwd }));
|
|
2557
2557
|
return;
|
|
2558
2558
|
} catch (error) {
|
|
@@ -4356,7 +4356,7 @@ ${chalk14.bold("Config file:")} ${chalk14.cyan(configPath)}
|
|
|
4356
4356
|
}
|
|
4357
4357
|
|
|
4358
4358
|
// src/index.ts
|
|
4359
|
-
var AGENT_VERSION = "1.2.
|
|
4359
|
+
var AGENT_VERSION = "1.2.28";
|
|
4360
4360
|
var program = new Command();
|
|
4361
4361
|
program.name("stint").description("Stint Agent - Local daemon for Stint Project Assistant").version(AGENT_VERSION, "-v, --version", "output the current version").addHelpText("after", `
|
|
4362
4362
|
${chalk15.bold("Examples:")}
|
package/package.json
CHANGED