@gowelle/stint-agent 1.2.21 → 1.2.23

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
@@ -20,6 +20,7 @@ The official CLI agent for [Stint](https://stint.codes) — a lightweight daemon
20
20
  - 🚀 Multiple release channels (stable/beta/nightly)
21
21
  - 🔍 Built-in environment diagnostics
22
22
  - 📈 Resource usage monitoring
23
+ - 📁 File selection for commits (sync changed files to web app)
23
24
 
24
25
  For detailed feature documentation, see the **[Features Guide](docs/features.md)**.
25
26
 
@@ -2,10 +2,10 @@ import {
2
2
  gitService,
3
3
  projectService,
4
4
  validatePidFile
5
- } from "./chunk-5OXEEP67.js";
5
+ } from "./chunk-ZUQTJV35.js";
6
6
  import {
7
7
  authService
8
- } from "./chunk-E5GW4WNQ.js";
8
+ } from "./chunk-WQUVXZWM.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-LTVAFGVL.js";
4
+ import "./chunk-WQUVXZWM.js";
5
+ export {
6
+ apiService
7
+ };
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  apiService
3
- } from "./chunk-CJHTK5DX.js";
3
+ } from "./chunk-LTVAFGVL.js";
4
4
  import {
5
5
  gitService,
6
6
  projectService
7
- } from "./chunk-5OXEEP67.js";
7
+ } from "./chunk-ZUQTJV35.js";
8
8
  import {
9
9
  authService,
10
10
  config,
11
11
  logger
12
- } from "./chunk-E5GW4WNQ.js";
12
+ } from "./chunk-WQUVXZWM.js";
13
13
 
14
14
  // src/utils/notify.ts
15
15
  import notifier from "node-notifier";
@@ -93,7 +93,7 @@ var HookService = class {
93
93
  const startTime = Date.now();
94
94
  logger.debug("hooks", `Executing hook: ${hook.name} (${hook.command})`);
95
95
  const timeout = hook.timeout || 3e4;
96
- const childProcess = exec(hook.command, {
96
+ exec(hook.command, {
97
97
  cwd,
98
98
  timeout,
99
99
  maxBuffer: 10 * 1024 * 1024
@@ -549,11 +549,29 @@ var WebSocketServiceImpl = class {
549
549
  logger.info("websocket", `Subscribing to private channel: ${channel}`);
550
550
  const privateChannel = this.echo.private(channel);
551
551
  writeStatus({ channel });
552
- privateChannel.listen(".commit.approved", (data) => {
552
+ privateChannel.listen(".commit.approved", async (data) => {
553
553
  logger.info("websocket", `Commit approved: ${data.pendingCommit.id}`);
554
554
  writeStatus({ lastEvent: "commit.approved", lastEventTime: (/* @__PURE__ */ new Date()).toISOString() });
555
+ let commit = data.pendingCommit;
556
+ if (commit.has_large_files) {
557
+ try {
558
+ logger.info("websocket", `Commit ${commit.id} marked as large, fetching full details...`);
559
+ const { apiService: apiService2 } = await import("./api-GSYJMF33.js");
560
+ const fullCommit = await apiService2.getCommit(commit.id);
561
+ commit = {
562
+ ...commit,
563
+ files: fullCommit.files,
564
+ has_large_files: false
565
+ // Clear flag as we now have the files
566
+ };
567
+ logger.success("websocket", `Fetched full details for commit ${commit.id}`);
568
+ } catch (error) {
569
+ logger.error("websocket", `Failed to fetch full commit details for ${commit.id}`, error);
570
+ }
571
+ }
555
572
  this.commitApprovedHandlers.forEach(
556
- (handler) => handler(data.pendingCommit, data.pendingCommit.project)
573
+ (handler) => handler(commit, data.pendingCommit.project)
574
+ // Use the potentially updated commit object
557
575
  );
558
576
  }).listen(".commit.pending", (data) => {
559
577
  logger.info("websocket", `Commit pending: ${data.pendingCommit.id}`);
@@ -2,7 +2,7 @@ import {
2
2
  authService,
3
3
  config,
4
4
  logger
5
- } from "./chunk-E5GW4WNQ.js";
5
+ } from "./chunk-WQUVXZWM.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.21";
101
+ var AGENT_VERSION = "1.2.23";
102
102
  var ApiServiceImpl = class {
103
103
  sessionId = null;
104
104
  circuitBreaker = new CircuitBreaker({
@@ -272,6 +272,30 @@ var ApiServiceImpl = class {
272
272
  logger.info("api", `Found ${commits.length} pending commits`);
273
273
  return commits;
274
274
  }
275
+ /**
276
+ * Get a specific commit by ID
277
+ * @param commitId - Commit ID
278
+ * @returns The pending commit details
279
+ */
280
+ async getCommit(commitId) {
281
+ logger.info("api", `Fetching commit ${commitId}`);
282
+ const response = await this.request(`/api/agent/commits/${commitId}`);
283
+ const item = response.data;
284
+ const projectId = item.project_id || item.projectId;
285
+ const createdAt = item.created_at || item.createdAt;
286
+ const hasLargeFiles = item.has_large_files || item.hasLargeFiles;
287
+ if (!projectId || !createdAt) {
288
+ throw new Error(`Invalid commit data received from API: ${JSON.stringify(item)}`);
289
+ }
290
+ return {
291
+ id: item.id,
292
+ projectId,
293
+ message: item.message,
294
+ files: item.files,
295
+ has_large_files: hasLargeFiles,
296
+ createdAt
297
+ };
298
+ }
275
299
  /**
276
300
  * Mark a commit as successfully executed
277
301
  * @param commitId - Commit ID
@@ -330,8 +354,9 @@ var ApiServiceImpl = class {
330
354
  * Sync project repository information with the API
331
355
  * @param projectId - Project ID
332
356
  * @param data - Repository information (path, remote URL, branches)
357
+ * @param changedFiles - Optional array of changed files for commit file selection
333
358
  */
334
- async syncProject(projectId, data) {
359
+ async syncProject(projectId, data, changedFiles) {
335
360
  logger.info("api", `Syncing project ${projectId}`);
336
361
  await this.withRetry(async () => {
337
362
  const payload = {
@@ -341,11 +366,14 @@ var ApiServiceImpl = class {
341
366
  current_branch: data.currentBranch,
342
367
  branches: data.branches
343
368
  };
369
+ if (changedFiles && changedFiles.length > 0) {
370
+ payload.changed_files = changedFiles;
371
+ }
344
372
  await this.request(`/api/agent/projects/${projectId}/sync`, {
345
373
  method: "POST",
346
374
  body: JSON.stringify(payload)
347
375
  });
348
- logger.success("api", `Project ${projectId} synced`);
376
+ logger.success("api", `Project ${projectId} synced (${changedFiles?.length ?? 0} changed files)`);
349
377
  }, "Sync project");
350
378
  }
351
379
  /**
@@ -308,7 +308,7 @@ var AuthServiceImpl = class {
308
308
  return null;
309
309
  }
310
310
  try {
311
- const { apiService } = await import("./api-EZ3J5BUL.js");
311
+ const { apiService } = await import("./api-GSYJMF33.js");
312
312
  const user = await apiService.getCurrentUser();
313
313
  logger.info("auth", `Token validated for user: ${user.email}`);
314
314
  return user;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  config,
3
3
  logger
4
- } from "./chunk-E5GW4WNQ.js";
4
+ } from "./chunk-WQUVXZWM.js";
5
5
 
6
6
  // src/services/git.ts
7
7
  import simpleGit from "simple-git";
@@ -150,6 +150,73 @@ var GitServiceImpl = class {
150
150
  throw new Error(`Failed to get git status: ${error.message}`);
151
151
  }
152
152
  }
153
+ /**
154
+ * Get detailed information about all changed files in the working directory
155
+ * Used for file selection during commit generation in the web app
156
+ * @param path - Repository path
157
+ * @returns Array of changed files with their status and staging state
158
+ */
159
+ async getChangedFiles(path3) {
160
+ try {
161
+ const git = this.getGit(path3);
162
+ const status = await git.status();
163
+ const changedFiles = [];
164
+ for (const file of status.staged) {
165
+ let fileStatus = "modified";
166
+ if (status.created.includes(file)) {
167
+ fileStatus = "added";
168
+ } else if (status.deleted.includes(file)) {
169
+ fileStatus = "deleted";
170
+ } else if (status.renamed.some((r) => r.to === file)) {
171
+ fileStatus = "renamed";
172
+ }
173
+ changedFiles.push({
174
+ path: file,
175
+ status: fileStatus,
176
+ staged: true
177
+ });
178
+ }
179
+ for (const file of status.modified) {
180
+ if (!status.staged.includes(file)) {
181
+ changedFiles.push({
182
+ path: file,
183
+ status: "modified",
184
+ staged: false
185
+ });
186
+ }
187
+ }
188
+ for (const file of status.deleted) {
189
+ if (!status.staged.includes(file)) {
190
+ changedFiles.push({
191
+ path: file,
192
+ status: "deleted",
193
+ staged: false
194
+ });
195
+ }
196
+ }
197
+ for (const file of status.not_added) {
198
+ changedFiles.push({
199
+ path: file,
200
+ status: "untracked",
201
+ staged: false
202
+ });
203
+ }
204
+ for (const renamed of status.renamed) {
205
+ if (!status.staged.includes(renamed.to)) {
206
+ changedFiles.push({
207
+ path: renamed.to,
208
+ status: "renamed",
209
+ staged: false
210
+ });
211
+ }
212
+ }
213
+ logger.info("git", `Found ${changedFiles.length} changed files in ${path3}`);
214
+ return changedFiles;
215
+ } catch (error) {
216
+ logger.error("git", `Failed to get changed files in ${path3}`, error);
217
+ throw new Error(`Failed to get changed files: ${error.message}`);
218
+ }
219
+ }
153
220
  /**
154
221
  * Push commits to remote repository
155
222
  * @param path - Repository path
@@ -3,20 +3,20 @@ import {
3
3
  commitQueue,
4
4
  notify,
5
5
  websocketService
6
- } from "../chunk-EGEDPYQY.js";
6
+ } from "../chunk-BPDL5KWL.js";
7
7
  import {
8
8
  apiService
9
- } from "../chunk-CJHTK5DX.js";
9
+ } from "../chunk-LTVAFGVL.js";
10
10
  import {
11
11
  gitService,
12
12
  projectService,
13
13
  removePidFile,
14
14
  writePidFile
15
- } from "../chunk-5OXEEP67.js";
15
+ } from "../chunk-ZUQTJV35.js";
16
16
  import {
17
17
  authService,
18
18
  logger
19
- } from "../chunk-E5GW4WNQ.js";
19
+ } from "../chunk-WQUVXZWM.js";
20
20
 
21
21
  // src/daemon/runner.ts
22
22
  import "dotenv/config";
@@ -161,7 +161,8 @@ var FileWatcher = class {
161
161
  return;
162
162
  }
163
163
  const repoInfo = await gitService.getRepoInfo(projectPath);
164
- await apiService.syncProject(projectId, repoInfo);
164
+ const changedFiles = await gitService.getChangedFiles(projectPath);
165
+ await apiService.syncProject(projectId, repoInfo, changedFiles);
165
166
  logger.success("watcher", `Synced project ${projectId}`);
166
167
  let projectName = projectId;
167
168
  try {
package/dist/index.js CHANGED
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  commitQueue,
4
4
  websocketService
5
- } from "./chunk-EGEDPYQY.js";
5
+ } from "./chunk-BPDL5KWL.js";
6
6
  import {
7
7
  apiService
8
- } from "./chunk-CJHTK5DX.js";
8
+ } from "./chunk-LTVAFGVL.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-5OXEEP67.js";
17
+ } from "./chunk-ZUQTJV35.js";
18
18
  import {
19
19
  __commonJS,
20
20
  __toESM,
21
21
  authService,
22
22
  config,
23
23
  logger
24
- } from "./chunk-E5GW4WNQ.js";
24
+ } from "./chunk-WQUVXZWM.js";
25
25
 
26
26
  // node_modules/semver/internal/constants.js
27
27
  var require_constants = __commonJS({
@@ -1956,7 +1956,7 @@ var require_semver2 = __commonJS({
1956
1956
  // src/index.ts
1957
1957
  import "dotenv/config";
1958
1958
  import { Command } from "commander";
1959
- import chalk14 from "chalk";
1959
+ import chalk15 from "chalk";
1960
1960
 
1961
1961
  // src/commands/login.ts
1962
1962
  import open from "open";
@@ -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-A6WLLY4U.js");
2555
+ const { StatusDashboard } = await import("./StatusDashboard-NDXVTKKO.js");
2556
2556
  render(createElement(StatusDashboard, { cwd }));
2557
2557
  return;
2558
2558
  } catch (error) {
@@ -2660,10 +2660,12 @@ function registerSyncCommand(program2) {
2660
2660
  spinner.text = `Found ${totalFiles} files to analyze...`;
2661
2661
  spinner.text = "Getting branch information...";
2662
2662
  const repoInfo = await gitService.getRepoInfo(cwd);
2663
+ spinner.text = "Getting changed files...";
2664
+ const changedFiles = await gitService.getChangedFiles(cwd);
2663
2665
  spinner.text = "Preparing sync payload...";
2664
2666
  const syncSpinner = ora7("Connecting to server...").start();
2665
2667
  try {
2666
- await apiService.syncProject(linkedProject.projectId, repoInfo);
2668
+ await apiService.syncProject(linkedProject.projectId, repoInfo, changedFiles);
2667
2669
  syncSpinner.succeed("Server sync completed");
2668
2670
  } catch (error) {
2669
2671
  syncSpinner.fail("Server sync failed");
@@ -2672,6 +2674,7 @@ function registerSyncCommand(program2) {
2672
2674
  console.log(chalk7.green("\n\u2713 Repository sync completed"));
2673
2675
  console.log(chalk7.gray("\u2500".repeat(50)));
2674
2676
  console.log(`${chalk7.bold("Files:")} ${totalFiles} total (${status.staged.length} staged, ${status.unstaged.length} modified, ${status.untracked.length} untracked)`);
2677
+ console.log(`${chalk7.bold("Changed:")} ${changedFiles.length} files synced for commit selection`);
2675
2678
  console.log(`${chalk7.bold("Project ID:")} ${linkedProject.projectId}`);
2676
2679
  console.log(`${chalk7.bold("Branch:")} ${repoInfo.currentBranch}`);
2677
2680
  console.log(`${chalk7.bold("Commit:")} ${repoInfo.lastCommitSha.substring(0, 7)} - ${repoInfo.lastCommitMessage}`);
@@ -4150,20 +4153,222 @@ function registerDoctorCommand(program2) {
4150
4153
  });
4151
4154
  }
4152
4155
 
4156
+ // src/commands/config.ts
4157
+ import chalk14 from "chalk";
4158
+ import path6 from "path";
4159
+ import os6 from "os";
4160
+ var ALLOWED_KEYS = [
4161
+ "apiUrl",
4162
+ "wsUrl",
4163
+ "reverbAppKey",
4164
+ "notifications.enabled"
4165
+ ];
4166
+ var SENSITIVE_KEYS = ["token"];
4167
+ function isAllowedKey(key) {
4168
+ return ALLOWED_KEYS.includes(key);
4169
+ }
4170
+ function isSensitiveKey(key) {
4171
+ return SENSITIVE_KEYS.includes(key);
4172
+ }
4173
+ function getNestedValue(obj, path7) {
4174
+ const parts = path7.split(".");
4175
+ let current = obj;
4176
+ for (const part of parts) {
4177
+ if (current === null || current === void 0 || typeof current !== "object") {
4178
+ return void 0;
4179
+ }
4180
+ current = current[part];
4181
+ }
4182
+ return current;
4183
+ }
4184
+ function setNestedValue(obj, path7, value) {
4185
+ const parts = path7.split(".");
4186
+ let current = obj;
4187
+ for (let i = 0; i < parts.length - 1; i++) {
4188
+ const part = parts[i];
4189
+ if (!(part in current) || typeof current[part] !== "object") {
4190
+ current[part] = {};
4191
+ }
4192
+ current = current[part];
4193
+ }
4194
+ current[parts[parts.length - 1]] = value;
4195
+ }
4196
+ function formatValue(value) {
4197
+ if (value === void 0 || value === null) {
4198
+ return chalk14.gray("(not set)");
4199
+ }
4200
+ if (typeof value === "boolean") {
4201
+ return value ? chalk14.green("true") : chalk14.red("false");
4202
+ }
4203
+ if (typeof value === "object") {
4204
+ return chalk14.cyan(JSON.stringify(value));
4205
+ }
4206
+ return chalk14.white(String(value));
4207
+ }
4208
+ function getConfigPath() {
4209
+ const configDir = path6.join(os6.homedir(), ".config", "stint");
4210
+ return path6.join(configDir, "config.json");
4211
+ }
4212
+ function registerConfigCommand(program2) {
4213
+ const configCmd = program2.command("config").description("Manage agent configuration");
4214
+ configCmd.command("get <key>").description("Get a configuration value").action((key) => {
4215
+ try {
4216
+ if (isSensitiveKey(key)) {
4217
+ console.log(chalk14.yellow(`
4218
+ \u26A0 Cannot read sensitive key "${key}"`));
4219
+ console.log(chalk14.gray('Use "stint whoami" to check authentication status.\n'));
4220
+ return;
4221
+ }
4222
+ const allConfig = config.getAll();
4223
+ const value = getNestedValue(allConfig, key);
4224
+ if (value === void 0) {
4225
+ console.log(chalk14.yellow(`
4226
+ \u26A0 Key "${key}" is not set.
4227
+ `));
4228
+ console.log(chalk14.gray("Available keys:"));
4229
+ ALLOWED_KEYS.forEach((k) => console.log(chalk14.gray(` - ${k}`)));
4230
+ console.log();
4231
+ } else {
4232
+ console.log(`
4233
+ ${chalk14.bold(key)}: ${formatValue(value)}
4234
+ `);
4235
+ }
4236
+ logger.debug("config", `Get config key: ${key}`);
4237
+ } catch (error) {
4238
+ logger.error("config", "Failed to get config", error);
4239
+ console.error(chalk14.red(`
4240
+ \u2716 Error: ${error.message}
4241
+ `));
4242
+ }
4243
+ });
4244
+ configCmd.command("set <key> <value>").description("Set a configuration value").action((key, value) => {
4245
+ try {
4246
+ if (isSensitiveKey(key)) {
4247
+ console.log(chalk14.red(`
4248
+ \u2716 Cannot set sensitive key "${key}"`));
4249
+ console.log(chalk14.gray('Use "stint login" to set authentication.\n'));
4250
+ return;
4251
+ }
4252
+ if (!isAllowedKey(key)) {
4253
+ console.log(chalk14.yellow(`
4254
+ \u26A0 Unknown key "${key}"`));
4255
+ console.log(chalk14.gray("Allowed keys:"));
4256
+ ALLOWED_KEYS.forEach((k) => console.log(chalk14.gray(` - ${k}`)));
4257
+ console.log();
4258
+ return;
4259
+ }
4260
+ let parsedValue = value;
4261
+ if (value.toLowerCase() === "true") {
4262
+ parsedValue = true;
4263
+ } else if (value.toLowerCase() === "false") {
4264
+ parsedValue = false;
4265
+ }
4266
+ if (key.includes(".")) {
4267
+ const allConfig = config.getAll();
4268
+ setNestedValue(allConfig, key, parsedValue);
4269
+ const topKey = key.split(".")[0];
4270
+ config.set(topKey, allConfig[topKey]);
4271
+ } else {
4272
+ config.set(key, parsedValue);
4273
+ }
4274
+ console.log(chalk14.green(`
4275
+ \u2713 Set ${key} = ${formatValue(parsedValue)}
4276
+ `));
4277
+ logger.success("config", `Set config key: ${key} = ${value}`);
4278
+ } catch (error) {
4279
+ logger.error("config", "Failed to set config", error);
4280
+ console.error(chalk14.red(`
4281
+ \u2716 Error: ${error.message}
4282
+ `));
4283
+ }
4284
+ });
4285
+ configCmd.command("list").description("List all configuration values").action(() => {
4286
+ try {
4287
+ const allConfig = config.getAll();
4288
+ console.log(chalk14.bold("\n\u{1F4CB} Configuration:\n"));
4289
+ console.log(chalk14.gray("\u2500".repeat(50)));
4290
+ for (const key of ALLOWED_KEYS) {
4291
+ const value = getNestedValue(allConfig, key);
4292
+ console.log(`${chalk14.cyan(key.padEnd(25))} ${formatValue(value)}`);
4293
+ }
4294
+ console.log(chalk14.gray("\u2500".repeat(50)));
4295
+ console.log(`${chalk14.cyan("token".padEnd(25))} ${chalk14.yellow("[REDACTED]")}`);
4296
+ console.log(chalk14.gray("\u2500".repeat(50)));
4297
+ console.log(`${chalk14.gray("machineId".padEnd(25))} ${chalk14.gray(allConfig.machineId)}`);
4298
+ console.log(`${chalk14.gray("machineName".padEnd(25))} ${chalk14.gray(allConfig.machineName)}`);
4299
+ console.log();
4300
+ logger.debug("config", "Listed config");
4301
+ } catch (error) {
4302
+ logger.error("config", "Failed to list config", error);
4303
+ console.error(chalk14.red(`
4304
+ \u2716 Error: ${error.message}
4305
+ `));
4306
+ }
4307
+ });
4308
+ configCmd.command("path").description("Show the configuration file path").action(() => {
4309
+ const configPath = getConfigPath();
4310
+ console.log(`
4311
+ ${chalk14.bold("Config file:")} ${chalk14.cyan(configPath)}
4312
+ `);
4313
+ logger.debug("config", `Config path: ${configPath}`);
4314
+ });
4315
+ configCmd.command("reset").description("Reset configuration to defaults (keeps token)").option("--force", "Skip confirmation prompt").action(async (options) => {
4316
+ try {
4317
+ if (!options.force) {
4318
+ console.log(chalk14.yellow("\n\u26A0 This will reset all configuration to defaults."));
4319
+ console.log(chalk14.gray("Your authentication token will be preserved.\n"));
4320
+ const readline = await import("readline");
4321
+ const rl = readline.createInterface({
4322
+ input: process.stdin,
4323
+ output: process.stdout
4324
+ });
4325
+ const answer = await new Promise((resolve) => {
4326
+ rl.question(chalk14.bold("Are you sure? (y/N) "), resolve);
4327
+ });
4328
+ rl.close();
4329
+ if (answer.toLowerCase() !== "y" && answer.toLowerCase() !== "yes") {
4330
+ console.log(chalk14.gray("\nReset cancelled.\n"));
4331
+ return;
4332
+ }
4333
+ }
4334
+ const token = config.getToken();
4335
+ for (const key of ALLOWED_KEYS) {
4336
+ if (key === "notifications.enabled") {
4337
+ config.set("notifications", { enabled: true });
4338
+ } else {
4339
+ if (key === "apiUrl") config.set("apiUrl", "https://stint.codes");
4340
+ if (key === "wsUrl") config.set("wsUrl", "wss://stint.codes/reverb");
4341
+ if (key === "reverbAppKey") config.set("reverbAppKey", "wtn6tu6lirfv6yflujk7");
4342
+ }
4343
+ }
4344
+ if (token) {
4345
+ config.setToken(token);
4346
+ }
4347
+ console.log(chalk14.green("\n\u2713 Configuration reset to defaults.\n"));
4348
+ logger.success("config", "Reset config to defaults");
4349
+ } catch (error) {
4350
+ logger.error("config", "Failed to reset config", error);
4351
+ console.error(chalk14.red(`
4352
+ \u2716 Error: ${error.message}
4353
+ `));
4354
+ }
4355
+ });
4356
+ }
4357
+
4153
4358
  // src/index.ts
4154
- var AGENT_VERSION = "1.2.21";
4359
+ var AGENT_VERSION = "1.2.23";
4155
4360
  var program = new Command();
4156
4361
  program.name("stint").description("Stint Agent - Local daemon for Stint Project Assistant").version(AGENT_VERSION, "-v, --version", "output the current version").addHelpText("after", `
4157
- ${chalk14.bold("Examples:")}
4158
- ${chalk14.cyan("$")} stint login ${chalk14.gray("# Authenticate with Stint")}
4159
- ${chalk14.cyan("$")} stint install ${chalk14.gray("# Install agent to run on startup")}
4160
- ${chalk14.cyan("$")} stint link ${chalk14.gray("# Link current directory to a project")}
4161
- ${chalk14.cyan("$")} stint daemon start ${chalk14.gray("# Start background daemon")}
4162
- ${chalk14.cyan("$")} stint status ${chalk14.gray("# Check status")}
4163
- ${chalk14.cyan("$")} stint commits ${chalk14.gray("# List pending commits")}
4362
+ ${chalk15.bold("Examples:")}
4363
+ ${chalk15.cyan("$")} stint login ${chalk15.gray("# Authenticate with Stint")}
4364
+ ${chalk15.cyan("$")} stint install ${chalk15.gray("# Install agent to run on startup")}
4365
+ ${chalk15.cyan("$")} stint link ${chalk15.gray("# Link current directory to a project")}
4366
+ ${chalk15.cyan("$")} stint daemon start ${chalk15.gray("# Start background daemon")}
4367
+ ${chalk15.cyan("$")} stint status ${chalk15.gray("# Check status")}
4368
+ ${chalk15.cyan("$")} stint commits ${chalk15.gray("# List pending commits")}
4164
4369
 
4165
- ${chalk14.bold("Documentation:")}
4166
- For more information, visit: ${chalk14.blue("https://stint.codes/docs")}
4370
+ ${chalk15.bold("Documentation:")}
4371
+ For more information, visit: ${chalk15.blue("https://stint.codes/docs")}
4167
4372
  `);
4168
4373
  registerLoginCommand(program);
4169
4374
  registerLogoutCommand(program);
@@ -4178,6 +4383,7 @@ registerInstallCommand(program);
4178
4383
  registerUninstallCommand(program);
4179
4384
  registerUpdateCommand(program);
4180
4385
  registerDoctorCommand(program);
4386
+ registerConfigCommand(program);
4181
4387
  program.exitOverride();
4182
4388
  try {
4183
4389
  await program.parseAsync(process.argv);
@@ -4185,7 +4391,7 @@ try {
4185
4391
  const commanderError = error;
4186
4392
  if (commanderError.code !== "commander.help" && commanderError.code !== "commander.version" && commanderError.code !== "commander.helpDisplayed") {
4187
4393
  logger.error("cli", "Command execution failed", error);
4188
- console.error(chalk14.red(`
4394
+ console.error(chalk15.red(`
4189
4395
  \u2716 Error: ${error.message}
4190
4396
  `));
4191
4397
  process.exit(1);
package/package.json CHANGED
@@ -1,92 +1,98 @@
1
- {
2
- "name": "@gowelle/stint-agent",
3
- "version": "1.2.21",
4
- "description": "Local agent for Stint - Project Assistant",
5
- "author": "Gowelle John <gowelle.john@icloud.com>",
6
- "license": "MIT",
7
- "type": "module",
8
- "bin": {
9
- "stint": "./dist/index.js"
10
- },
11
- "files": [
12
- "dist",
13
- "assets",
14
- "README.md",
15
- "LICENSE"
16
- ],
17
- "repository": {
18
- "type": "git",
19
- "url": "git+https://github.com/gowelle/stint-agent.git"
20
- },
21
- "homepage": "https://github.com/gowelle/stint-agent#readme",
22
- "bugs": {
23
- "url": "https://github.com/gowelle/stint-agent/issues"
24
- },
25
- "keywords": [
26
- "stint",
27
- "agent",
28
- "project-assistant",
29
- "cli",
30
- "git"
31
- ],
32
- "dependencies": {
33
- "@inquirer/prompts": "^8.1.0",
34
- "chalk": "^5.3.0",
35
- "commander": "^12.0.0",
36
- "conf": "^12.0.0",
37
- "dotenv": "^17.2.3",
38
- "ink": "^5.2.1",
39
- "laravel-echo": "^2.2.6",
40
- "node-fetch": "^3.3.2",
41
- "node-notifier": "^10.0.1",
42
- "open": "^10.0.0",
43
- "ora": "^8.0.1",
44
- "prompts": "^2.4.2",
45
- "pusher-js": "^8.4.0",
46
- "react": "^18.3.1",
47
- "simple-git": "^3.22.0",
48
- "ws": "^8.16.0"
49
- },
50
- "devDependencies": {
51
- "@types/node": "^20.11.0",
52
- "@types/node-notifier": "^8.0.5",
53
- "@types/prompts": "^2.4.9",
54
- "@types/react": "^18.3.27",
55
- "@types/ws": "^8.5.10",
56
- "@typescript-eslint/eslint-plugin": "^8.50.0",
57
- "@typescript-eslint/parser": "^8.50.0",
58
- "@vitest/coverage-v8": "^4.0.16",
59
- "eslint": "^8.56.0",
60
- "ts-node": "^10.9.2",
61
- "tsup": "^8.0.1",
62
- "typescript": "^5.3.3",
63
- "vitest": "^4.0.16"
64
- },
65
- "engines": {
66
- "node": ">=20.0.0"
67
- },
68
- "stint": {
69
- "channels": {
70
- "stable": {
71
- "pattern": "^\\d+\\.\\d+\\.\\d+$",
72
- "description": "Production-ready releases"
73
- },
74
- "beta": {
75
- "pattern": "^\\d+\\.\\d+\\.\\d+-beta\\.\\d+$",
76
- "description": "Pre-release versions for testing"
77
- },
78
- "nightly": {
79
- "pattern": "^\\d+\\.\\d+\\.\\d+-nightly\\.\\d{8}$",
80
- "description": "Nightly builds from main branch"
81
- }
82
- },
83
- "defaultChannel": "stable"
84
- },
85
- "scripts": {
86
- "build": "tsup",
87
- "dev": "tsup --watch",
88
- "lint": "eslint src",
89
- "test": "vitest",
90
- "test:update": "node --loader ts-node/esm scripts/test-update.ts"
91
- }
92
- }
1
+ {
2
+ "name": "@gowelle/stint-agent",
3
+ "version": "1.2.23",
4
+ "description": "Local agent for Stint - Project Assistant",
5
+ "author": "Gowelle John <gowelle.john@icloud.com>",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "bin": {
9
+ "stint": "./dist/index.js"
10
+ },
11
+ "files": [
12
+ "dist",
13
+ "assets",
14
+ "README.md",
15
+ "LICENSE"
16
+ ],
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/gowelle/stint-agent.git"
20
+ },
21
+ "homepage": "https://github.com/gowelle/stint-agent#readme",
22
+ "bugs": {
23
+ "url": "https://github.com/gowelle/stint-agent/issues"
24
+ },
25
+ "keywords": [
26
+ "stint",
27
+ "agent",
28
+ "project-assistant",
29
+ "cli",
30
+ "git"
31
+ ],
32
+ "scripts": {
33
+ "build": "tsup",
34
+ "dev": "tsup --watch",
35
+ "lint": "eslint src",
36
+ "test": "vitest",
37
+ "test:update": "node --loader ts-node/esm scripts/test-update.ts",
38
+ "prepublishOnly": "npm run build"
39
+ },
40
+ "dependencies": {
41
+ "@inquirer/prompts": "^8.1.0",
42
+ "chalk": "^5.3.0",
43
+ "commander": "^12.0.0",
44
+ "conf": "^12.0.0",
45
+ "dotenv": "^17.2.3",
46
+ "ink": "^5.2.1",
47
+ "laravel-echo": "^2.2.6",
48
+ "node-fetch": "^3.3.2",
49
+ "node-notifier": "^10.0.1",
50
+ "open": "^10.0.0",
51
+ "ora": "^8.0.1",
52
+ "prompts": "^2.4.2",
53
+ "pusher-js": "^8.4.0",
54
+ "react": "^18.3.1",
55
+ "simple-git": "^3.22.0",
56
+ "ws": "^8.16.0"
57
+ },
58
+ "devDependencies": {
59
+ "@types/node": "^20.11.0",
60
+ "@types/node-notifier": "^8.0.5",
61
+ "@types/prompts": "^2.4.9",
62
+ "@types/react": "^18.3.27",
63
+ "@types/ws": "^8.5.10",
64
+ "@typescript-eslint/eslint-plugin": "^8.50.0",
65
+ "@typescript-eslint/parser": "^8.50.0",
66
+ "@vitest/coverage-v8": "^4.0.16",
67
+ "eslint": "^8.56.0",
68
+ "ts-node": "^10.9.2",
69
+ "tsup": "^8.0.1",
70
+ "typescript": "^5.3.3",
71
+ "vitest": "^4.0.16"
72
+ },
73
+ "engines": {
74
+ "node": ">=20.0.0"
75
+ },
76
+ "stint": {
77
+ "channels": {
78
+ "stable": {
79
+ "pattern": "^\\d+\\.\\d+\\.\\d+$",
80
+ "description": "Production-ready releases"
81
+ },
82
+ "beta": {
83
+ "pattern": "^\\d+\\.\\d+\\.\\d+-beta\\.\\d+$",
84
+ "description": "Pre-release versions for testing"
85
+ },
86
+ "nightly": {
87
+ "pattern": "^\\d+\\.\\d+\\.\\d+-nightly\\.\\d{8}$",
88
+ "description": "Nightly builds from main branch"
89
+ }
90
+ },
91
+ "defaultChannel": "stable"
92
+ },
93
+ "pnpm": {
94
+ "onlyBuiltDependencies": [
95
+ "esbuild"
96
+ ]
97
+ }
98
+ }
@@ -1,7 +0,0 @@
1
- import {
2
- apiService
3
- } from "./chunk-CJHTK5DX.js";
4
- import "./chunk-E5GW4WNQ.js";
5
- export {
6
- apiService
7
- };