@northflare/runner 0.0.1

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 (154) hide show
  1. package/DEBUG_LOGGING.md +60 -0
  2. package/LICENSE +21 -0
  3. package/MIGRATION_PLAN.md +52 -0
  4. package/README.md +220 -0
  5. package/SDK_IMPLEMENTATION_GUIDE.md +1036 -0
  6. package/bin/northflare-runner +367 -0
  7. package/coverage/base.css +224 -0
  8. package/coverage/block-navigation.js +87 -0
  9. package/coverage/coverage-final.json +12 -0
  10. package/coverage/favicon.png +0 -0
  11. package/coverage/index.html +176 -0
  12. package/coverage/lib/index.html +116 -0
  13. package/coverage/lib/preload-script.js.html +964 -0
  14. package/coverage/prettify.css +1 -0
  15. package/coverage/prettify.js +2 -0
  16. package/coverage/sort-arrow-sprite.png +0 -0
  17. package/coverage/sorter.js +196 -0
  18. package/coverage/src/collections/index.html +116 -0
  19. package/coverage/src/collections/runner-messages.ts.html +312 -0
  20. package/coverage/src/components/claude-manager.ts.html +1290 -0
  21. package/coverage/src/components/index.html +146 -0
  22. package/coverage/src/components/message-handler.ts.html +730 -0
  23. package/coverage/src/components/repository-manager.ts.html +841 -0
  24. package/coverage/src/index.html +131 -0
  25. package/coverage/src/index.ts.html +448 -0
  26. package/coverage/src/runner.ts.html +1239 -0
  27. package/coverage/src/utils/config.ts.html +780 -0
  28. package/coverage/src/utils/console.ts.html +121 -0
  29. package/coverage/src/utils/index.html +161 -0
  30. package/coverage/src/utils/logger.ts.html +475 -0
  31. package/coverage/src/utils/status-line.ts.html +445 -0
  32. package/dist/collections/runner-messages.d.ts +52 -0
  33. package/dist/collections/runner-messages.d.ts.map +1 -0
  34. package/dist/collections/runner-messages.js +161 -0
  35. package/dist/collections/runner-messages.js.map +1 -0
  36. package/dist/components/claude-manager.d.ts +39 -0
  37. package/dist/components/claude-manager.d.ts.map +1 -0
  38. package/dist/components/claude-manager.js +783 -0
  39. package/dist/components/claude-manager.js.map +1 -0
  40. package/dist/components/claude-sdk-manager.d.ts +47 -0
  41. package/dist/components/claude-sdk-manager.d.ts.map +1 -0
  42. package/dist/components/claude-sdk-manager.js +1088 -0
  43. package/dist/components/claude-sdk-manager.js.map +1 -0
  44. package/dist/components/enhanced-repository-manager.d.ts +134 -0
  45. package/dist/components/enhanced-repository-manager.d.ts.map +1 -0
  46. package/dist/components/enhanced-repository-manager.js +602 -0
  47. package/dist/components/enhanced-repository-manager.js.map +1 -0
  48. package/dist/components/message-handler-sse.d.ts +46 -0
  49. package/dist/components/message-handler-sse.d.ts.map +1 -0
  50. package/dist/components/message-handler-sse.js +734 -0
  51. package/dist/components/message-handler-sse.js.map +1 -0
  52. package/dist/components/message-handler.d.ts +35 -0
  53. package/dist/components/message-handler.d.ts.map +1 -0
  54. package/dist/components/message-handler.js +689 -0
  55. package/dist/components/message-handler.js.map +1 -0
  56. package/dist/components/repository-manager.d.ts +51 -0
  57. package/dist/components/repository-manager.d.ts.map +1 -0
  58. package/dist/components/repository-manager.js +295 -0
  59. package/dist/components/repository-manager.js.map +1 -0
  60. package/dist/index.d.ts +9 -0
  61. package/dist/index.d.ts.map +1 -0
  62. package/dist/index.js +166 -0
  63. package/dist/index.js.map +1 -0
  64. package/dist/runner-sse.d.ts +57 -0
  65. package/dist/runner-sse.d.ts.map +1 -0
  66. package/dist/runner-sse.js +698 -0
  67. package/dist/runner-sse.js.map +1 -0
  68. package/dist/runner.d.ts +51 -0
  69. package/dist/runner.d.ts.map +1 -0
  70. package/dist/runner.js +530 -0
  71. package/dist/runner.js.map +1 -0
  72. package/dist/services/RunnerAPIClient.d.ts +30 -0
  73. package/dist/services/RunnerAPIClient.d.ts.map +1 -0
  74. package/dist/services/RunnerAPIClient.js +112 -0
  75. package/dist/services/RunnerAPIClient.js.map +1 -0
  76. package/dist/services/SSEClient.d.ts +60 -0
  77. package/dist/services/SSEClient.d.ts.map +1 -0
  78. package/dist/services/SSEClient.js +204 -0
  79. package/dist/services/SSEClient.js.map +1 -0
  80. package/dist/types/claude.d.ts +45 -0
  81. package/dist/types/claude.d.ts.map +1 -0
  82. package/dist/types/claude.js +6 -0
  83. package/dist/types/claude.js.map +1 -0
  84. package/dist/types/index.d.ts +47 -0
  85. package/dist/types/index.d.ts.map +1 -0
  86. package/dist/types/index.js +23 -0
  87. package/dist/types/index.js.map +1 -0
  88. package/dist/types/messages.d.ts +31 -0
  89. package/dist/types/messages.d.ts.map +1 -0
  90. package/dist/types/messages.js +6 -0
  91. package/dist/types/messages.js.map +1 -0
  92. package/dist/types/runner-interface.d.ts +24 -0
  93. package/dist/types/runner-interface.d.ts.map +1 -0
  94. package/dist/types/runner-interface.js +6 -0
  95. package/dist/types/runner-interface.js.map +1 -0
  96. package/dist/utils/StateManager.d.ts +52 -0
  97. package/dist/utils/StateManager.d.ts.map +1 -0
  98. package/dist/utils/StateManager.js +162 -0
  99. package/dist/utils/StateManager.js.map +1 -0
  100. package/dist/utils/config.d.ts +41 -0
  101. package/dist/utils/config.d.ts.map +1 -0
  102. package/dist/utils/config.js +250 -0
  103. package/dist/utils/config.js.map +1 -0
  104. package/dist/utils/console.d.ts +11 -0
  105. package/dist/utils/console.d.ts.map +1 -0
  106. package/dist/utils/console.js +15 -0
  107. package/dist/utils/console.js.map +1 -0
  108. package/dist/utils/expand-env.d.ts +2 -0
  109. package/dist/utils/expand-env.d.ts.map +1 -0
  110. package/dist/utils/expand-env.js +20 -0
  111. package/dist/utils/expand-env.js.map +1 -0
  112. package/dist/utils/logger.d.ts +9 -0
  113. package/dist/utils/logger.d.ts.map +1 -0
  114. package/dist/utils/logger.js +108 -0
  115. package/dist/utils/logger.js.map +1 -0
  116. package/dist/utils/status-line.d.ts +37 -0
  117. package/dist/utils/status-line.d.ts.map +1 -0
  118. package/dist/utils/status-line.js +113 -0
  119. package/dist/utils/status-line.js.map +1 -0
  120. package/docs/claude-manager.md +91 -0
  121. package/exceptions.log +22 -0
  122. package/lib/preload-script.js +293 -0
  123. package/package.json +55 -0
  124. package/rejections.log +63 -0
  125. package/runner.log +488 -0
  126. package/src/components/claude-sdk-manager.ts +1354 -0
  127. package/src/components/enhanced-repository-manager.ts +823 -0
  128. package/src/components/message-handler-sse.ts +1011 -0
  129. package/src/components/repository-manager.ts +337 -0
  130. package/src/index.ts +166 -0
  131. package/src/runner-sse.ts +847 -0
  132. package/src/services/RunnerAPIClient.ts +135 -0
  133. package/src/services/SSEClient.ts +258 -0
  134. package/src/types/claude.ts +55 -0
  135. package/src/types/computer-name.d.ts +4 -0
  136. package/src/types/index.ts +63 -0
  137. package/src/types/messages.ts +39 -0
  138. package/src/types/runner-interface.ts +34 -0
  139. package/src/utils/StateManager.ts +187 -0
  140. package/src/utils/codex-sdk.js +448 -0
  141. package/src/utils/config.ts +315 -0
  142. package/src/utils/console.ts +13 -0
  143. package/src/utils/expand-env.ts +22 -0
  144. package/src/utils/logger.ts +131 -0
  145. package/src/utils/sdk-demo.js +34 -0
  146. package/src/utils/status-line.ts +121 -0
  147. package/test-debug.sh +26 -0
  148. package/tests/retry-strategies.test.ts +410 -0
  149. package/tests/sdk-integration.test.ts +329 -0
  150. package/tests/sdk-streaming.test.ts +1180 -0
  151. package/tests/setup.ts +5 -0
  152. package/tests/test-claude-manager.ts +120 -0
  153. package/tsconfig.json +36 -0
  154. package/vitest.config.ts +27 -0
@@ -0,0 +1,293 @@
1
+ // Check if logging is enabled via environment variable
2
+ const loggingEnabled =
3
+ process.env.DEBUG_PRELOAD_SCRIPT === "1" ||
4
+ process.env.DEBUG_PRELOAD_SCRIPT === "true";
5
+
6
+ // Patch child_process to prevent security commands
7
+ const childProcess = require("child_process");
8
+ const fs = require("fs");
9
+ const path = require("path");
10
+ const os = require("os");
11
+
12
+ const originalExecSync = childProcess.execSync;
13
+
14
+ function logToFile(...args) {
15
+ try {
16
+ const logFilePath = path.join(os.homedir(), ".preload-script.log");
17
+ const timestamp = new Date().toISOString();
18
+ const message = args
19
+ .map((arg) => {
20
+ if (typeof arg === "string") return arg;
21
+ try {
22
+ return JSON.stringify(arg, null, 2);
23
+ } catch {
24
+ return String(arg);
25
+ }
26
+ })
27
+ .join(" ");
28
+ fs.appendFileSync(logFilePath, `[${timestamp}] ${message}\n`);
29
+ } catch (err) {
30
+ // Fallback: do nothing if logging fails
31
+ }
32
+ }
33
+
34
+ // Patch console.log and console.error to use logToFile
35
+ //console.log = (...args) => logToFile(...args);
36
+ //console.error = (...args) => logToFile("ERROR:", ...args);
37
+
38
+ // === macOS Security Commands Patching ===
39
+ childProcess.execSync = function (command, options) {
40
+ // Check if command starts with "security "
41
+ if (
42
+ typeof command === "string" &&
43
+ command.trim().startsWith("security find-generic-password ")
44
+ ) {
45
+ if (loggingEnabled) {
46
+ console.log("šŸ”€ Intercepted execSync call:", command);
47
+ }
48
+
49
+ // Check if CLAUDE_CREDENTIALS is set
50
+ const credentials = process.env.CLAUDE_CREDENTIALS;
51
+ if (credentials) {
52
+ if (loggingEnabled) {
53
+ console.log("šŸ” Reading credentials from CLAUDE_CREDENTIALS env var");
54
+ }
55
+ // Return credentials directly as buffer
56
+ return Buffer.from(credentials);
57
+ } else {
58
+ if (loggingEnabled) {
59
+ console.log("āš ļø CLAUDE_CREDENTIALS not set, returning empty buffer");
60
+ }
61
+ // Return empty buffer to mimic successful execution
62
+ return Buffer.from("");
63
+ }
64
+ }
65
+
66
+ // Check if command starts with "security "
67
+ if (typeof command === "string" && command.trim().startsWith("security ")) {
68
+ if (loggingEnabled) {
69
+ console.log("🚫 Blocked execSync call:", command);
70
+ }
71
+ // Return empty buffer to mimic successful execution
72
+ return Buffer.from("");
73
+ }
74
+
75
+ if (loggingEnabled) {
76
+ console.log("šŸ”§ Allowed execSync call:", command);
77
+ }
78
+
79
+ return originalExecSync.apply(this, arguments);
80
+ };
81
+
82
+ // === macOS Security Commands Patching ===
83
+ const originalSpawnSync = childProcess.spawnSync;
84
+
85
+ // Helper function to create spawnSync return format
86
+ function createSpawnSyncResult(stdout = "", stderr = "", status = 0) {
87
+ return {
88
+ pid: 0,
89
+ output: [null, stdout, stderr],
90
+ stdout: stdout,
91
+ stderr: stderr,
92
+ status: status,
93
+ signal: null,
94
+ error: null,
95
+ };
96
+ }
97
+
98
+ childProcess.spawnSync = function (command) {
99
+ // Check if command starts with "security "
100
+ if (
101
+ typeof command === "string" &&
102
+ command.trim().startsWith("security find-generic-password ")
103
+ ) {
104
+ if (loggingEnabled) {
105
+ console.log("šŸ”€ Intercepted spawnSync call:", command);
106
+ }
107
+
108
+ // Check if CLAUDE_CREDENTIALS is set
109
+ const credentials = process.env.CLAUDE_CREDENTIALS;
110
+ if (credentials) {
111
+ if (loggingEnabled) {
112
+ console.log("šŸ” Reading credentials from CLAUDE_CREDENTIALS env var");
113
+ }
114
+ // Return credentials directly in spawnSync format
115
+ return createSpawnSyncResult(credentials);
116
+ } else {
117
+ if (loggingEnabled) {
118
+ console.log("āš ļø CLAUDE_CREDENTIALS not set, returning empty result");
119
+ }
120
+ // Return empty result to mimic successful execution
121
+ return createSpawnSyncResult();
122
+ }
123
+ }
124
+
125
+ // Check if command starts with "security "
126
+ if (typeof command === "string" && command.trim().startsWith("security ")) {
127
+ if (loggingEnabled) {
128
+ console.log("🚫 Blocked spawnSync call:", command);
129
+ }
130
+ // Return empty result to mimic successful execution
131
+ return createSpawnSyncResult();
132
+ }
133
+
134
+ if (loggingEnabled) {
135
+ console.log("šŸ”§ Allowed spawnSync call:", command);
136
+ }
137
+
138
+ return originalSpawnSync.apply(this, arguments);
139
+ };
140
+
141
+ // === Windows/Linux Credential File Support ===
142
+ if (process.platform !== "darwin") {
143
+ const originalExistsSync = fs.existsSync;
144
+ const originalReadFileSync = fs.readFileSync;
145
+ const originalWriteFileSync = fs.writeFileSync;
146
+ const originalUnlinkSync = fs.unlinkSync;
147
+ const originalChmodSync = fs.chmodSync;
148
+
149
+ // Hook fs.existsSync to handle credential files
150
+ fs.existsSync = function (filePath) {
151
+ if (
152
+ typeof filePath === "string" &&
153
+ filePath.endsWith(".credentials.json")
154
+ ) {
155
+ if (loggingEnabled) {
156
+ console.log("āœ… Mocking existsSync for credentials file:", filePath);
157
+ }
158
+ return true;
159
+ }
160
+
161
+ return originalExistsSync.apply(this, arguments);
162
+ };
163
+
164
+ // Hook fs.readFileSync to handle credential files
165
+ fs.readFileSync = function (filePath, options) {
166
+ if (
167
+ typeof filePath === "string" &&
168
+ filePath.endsWith(".credentials.json")
169
+ ) {
170
+ if (loggingEnabled) {
171
+ console.log(
172
+ "šŸ”€ Intercepted readFileSync for credentials file:",
173
+ filePath
174
+ );
175
+ }
176
+
177
+ // Check if CLAUDE_CREDENTIALS is set
178
+ const credentialsData = process.env.CLAUDE_CREDENTIALS;
179
+ if (credentialsData) {
180
+ try {
181
+ if (loggingEnabled) {
182
+ console.log(
183
+ "šŸ” Reading credentials from CLAUDE_CREDENTIALS env var"
184
+ );
185
+ }
186
+ // Parse credentials as JSON
187
+ const credentials = JSON.parse(credentialsData);
188
+
189
+ // Replace refreshToken with empty string
190
+ if (
191
+ credentials.claudeAiOauth &&
192
+ credentials.claudeAiOauth.refreshToken
193
+ ) {
194
+ credentials.claudeAiOauth.refreshToken = "";
195
+ if (loggingEnabled) {
196
+ console.log("šŸ” Replaced refreshToken with empty string");
197
+ }
198
+ }
199
+
200
+ // Return as string or buffer depending on options
201
+ const result = JSON.stringify(credentials);
202
+
203
+ // TEMPORARY DEBUG: Log full credentials string being returned
204
+ console.log(
205
+ "šŸ” TEMP DEBUG - Full credentials string being returned:"
206
+ );
207
+ console.log(result);
208
+
209
+ if (
210
+ options &&
211
+ typeof options === "object" &&
212
+ options.encoding === null
213
+ ) {
214
+ return Buffer.from(result);
215
+ }
216
+ return result;
217
+ } catch (error) {
218
+ if (loggingEnabled) {
219
+ console.error(
220
+ "āŒ Error parsing credentials from env var:",
221
+ error.message
222
+ );
223
+ }
224
+ // Fall back to empty string if credentials can't be parsed
225
+ return "";
226
+ }
227
+ } else {
228
+ if (loggingEnabled) {
229
+ console.log("āš ļø CLAUDE_CREDENTIALS not set, returning empty string");
230
+ }
231
+ // Return empty string to mimic file not found
232
+ return "";
233
+ }
234
+ }
235
+
236
+ return originalReadFileSync.apply(this, arguments);
237
+ };
238
+
239
+ // Hook fs.writeFileSync to be a no-op for credential files
240
+ fs.writeFileSync = function (filePath, data, options) {
241
+ if (
242
+ typeof filePath === "string" &&
243
+ filePath.endsWith(".credentials.json")
244
+ ) {
245
+ if (loggingEnabled) {
246
+ console.log("🚫 Blocked writeFileSync for credentials file:", filePath);
247
+ }
248
+ // No-op - do nothing
249
+ return;
250
+ }
251
+
252
+ return originalWriteFileSync.apply(this, arguments);
253
+ };
254
+
255
+ // Hook fs.unlinkSync to be a no-op for credential files
256
+ fs.unlinkSync = function (filePath) {
257
+ if (
258
+ typeof filePath === "string" &&
259
+ filePath.endsWith(".credentials.json")
260
+ ) {
261
+ if (loggingEnabled) {
262
+ console.log("🚫 Blocked unlinkSync for credentials file:", filePath);
263
+ }
264
+ // No-op - do nothing
265
+ return;
266
+ }
267
+
268
+ return originalUnlinkSync.apply(this, arguments);
269
+ };
270
+
271
+ // Hook fs.chmodSync to be a no-op for credential files
272
+ fs.chmodSync = function (filePath, mode) {
273
+ if (
274
+ typeof filePath === "string" &&
275
+ filePath.endsWith(".credentials.json")
276
+ ) {
277
+ if (loggingEnabled) {
278
+ console.log("🚫 Blocked chmodSync for credentials file:", filePath);
279
+ }
280
+ // No-op - do nothing
281
+ return;
282
+ }
283
+
284
+ return originalChmodSync.apply(this, arguments);
285
+ };
286
+ }
287
+
288
+ if (loggingEnabled) {
289
+ console.log(
290
+ "āœ… Preload script loaded with platform support:",
291
+ process.platform
292
+ );
293
+ }
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@northflare/runner",
3
+ "version": "0.0.1",
4
+ "description": "Distributed conversation runner for Northflare",
5
+ "license": "MIT",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "bin": {
9
+ "runner": "./bin/northflare-runner"
10
+ },
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "start": "node dist/index.js",
14
+ "dev": "tsx src/index.ts",
15
+ "test": "vitest run",
16
+ "test:watch": "vitest watch",
17
+ "test:coverage": "vitest run --coverage",
18
+ "lint": "eslint src",
19
+ "prepublishOnly": "npm run build",
20
+ "postbuild": "chmod +x bin/northflare-runner",
21
+ "postinstall": "node -e \"console.log('\\nāœ… Northflare Runner installed successfully!\\n\\nTo start the runner:\\n npx @northflare/runner start\\n\\nFor help:\\n npx @northflare/runner --help\\n')\"",
22
+ "release": "npm publish --access public",
23
+ "release:env": "source .env && npm publish --access public"
24
+ },
25
+ "dependencies": {
26
+ "@anthropic-ai/claude-agent-sdk": "0.1.30",
27
+ "@botanicastudios/claude-code-sdk-ts": "0.2.22-fork",
28
+ "@botanicastudios/mcp-host-rpc": "^0.4.0",
29
+ "@tanstack/react-query": "^5.x.x",
30
+ "@types/jsonwebtoken": "^9.0.10",
31
+ "ajv": "^8.x.x",
32
+ "commander": "^11.x.x",
33
+ "computer-name": "^0.1.0",
34
+ "env-paths": "^3.0.0",
35
+ "eventsource": "^4.0.0",
36
+ "jsonrpc-lite": "^2.2.0",
37
+ "jsonwebtoken": "^9.0.2",
38
+ "simple-git": "^3.x.x",
39
+ "winston": "^3.x.x",
40
+ "zod": "^3.x.x"
41
+ },
42
+ "devDependencies": {
43
+ "@types/eventsource": "^1.1.15",
44
+ "@types/express": "^4.x.x",
45
+ "@types/node": "^20.x.x",
46
+ "@vitest/coverage-v8": "^1.x.x",
47
+ "eslint": "^8.x.x",
48
+ "tsx": "^4.x.x",
49
+ "typescript": "^5.x.x",
50
+ "vitest": "^1.x.x"
51
+ },
52
+ "engines": {
53
+ "node": ">=18.0.0"
54
+ }
55
+ }