episoda 0.2.0

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 (111) hide show
  1. package/dist/commands/auth.d.ts +22 -0
  2. package/dist/commands/auth.d.ts.map +1 -0
  3. package/dist/commands/auth.js +384 -0
  4. package/dist/commands/auth.js.map +1 -0
  5. package/dist/commands/dev.d.ts +20 -0
  6. package/dist/commands/dev.d.ts.map +1 -0
  7. package/dist/commands/dev.js +305 -0
  8. package/dist/commands/dev.js.map +1 -0
  9. package/dist/commands/status.d.ts +9 -0
  10. package/dist/commands/status.d.ts.map +1 -0
  11. package/dist/commands/status.js +75 -0
  12. package/dist/commands/status.js.map +1 -0
  13. package/dist/commands/stop.d.ts +17 -0
  14. package/dist/commands/stop.d.ts.map +1 -0
  15. package/dist/commands/stop.js +81 -0
  16. package/dist/commands/stop.js.map +1 -0
  17. package/dist/core/auth.d.ts +26 -0
  18. package/dist/core/auth.d.ts.map +1 -0
  19. package/dist/core/auth.js +113 -0
  20. package/dist/core/auth.js.map +1 -0
  21. package/dist/core/command-protocol.d.ts +262 -0
  22. package/dist/core/command-protocol.d.ts.map +1 -0
  23. package/dist/core/command-protocol.js +13 -0
  24. package/dist/core/command-protocol.js.map +1 -0
  25. package/dist/core/connection-manager.d.ts +58 -0
  26. package/dist/core/connection-manager.d.ts.map +1 -0
  27. package/dist/core/connection-manager.js +215 -0
  28. package/dist/core/connection-manager.js.map +1 -0
  29. package/dist/core/errors.d.ts +18 -0
  30. package/dist/core/errors.d.ts.map +1 -0
  31. package/dist/core/errors.js +55 -0
  32. package/dist/core/errors.js.map +1 -0
  33. package/dist/core/git-executor.d.ts +157 -0
  34. package/dist/core/git-executor.d.ts.map +1 -0
  35. package/dist/core/git-executor.js +1605 -0
  36. package/dist/core/git-executor.js.map +1 -0
  37. package/dist/core/git-parser.d.ts +40 -0
  38. package/dist/core/git-parser.d.ts.map +1 -0
  39. package/dist/core/git-parser.js +194 -0
  40. package/dist/core/git-parser.js.map +1 -0
  41. package/dist/core/git-validator.d.ts +42 -0
  42. package/dist/core/git-validator.d.ts.map +1 -0
  43. package/dist/core/git-validator.js +102 -0
  44. package/dist/core/git-validator.js.map +1 -0
  45. package/dist/core/index.d.ts +17 -0
  46. package/dist/core/index.d.ts.map +1 -0
  47. package/dist/core/index.js +41 -0
  48. package/dist/core/index.js.map +1 -0
  49. package/dist/core/version.d.ts +9 -0
  50. package/dist/core/version.d.ts.map +1 -0
  51. package/dist/core/version.js +19 -0
  52. package/dist/core/version.js.map +1 -0
  53. package/dist/core/websocket-client.d.ts +122 -0
  54. package/dist/core/websocket-client.d.ts.map +1 -0
  55. package/dist/core/websocket-client.js +438 -0
  56. package/dist/core/websocket-client.js.map +1 -0
  57. package/dist/daemon/daemon-manager.d.ts +71 -0
  58. package/dist/daemon/daemon-manager.d.ts.map +1 -0
  59. package/dist/daemon/daemon-manager.js +289 -0
  60. package/dist/daemon/daemon-manager.js.map +1 -0
  61. package/dist/daemon/daemon-process.d.ts +13 -0
  62. package/dist/daemon/daemon-process.d.ts.map +1 -0
  63. package/dist/daemon/daemon-process.js +608 -0
  64. package/dist/daemon/daemon-process.js.map +1 -0
  65. package/dist/daemon/machine-id.d.ts +36 -0
  66. package/dist/daemon/machine-id.d.ts.map +1 -0
  67. package/dist/daemon/machine-id.js +195 -0
  68. package/dist/daemon/machine-id.js.map +1 -0
  69. package/dist/daemon/project-tracker.d.ts +92 -0
  70. package/dist/daemon/project-tracker.d.ts.map +1 -0
  71. package/dist/daemon/project-tracker.js +259 -0
  72. package/dist/daemon/project-tracker.js.map +1 -0
  73. package/dist/dev-wrapper.d.ts +88 -0
  74. package/dist/dev-wrapper.d.ts.map +1 -0
  75. package/dist/dev-wrapper.js +288 -0
  76. package/dist/dev-wrapper.js.map +1 -0
  77. package/dist/framework-detector.d.ts +29 -0
  78. package/dist/framework-detector.d.ts.map +1 -0
  79. package/dist/framework-detector.js +276 -0
  80. package/dist/framework-detector.js.map +1 -0
  81. package/dist/git-helpers/git-credential-helper.d.ts +29 -0
  82. package/dist/git-helpers/git-credential-helper.d.ts.map +1 -0
  83. package/dist/git-helpers/git-credential-helper.js +349 -0
  84. package/dist/git-helpers/git-credential-helper.js.map +1 -0
  85. package/dist/hooks/post-checkout +296 -0
  86. package/dist/hooks/pre-commit +139 -0
  87. package/dist/index.d.ts +8 -0
  88. package/dist/index.d.ts.map +1 -0
  89. package/dist/index.js +102 -0
  90. package/dist/index.js.map +1 -0
  91. package/dist/ipc/ipc-client.d.ts +95 -0
  92. package/dist/ipc/ipc-client.d.ts.map +1 -0
  93. package/dist/ipc/ipc-client.js +204 -0
  94. package/dist/ipc/ipc-client.js.map +1 -0
  95. package/dist/ipc/ipc-server.d.ts +55 -0
  96. package/dist/ipc/ipc-server.d.ts.map +1 -0
  97. package/dist/ipc/ipc-server.js +177 -0
  98. package/dist/ipc/ipc-server.js.map +1 -0
  99. package/dist/output.d.ts +48 -0
  100. package/dist/output.d.ts.map +1 -0
  101. package/dist/output.js +129 -0
  102. package/dist/output.js.map +1 -0
  103. package/dist/utils/port-check.d.ts +15 -0
  104. package/dist/utils/port-check.d.ts.map +1 -0
  105. package/dist/utils/port-check.js +79 -0
  106. package/dist/utils/port-check.js.map +1 -0
  107. package/dist/utils/update-checker.d.ts +23 -0
  108. package/dist/utils/update-checker.d.ts.map +1 -0
  109. package/dist/utils/update-checker.js +95 -0
  110. package/dist/utils/update-checker.js.map +1 -0
  111. package/package.json +51 -0
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ /**
3
+ * Authentication utilities
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.getConfigDir = getConfigDir;
40
+ exports.getConfigPath = getConfigPath;
41
+ exports.loadConfig = loadConfig;
42
+ exports.saveConfig = saveConfig;
43
+ exports.validateToken = validateToken;
44
+ const fs = __importStar(require("fs"));
45
+ const path = __importStar(require("path"));
46
+ const os = __importStar(require("os"));
47
+ const DEFAULT_CONFIG_FILE = 'config.json';
48
+ /**
49
+ * Get the config directory path
50
+ * Supports EPISODA_CONFIG_DIR env var for running multiple environments
51
+ */
52
+ function getConfigDir() {
53
+ return process.env.EPISODA_CONFIG_DIR || path.join(os.homedir(), '.episoda');
54
+ }
55
+ /**
56
+ * Get the full path to the config file
57
+ */
58
+ function getConfigPath(configPath) {
59
+ if (configPath) {
60
+ return configPath;
61
+ }
62
+ return path.join(getConfigDir(), DEFAULT_CONFIG_FILE);
63
+ }
64
+ /**
65
+ * Ensure the config directory exists
66
+ */
67
+ function ensureConfigDir(configPath) {
68
+ const dir = path.dirname(configPath);
69
+ if (!fs.existsSync(dir)) {
70
+ fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
71
+ }
72
+ }
73
+ /**
74
+ * Load configuration from .episoda/config.json
75
+ */
76
+ async function loadConfig(configPath) {
77
+ const fullPath = getConfigPath(configPath);
78
+ if (!fs.existsSync(fullPath)) {
79
+ return null;
80
+ }
81
+ try {
82
+ const content = fs.readFileSync(fullPath, 'utf8');
83
+ const config = JSON.parse(content);
84
+ return config;
85
+ }
86
+ catch (error) {
87
+ console.error('Error loading config:', error);
88
+ return null;
89
+ }
90
+ }
91
+ /**
92
+ * Save configuration to .episoda/config.json
93
+ */
94
+ async function saveConfig(config, configPath) {
95
+ const fullPath = getConfigPath(configPath);
96
+ ensureConfigDir(fullPath);
97
+ try {
98
+ const content = JSON.stringify(config, null, 2);
99
+ fs.writeFileSync(fullPath, content, { mode: 0o600 });
100
+ }
101
+ catch (error) {
102
+ throw new Error(`Failed to save config: ${error instanceof Error ? error.message : String(error)}`);
103
+ }
104
+ }
105
+ /**
106
+ * Validate an access token
107
+ */
108
+ async function validateToken(token) {
109
+ // For now, just check if token exists and is non-empty
110
+ // In the future, we can make an API call to validate
111
+ return Boolean(token && token.length > 0);
112
+ }
113
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/core/auth.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAaH,oCAEC;AAKD,sCAKC;AAeD,gCAeC;AAKD,gCAUC;AAKD,sCAIC;AA7ED,uCAAwB;AACxB,2CAA4B;AAC5B,uCAAwB;AAGxB,MAAM,mBAAmB,GAAG,aAAa,CAAA;AAEzC;;;GAGG;AACH,SAAgB,YAAY;IAC1B,OAAO,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,UAAU,CAAC,CAAA;AAC9E,CAAC;AAED;;GAEG;AACH,SAAgB,aAAa,CAAC,UAAmB;IAC/C,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,UAAU,CAAA;IACnB,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,mBAAmB,CAAC,CAAA;AACvD,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CAAC,UAAkB;IACzC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;IACpC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IACrD,CAAC;AACH,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,UAAU,CAAC,UAAmB;IAClD,MAAM,QAAQ,GAAG,aAAa,CAAC,UAAU,CAAC,CAAA;IAE1C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAA;IACb,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;QACjD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAkB,CAAA;QACnD,OAAO,MAAM,CAAA;IACf,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,uBAAuB,EAAE,KAAK,CAAC,CAAA;QAC7C,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,UAAU,CAAC,MAAqB,EAAE,UAAmB;IACzE,MAAM,QAAQ,GAAG,aAAa,CAAC,UAAU,CAAC,CAAA;IAC1C,eAAe,CAAC,QAAQ,CAAC,CAAA;IAEzB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;QAC/C,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IACtD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,0BAA0B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;IACrG,CAAC;AACH,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,aAAa,CAAC,KAAa;IAC/C,uDAAuD;IACvD,qDAAqD;IACrD,OAAO,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;AAC3C,CAAC"}
@@ -0,0 +1,262 @@
1
+ /**
2
+ * Command Protocol Types for Episoda Local Development
3
+ *
4
+ * IMPORTANT: These types are LOCKED for Phase 2 concurrent development.
5
+ * DO NOT modify after EP589-1 is complete without coordinating with all agents.
6
+ *
7
+ * These types are interface-agnostic and used by both:
8
+ * - @episoda/cli (current)
9
+ * - @episoda/mcp-local-dev (future)
10
+ */
11
+ /**
12
+ * Git command types supported by GitExecutor
13
+ */
14
+ export type GitCommand = {
15
+ action: 'checkout';
16
+ branch: string;
17
+ create?: boolean;
18
+ } | {
19
+ action: 'create_branch';
20
+ branch: string;
21
+ from?: string;
22
+ } | {
23
+ action: 'commit';
24
+ message: string;
25
+ files?: string[];
26
+ } | {
27
+ action: 'push';
28
+ branch: string;
29
+ setUpstream?: boolean;
30
+ force?: boolean;
31
+ } | {
32
+ action: 'status';
33
+ } | {
34
+ action: 'pull';
35
+ branch?: string;
36
+ } | {
37
+ action: 'delete_branch';
38
+ branch: string;
39
+ force?: boolean;
40
+ } | {
41
+ action: 'branch_exists';
42
+ branch: string;
43
+ } | {
44
+ action: 'branch_has_commits';
45
+ branch: string;
46
+ baseBranch?: string;
47
+ } | {
48
+ action: 'main_branch_check';
49
+ } | {
50
+ action: 'get_commits';
51
+ branch: string;
52
+ limit?: number;
53
+ baseBranch?: string;
54
+ } | {
55
+ action: 'stash';
56
+ operation: 'push' | 'pop' | 'drop' | 'list';
57
+ message?: string;
58
+ includeUntracked?: boolean;
59
+ } | {
60
+ action: 'reset';
61
+ mode: 'soft' | 'mixed' | 'hard';
62
+ target?: string;
63
+ } | {
64
+ action: 'merge';
65
+ branch: string;
66
+ strategy?: 'ours' | 'theirs';
67
+ noEdit?: boolean;
68
+ abort?: boolean;
69
+ } | {
70
+ action: 'cherry_pick';
71
+ sha: string;
72
+ abort?: boolean;
73
+ } | {
74
+ action: 'clean';
75
+ force?: boolean;
76
+ directories?: boolean;
77
+ } | {
78
+ action: 'add';
79
+ files?: string[];
80
+ all?: boolean;
81
+ } | {
82
+ action: 'fetch';
83
+ remote?: string;
84
+ branch?: string;
85
+ } | {
86
+ action: 'move_to_module';
87
+ targetBranch: string;
88
+ commitShas?: string[];
89
+ conflictResolution?: 'ours' | 'theirs';
90
+ } | {
91
+ action: 'discard_main_changes';
92
+ } | {
93
+ action: 'sync_status';
94
+ branch: string;
95
+ } | {
96
+ action: 'sync_main';
97
+ } | {
98
+ action: 'rebase_branch';
99
+ branch: string;
100
+ } | {
101
+ action: 'rebase_abort';
102
+ } | {
103
+ action: 'rebase_continue';
104
+ } | {
105
+ action: 'rebase_status';
106
+ };
107
+ /**
108
+ * Result of executing a git command
109
+ * Returns structured data (not formatted strings) for interface-agnostic use
110
+ */
111
+ export type ExecutionResult = {
112
+ success: boolean;
113
+ output?: string;
114
+ error?: ErrorCode;
115
+ details?: {
116
+ uncommittedFiles?: string[];
117
+ conflictingFiles?: string[];
118
+ exitCode?: number;
119
+ branchName?: string;
120
+ branchExists?: boolean;
121
+ isLocal?: boolean;
122
+ isRemote?: boolean;
123
+ hasCommits?: boolean;
124
+ currentBranch?: string;
125
+ localCommits?: Array<{
126
+ sha: string;
127
+ message: string;
128
+ author: string;
129
+ }>;
130
+ commits?: Array<{
131
+ sha: string;
132
+ message: string;
133
+ authorName: string;
134
+ authorEmail: string;
135
+ date: string;
136
+ isPushed: boolean;
137
+ }>;
138
+ stashList?: Array<{
139
+ index: number;
140
+ message: string;
141
+ }>;
142
+ mergeConflicts?: boolean;
143
+ cherryPickConflicts?: boolean;
144
+ cleanedFiles?: string[];
145
+ stagedFiles?: string[];
146
+ movedToBranch?: string;
147
+ cherryPickedCommits?: string[];
148
+ discardedFiles?: number;
149
+ discardedCommits?: number;
150
+ hasConflicts?: boolean;
151
+ conflictedFiles?: string[];
152
+ commitsBehind?: number;
153
+ commitsAhead?: number;
154
+ isBehind?: boolean;
155
+ isAhead?: boolean;
156
+ needsSync?: boolean;
157
+ inRebase?: boolean;
158
+ rebaseConflicts?: string[];
159
+ };
160
+ };
161
+ /**
162
+ * Standardized error codes for git operations
163
+ * Interfaces can map these to user-friendly messages
164
+ */
165
+ export type ErrorCode = 'GIT_NOT_INSTALLED' | 'NOT_GIT_REPO' | 'MERGE_CONFLICT' | 'REBASE_CONFLICT' | 'UNCOMMITTED_CHANGES' | 'NETWORK_ERROR' | 'AUTH_FAILURE' | 'BRANCH_NOT_FOUND' | 'BRANCH_ALREADY_EXISTS' | 'PUSH_REJECTED' | 'COMMAND_TIMEOUT' | 'UNKNOWN_ERROR';
166
+ /**
167
+ * WebSocket message types for server → CLI communication
168
+ */
169
+ export type ServerMessage = {
170
+ type: 'auth_success';
171
+ userId: string;
172
+ projectId: string;
173
+ workspaceId: string;
174
+ deviceName?: string;
175
+ deviceId?: string;
176
+ flyMachineId?: string;
177
+ } | {
178
+ type: 'command';
179
+ id: string;
180
+ command: GitCommand;
181
+ } | {
182
+ type: 'ping';
183
+ } | {
184
+ type: 'error';
185
+ code: string;
186
+ message: string;
187
+ retryAfter?: number;
188
+ } | {
189
+ type: 'shutdown';
190
+ message: string;
191
+ reason?: 'user_requested' | 'server_restart' | 'deployment';
192
+ };
193
+ /**
194
+ * WebSocket message types for CLI → server communication
195
+ */
196
+ export type ClientMessage = {
197
+ type: 'auth';
198
+ token: string;
199
+ version: string;
200
+ machineId?: string;
201
+ hostname?: string;
202
+ osPlatform?: string;
203
+ osArch?: string;
204
+ daemonPid?: number;
205
+ } | {
206
+ type: 'pong';
207
+ } | {
208
+ type: 'result';
209
+ commandId: string;
210
+ result: ExecutionResult;
211
+ } | {
212
+ type: 'status';
213
+ connected: boolean;
214
+ workingDirectory?: string;
215
+ };
216
+ /**
217
+ * CLI connection status
218
+ */
219
+ export type ConnectionStatus = {
220
+ connected: boolean;
221
+ projectId?: string;
222
+ connectedAt?: Date;
223
+ lastActivity?: Date;
224
+ cliVersion?: string;
225
+ workingDirectory?: string;
226
+ machineId?: string;
227
+ deviceName?: string;
228
+ hostname?: string;
229
+ osPlatform?: string;
230
+ osArch?: string;
231
+ userId?: string;
232
+ lastPingAt?: Date;
233
+ };
234
+ /**
235
+ * Configuration stored in .episoda/config.json
236
+ */
237
+ export type EpisodaConfig = {
238
+ project_id: string;
239
+ user_id: string;
240
+ workspace_id: string;
241
+ access_token: string;
242
+ refresh_token?: string;
243
+ expires_at?: number;
244
+ api_url: string;
245
+ cli_version?: string;
246
+ device_id?: string;
247
+ machine_id?: string;
248
+ project_settings?: {
249
+ local_project_path?: string;
250
+ local_server_url?: string;
251
+ cached_at: number;
252
+ };
253
+ };
254
+ /**
255
+ * Command execution options
256
+ */
257
+ export type ExecutionOptions = {
258
+ timeout?: number;
259
+ cwd?: string;
260
+ githubToken?: string;
261
+ };
262
+ //# sourceMappingURL=command-protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-protocol.d.ts","sourceRoot":"","sources":["../../src/core/command-protocol.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ /**
3
+ * Command Protocol Types for Episoda Local Development
4
+ *
5
+ * IMPORTANT: These types are LOCKED for Phase 2 concurrent development.
6
+ * DO NOT modify after EP589-1 is complete without coordinating with all agents.
7
+ *
8
+ * These types are interface-agnostic and used by both:
9
+ * - @episoda/cli (current)
10
+ * - @episoda/mcp-local-dev (future)
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ //# sourceMappingURL=command-protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-protocol.js","sourceRoot":"","sources":["../../src/core/command-protocol.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Connection Manager for CLI WebSocket tracking (Phase 2)
3
+ *
4
+ * Simpler than the full Git command WebSocket client.
5
+ * Focuses only on maintaining connection status via heartbeats.
6
+ */
7
+ export interface ConnectionConfig {
8
+ apiUrl: string;
9
+ projectId: string;
10
+ userId: string;
11
+ workspaceId: string;
12
+ cliVersion: string;
13
+ workingDirectory: string;
14
+ }
15
+ export declare class ConnectionManager {
16
+ private ws;
17
+ private pingInterval;
18
+ private reconnectTimeout;
19
+ private config;
20
+ private connectionId;
21
+ private isIntentionalClose;
22
+ private reconnectAttempts;
23
+ private maxReconnectAttempts;
24
+ constructor(config: ConnectionConfig);
25
+ /**
26
+ * Connect to the WebSocket server
27
+ */
28
+ connect(): Promise<string>;
29
+ /**
30
+ * Disconnect from the server
31
+ */
32
+ disconnect(): void;
33
+ /**
34
+ * Send a message to the server
35
+ */
36
+ private send;
37
+ /**
38
+ * Start sending heartbeat pings
39
+ */
40
+ private startHeartbeat;
41
+ /**
42
+ * Stop heartbeat
43
+ */
44
+ private stopHeartbeat;
45
+ /**
46
+ * Schedule reconnection with exponential backoff
47
+ */
48
+ private scheduleReconnect;
49
+ /**
50
+ * Clear reconnect timeout
51
+ */
52
+ private clearReconnectTimeout;
53
+ /**
54
+ * Check if connected
55
+ */
56
+ isConnected(): boolean;
57
+ }
58
+ //# sourceMappingURL=connection-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection-manager.d.ts","sourceRoot":"","sources":["../../src/core/connection-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,YAAY,CAA+B;IACnD,OAAO,CAAC,gBAAgB,CAA+B;IACvD,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,oBAAoB,CAAM;gBAEtB,MAAM,EAAE,gBAAgB;IAIpC;;OAEG;IACH,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;IAiF1B;;OAEG;IACH,UAAU,IAAI,IAAI;IAelB;;OAEG;IACH,OAAO,CAAC,IAAI;IAMZ;;OAEG;IACH,OAAO,CAAC,cAAc;IAkBtB;;OAEG;IACH,OAAO,CAAC,aAAa;IAOrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAczB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAO7B;;OAEG;IACH,WAAW,IAAI,OAAO;CAGvB"}
@@ -0,0 +1,215 @@
1
+ "use strict";
2
+ /**
3
+ * Connection Manager for CLI WebSocket tracking (Phase 2)
4
+ *
5
+ * Simpler than the full Git command WebSocket client.
6
+ * Focuses only on maintaining connection status via heartbeats.
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ var __importDefault = (this && this.__importDefault) || function (mod) {
42
+ return (mod && mod.__esModule) ? mod : { "default": mod };
43
+ };
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.ConnectionManager = void 0;
46
+ const ws_1 = __importDefault(require("ws"));
47
+ const os = __importStar(require("os"));
48
+ class ConnectionManager {
49
+ constructor(config) {
50
+ this.ws = null;
51
+ this.pingInterval = null;
52
+ this.reconnectTimeout = null;
53
+ this.connectionId = null;
54
+ this.isIntentionalClose = false;
55
+ this.reconnectAttempts = 0;
56
+ this.maxReconnectAttempts = 10;
57
+ this.config = config;
58
+ }
59
+ /**
60
+ * Connect to the WebSocket server
61
+ */
62
+ connect() {
63
+ return new Promise((resolve, reject) => {
64
+ try {
65
+ // Convert HTTP to WebSocket URL
66
+ const wsUrl = this.config.apiUrl
67
+ .replace('http://', 'ws://')
68
+ .replace('https://', 'wss://');
69
+ const url = `${wsUrl}/api/cli/ws`;
70
+ console.log(`[Connection] Connecting to ${url}`);
71
+ this.ws = new ws_1.default(url);
72
+ this.isIntentionalClose = false;
73
+ this.ws.on('open', () => {
74
+ console.log('[Connection] WebSocket connected');
75
+ this.reconnectAttempts = 0;
76
+ // Send connect message
77
+ this.send({
78
+ type: 'connect',
79
+ projectId: this.config.projectId,
80
+ userId: this.config.userId,
81
+ workspaceId: this.config.workspaceId,
82
+ cliVersion: this.config.cliVersion,
83
+ workingDirectory: this.config.workingDirectory,
84
+ osPlatform: os.platform(),
85
+ osArch: os.arch(),
86
+ });
87
+ });
88
+ this.ws.on('message', (data) => {
89
+ try {
90
+ const message = JSON.parse(data.toString());
91
+ switch (message.type) {
92
+ case 'connected':
93
+ this.connectionId = message.connectionId;
94
+ console.log(`[Connection] Connected with ID: ${this.connectionId}`);
95
+ this.startHeartbeat();
96
+ if (this.connectionId) {
97
+ resolve(this.connectionId);
98
+ }
99
+ else {
100
+ reject(new Error('Connection ID not received from server'));
101
+ }
102
+ break;
103
+ case 'pong':
104
+ // Heartbeat acknowledged
105
+ break;
106
+ case 'error':
107
+ console.error(`[Connection] Server error: ${message.message}`);
108
+ reject(new Error(message.message));
109
+ break;
110
+ }
111
+ }
112
+ catch (error) {
113
+ console.error('[Connection] Failed to parse message:', error);
114
+ }
115
+ });
116
+ this.ws.on('close', (code, reason) => {
117
+ console.log(`[Connection] WebSocket closed: ${code} ${reason.toString()}`);
118
+ this.stopHeartbeat();
119
+ if (!this.isIntentionalClose && this.reconnectAttempts < this.maxReconnectAttempts) {
120
+ this.scheduleReconnect();
121
+ }
122
+ });
123
+ this.ws.on('error', (error) => {
124
+ console.error('[Connection] WebSocket error:', error);
125
+ reject(error);
126
+ });
127
+ }
128
+ catch (error) {
129
+ reject(error);
130
+ }
131
+ });
132
+ }
133
+ /**
134
+ * Disconnect from the server
135
+ */
136
+ disconnect() {
137
+ console.log('[Connection] Disconnecting...');
138
+ this.isIntentionalClose = true;
139
+ this.stopHeartbeat();
140
+ this.clearReconnectTimeout();
141
+ if (this.ws) {
142
+ if (this.ws.readyState === ws_1.default.OPEN) {
143
+ this.send({ type: 'disconnect' });
144
+ }
145
+ this.ws.close();
146
+ this.ws = null;
147
+ }
148
+ }
149
+ /**
150
+ * Send a message to the server
151
+ */
152
+ send(message) {
153
+ if (this.ws?.readyState === ws_1.default.OPEN) {
154
+ this.ws.send(JSON.stringify(message));
155
+ }
156
+ }
157
+ /**
158
+ * Start sending heartbeat pings
159
+ */
160
+ startHeartbeat() {
161
+ this.stopHeartbeat();
162
+ // Send ping every 15 seconds
163
+ this.pingInterval = setInterval(() => {
164
+ this.send({
165
+ type: 'ping',
166
+ timestamp: new Date().toISOString(),
167
+ });
168
+ }, 15000);
169
+ // Send initial ping
170
+ this.send({
171
+ type: 'ping',
172
+ timestamp: new Date().toISOString(),
173
+ });
174
+ }
175
+ /**
176
+ * Stop heartbeat
177
+ */
178
+ stopHeartbeat() {
179
+ if (this.pingInterval) {
180
+ clearInterval(this.pingInterval);
181
+ this.pingInterval = null;
182
+ }
183
+ }
184
+ /**
185
+ * Schedule reconnection with exponential backoff
186
+ */
187
+ scheduleReconnect() {
188
+ this.clearReconnectTimeout();
189
+ const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 30000);
190
+ console.log(`[Connection] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts + 1}/${this.maxReconnectAttempts})`);
191
+ this.reconnectTimeout = setTimeout(() => {
192
+ this.reconnectAttempts++;
193
+ this.connect().catch((error) => {
194
+ console.error('[Connection] Reconnection failed:', error);
195
+ });
196
+ }, delay);
197
+ }
198
+ /**
199
+ * Clear reconnect timeout
200
+ */
201
+ clearReconnectTimeout() {
202
+ if (this.reconnectTimeout) {
203
+ clearTimeout(this.reconnectTimeout);
204
+ this.reconnectTimeout = null;
205
+ }
206
+ }
207
+ /**
208
+ * Check if connected
209
+ */
210
+ isConnected() {
211
+ return this.ws?.readyState === ws_1.default.OPEN && this.connectionId !== null;
212
+ }
213
+ }
214
+ exports.ConnectionManager = ConnectionManager;
215
+ //# sourceMappingURL=connection-manager.js.map