@gowelle/stint-agent 1.2.17 → 1.2.19

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.
@@ -1,149 +1,28 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  commitQueue,
4
+ notify,
5
+ versionService,
4
6
  websocketService
5
- } from "../chunk-VHCNMUHN.js";
7
+ } from "../chunk-ZUQRDCS2.js";
6
8
  import {
7
9
  apiService
8
- } from "../chunk-D6BP2Z5S.js";
10
+ } from "../chunk-6LQKDEQR.js";
9
11
  import {
10
12
  gitService,
11
13
  projectService,
12
14
  removePidFile,
13
15
  writePidFile
14
- } from "../chunk-QQP6IASS.js";
15
- import {
16
- authService
17
- } from "../chunk-ES33YYVA.js";
18
- import {
19
- notify
20
- } from "../chunk-DCY3EXDX.js";
16
+ } from "../chunk-NVQIKLOA.js";
21
17
  import {
18
+ authService,
19
+ config,
22
20
  logger
23
- } from "../chunk-XHXSWLUC.js";
21
+ } from "../chunk-HZ4K7EPF.js";
24
22
 
25
23
  // src/daemon/runner.ts
26
24
  import "dotenv/config";
27
25
 
28
- // src/services/polling.ts
29
- var PollingServiceImpl = class {
30
- interval = null;
31
- knownCommitIds = /* @__PURE__ */ new Set();
32
- knownProjects = /* @__PURE__ */ new Map();
33
- commitApprovedHandlers = [];
34
- projectUpdatedHandlers = [];
35
- isFirstRun = true;
36
- isPolling = false;
37
- /**
38
- * Start polling for pending commits
39
- * @param intervalMs - Polling interval in milliseconds (default: 10000)
40
- */
41
- start(intervalMs = 1e4) {
42
- if (this.interval) {
43
- return;
44
- }
45
- logger.info("polling", `Starting polling service (interval: ${intervalMs}ms)`);
46
- this.poll();
47
- this.interval = setInterval(() => {
48
- this.poll();
49
- }, intervalMs);
50
- }
51
- /**
52
- * Stop polling
53
- */
54
- stop() {
55
- if (this.interval) {
56
- clearInterval(this.interval);
57
- this.interval = null;
58
- logger.info("polling", "Stopping polling service");
59
- }
60
- }
61
- /**
62
- * Register handler for commit approved event
63
- * @param handler - Function to call when a commit is approved where it was previously unknown
64
- */
65
- onCommitApproved(handler) {
66
- this.commitApprovedHandlers.push(handler);
67
- }
68
- /**
69
- * Register handler for project updated event
70
- * @param handler - Function to call when a project is updated
71
- */
72
- onProjectUpdated(handler) {
73
- this.projectUpdatedHandlers.push(handler);
74
- }
75
- /**
76
- * Poll for updates
77
- */
78
- async poll() {
79
- if (this.isPolling) {
80
- return;
81
- }
82
- this.isPolling = true;
83
- try {
84
- const linkedProjects = projectService.getAllLinkedProjects();
85
- const projectIds = Object.values(linkedProjects).map((p) => p.projectId);
86
- if (projectIds.length === 0) {
87
- this.isFirstRun = false;
88
- this.isPolling = false;
89
- return;
90
- }
91
- const apiProjects = await apiService.getLinkedProjects();
92
- const projects = apiProjects.filter((p) => projectIds.includes(p.id));
93
- for (const project of projects) {
94
- const cachedProject = this.knownProjects.get(project.id);
95
- if (cachedProject) {
96
- if (cachedProject.updatedAt !== project.updatedAt) {
97
- if (!this.isFirstRun) {
98
- logger.info("polling", `Project update detected: ${project.id}`);
99
- this.notifyProjectUpdated(project);
100
- }
101
- }
102
- }
103
- this.knownProjects.set(project.id, project);
104
- try {
105
- const commits = await apiService.getPendingCommits(project.id);
106
- for (const commit of commits) {
107
- if (!this.knownCommitIds.has(commit.id)) {
108
- this.knownCommitIds.add(commit.id);
109
- if (!this.isFirstRun) {
110
- logger.info("polling", `New pending commit detected: ${commit.id}`);
111
- this.notifyCommitApproved(commit, project);
112
- }
113
- }
114
- }
115
- } catch (error) {
116
- logger.debug("polling", `Failed to poll project ${project.id}: ${error.message}`);
117
- }
118
- }
119
- this.isFirstRun = false;
120
- } catch (error) {
121
- logger.error("polling", "Poll cycle failed", error);
122
- } finally {
123
- this.isPolling = false;
124
- }
125
- }
126
- notifyCommitApproved(commit, project) {
127
- this.commitApprovedHandlers.forEach((handler) => {
128
- try {
129
- handler(commit, project);
130
- } catch (error) {
131
- logger.error("polling", "Error in commit approved handler", error);
132
- }
133
- });
134
- }
135
- notifyProjectUpdated(project) {
136
- this.projectUpdatedHandlers.forEach((handler) => {
137
- try {
138
- handler(project);
139
- } catch (error) {
140
- logger.error("polling", "Error in project updated handler", error);
141
- }
142
- });
143
- }
144
- };
145
- var pollingService = new PollingServiceImpl();
146
-
147
26
  // src/daemon/watcher.ts
148
27
  import fs from "fs";
149
28
  var FileWatcher = class {
@@ -291,7 +170,7 @@ var FileWatcher = class {
291
170
  const projects = await apiService.getLinkedProjects();
292
171
  const p = projects.find((proj) => proj.id === projectId);
293
172
  if (p) projectName = p.name;
294
- } catch (e) {
173
+ } catch (_e) {
295
174
  }
296
175
  notify({
297
176
  title: "Sync Complete",
@@ -363,6 +242,39 @@ var heartbeatInterval = null;
363
242
  var isShuttingDown = false;
364
243
  var shutdownReason;
365
244
  var fileWatcher = new FileWatcher();
245
+ async function checkForUpdatesIfEnabled() {
246
+ try {
247
+ const autoCheck = config.get("autoCheckUpdates");
248
+ if (!autoCheck) {
249
+ logger.debug("daemon", "Automatic update checks disabled");
250
+ return;
251
+ }
252
+ const lastCheck = config.get("lastUpdateCheck");
253
+ if (lastCheck) {
254
+ const lastCheckTime = new Date(lastCheck).getTime();
255
+ const now = Date.now();
256
+ const cooldownMs = 24 * 60 * 60 * 1e3;
257
+ if (now - lastCheckTime < cooldownMs) {
258
+ logger.debug("daemon", "Update check cooldown active");
259
+ return;
260
+ }
261
+ }
262
+ logger.info("daemon", "Checking for updates...");
263
+ const versionInfo = await versionService.checkForUpdates("stable");
264
+ config.set("lastUpdateCheck", (/* @__PURE__ */ new Date()).toISOString());
265
+ if (versionInfo.hasUpdate) {
266
+ logger.info("daemon", `Update available: ${versionInfo.current} \u2192 ${versionInfo.latest}`);
267
+ notify({
268
+ title: "Stint Agent Update Available",
269
+ message: `Version ${versionInfo.latest} is available. Run "stint update" to install.`
270
+ });
271
+ } else {
272
+ logger.debug("daemon", "No updates available");
273
+ }
274
+ } catch (error) {
275
+ logger.debug("daemon", "Failed to check for updates", error);
276
+ }
277
+ }
366
278
  async function startDaemon() {
367
279
  logger.info("daemon", "Starting daemon...");
368
280
  try {
@@ -387,15 +299,6 @@ async function startDaemon() {
387
299
  notify({
388
300
  title: "Commit Approved",
389
301
  message: `${commit.message}
390
- Project: ${project.name}`
391
- });
392
- commitQueue.addToQueue(commit, project);
393
- });
394
- pollingService.onCommitApproved((commit, project) => {
395
- logger.info("daemon", `Commit approved (via polling): ${commit.id} for project ${project.name}`);
396
- notify({
397
- title: "Commit Approved",
398
- message: `${commit.message}
399
302
  Project: ${project.name}`
400
303
  });
401
304
  commitQueue.addToQueue(commit, project);
@@ -408,7 +311,7 @@ Project: ${project.name}`
408
311
  const projects = await apiService.getLinkedProjects();
409
312
  const p = projects.find((proj) => proj.id === commit.projectId);
410
313
  if (p) projectName = p.name;
411
- } catch (e) {
314
+ } catch (_e) {
412
315
  }
413
316
  notify({
414
317
  title: `New Proposal - ${projectName}`,
@@ -422,13 +325,6 @@ Project: ${project.name}`
422
325
  message: project.name
423
326
  });
424
327
  });
425
- pollingService.onProjectUpdated((project) => {
426
- logger.info("daemon", `Project updated (via polling): ${project.id} - ${project.name}`);
427
- notify({
428
- title: "Project Updated",
429
- message: project.name
430
- });
431
- });
432
328
  websocketService.onDisconnect(() => {
433
329
  logger.warn("daemon", "WebSocket disconnected, will attempt to reconnect");
434
330
  });
@@ -458,7 +354,7 @@ Priority: ${suggestion.priority}`,
458
354
  if (project) {
459
355
  projectName = project.name;
460
356
  }
461
- } catch (e) {
357
+ } catch (_e) {
462
358
  }
463
359
  notify({
464
360
  title: "Sync Requested",
@@ -477,7 +373,6 @@ Priority: ${suggestion.priority}`,
477
373
  logger.info("daemon", `Linked project: ${project.projectId}`);
478
374
  fileWatcher.watchProject(project.projectId);
479
375
  });
480
- pollingService.start();
481
376
  logger.info("daemon", "Daemon started successfully");
482
377
  const projectEntries = Object.entries(linkedProjects);
483
378
  if (projectEntries.length > 0) {
@@ -492,6 +387,7 @@ Priority: ${suggestion.priority}`,
492
387
  logger.success("daemon", "Initial project sync complete");
493
388
  }
494
389
  logger.success("daemon", "Daemon started successfully");
390
+ await checkForUpdatesIfEnabled();
495
391
  await new Promise(() => {
496
392
  });
497
393
  } catch (error) {