@gowelle/stint-agent 1.2.10 → 1.2.12

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.
@@ -5,7 +5,7 @@ import {
5
5
  } from "./chunk-QQP6IASS.js";
6
6
  import {
7
7
  authService
8
- } from "./chunk-6UZKZMVM.js";
8
+ } from "./chunk-2WOTPUFG.js";
9
9
  import "./chunk-XHXSWLUC.js";
10
10
 
11
11
  // src/components/StatusDashboard.tsx
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  apiService
3
- } from "./chunk-GCER6THJ.js";
4
- import "./chunk-6UZKZMVM.js";
3
+ } from "./chunk-2SYLDIKC.js";
4
+ import "./chunk-2WOTPUFG.js";
5
5
  import "./chunk-XHXSWLUC.js";
6
6
  export {
7
7
  apiService
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  authService
3
- } from "./chunk-6UZKZMVM.js";
3
+ } from "./chunk-2WOTPUFG.js";
4
4
  import {
5
5
  config,
6
6
  logger
@@ -100,7 +100,7 @@ var CircuitBreaker = class {
100
100
  };
101
101
 
102
102
  // src/services/api.ts
103
- var AGENT_VERSION = "1.2.10";
103
+ var AGENT_VERSION = "1.2.12";
104
104
  var ApiServiceImpl = class {
105
105
  sessionId = null;
106
106
  circuitBreaker = new CircuitBreaker({
@@ -71,7 +71,7 @@ var AuthServiceImpl = class {
71
71
  return null;
72
72
  }
73
73
  try {
74
- const { apiService } = await import("./api-IYEVRNRO.js");
74
+ const { apiService } = await import("./api-WJZ3DW4X.js");
75
75
  const user = await apiService.getCurrentUser();
76
76
  logger.info("auth", `Token validated for user: ${user.email}`);
77
77
  return user;
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  apiService
3
- } from "./chunk-GCER6THJ.js";
3
+ } from "./chunk-2SYLDIKC.js";
4
4
  import {
5
5
  gitService,
6
6
  projectService
7
7
  } from "./chunk-QQP6IASS.js";
8
8
  import {
9
9
  authService
10
- } from "./chunk-6UZKZMVM.js";
10
+ } from "./chunk-2WOTPUFG.js";
11
11
  import {
12
12
  notify
13
13
  } from "./chunk-HUQ7VJO6.js";
@@ -306,7 +306,7 @@ var WebSocketServiceImpl = class {
306
306
  * Get authentication signature for private channel from Laravel backend
307
307
  */
308
308
  async getChannelAuth(channel, socketId) {
309
- const { apiService: apiService2 } = await import("./api-IYEVRNRO.js");
309
+ const { apiService: apiService2 } = await import("./api-WJZ3DW4X.js");
310
310
  const response = await apiService2.request("/broadcasting/auth", {
311
311
  method: "POST",
312
312
  body: JSON.stringify({
@@ -381,8 +381,8 @@ var WebSocketServiceImpl = class {
381
381
  logger.error("websocket", "Connection is unauthorized - authentication token may be invalid or expired");
382
382
  const { notify: notify2 } = await import("./notify-R6CUXTEF.js");
383
383
  notify2({
384
- title: "Stint Agent - WebSocket Error",
385
- message: 'Connection is unauthorized. Please try restarting the daemon or running "stint login" again.'
384
+ title: "Stint Agent - Connection Issue",
385
+ message: "WebSocket authentication failed. Notifications may be delayed (falling back to polling)."
386
386
  });
387
387
  }
388
388
  } catch (parseError) {
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  commitQueue,
4
4
  websocketService
5
- } from "../chunk-5EAIKWFZ.js";
5
+ } from "../chunk-SXOOKMTP.js";
6
6
  import {
7
7
  apiService
8
- } from "../chunk-GCER6THJ.js";
8
+ } from "../chunk-2SYLDIKC.js";
9
9
  import {
10
10
  gitService,
11
11
  projectService,
@@ -14,7 +14,7 @@ import {
14
14
  } from "../chunk-QQP6IASS.js";
15
15
  import {
16
16
  authService
17
- } from "../chunk-6UZKZMVM.js";
17
+ } from "../chunk-2WOTPUFG.js";
18
18
  import {
19
19
  notify
20
20
  } from "../chunk-HUQ7VJO6.js";
@@ -25,6 +25,125 @@ import {
25
25
  // src/daemon/runner.ts
26
26
  import "dotenv/config";
27
27
 
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
+
28
147
  // src/daemon/watcher.ts
29
148
  import fs from "fs";
30
149
  var FileWatcher = class {
@@ -257,6 +376,15 @@ async function startDaemon() {
257
376
  notify({
258
377
  title: "Commit Approved",
259
378
  message: `${commit.message}
379
+ Project: ${project.name}`
380
+ });
381
+ commitQueue.addToQueue(commit, project);
382
+ });
383
+ pollingService.onCommitApproved((commit, project) => {
384
+ logger.info("daemon", `Commit approved (via polling): ${commit.id} for project ${project.name}`);
385
+ notify({
386
+ title: "Commit Approved",
387
+ message: `${commit.message}
260
388
  Project: ${project.name}`
261
389
  });
262
390
  commitQueue.addToQueue(commit, project);
@@ -275,6 +403,13 @@ Project: ${project.name}`
275
403
  message: project.name
276
404
  });
277
405
  });
406
+ pollingService.onProjectUpdated((project) => {
407
+ logger.info("daemon", `Project updated (via polling): ${project.id} - ${project.name}`);
408
+ notify({
409
+ title: "Project Updated",
410
+ message: project.name
411
+ });
412
+ });
278
413
  websocketService.onDisconnect(() => {
279
414
  logger.warn("daemon", "WebSocket disconnected, will attempt to reconnect");
280
415
  });
@@ -304,8 +439,14 @@ Priority: ${suggestion.priority}`,
304
439
  });
305
440
  setupSignalHandlers();
306
441
  startHeartbeat();
307
- fileWatcher.start();
442
+ logger.info("daemon", "Initializing projects...");
308
443
  const linkedProjects = projectService.getAllLinkedProjects();
444
+ Object.values(linkedProjects).forEach((project) => {
445
+ logger.info("daemon", `Linked project: ${project.projectId}`);
446
+ fileWatcher.watchProject(project.projectId);
447
+ });
448
+ pollingService.start();
449
+ logger.info("daemon", "Daemon started successfully");
309
450
  const projectEntries = Object.entries(linkedProjects);
310
451
  if (projectEntries.length > 0) {
311
452
  logger.info("daemon", `Syncing ${projectEntries.length} linked project(s) on startup...`);
package/dist/index.js CHANGED
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  commitQueue,
4
4
  websocketService
5
- } from "./chunk-5EAIKWFZ.js";
5
+ } from "./chunk-SXOOKMTP.js";
6
6
  import {
7
7
  apiService
8
- } from "./chunk-GCER6THJ.js";
8
+ } from "./chunk-2SYLDIKC.js";
9
9
  import {
10
10
  getPidFilePath,
11
11
  gitService,
@@ -17,7 +17,7 @@ import {
17
17
  } from "./chunk-QQP6IASS.js";
18
18
  import {
19
19
  authService
20
- } from "./chunk-6UZKZMVM.js";
20
+ } from "./chunk-2WOTPUFG.js";
21
21
  import "./chunk-HUQ7VJO6.js";
22
22
  import {
23
23
  config,
@@ -623,7 +623,7 @@ function registerStatusCommand(program2) {
623
623
  try {
624
624
  const { render } = await import("ink");
625
625
  const { createElement } = await import("react");
626
- const { StatusDashboard } = await import("./StatusDashboard-EV4VUUMZ.js");
626
+ const { StatusDashboard } = await import("./StatusDashboard-T2S3IE7E.js");
627
627
  render(createElement(StatusDashboard, { cwd }));
628
628
  return;
629
629
  } catch (error) {
@@ -2003,7 +2003,7 @@ function registerDoctorCommand(program2) {
2003
2003
  }
2004
2004
 
2005
2005
  // src/index.ts
2006
- var AGENT_VERSION = "1.2.10";
2006
+ var AGENT_VERSION = "1.2.12";
2007
2007
  var program = new Command();
2008
2008
  program.name("stint").description("Stint Agent - Local daemon for Stint Project Assistant").version(AGENT_VERSION, "-v, --version", "output the current version").addHelpText("after", `
2009
2009
  ${chalk13.bold("Examples:")}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gowelle/stint-agent",
3
- "version": "1.2.10",
3
+ "version": "1.2.12",
4
4
  "description": "Local agent for Stint - Project Assistant",
5
5
  "author": "Gowelle John <gowelle.john@icloud.com>",
6
6
  "license": "MIT",