@gowelle/stint-agent 1.2.3 → 1.2.5

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/README.md CHANGED
@@ -92,10 +92,18 @@ stint daemon status
92
92
 
93
93
  ### Commit Operations
94
94
 
95
- | Command | Description |
96
- | ------------------- | ---------------------------------------- |
97
- | `stint commits` | List pending commits for this repository |
98
- | `stint commit <id>` | Execute a specific pending commit |
95
+ | Command | Description |
96
+ | -------------------------- | ------------------------------------------------------ |
97
+ | `stint commits` | List pending commits for this repository |
98
+ | `stint commit <id>` | Execute a specific pending commit (supports partial ID)|
99
+
100
+ **`stint commit` Options:**
101
+
102
+ | Option | Description |
103
+ | -------------- | --------------------------------------------------- |
104
+ | `--auto-stage` | Automatically stage files specified in the commit |
105
+ | `--push` | Push changes to remote after committing |
106
+ | `--force` | Skip file validation warnings |
99
107
 
100
108
  ## Complete Workflow
101
109
 
@@ -117,6 +125,26 @@ stint status
117
125
  # Now commits approved in the web app will execute automatically!
118
126
  ```
119
127
 
128
+ ## Configuration
129
+
130
+ ### Desktop Notifications
131
+
132
+ The daemon sends desktop notifications for important events (commit approved, new pending commits, project updates). Notifications are **enabled by default**.
133
+
134
+ **Disable notifications:**
135
+
136
+ ```bash
137
+ stint config set notifications.enabled false
138
+ ```
139
+
140
+ **Enable notifications:**
141
+
142
+ ```bash
143
+ stint config set notifications.enabled true
144
+ ```
145
+
146
+ > **Note:** Events are still logged even when notifications are disabled.
147
+
120
148
  ## Troubleshooting
121
149
 
122
150
  For comprehensive troubleshooting help, see the **[Troubleshooting Guide](docs/TROUBLESHOOTING.md)**.
@@ -2,10 +2,10 @@ import {
2
2
  gitService,
3
3
  projectService,
4
4
  validatePidFile
5
- } from "./chunk-RLW3QCR7.js";
5
+ } from "./chunk-7RFRGXTU.js";
6
6
  import {
7
7
  authService
8
- } from "./chunk-J27QHXXT.js";
8
+ } from "./chunk-M62KR3LR.js";
9
9
 
10
10
  // src/components/StatusDashboard.tsx
11
11
  import { useState, useEffect } from "react";
@@ -0,0 +1,7 @@
1
+ import {
2
+ apiService
3
+ } from "./chunk-QSQGPVIU.js";
4
+ import "./chunk-M62KR3LR.js";
5
+ export {
6
+ apiService
7
+ };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  config,
3
3
  logger
4
- } from "./chunk-J27QHXXT.js";
4
+ } from "./chunk-M62KR3LR.js";
5
5
 
6
6
  // src/services/git.ts
7
7
  import simpleGit from "simple-git";
@@ -16,7 +16,10 @@ var DEFAULT_CONFIG = {
16
16
  apiUrl: "https://stint.codes",
17
17
  wsUrl: "wss://stint.codes/reverb",
18
18
  reverbAppKey: "wtn6tu6lirfv6yflujk7",
19
- projects: {}
19
+ projects: {},
20
+ notifications: {
21
+ enabled: true
22
+ }
20
23
  };
21
24
  var ConfigManager = class {
22
25
  conf;
@@ -130,6 +133,14 @@ var ConfigManager = class {
130
133
  setReverbAppKey(reverbAppKey) {
131
134
  this.conf.set("reverbAppKey", reverbAppKey);
132
135
  }
136
+ // Notification management
137
+ areNotificationsEnabled() {
138
+ const notifConfig = this.conf.get("notifications");
139
+ return notifConfig?.enabled ?? true;
140
+ }
141
+ setNotificationsEnabled(enabled) {
142
+ this.conf.set("notifications", { enabled });
143
+ }
133
144
  };
134
145
  var config = new ConfigManager();
135
146
 
@@ -271,7 +282,7 @@ var AuthServiceImpl = class {
271
282
  return null;
272
283
  }
273
284
  try {
274
- const { apiService } = await import("./api-PEHB3UYL.js");
285
+ const { apiService } = await import("./api-CTKZUAEV.js");
275
286
  const user = await apiService.getCurrentUser();
276
287
  logger.info("auth", `Token validated for user: ${user.email}`);
277
288
  return user;
@@ -1,24 +1,29 @@
1
1
  import {
2
2
  apiService
3
- } from "./chunk-4KNUG3GA.js";
3
+ } from "./chunk-QSQGPVIU.js";
4
4
  import {
5
5
  gitService,
6
6
  projectService
7
- } from "./chunk-RLW3QCR7.js";
7
+ } from "./chunk-7RFRGXTU.js";
8
8
  import {
9
9
  authService,
10
10
  config,
11
11
  logger
12
- } from "./chunk-J27QHXXT.js";
12
+ } from "./chunk-M62KR3LR.js";
13
13
 
14
14
  // src/utils/notify.ts
15
15
  import notifier from "node-notifier";
16
16
  function notify(options) {
17
+ if (!config.areNotificationsEnabled()) {
18
+ logger.debug("notify", "Notifications disabled, skipping notification");
19
+ return;
20
+ }
17
21
  try {
18
22
  notifier.notify({
19
23
  title: options.title,
20
24
  message: options.message,
21
25
  open: options.open,
26
+ icon: options.icon,
22
27
  sound: true,
23
28
  wait: false,
24
29
  appID: "Stint Agent"
@@ -353,9 +358,9 @@ var WebSocketServiceImpl = class {
353
358
  return;
354
359
  }
355
360
  if (message.event === "commit.approved") {
356
- const { commit, project } = message.data;
357
- logger.info("websocket", `Commit approved: ${commit.id}`);
358
- this.commitApprovedHandlers.forEach((handler) => handler(commit, project));
361
+ const { pendingCommit } = message.data;
362
+ logger.info("websocket", `Commit approved: ${pendingCommit.id}`);
363
+ this.commitApprovedHandlers.forEach((handler) => handler(pendingCommit, pendingCommit.project));
359
364
  return;
360
365
  }
361
366
  if (message.event === "commit.pending") {
@@ -377,15 +382,15 @@ var WebSocketServiceImpl = class {
377
382
  return;
378
383
  }
379
384
  if (message.event === "sync.requested") {
380
- const { projectId } = message.data;
381
- logger.info("websocket", `Sync requested for project: ${projectId}`);
382
- this.syncRequestedHandlers.forEach((handler) => handler(projectId));
385
+ const { project } = message.data;
386
+ logger.info("websocket", `Sync requested for project: ${project.id}`);
387
+ this.syncRequestedHandlers.forEach((handler) => handler(project.id));
383
388
  return;
384
389
  }
385
390
  if (message.event === "agent.disconnected") {
386
- const reason = message.data?.reason || "Server requested disconnect";
387
- logger.warn("websocket", `Agent disconnected by server: ${reason}`);
388
- this.agentDisconnectedHandlers.forEach((handler) => handler(reason));
391
+ const { reason } = message.data;
392
+ logger.warn("websocket", `Agent disconnected by server: ${reason ?? "Server requested disconnect"}`);
393
+ this.agentDisconnectedHandlers.forEach((handler) => handler(reason ?? "Server requested disconnect"));
389
394
  return;
390
395
  }
391
396
  logger.debug("websocket", `Unhandled event: ${message.event}`);
@@ -2,7 +2,7 @@ import {
2
2
  authService,
3
3
  config,
4
4
  logger
5
- } from "./chunk-J27QHXXT.js";
5
+ } from "./chunk-M62KR3LR.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.3";
101
+ var AGENT_VERSION = "1.2.5";
102
102
  var ApiServiceImpl = class {
103
103
  sessionId = null;
104
104
  circuitBreaker = new CircuitBreaker({
@@ -3,20 +3,20 @@ import {
3
3
  commitQueue,
4
4
  notify,
5
5
  websocketService
6
- } from "../chunk-E5B6S5EK.js";
6
+ } from "../chunk-MMZYYFJF.js";
7
7
  import {
8
8
  apiService
9
- } from "../chunk-4KNUG3GA.js";
9
+ } from "../chunk-QSQGPVIU.js";
10
10
  import {
11
11
  gitService,
12
12
  projectService,
13
13
  removePidFile,
14
14
  writePidFile
15
- } from "../chunk-RLW3QCR7.js";
15
+ } from "../chunk-7RFRGXTU.js";
16
16
  import {
17
17
  authService,
18
18
  logger
19
- } from "../chunk-J27QHXXT.js";
19
+ } from "../chunk-M62KR3LR.js";
20
20
 
21
21
  // src/daemon/runner.ts
22
22
  import "dotenv/config";
@@ -250,10 +250,26 @@ async function startDaemon() {
250
250
  websocketService.subscribeToUserChannel(user.id);
251
251
  websocketService.onCommitApproved((commit, project) => {
252
252
  logger.info("daemon", `Commit approved: ${commit.id} for project ${project.name}`);
253
+ notify({
254
+ title: "Commit Approved",
255
+ message: `${commit.message}
256
+ Project: ${project.name}`
257
+ });
253
258
  commitQueue.addToQueue(commit, project);
254
259
  });
260
+ websocketService.onCommitPending((commit) => {
261
+ logger.info("daemon", `Commit pending: ${commit.id}`);
262
+ notify({
263
+ title: "New Pending Commit",
264
+ message: commit.message
265
+ });
266
+ });
255
267
  websocketService.onProjectUpdated((project) => {
256
268
  logger.info("daemon", `Project updated: ${project.id} - ${project.name}`);
269
+ notify({
270
+ title: "Project Updated",
271
+ message: project.name
272
+ });
257
273
  });
258
274
  websocketService.onDisconnect(() => {
259
275
  logger.warn("daemon", "WebSocket disconnected, will attempt to reconnect");
@@ -285,6 +301,19 @@ Priority: ${suggestion.priority}`,
285
301
  setupSignalHandlers();
286
302
  startHeartbeat();
287
303
  fileWatcher.start();
304
+ const linkedProjects = projectService.getAllLinkedProjects();
305
+ const projectEntries = Object.entries(linkedProjects);
306
+ if (projectEntries.length > 0) {
307
+ logger.info("daemon", `Syncing ${projectEntries.length} linked project(s) on startup...`);
308
+ for (const [, linkedProject] of projectEntries) {
309
+ try {
310
+ await fileWatcher.syncProjectById(linkedProject.projectId);
311
+ } catch (error) {
312
+ logger.error("daemon", `Failed to sync project ${linkedProject.projectId} on startup`, error);
313
+ }
314
+ }
315
+ logger.success("daemon", "Initial project sync complete");
316
+ }
288
317
  logger.success("daemon", "Daemon started successfully");
289
318
  await new Promise(() => {
290
319
  });
package/dist/index.js CHANGED
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  commitQueue,
4
4
  websocketService
5
- } from "./chunk-E5B6S5EK.js";
5
+ } from "./chunk-MMZYYFJF.js";
6
6
  import {
7
7
  apiService
8
- } from "./chunk-4KNUG3GA.js";
8
+ } from "./chunk-QSQGPVIU.js";
9
9
  import {
10
10
  getPidFilePath,
11
11
  gitService,
@@ -14,12 +14,12 @@ import {
14
14
  projectService,
15
15
  spawnDetached,
16
16
  validatePidFile
17
- } from "./chunk-RLW3QCR7.js";
17
+ } from "./chunk-7RFRGXTU.js";
18
18
  import {
19
19
  authService,
20
20
  config,
21
21
  logger
22
- } from "./chunk-J27QHXXT.js";
22
+ } from "./chunk-M62KR3LR.js";
23
23
 
24
24
  // src/index.ts
25
25
  import "dotenv/config";
@@ -620,7 +620,7 @@ function registerStatusCommand(program2) {
620
620
  try {
621
621
  const { render } = await import("ink");
622
622
  const { createElement } = await import("react");
623
- const { StatusDashboard } = await import("./StatusDashboard-63AGKYJB.js");
623
+ const { StatusDashboard } = await import("./StatusDashboard-N6F7NTE6.js");
624
624
  render(createElement(StatusDashboard, { cwd }));
625
625
  return;
626
626
  } catch (error) {
@@ -1281,11 +1281,17 @@ function registerCommitCommands(program2) {
1281
1281
  }
1282
1282
  const commit = matchingCommits[0];
1283
1283
  let status = await gitService.getStatus(cwd);
1284
- if (options.autoStage && commit.files && commit.files.length > 0) {
1285
- activeSpinner.text = `Staging ${commit.files.length} files...`;
1286
- await gitService.stageFiles(cwd, commit.files);
1284
+ if (options.autoStage) {
1285
+ if (commit.files && commit.files.length > 0) {
1286
+ activeSpinner.text = `Staging ${commit.files.length} files...`;
1287
+ await gitService.stageFiles(cwd, commit.files);
1288
+ logger.info("commit", `Auto-staged files: ${commit.files.join(", ")}`);
1289
+ } else {
1290
+ activeSpinner.text = "Staging all changes...";
1291
+ await gitService.stageAll(cwd);
1292
+ logger.info("commit", "Auto-staged all changes");
1293
+ }
1287
1294
  status = await gitService.getStatus(cwd);
1288
- logger.info("commit", `Auto-staged files: ${commit.files.join(", ")}`);
1289
1295
  }
1290
1296
  if (status.staged.length === 0) {
1291
1297
  activeSpinner.fail("No staged changes");
@@ -1294,7 +1300,7 @@ function registerCommitCommands(program2) {
1294
1300
  console.log(chalk9.gray("Expected files: " + commit.files.join(", ")));
1295
1301
  console.log(chalk9.gray("\nUse --auto-stage to automatically stage expected files."));
1296
1302
  } else {
1297
- console.log(chalk9.gray("Please stage the files you want to commit first."));
1303
+ console.log(chalk9.gray("Use --auto-stage to automatically stage all changes, or stage files manually:"));
1298
1304
  console.log(chalk9.gray(" git add <files>\n"));
1299
1305
  }
1300
1306
  process6.exit(1);
@@ -1994,7 +2000,7 @@ function registerDoctorCommand(program2) {
1994
2000
  }
1995
2001
 
1996
2002
  // src/index.ts
1997
- var AGENT_VERSION = "1.2.3";
2003
+ var AGENT_VERSION = "1.2.5";
1998
2004
  var program = new Command();
1999
2005
  program.name("stint").description("Stint Agent - Local daemon for Stint Project Assistant").version(AGENT_VERSION, "-v, --version", "output the current version").addHelpText("after", `
2000
2006
  ${chalk13.bold("Examples:")}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gowelle/stint-agent",
3
- "version": "1.2.3",
3
+ "version": "1.2.5",
4
4
  "description": "Local agent for Stint - Project Assistant",
5
5
  "author": "Gowelle John <gowelle.john@icloud.com>",
6
6
  "license": "MIT",
@@ -1,7 +0,0 @@
1
- import {
2
- apiService
3
- } from "./chunk-4KNUG3GA.js";
4
- import "./chunk-J27QHXXT.js";
5
- export {
6
- apiService
7
- };