devclocked 2.1.1 → 2.1.2

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.
Files changed (74) hide show
  1. package/dist/auth.d.ts +16 -0
  2. package/dist/auth.d.ts.map +1 -0
  3. package/dist/auth.js +68 -0
  4. package/dist/auth.js.map +1 -0
  5. package/dist/branding/banner.d.ts +16 -0
  6. package/dist/branding/banner.d.ts.map +1 -0
  7. package/dist/branding/banner.js +109 -0
  8. package/dist/branding/banner.js.map +1 -0
  9. package/dist/branding/dashboard.d.ts +28 -0
  10. package/dist/branding/dashboard.d.ts.map +1 -0
  11. package/dist/branding/dashboard.js +508 -0
  12. package/dist/branding/dashboard.js.map +1 -0
  13. package/dist/commands/flush.d.ts +6 -0
  14. package/dist/commands/flush.d.ts.map +1 -0
  15. package/dist/commands/flush.js +54 -0
  16. package/dist/commands/flush.js.map +1 -0
  17. package/dist/commands/login.d.ts +6 -0
  18. package/dist/commands/login.d.ts.map +1 -0
  19. package/dist/commands/login.js +108 -0
  20. package/dist/commands/login.js.map +1 -0
  21. package/dist/commands/logout.d.ts +6 -0
  22. package/dist/commands/logout.d.ts.map +1 -0
  23. package/dist/commands/logout.js +38 -0
  24. package/dist/commands/logout.js.map +1 -0
  25. package/dist/commands/mcp-health.d.ts +8 -0
  26. package/dist/commands/mcp-health.d.ts.map +1 -0
  27. package/dist/commands/mcp-health.js +75 -0
  28. package/dist/commands/mcp-health.js.map +1 -0
  29. package/dist/commands/mcp-server.d.ts +65 -0
  30. package/dist/commands/mcp-server.d.ts.map +1 -0
  31. package/dist/commands/mcp-server.js +280 -0
  32. package/dist/commands/mcp-server.js.map +1 -0
  33. package/dist/commands/session.d.ts +6 -0
  34. package/dist/commands/session.d.ts.map +1 -0
  35. package/dist/commands/session.js +90 -0
  36. package/dist/commands/session.js.map +1 -0
  37. package/dist/commands/setup.d.ts +8 -0
  38. package/dist/commands/setup.d.ts.map +1 -0
  39. package/dist/commands/setup.js +164 -0
  40. package/dist/commands/setup.js.map +1 -0
  41. package/dist/commands/status.d.ts +6 -0
  42. package/dist/commands/status.d.ts.map +1 -0
  43. package/dist/commands/status.js +78 -0
  44. package/dist/commands/status.js.map +1 -0
  45. package/dist/commands/summary.d.ts +6 -0
  46. package/dist/commands/summary.d.ts.map +1 -0
  47. package/dist/commands/summary.js +45 -0
  48. package/dist/commands/summary.js.map +1 -0
  49. package/dist/config.d.ts +13 -0
  50. package/dist/config.d.ts.map +1 -0
  51. package/dist/config.js +22 -0
  52. package/dist/config.js.map +1 -0
  53. package/dist/index.d.ts +13 -0
  54. package/dist/index.d.ts.map +1 -0
  55. package/dist/index.js +40 -0
  56. package/dist/index.js.map +1 -0
  57. package/dist/mcp-utils.d.ts +15 -0
  58. package/dist/mcp-utils.d.ts.map +1 -0
  59. package/dist/mcp-utils.js +60 -0
  60. package/dist/mcp-utils.js.map +1 -0
  61. package/dist/storage/FileStorageAdapter.d.ts +19 -0
  62. package/dist/storage/FileStorageAdapter.d.ts.map +1 -0
  63. package/dist/storage/FileStorageAdapter.js +80 -0
  64. package/dist/storage/FileStorageAdapter.js.map +1 -0
  65. package/dist/terminal/WrappedShell.d.ts +24 -0
  66. package/dist/terminal/WrappedShell.d.ts.map +1 -0
  67. package/dist/terminal/WrappedShell.js +121 -0
  68. package/dist/terminal/WrappedShell.js.map +1 -0
  69. package/dist/terminal/activityDetector.d.ts +33 -0
  70. package/dist/terminal/activityDetector.d.ts.map +1 -0
  71. package/dist/terminal/activityDetector.js +158 -0
  72. package/dist/terminal/activityDetector.js.map +1 -0
  73. package/package.json +41 -7
  74. package/index.js +0 -2
@@ -0,0 +1,19 @@
1
+ /**
2
+ * File-based storage adapter for CLI
3
+ * Stores data in ~/.config/devclocked/cli.json
4
+ */
5
+ import { StorageAdapter } from '@devclocked/tracker-core';
6
+ export declare class FileStorageAdapter extends StorageAdapter {
7
+ private data;
8
+ private loaded;
9
+ constructor();
10
+ private ensureConfigDir;
11
+ private loadFromDisk;
12
+ private saveToDisk;
13
+ get(key: string): Promise<string | null>;
14
+ set(key: string, value: string): Promise<void>;
15
+ remove(key: string): Promise<void>;
16
+ clear(): Promise<void>;
17
+ keys(): Promise<string[]>;
18
+ }
19
+ //# sourceMappingURL=FileStorageAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileStorageAdapter.d.ts","sourceRoot":"","sources":["../../src/storage/FileStorageAdapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAS1D,qBAAa,kBAAmB,SAAQ,cAAc;IACpD,OAAO,CAAC,IAAI,CAAmB;IAC/B,OAAO,CAAC,MAAM,CAAS;;IAQvB,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,UAAU;IAkBZ,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAKxC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM9C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMlC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAKtB,IAAI,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;CAIhC"}
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ /**
3
+ * File-based storage adapter for CLI
4
+ * Stores data in ~/.config/devclocked/cli.json
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.FileStorageAdapter = void 0;
8
+ const tracker_core_1 = require("@devclocked/tracker-core");
9
+ const fs_1 = require("fs");
10
+ const path_1 = require("path");
11
+ const config_1 = require("../config");
12
+ class FileStorageAdapter extends tracker_core_1.StorageAdapter {
13
+ constructor() {
14
+ super();
15
+ this.data = {};
16
+ this.loaded = false;
17
+ this.ensureConfigDir();
18
+ this.loadFromDisk();
19
+ }
20
+ ensureConfigDir() {
21
+ if (!(0, fs_1.existsSync)(config_1.CONFIG_DIR)) {
22
+ (0, fs_1.mkdirSync)(config_1.CONFIG_DIR, { recursive: true, mode: 0o700 });
23
+ }
24
+ }
25
+ loadFromDisk() {
26
+ if (this.loaded)
27
+ return;
28
+ try {
29
+ if ((0, fs_1.existsSync)(config_1.CONFIG_FILE)) {
30
+ const content = (0, fs_1.readFileSync)(config_1.CONFIG_FILE, 'utf-8');
31
+ this.data = JSON.parse(content);
32
+ }
33
+ }
34
+ catch (error) {
35
+ // Start fresh if file is corrupted
36
+ this.data = {};
37
+ }
38
+ this.loaded = true;
39
+ }
40
+ saveToDisk() {
41
+ try {
42
+ const dir = (0, path_1.dirname)(config_1.CONFIG_FILE);
43
+ if (!(0, fs_1.existsSync)(dir)) {
44
+ (0, fs_1.mkdirSync)(dir, { recursive: true, mode: 0o700 });
45
+ }
46
+ (0, fs_1.writeFileSync)(config_1.CONFIG_FILE, JSON.stringify(this.data, null, 2), {
47
+ mode: 0o600, // User-only read/write
48
+ });
49
+ // Ensure permissions are correct
50
+ (0, fs_1.chmodSync)(config_1.CONFIG_FILE, 0o600);
51
+ }
52
+ catch (error) {
53
+ console.error('Failed to save config:', error);
54
+ }
55
+ }
56
+ async get(key) {
57
+ this.loadFromDisk();
58
+ return this.data[key] ?? null;
59
+ }
60
+ async set(key, value) {
61
+ this.loadFromDisk();
62
+ this.data[key] = value;
63
+ this.saveToDisk();
64
+ }
65
+ async remove(key) {
66
+ this.loadFromDisk();
67
+ delete this.data[key];
68
+ this.saveToDisk();
69
+ }
70
+ async clear() {
71
+ this.data = {};
72
+ this.saveToDisk();
73
+ }
74
+ async keys() {
75
+ this.loadFromDisk();
76
+ return Object.keys(this.data);
77
+ }
78
+ }
79
+ exports.FileStorageAdapter = FileStorageAdapter;
80
+ //# sourceMappingURL=FileStorageAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileStorageAdapter.js","sourceRoot":"","sources":["../../src/storage/FileStorageAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Wrapped Shell - PTY wrapper for terminal activity detection
3
+ *
4
+ * Privacy guarantees:
5
+ * - Commands are NOT logged
6
+ * - Output is NOT stored
7
+ * - Only timestamps and cwd are tracked
8
+ */
9
+ export type ActivityCallback = (cwd: string) => void;
10
+ export type ExitCallback = (code: number) => void;
11
+ export declare class WrappedShell {
12
+ private ptyProcess;
13
+ private cwd;
14
+ private shell;
15
+ private activityCallback;
16
+ private exitCallback;
17
+ constructor(cwd: string, activityCallback: ActivityCallback, exitCallback: ExitCallback);
18
+ private detectShell;
19
+ getShell(): string;
20
+ spawn(): void;
21
+ private cleanup;
22
+ destroy(): void;
23
+ }
24
+ //# sourceMappingURL=WrappedShell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WrappedShell.d.ts","sourceRoot":"","sources":["../../src/terminal/WrappedShell.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,MAAM,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;AACrD,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;AAElD,qBAAa,YAAY;IACvB,OAAO,CAAC,UAAU,CAAyB;IAC3C,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,YAAY,CAAe;gBAGjC,GAAG,EAAE,MAAM,EACX,gBAAgB,EAAE,gBAAgB,EAClC,YAAY,EAAE,YAAY;IAQ5B,OAAO,CAAC,WAAW;IAWnB,QAAQ,IAAI,MAAM;IAIlB,KAAK,IAAI,IAAI;IAiDb,OAAO,CAAC,OAAO;IAOf,OAAO,IAAI,IAAI;CAOhB"}
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ /**
3
+ * Wrapped Shell - PTY wrapper for terminal activity detection
4
+ *
5
+ * Privacy guarantees:
6
+ * - Commands are NOT logged
7
+ * - Output is NOT stored
8
+ * - Only timestamps and cwd are tracked
9
+ */
10
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ var desc = Object.getOwnPropertyDescriptor(m, k);
13
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
14
+ desc = { enumerable: true, get: function() { return m[k]; } };
15
+ }
16
+ Object.defineProperty(o, k2, desc);
17
+ }) : (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ o[k2] = m[k];
20
+ }));
21
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
22
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
23
+ }) : function(o, v) {
24
+ o["default"] = v;
25
+ });
26
+ var __importStar = (this && this.__importStar) || (function () {
27
+ var ownKeys = function(o) {
28
+ ownKeys = Object.getOwnPropertyNames || function (o) {
29
+ var ar = [];
30
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
31
+ return ar;
32
+ };
33
+ return ownKeys(o);
34
+ };
35
+ return function (mod) {
36
+ if (mod && mod.__esModule) return mod;
37
+ var result = {};
38
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
39
+ __setModuleDefault(result, mod);
40
+ return result;
41
+ };
42
+ })();
43
+ Object.defineProperty(exports, "__esModule", { value: true });
44
+ exports.WrappedShell = void 0;
45
+ const pty = __importStar(require("node-pty"));
46
+ const os_1 = require("os");
47
+ class WrappedShell {
48
+ constructor(cwd, activityCallback, exitCallback) {
49
+ this.ptyProcess = null;
50
+ this.cwd = cwd;
51
+ this.activityCallback = activityCallback;
52
+ this.exitCallback = exitCallback;
53
+ this.shell = this.detectShell();
54
+ }
55
+ detectShell() {
56
+ const shellEnv = process.env.SHELL;
57
+ if (shellEnv)
58
+ return shellEnv;
59
+ if ((0, os_1.platform)() === 'win32') {
60
+ return process.env.COMSPEC || 'cmd.exe';
61
+ }
62
+ return '/bin/sh';
63
+ }
64
+ getShell() {
65
+ return this.shell;
66
+ }
67
+ spawn() {
68
+ const isWindows = (0, os_1.platform)() === 'win32';
69
+ this.ptyProcess = pty.spawn(this.shell, [], {
70
+ name: 'xterm-256color',
71
+ cols: process.stdout.columns || 80,
72
+ rows: process.stdout.rows || 24,
73
+ cwd: this.cwd,
74
+ env: process.env,
75
+ useConpty: isWindows,
76
+ });
77
+ // Pipe PTY output to stdout (transparent)
78
+ this.ptyProcess.onData((data) => {
79
+ process.stdout.write(data);
80
+ });
81
+ // Pipe stdin to PTY
82
+ if (process.stdin.isTTY) {
83
+ process.stdin.setRawMode(true);
84
+ }
85
+ process.stdin.resume();
86
+ process.stdin.setEncoding('utf8');
87
+ process.stdin.on('data', (data) => {
88
+ if (this.ptyProcess) {
89
+ this.ptyProcess.write(data.toString());
90
+ // Signal activity on input (NOT logging the content)
91
+ this.activityCallback(this.cwd);
92
+ }
93
+ });
94
+ // Handle terminal resize
95
+ process.stdout.on('resize', () => {
96
+ if (this.ptyProcess) {
97
+ this.ptyProcess.resize(process.stdout.columns || 80, process.stdout.rows || 24);
98
+ }
99
+ });
100
+ // Handle shell exit
101
+ this.ptyProcess.onExit(({ exitCode }) => {
102
+ this.cleanup();
103
+ this.exitCallback(exitCode);
104
+ });
105
+ }
106
+ cleanup() {
107
+ if (process.stdin.isTTY) {
108
+ process.stdin.setRawMode(false);
109
+ }
110
+ process.stdin.pause();
111
+ }
112
+ destroy() {
113
+ this.cleanup();
114
+ if (this.ptyProcess) {
115
+ this.ptyProcess.kill();
116
+ this.ptyProcess = null;
117
+ }
118
+ }
119
+ }
120
+ exports.WrappedShell = WrappedShell;
121
+ //# sourceMappingURL=WrappedShell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WrappedShell.js","sourceRoot":"","sources":["../../src/terminal/WrappedShell.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Activity Detector - Debounces activity and detects git repo context
3
+ *
4
+ * Privacy guarantees:
5
+ * - Only tracks timestamps and cwd
6
+ * - No command or output logging
7
+ */
8
+ import { TrackerClient } from '@devclocked/tracker-core';
9
+ export interface RepoContext {
10
+ repoUrl?: string;
11
+ repoFullName?: string;
12
+ branch?: string;
13
+ }
14
+ export declare class ActivityDetector {
15
+ private lastTickAt;
16
+ private lastActivityAt;
17
+ private idleTimer;
18
+ private client;
19
+ private shell;
20
+ private onIdle;
21
+ private cachedRepo;
22
+ constructor(client: TrackerClient, shell: string, onIdle: () => void);
23
+ onActivity(cwd: string): void;
24
+ private resetIdleTimer;
25
+ private emitTick;
26
+ private detectGitRepo;
27
+ private findGitDir;
28
+ private normalizeRepoUrl;
29
+ private extractRepoFullName;
30
+ getLastActivityAt(): number;
31
+ destroy(): void;
32
+ }
33
+ //# sourceMappingURL=activityDetector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activityDetector.d.ts","sourceRoot":"","sources":["../../src/terminal/activityDetector.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAMzD,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,UAAU,CAAsD;gBAGtE,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,IAAI;IAOpB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAgB7B,OAAO,CAAC,cAAc;YAUR,QAAQ;IActB,OAAO,CAAC,aAAa;IAsDrB,OAAO,CAAC,UAAU;IAclB,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,mBAAmB;IA2B3B,iBAAiB,IAAI,MAAM;IAI3B,OAAO,IAAI,IAAI;CAMhB"}
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+ /**
3
+ * Activity Detector - Debounces activity and detects git repo context
4
+ *
5
+ * Privacy guarantees:
6
+ * - Only tracks timestamps and cwd
7
+ * - No command or output logging
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.ActivityDetector = void 0;
11
+ const child_process_1 = require("child_process");
12
+ const fs_1 = require("fs");
13
+ const path_1 = require("path");
14
+ const config_1 = require("../config");
15
+ class ActivityDetector {
16
+ constructor(client, shell, onIdle) {
17
+ this.lastTickAt = 0;
18
+ this.lastActivityAt = 0;
19
+ this.idleTimer = null;
20
+ this.cachedRepo = null;
21
+ this.client = client;
22
+ this.shell = shell;
23
+ this.onIdle = onIdle;
24
+ }
25
+ onActivity(cwd) {
26
+ const now = Date.now();
27
+ this.lastActivityAt = now;
28
+ // Reset idle timer
29
+ this.resetIdleTimer();
30
+ // Debounce ticks
31
+ if (now - this.lastTickAt < config_1.TICK_INTERVAL_MS) {
32
+ return;
33
+ }
34
+ this.lastTickAt = now;
35
+ this.emitTick(cwd);
36
+ }
37
+ resetIdleTimer() {
38
+ if (this.idleTimer) {
39
+ clearTimeout(this.idleTimer);
40
+ }
41
+ this.idleTimer = setTimeout(() => {
42
+ this.onIdle();
43
+ }, config_1.IDLE_TIMEOUT_MS);
44
+ }
45
+ async emitTick(cwd) {
46
+ const repoContext = this.detectGitRepo(cwd);
47
+ try {
48
+ await this.client.sendTick('terminal', 'window', {
49
+ repo_url: repoContext.repoUrl,
50
+ branch: repoContext.branch,
51
+ repository_full_name: repoContext.repoFullName,
52
+ });
53
+ }
54
+ catch (error) {
55
+ // Queue will retry
56
+ }
57
+ }
58
+ detectGitRepo(cwd) {
59
+ // Use cache if same cwd
60
+ if (this.cachedRepo && this.cachedRepo.cwd === cwd) {
61
+ return this.cachedRepo.context;
62
+ }
63
+ const context = {};
64
+ try {
65
+ // Find git root
66
+ const gitDir = this.findGitDir(cwd);
67
+ if (!gitDir) {
68
+ this.cachedRepo = { cwd, context };
69
+ return context;
70
+ }
71
+ // Get remote URL
72
+ try {
73
+ const remoteUrl = (0, child_process_1.execSync)('git config --get remote.origin.url', {
74
+ cwd,
75
+ encoding: 'utf-8',
76
+ stdio: ['pipe', 'pipe', 'pipe'],
77
+ }).trim();
78
+ if (remoteUrl) {
79
+ context.repoUrl = this.normalizeRepoUrl(remoteUrl);
80
+ context.repoFullName = this.extractRepoFullName(remoteUrl);
81
+ }
82
+ }
83
+ catch {
84
+ // No remote
85
+ }
86
+ // Get current branch
87
+ try {
88
+ const branch = (0, child_process_1.execSync)('git rev-parse --abbrev-ref HEAD', {
89
+ cwd,
90
+ encoding: 'utf-8',
91
+ stdio: ['pipe', 'pipe', 'pipe'],
92
+ }).trim();
93
+ if (branch && branch !== 'HEAD') {
94
+ context.branch = branch;
95
+ }
96
+ }
97
+ catch {
98
+ // Not in git repo or detached HEAD
99
+ }
100
+ }
101
+ catch {
102
+ // Git not available
103
+ }
104
+ this.cachedRepo = { cwd, context };
105
+ return context;
106
+ }
107
+ findGitDir(startPath) {
108
+ let current = startPath;
109
+ while (current !== (0, path_1.dirname)(current)) {
110
+ const gitPath = (0, path_1.join)(current, '.git');
111
+ if ((0, fs_1.existsSync)(gitPath)) {
112
+ return gitPath;
113
+ }
114
+ current = (0, path_1.dirname)(current);
115
+ }
116
+ return null;
117
+ }
118
+ normalizeRepoUrl(url) {
119
+ // git@github.com:owner/repo.git -> https://github.com/owner/repo
120
+ let normalized = url
121
+ .replace(/^git@([^:]+):(.+)\.git$/, 'https://$1/$2')
122
+ .replace(/\.git$/, '');
123
+ return normalized;
124
+ }
125
+ extractRepoFullName(url) {
126
+ // Extract owner/repo from various URL formats
127
+ let path = '';
128
+ // SSH format: git@github.com:owner/repo.git
129
+ const sshMatch = /^git@[^:]+:(.+?)(?:\.git)?$/.exec(url);
130
+ if (sshMatch) {
131
+ path = sshMatch[1];
132
+ }
133
+ // HTTPS format: https://github.com/owner/repo.git
134
+ const httpsMatch = /^https?:\/\/[^/]+\/(.+?)(?:\.git)?$/.exec(url);
135
+ if (httpsMatch) {
136
+ path = httpsMatch[1];
137
+ }
138
+ if (!path)
139
+ return undefined;
140
+ // Return owner/repo format
141
+ const parts = path.split('/');
142
+ if (parts.length >= 2) {
143
+ return `${parts[0]}/${parts[1]}`.toLowerCase();
144
+ }
145
+ return undefined;
146
+ }
147
+ getLastActivityAt() {
148
+ return this.lastActivityAt;
149
+ }
150
+ destroy() {
151
+ if (this.idleTimer) {
152
+ clearTimeout(this.idleTimer);
153
+ this.idleTimer = null;
154
+ }
155
+ }
156
+ }
157
+ exports.ActivityDetector = ActivityDetector;
158
+ //# sourceMappingURL=activityDetector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activityDetector.js","sourceRoot":"","sources":["../../src/terminal/activityDetector.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,17 +1,51 @@
1
1
  {
2
2
  "name": "devclocked",
3
- "version": "2.1.1",
4
- "description": "DevClocked AI coding time tracker. Tracks your development activity in Claude Code, VS Code, and more.",
3
+ "version": "2.1.2",
4
+ "description": "DevClocked CLI - Terminal time tracking for developers",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
5
7
  "bin": {
6
- "devclocked": "./index.js"
8
+ "devclocked": "./dist/index.js"
7
9
  },
8
- "dependencies": {
9
- "@devclocked/cli": "^2.1.1"
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "tsc --watch",
13
+ "clean": "rm -rf dist",
14
+ "lint": "eslint src --ext ts",
15
+ "start": "node dist/index.js"
10
16
  },
11
- "keywords": ["devclocked", "time-tracking", "developer-tools", "claude-code", "mcp"],
17
+ "keywords": [
18
+ "devclocked",
19
+ "time-tracking",
20
+ "cli",
21
+ "terminal",
22
+ "developer-tools",
23
+ "productivity"
24
+ ],
25
+ "author": "DevClocked",
12
26
  "license": "MIT",
13
27
  "repository": {
14
28
  "type": "git",
15
- "url": "https://github.com/devclocked/trackers"
29
+ "url": "https://github.com/devclocked/trackers.git",
30
+ "directory": "packages/cli"
31
+ },
32
+ "homepage": "https://devclocked.com",
33
+ "bugs": {
34
+ "url": "https://github.com/devclocked/trackers/issues"
35
+ },
36
+ "dependencies": {
37
+ "@devclocked/tracker-core": "^2.1.0",
38
+ "@modelcontextprotocol/sdk": "^1.12.1",
39
+ "chalk": "^5.3.0",
40
+ "commander": "^11.1.0",
41
+ "node-pty": "^1.0.0",
42
+ "open": "^10.0.0"
43
+ },
44
+ "devDependencies": {
45
+ "@types/node": "^20.0.0",
46
+ "typescript": "^5.0.0"
47
+ },
48
+ "engines": {
49
+ "node": ">=18.0.0"
16
50
  }
17
51
  }
package/index.js DELETED
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- require('@devclocked/cli');