@nocville/npc 0.0.0-stage → 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 (210) hide show
  1. package/README.md +243 -2
  2. package/dist/cjs/cli.js +533 -0
  3. package/dist/cjs/core/api-key.js +69 -0
  4. package/dist/cjs/core/base-npc.js +160 -0
  5. package/dist/cjs/core/config.js +108 -0
  6. package/dist/cjs/core/event-npc.js +14 -0
  7. package/dist/cjs/core/logger.js +39 -0
  8. package/dist/cjs/core/polling-npc.js +65 -0
  9. package/dist/cjs/core/screen.js +28 -0
  10. package/dist/cjs/core/text.js +15 -0
  11. package/dist/cjs/core/thresholds.js +48 -0
  12. package/dist/cjs/core/types.js +10 -0
  13. package/dist/cjs/core/user-config.js +92 -0
  14. package/dist/cjs/doctor.js +130 -0
  15. package/dist/cjs/index.js +90 -0
  16. package/dist/cjs/npcs/agent-common/activity.js +291 -0
  17. package/dist/cjs/npcs/agent-common/git-stats.js +71 -0
  18. package/dist/cjs/npcs/agent-common/hook-runner.js +252 -0
  19. package/dist/cjs/npcs/agent-common/hook-settings.js +279 -0
  20. package/dist/cjs/npcs/agent-common/liveness.js +112 -0
  21. package/dist/cjs/npcs/agent-common/lock.js +99 -0
  22. package/dist/cjs/npcs/agent-common/runtime.js +154 -0
  23. package/dist/cjs/npcs/agent-common/session.js +390 -0
  24. package/dist/cjs/npcs/agent-common/shim.js +96 -0
  25. package/dist/cjs/npcs/agent-common/watchdog.js +149 -0
  26. package/dist/cjs/npcs/claude-code/defaults.js +20 -0
  27. package/dist/cjs/npcs/claude-code/hook-handler.js +139 -0
  28. package/dist/cjs/npcs/claude-code/index.js +104 -0
  29. package/dist/cjs/npcs/claude-code/setup.js +133 -0
  30. package/dist/cjs/npcs/claude-code/state-machine.js +130 -0
  31. package/dist/cjs/npcs/codex/defaults.js +32 -0
  32. package/dist/cjs/npcs/codex/hook-handler.js +116 -0
  33. package/dist/cjs/npcs/codex/index.js +92 -0
  34. package/dist/cjs/npcs/codex/rollout.js +246 -0
  35. package/dist/cjs/npcs/codex/setup.js +104 -0
  36. package/dist/cjs/npcs/codex/watcher.js +346 -0
  37. package/dist/cjs/npcs/cursor/defaults.js +15 -0
  38. package/dist/cjs/npcs/cursor/hook-handler.js +65 -0
  39. package/dist/cjs/npcs/cursor/index.js +72 -0
  40. package/dist/cjs/npcs/cursor/normalize.js +54 -0
  41. package/dist/cjs/npcs/cursor/setup.js +98 -0
  42. package/dist/cjs/npcs/gemini/defaults.js +15 -0
  43. package/dist/cjs/npcs/gemini/hook-handler.js +93 -0
  44. package/dist/cjs/npcs/gemini/index.js +69 -0
  45. package/dist/cjs/npcs/gemini/setup.js +98 -0
  46. package/dist/cjs/npcs/github-watcher/defaults.js +11 -0
  47. package/dist/cjs/npcs/github-watcher/format.js +21 -0
  48. package/dist/cjs/npcs/github-watcher/github-api.js +126 -0
  49. package/dist/cjs/npcs/github-watcher/index.js +148 -0
  50. package/dist/cjs/npcs/internet-connectivity/checks.js +92 -0
  51. package/dist/cjs/npcs/internet-connectivity/defaults.js +22 -0
  52. package/dist/cjs/npcs/internet-connectivity/index.js +251 -0
  53. package/dist/cjs/npcs/log-watcher/buffer.js +40 -0
  54. package/dist/cjs/npcs/log-watcher/defaults.js +12 -0
  55. package/dist/cjs/npcs/log-watcher/index.js +161 -0
  56. package/dist/cjs/npcs/log-watcher/tail.js +81 -0
  57. package/dist/cjs/npcs/process-watcher/defaults.js +9 -0
  58. package/dist/cjs/npcs/process-watcher/index.js +140 -0
  59. package/dist/cjs/npcs/process-watcher/process-scanner.js +114 -0
  60. package/dist/cjs/npcs/receptionist/defaults.js +9 -0
  61. package/dist/cjs/npcs/receptionist/index.js +120 -0
  62. package/dist/cjs/npcs/receptionist/weather.js +129 -0
  63. package/dist/cjs/npcs/system-monitor/collectors.js +68 -0
  64. package/dist/cjs/npcs/system-monitor/defaults.js +13 -0
  65. package/dist/cjs/npcs/system-monitor/index.js +105 -0
  66. package/dist/cjs/npcs/web-page-watcher/basic-mode.js +58 -0
  67. package/dist/cjs/npcs/web-page-watcher/capture.js +80 -0
  68. package/dist/cjs/npcs/web-page-watcher/defaults.js +31 -0
  69. package/dist/cjs/npcs/web-page-watcher/index.js +234 -0
  70. package/dist/cjs/npcs/web-page-watcher/pixelate.js +181 -0
  71. package/dist/cjs/package.json +1 -0
  72. package/dist/cli.d.ts +3 -0
  73. package/dist/cli.js +498 -0
  74. package/dist/core/api-key.d.ts +34 -0
  75. package/dist/core/api-key.js +64 -0
  76. package/dist/core/base-npc.d.ts +41 -0
  77. package/dist/core/base-npc.js +156 -0
  78. package/dist/core/config.d.ts +22 -0
  79. package/dist/core/config.js +101 -0
  80. package/dist/core/event-npc.d.ts +8 -0
  81. package/dist/core/event-npc.js +10 -0
  82. package/dist/core/logger.d.ts +11 -0
  83. package/dist/core/logger.js +35 -0
  84. package/dist/core/polling-npc.d.ts +18 -0
  85. package/dist/core/polling-npc.js +61 -0
  86. package/dist/core/screen.d.ts +11 -0
  87. package/dist/core/screen.js +24 -0
  88. package/dist/core/text.d.ts +6 -0
  89. package/dist/core/text.js +12 -0
  90. package/dist/core/thresholds.d.ts +10 -0
  91. package/dist/core/thresholds.js +44 -0
  92. package/dist/core/types.d.ts +60 -0
  93. package/dist/core/types.js +7 -0
  94. package/dist/core/user-config.d.ts +43 -0
  95. package/dist/core/user-config.js +85 -0
  96. package/dist/doctor.d.ts +8 -0
  97. package/dist/doctor.js +126 -0
  98. package/dist/index.d.ts +39 -0
  99. package/dist/index.js +25 -0
  100. package/dist/npcs/agent-common/activity.d.ts +42 -0
  101. package/dist/npcs/agent-common/activity.js +280 -0
  102. package/dist/npcs/agent-common/git-stats.d.ts +11 -0
  103. package/dist/npcs/agent-common/git-stats.js +67 -0
  104. package/dist/npcs/agent-common/hook-runner.d.ts +62 -0
  105. package/dist/npcs/agent-common/hook-runner.js +245 -0
  106. package/dist/npcs/agent-common/hook-settings.d.ts +75 -0
  107. package/dist/npcs/agent-common/hook-settings.js +265 -0
  108. package/dist/npcs/agent-common/liveness.d.ts +12 -0
  109. package/dist/npcs/agent-common/liveness.js +105 -0
  110. package/dist/npcs/agent-common/lock.d.ts +6 -0
  111. package/dist/npcs/agent-common/lock.js +95 -0
  112. package/dist/npcs/agent-common/runtime.d.ts +16 -0
  113. package/dist/npcs/agent-common/runtime.js +149 -0
  114. package/dist/npcs/agent-common/session.d.ts +184 -0
  115. package/dist/npcs/agent-common/session.js +368 -0
  116. package/dist/npcs/agent-common/shim.d.ts +4 -0
  117. package/dist/npcs/agent-common/shim.js +90 -0
  118. package/dist/npcs/agent-common/watchdog.d.ts +16 -0
  119. package/dist/npcs/agent-common/watchdog.js +144 -0
  120. package/dist/npcs/claude-code/defaults.d.ts +15 -0
  121. package/dist/npcs/claude-code/defaults.js +17 -0
  122. package/dist/npcs/claude-code/hook-handler.d.ts +40 -0
  123. package/dist/npcs/claude-code/hook-handler.js +131 -0
  124. package/dist/npcs/claude-code/index.d.ts +36 -0
  125. package/dist/npcs/claude-code/index.js +92 -0
  126. package/dist/npcs/claude-code/setup.d.ts +58 -0
  127. package/dist/npcs/claude-code/setup.js +121 -0
  128. package/dist/npcs/claude-code/state-machine.d.ts +28 -0
  129. package/dist/npcs/claude-code/state-machine.js +125 -0
  130. package/dist/npcs/codex/defaults.d.ts +24 -0
  131. package/dist/npcs/codex/defaults.js +28 -0
  132. package/dist/npcs/codex/hook-handler.d.ts +24 -0
  133. package/dist/npcs/codex/hook-handler.js +110 -0
  134. package/dist/npcs/codex/index.d.ts +21 -0
  135. package/dist/npcs/codex/index.js +76 -0
  136. package/dist/npcs/codex/rollout.d.ts +39 -0
  137. package/dist/npcs/codex/rollout.js +242 -0
  138. package/dist/npcs/codex/setup.d.ts +37 -0
  139. package/dist/npcs/codex/setup.js +96 -0
  140. package/dist/npcs/codex/watcher.d.ts +62 -0
  141. package/dist/npcs/codex/watcher.js +341 -0
  142. package/dist/npcs/cursor/defaults.d.ts +9 -0
  143. package/dist/npcs/cursor/defaults.js +11 -0
  144. package/dist/npcs/cursor/hook-handler.d.ts +8 -0
  145. package/dist/npcs/cursor/hook-handler.js +60 -0
  146. package/dist/npcs/cursor/index.d.ts +18 -0
  147. package/dist/npcs/cursor/index.js +57 -0
  148. package/dist/npcs/cursor/normalize.d.ts +6 -0
  149. package/dist/npcs/cursor/normalize.js +49 -0
  150. package/dist/npcs/cursor/setup.d.ts +29 -0
  151. package/dist/npcs/cursor/setup.js +90 -0
  152. package/dist/npcs/gemini/defaults.d.ts +9 -0
  153. package/dist/npcs/gemini/defaults.js +11 -0
  154. package/dist/npcs/gemini/hook-handler.d.ts +10 -0
  155. package/dist/npcs/gemini/hook-handler.js +87 -0
  156. package/dist/npcs/gemini/index.d.ts +17 -0
  157. package/dist/npcs/gemini/index.js +56 -0
  158. package/dist/npcs/gemini/setup.d.ts +29 -0
  159. package/dist/npcs/gemini/setup.js +90 -0
  160. package/dist/npcs/github-watcher/defaults.d.ts +8 -0
  161. package/dist/npcs/github-watcher/defaults.js +8 -0
  162. package/dist/npcs/github-watcher/format.d.ts +3 -0
  163. package/dist/npcs/github-watcher/format.js +18 -0
  164. package/dist/npcs/github-watcher/github-api.d.ts +55 -0
  165. package/dist/npcs/github-watcher/github-api.js +120 -0
  166. package/dist/npcs/github-watcher/index.d.ts +35 -0
  167. package/dist/npcs/github-watcher/index.js +144 -0
  168. package/dist/npcs/internet-connectivity/checks.d.ts +24 -0
  169. package/dist/npcs/internet-connectivity/checks.js +84 -0
  170. package/dist/npcs/internet-connectivity/defaults.d.ts +20 -0
  171. package/dist/npcs/internet-connectivity/defaults.js +19 -0
  172. package/dist/npcs/internet-connectivity/index.d.ts +55 -0
  173. package/dist/npcs/internet-connectivity/index.js +246 -0
  174. package/dist/npcs/log-watcher/buffer.d.ts +18 -0
  175. package/dist/npcs/log-watcher/buffer.js +34 -0
  176. package/dist/npcs/log-watcher/defaults.d.ts +9 -0
  177. package/dist/npcs/log-watcher/defaults.js +9 -0
  178. package/dist/npcs/log-watcher/index.d.ts +45 -0
  179. package/dist/npcs/log-watcher/index.js +157 -0
  180. package/dist/npcs/log-watcher/tail.d.ts +9 -0
  181. package/dist/npcs/log-watcher/tail.js +78 -0
  182. package/dist/npcs/process-watcher/defaults.d.ts +6 -0
  183. package/dist/npcs/process-watcher/defaults.js +6 -0
  184. package/dist/npcs/process-watcher/index.d.ts +26 -0
  185. package/dist/npcs/process-watcher/index.js +136 -0
  186. package/dist/npcs/process-watcher/process-scanner.d.ts +19 -0
  187. package/dist/npcs/process-watcher/process-scanner.js +110 -0
  188. package/dist/npcs/receptionist/defaults.d.ts +6 -0
  189. package/dist/npcs/receptionist/defaults.js +6 -0
  190. package/dist/npcs/receptionist/index.d.ts +29 -0
  191. package/dist/npcs/receptionist/index.js +116 -0
  192. package/dist/npcs/receptionist/weather.d.ts +37 -0
  193. package/dist/npcs/receptionist/weather.js +121 -0
  194. package/dist/npcs/system-monitor/collectors.d.ts +45 -0
  195. package/dist/npcs/system-monitor/collectors.js +60 -0
  196. package/dist/npcs/system-monitor/defaults.d.ts +7 -0
  197. package/dist/npcs/system-monitor/defaults.js +10 -0
  198. package/dist/npcs/system-monitor/index.d.ts +27 -0
  199. package/dist/npcs/system-monitor/index.js +101 -0
  200. package/dist/npcs/web-page-watcher/basic-mode.d.ts +16 -0
  201. package/dist/npcs/web-page-watcher/basic-mode.js +52 -0
  202. package/dist/npcs/web-page-watcher/capture.d.ts +49 -0
  203. package/dist/npcs/web-page-watcher/capture.js +75 -0
  204. package/dist/npcs/web-page-watcher/defaults.d.ts +19 -0
  205. package/dist/npcs/web-page-watcher/defaults.js +27 -0
  206. package/dist/npcs/web-page-watcher/index.d.ts +42 -0
  207. package/dist/npcs/web-page-watcher/index.js +230 -0
  208. package/dist/npcs/web-page-watcher/pixelate.d.ts +36 -0
  209. package/dist/npcs/web-page-watcher/pixelate.js +172 -0
  210. package/package.json +73 -3
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runDoctor = runDoctor;
4
+ exports.hasCodexHookWatcherOverlap = hasCodexHookWatcherOverlap;
5
+ const node_crypto_1 = require("node:crypto");
6
+ const node_fs_1 = require("node:fs");
7
+ const liveness_js_1 = require("./npcs/agent-common/liveness.js");
8
+ const defaults_js_1 = require("./npcs/codex/defaults.js");
9
+ /**
10
+ * Diagnose connectivity to the Nocville API: hit `/api/v1/health/ready`, then POST a single
11
+ * offline status push and report HTTP status, latency, and rate-limit headroom.
12
+ */
13
+ async function runDoctor(config) {
14
+ const apiUrl = config.apiUrl.replace(/\/+$/, '');
15
+ console.log(`nocville-npc doctor — checking ${apiUrl}`);
16
+ console.log('');
17
+ if (hasCodexHookWatcherOverlap())
18
+ console.warn(' [WARN] Codex hooks and codex watch are both active. Stop the fallback watcher; hooks own these sessions.');
19
+ // 1) Health check
20
+ let healthOk = false;
21
+ {
22
+ const start = Date.now();
23
+ const t = withTimeout(5000);
24
+ try {
25
+ const res = await fetch(`${apiUrl}/api/v1/health/ready`, { method: 'GET', signal: t.signal });
26
+ const ms = Date.now() - start;
27
+ const body = await res.text();
28
+ healthOk = res.ok;
29
+ console.log(` [${res.ok ? 'OK' : 'FAIL'}] GET /api/v1/health/ready -> ${res.status} (${ms}ms)`);
30
+ if (config.debug)
31
+ console.log(` ${body.slice(0, 200)}`);
32
+ }
33
+ catch (err) {
34
+ console.log(` [FAIL] GET /api/v1/health/ready -> ${err instanceof Error ? err.message : String(err)}`);
35
+ }
36
+ finally {
37
+ t.done();
38
+ }
39
+ }
40
+ // 2) Test status push
41
+ let pushOk = false;
42
+ const hasKey = Boolean(config.apiKey);
43
+ if (!hasKey) {
44
+ console.log(' [SKIP] POST /api/v1/status — no --api-key / NOCVILLE_API_KEY set');
45
+ }
46
+ else {
47
+ const start = Date.now();
48
+ const t = withTimeout(5000);
49
+ try {
50
+ const res = await fetch(`${apiUrl}/api/v1/status`, {
51
+ method: 'POST',
52
+ headers: {
53
+ 'Content-Type': 'application/json',
54
+ Authorization: `Bearer ${config.apiKey}`,
55
+ },
56
+ signal: t.signal,
57
+ body: JSON.stringify({
58
+ // Unique offline probe: personal-key ownership must not reserve a shared doctor ID.
59
+ serviceId: `${(config.serviceId || 'npc').slice(0, 60)}-doctor-${(0, node_crypto_1.randomUUID)().slice(0, 16)}`,
60
+ status: 'unknown',
61
+ mood: 'idle',
62
+ offline: true,
63
+ subStatus: 'offline',
64
+ ...(config.map ? { map: config.map } : {}),
65
+ }),
66
+ });
67
+ const ms = Date.now() - start;
68
+ const text = await res.text();
69
+ pushOk = res.ok;
70
+ let remaining = res.headers.get('x-ratelimit-remaining') ?? res.headers.get('ratelimit-remaining');
71
+ if (!remaining) {
72
+ try {
73
+ const parsed = JSON.parse(text);
74
+ if (typeof parsed.remaining === 'number')
75
+ remaining = String(parsed.remaining);
76
+ }
77
+ catch {
78
+ // non-JSON body
79
+ }
80
+ }
81
+ console.log(` [${res.ok ? 'OK' : 'FAIL'}] POST /api/v1/status -> ${res.status} ` +
82
+ `(${ms}ms, rate-limit remaining: ${remaining ?? 'n/a'})`);
83
+ if (config.map)
84
+ console.log(` target map: ${config.map}`);
85
+ if (!res.ok)
86
+ console.log(` ${text.slice(0, 200)}`);
87
+ }
88
+ catch (err) {
89
+ console.log(` [FAIL] POST /api/v1/status -> ${err instanceof Error ? err.message : String(err)}`);
90
+ }
91
+ finally {
92
+ t.done();
93
+ }
94
+ }
95
+ // Verdict
96
+ console.log('');
97
+ if (healthOk && pushOk) {
98
+ console.log('Verdict: OK — API reachable and status push accepted.');
99
+ console.log('The offline probe does not create a coworker in your office.');
100
+ }
101
+ else if (!healthOk) {
102
+ console.log('Verdict: FAIL — API health check is unreachable. Check --api-url and that the server is running.');
103
+ }
104
+ else if (!hasKey) {
105
+ console.log('Verdict: PARTIAL — API is up, but no API key was provided to test a push.');
106
+ }
107
+ else {
108
+ console.log('Verdict: FAIL — API is up but the push was rejected. Check your API key / team settings.');
109
+ }
110
+ process.exitCode = healthOk && (pushOk || !hasKey) ? 0 : 1;
111
+ }
112
+ function withTimeout(timeoutMs) {
113
+ const controller = new AbortController();
114
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
115
+ return { signal: controller.signal, done: () => clearTimeout(timer) };
116
+ }
117
+ function hasCodexHookWatcherOverlap(dir = defaults_js_1.CODEX_DEFAULTS.stateDir) {
118
+ try {
119
+ const files = (0, node_fs_1.readdirSync)(dir);
120
+ return (files.some((file) => /^session-.*\.json$/.test(file)) &&
121
+ files.some((file) => {
122
+ const match = file.match(/^watcher-(\d+)\.pid$/);
123
+ return !!match && (0, liveness_js_1.isAgentAlive)({ pid: Number(match[1]) });
124
+ }));
125
+ }
126
+ catch {
127
+ return false;
128
+ }
129
+ }
130
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.installGeminiHooksInto = exports.uninstallGeminiHooks = exports.setupGeminiHooks = exports.handleGeminiHookEvent = exports.geminiServiceId = exports.geminiTransition = exports.GEMINI_ADAPTER = exports.GEMINI_DEFAULTS = exports.WebPageWatcherNPC = exports.GitHubWatcherNPC = exports.ReceptionistNPC = exports.LogWatcherNPC = exports.ProcessWatcherNPC = exports.InternetConnectivityNPC = exports.userConfigPath = exports.saveUserConfig = exports.loadUserConfig = exports.redactSecrets = exports.shortPath = exports.shortCommand = exports.describeToolUse = exports.CodexWatcher = exports.parseRolloutLine = exports.uninstallCodexHooks = exports.setupCodexHooks = exports.codexTransition = exports.handleCodexHookEvent = exports.handleCodexCommand = exports.claudeTransition = exports.processHookEvent = exports.uninstallHooks = exports.setupHooks = exports.handleHookEvent = exports.handleClaudeCodeCommand = exports.ClaudeCodeNPC = exports.SystemMonitorNPC = exports.pushHistory = exports.statusColor = exports.truncate = exports.worstStatus = exports.evaluateThreshold = exports.numberFlag = exports.boolFlag = exports.stringFlag = exports.resolveConfig = exports.parseArgs = exports.Logger = exports.EventNPC = exports.PollingNPC = exports.BaseNPC = void 0;
4
+ exports.normalizeCursorEvent = exports.isCursorInvocation = exports.CURSOR_HOOK_EVENTS = exports.installCursorHooksInto = exports.uninstallCursorHooks = exports.setupCursorHooks = exports.handleCursorHookEvent = exports.cursorServiceId = exports.CURSOR_ADAPTER = exports.CURSOR_DEFAULTS = exports.GEMINI_HOOK_EVENTS = void 0;
5
+ // Core
6
+ var base_npc_js_1 = require("./core/base-npc.js");
7
+ Object.defineProperty(exports, "BaseNPC", { enumerable: true, get: function () { return base_npc_js_1.BaseNPC; } });
8
+ var polling_npc_js_1 = require("./core/polling-npc.js");
9
+ Object.defineProperty(exports, "PollingNPC", { enumerable: true, get: function () { return polling_npc_js_1.PollingNPC; } });
10
+ var event_npc_js_1 = require("./core/event-npc.js");
11
+ Object.defineProperty(exports, "EventNPC", { enumerable: true, get: function () { return event_npc_js_1.EventNPC; } });
12
+ var logger_js_1 = require("./core/logger.js");
13
+ Object.defineProperty(exports, "Logger", { enumerable: true, get: function () { return logger_js_1.Logger; } });
14
+ var config_js_1 = require("./core/config.js");
15
+ Object.defineProperty(exports, "parseArgs", { enumerable: true, get: function () { return config_js_1.parseArgs; } });
16
+ Object.defineProperty(exports, "resolveConfig", { enumerable: true, get: function () { return config_js_1.resolveConfig; } });
17
+ Object.defineProperty(exports, "stringFlag", { enumerable: true, get: function () { return config_js_1.stringFlag; } });
18
+ Object.defineProperty(exports, "boolFlag", { enumerable: true, get: function () { return config_js_1.boolFlag; } });
19
+ Object.defineProperty(exports, "numberFlag", { enumerable: true, get: function () { return config_js_1.numberFlag; } });
20
+ var thresholds_js_1 = require("./core/thresholds.js");
21
+ Object.defineProperty(exports, "evaluateThreshold", { enumerable: true, get: function () { return thresholds_js_1.evaluateThreshold; } });
22
+ Object.defineProperty(exports, "worstStatus", { enumerable: true, get: function () { return thresholds_js_1.worstStatus; } });
23
+ var text_js_1 = require("./core/text.js");
24
+ Object.defineProperty(exports, "truncate", { enumerable: true, get: function () { return text_js_1.truncate; } });
25
+ var screen_js_1 = require("./core/screen.js");
26
+ Object.defineProperty(exports, "statusColor", { enumerable: true, get: function () { return screen_js_1.statusColor; } });
27
+ Object.defineProperty(exports, "pushHistory", { enumerable: true, get: function () { return screen_js_1.pushHistory; } });
28
+ // NPCs
29
+ var index_js_1 = require("./npcs/system-monitor/index.js");
30
+ Object.defineProperty(exports, "SystemMonitorNPC", { enumerable: true, get: function () { return index_js_1.SystemMonitorNPC; } });
31
+ var index_js_2 = require("./npcs/claude-code/index.js");
32
+ Object.defineProperty(exports, "ClaudeCodeNPC", { enumerable: true, get: function () { return index_js_2.ClaudeCodeNPC; } });
33
+ Object.defineProperty(exports, "handleClaudeCodeCommand", { enumerable: true, get: function () { return index_js_2.handleClaudeCodeCommand; } });
34
+ Object.defineProperty(exports, "handleHookEvent", { enumerable: true, get: function () { return index_js_2.handleHookEvent; } });
35
+ Object.defineProperty(exports, "setupHooks", { enumerable: true, get: function () { return index_js_2.setupHooks; } });
36
+ Object.defineProperty(exports, "uninstallHooks", { enumerable: true, get: function () { return index_js_2.uninstallHooks; } });
37
+ Object.defineProperty(exports, "processHookEvent", { enumerable: true, get: function () { return index_js_2.processHookEvent; } });
38
+ Object.defineProperty(exports, "claudeTransition", { enumerable: true, get: function () { return index_js_2.claudeTransition; } });
39
+ var index_js_3 = require("./npcs/codex/index.js");
40
+ Object.defineProperty(exports, "handleCodexCommand", { enumerable: true, get: function () { return index_js_3.handleCodexCommand; } });
41
+ Object.defineProperty(exports, "handleCodexHookEvent", { enumerable: true, get: function () { return index_js_3.handleCodexHookEvent; } });
42
+ Object.defineProperty(exports, "codexTransition", { enumerable: true, get: function () { return index_js_3.codexTransition; } });
43
+ Object.defineProperty(exports, "setupCodexHooks", { enumerable: true, get: function () { return index_js_3.setupCodexHooks; } });
44
+ Object.defineProperty(exports, "uninstallCodexHooks", { enumerable: true, get: function () { return index_js_3.uninstallCodexHooks; } });
45
+ Object.defineProperty(exports, "parseRolloutLine", { enumerable: true, get: function () { return index_js_3.parseRolloutLine; } });
46
+ Object.defineProperty(exports, "CodexWatcher", { enumerable: true, get: function () { return index_js_3.CodexWatcher; } });
47
+ var activity_js_1 = require("./npcs/agent-common/activity.js");
48
+ Object.defineProperty(exports, "describeToolUse", { enumerable: true, get: function () { return activity_js_1.describeToolUse; } });
49
+ Object.defineProperty(exports, "shortCommand", { enumerable: true, get: function () { return activity_js_1.shortCommand; } });
50
+ Object.defineProperty(exports, "shortPath", { enumerable: true, get: function () { return activity_js_1.shortPath; } });
51
+ Object.defineProperty(exports, "redactSecrets", { enumerable: true, get: function () { return activity_js_1.redactSecrets; } });
52
+ var user_config_js_1 = require("./core/user-config.js");
53
+ Object.defineProperty(exports, "loadUserConfig", { enumerable: true, get: function () { return user_config_js_1.loadUserConfig; } });
54
+ Object.defineProperty(exports, "saveUserConfig", { enumerable: true, get: function () { return user_config_js_1.saveUserConfig; } });
55
+ Object.defineProperty(exports, "userConfigPath", { enumerable: true, get: function () { return user_config_js_1.userConfigPath; } });
56
+ var index_js_4 = require("./npcs/internet-connectivity/index.js");
57
+ Object.defineProperty(exports, "InternetConnectivityNPC", { enumerable: true, get: function () { return index_js_4.InternetConnectivityNPC; } });
58
+ var index_js_5 = require("./npcs/process-watcher/index.js");
59
+ Object.defineProperty(exports, "ProcessWatcherNPC", { enumerable: true, get: function () { return index_js_5.ProcessWatcherNPC; } });
60
+ var index_js_6 = require("./npcs/log-watcher/index.js");
61
+ Object.defineProperty(exports, "LogWatcherNPC", { enumerable: true, get: function () { return index_js_6.LogWatcherNPC; } });
62
+ var index_js_7 = require("./npcs/receptionist/index.js");
63
+ Object.defineProperty(exports, "ReceptionistNPC", { enumerable: true, get: function () { return index_js_7.ReceptionistNPC; } });
64
+ var index_js_8 = require("./npcs/github-watcher/index.js");
65
+ Object.defineProperty(exports, "GitHubWatcherNPC", { enumerable: true, get: function () { return index_js_8.GitHubWatcherNPC; } });
66
+ var index_js_9 = require("./npcs/web-page-watcher/index.js");
67
+ Object.defineProperty(exports, "WebPageWatcherNPC", { enumerable: true, get: function () { return index_js_9.WebPageWatcherNPC; } });
68
+ var index_js_10 = require("./npcs/gemini/index.js");
69
+ Object.defineProperty(exports, "GEMINI_DEFAULTS", { enumerable: true, get: function () { return index_js_10.GEMINI_DEFAULTS; } });
70
+ Object.defineProperty(exports, "GEMINI_ADAPTER", { enumerable: true, get: function () { return index_js_10.GEMINI_ADAPTER; } });
71
+ Object.defineProperty(exports, "geminiTransition", { enumerable: true, get: function () { return index_js_10.geminiTransition; } });
72
+ Object.defineProperty(exports, "geminiServiceId", { enumerable: true, get: function () { return index_js_10.geminiServiceId; } });
73
+ Object.defineProperty(exports, "handleGeminiHookEvent", { enumerable: true, get: function () { return index_js_10.handleGeminiHookEvent; } });
74
+ Object.defineProperty(exports, "setupGeminiHooks", { enumerable: true, get: function () { return index_js_10.setupGeminiHooks; } });
75
+ Object.defineProperty(exports, "uninstallGeminiHooks", { enumerable: true, get: function () { return index_js_10.uninstallGeminiHooks; } });
76
+ Object.defineProperty(exports, "installGeminiHooksInto", { enumerable: true, get: function () { return index_js_10.installGeminiHooksInto; } });
77
+ Object.defineProperty(exports, "GEMINI_HOOK_EVENTS", { enumerable: true, get: function () { return index_js_10.GEMINI_HOOK_EVENTS; } });
78
+ var index_js_11 = require("./npcs/cursor/index.js");
79
+ Object.defineProperty(exports, "CURSOR_DEFAULTS", { enumerable: true, get: function () { return index_js_11.CURSOR_DEFAULTS; } });
80
+ Object.defineProperty(exports, "CURSOR_ADAPTER", { enumerable: true, get: function () { return index_js_11.CURSOR_ADAPTER; } });
81
+ Object.defineProperty(exports, "cursorServiceId", { enumerable: true, get: function () { return index_js_11.cursorServiceId; } });
82
+ Object.defineProperty(exports, "handleCursorHookEvent", { enumerable: true, get: function () { return index_js_11.handleCursorHookEvent; } });
83
+ Object.defineProperty(exports, "setupCursorHooks", { enumerable: true, get: function () { return index_js_11.setupCursorHooks; } });
84
+ Object.defineProperty(exports, "uninstallCursorHooks", { enumerable: true, get: function () { return index_js_11.uninstallCursorHooks; } });
85
+ Object.defineProperty(exports, "installCursorHooksInto", { enumerable: true, get: function () { return index_js_11.installCursorHooksInto; } });
86
+ Object.defineProperty(exports, "CURSOR_HOOK_EVENTS", { enumerable: true, get: function () { return index_js_11.CURSOR_HOOK_EVENTS; } });
87
+ var normalize_js_1 = require("./npcs/cursor/normalize.js");
88
+ Object.defineProperty(exports, "isCursorInvocation", { enumerable: true, get: function () { return normalize_js_1.isCursorInvocation; } });
89
+ Object.defineProperty(exports, "normalizeCursorEvent", { enumerable: true, get: function () { return normalize_js_1.normalizeCursorEvent; } });
90
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,291 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.THINKING = exports.ACTIVITY_MAX = void 0;
4
+ exports.shortPath = shortPath;
5
+ exports.redactSecrets = redactSecrets;
6
+ exports.shortCommand = shortCommand;
7
+ exports.patchFiles = patchFiles;
8
+ exports.editingFiles = editingFiles;
9
+ exports.describeToolUse = describeToolUse;
10
+ exports.isQuestionTool = isQuestionTool;
11
+ exports.failureText = failureText;
12
+ const node_os_1 = require("node:os");
13
+ const text_js_1 = require("../../core/text.js");
14
+ /**
15
+ * Human-friendly activity strings for AI coding agents (Claude Code, Codex).
16
+ *
17
+ * These end up on the NPC's speech bubble and desk-sign ticker, which teammates
18
+ * see — so they must be short, readable, and never leak secrets or prompt text.
19
+ */
20
+ /** Max length of a full activity line ("Running pnpm test", "Editing src/x.ts"). */
21
+ exports.ACTIVITY_MAX = 60;
22
+ /** Max length of an embedded shell command. */
23
+ const COMMAND_MAX = 44;
24
+ /** Max length of an embedded path. */
25
+ const PATH_MAX = 40;
26
+ /** Max length of an embedded search pattern / query. */
27
+ const PATTERN_MAX = 28;
28
+ exports.THINKING = 'Thinking…';
29
+ function str(input, ...keys) {
30
+ for (const k of keys) {
31
+ const v = input[k];
32
+ if (typeof v === 'string' && v.trim())
33
+ return v.trim();
34
+ }
35
+ return undefined;
36
+ }
37
+ function asInput(raw) {
38
+ if (raw && typeof raw === 'object' && !Array.isArray(raw))
39
+ return raw;
40
+ if (typeof raw === 'string') {
41
+ // Some agents pass JSON-encoded arguments.
42
+ try {
43
+ const parsed = JSON.parse(raw);
44
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed))
45
+ return parsed;
46
+ }
47
+ catch {
48
+ // Not JSON — treat as a bare command string.
49
+ }
50
+ return { command: raw };
51
+ }
52
+ if (Array.isArray(raw))
53
+ return { command: raw };
54
+ return {};
55
+ }
56
+ /**
57
+ * Make a path short and relative: strip the project cwd (or the home dir to
58
+ * `~`), then keep only the trailing segments if it is still long.
59
+ */
60
+ function shortPath(p, cwd) {
61
+ let out = p.trim().replace(/^file:\/\//, '');
62
+ const norm = (s) => s.replace(/\\/g, '/').replace(/\/+$/, '');
63
+ out = norm(out);
64
+ const base = cwd ? norm(cwd) : '';
65
+ if (base && (out === base || out.startsWith(base + '/'))) {
66
+ out = out.slice(base.length + 1) || '.';
67
+ }
68
+ else {
69
+ const home = norm((0, node_os_1.homedir)());
70
+ if (home && out.startsWith(home + '/'))
71
+ out = '~' + out.slice(home.length);
72
+ }
73
+ if (out.length <= PATH_MAX)
74
+ return out;
75
+ const parts = out.split('/');
76
+ // Keep the last two segments; fall back to truncating the filename.
77
+ const tail = parts.slice(-2).join('/');
78
+ if (tail.length + 2 <= PATH_MAX)
79
+ return '…/' + tail;
80
+ return (0, text_js_1.truncate)(parts[parts.length - 1] ?? out, PATH_MAX);
81
+ }
82
+ const SECRET_FLAG = /(--?[\w-]*(?:token|key|secret|password|passwd|pwd|auth|credential)[\w-]*)(=|\s+)("[^"]*"|'[^']*'|\S+)/gi;
83
+ /**
84
+ * Redact anything secret-looking from a shell command: env assignments,
85
+ * `--token=…`-style flags, bearer headers, URL credentials, and long opaque
86
+ * strings (API keys, hashes). Conservative by design — false positives are fine.
87
+ */
88
+ function redactSecrets(cmd) {
89
+ return (cmd
90
+ // URL credentials: scheme://user:pass@host
91
+ .replace(/([a-z][a-z0-9+.-]*:\/\/)[^\s/@:]+:[^\s/@]+@/gi, '$1***@')
92
+ // Authorization headers
93
+ .replace(/(bearer|basic|token)\s+[A-Za-z0-9._~+/=-]{8,}/gi, '$1 ***')
94
+ // --api-key=…, --password …, -token …
95
+ .replace(SECRET_FLAG, (_m, flag, sep) => `${flag}${sep}***`)
96
+ // Well-known key prefixes
97
+ .replace(/\b(sk|pk|rk)-[A-Za-z0-9_-]{8,}/g, '***')
98
+ .replace(/\b(ghp|gho|ghs|ghu|github_pat|xox[abprs]|glpat|AKIA)[A-Za-z0-9_-]{8,}/g, '***')
99
+ // Long opaque tokens (≥32 chars of key-ish alphabet, no path separators)
100
+ .replace(/\b[A-Za-z0-9_+=-]{32,}\b/g, '***'));
101
+ }
102
+ /**
103
+ * Shorten a shell command for display: first line only, drop a leading
104
+ * `cd … &&`, drop leading `VAR=value` env assignments (often secrets), unwrap
105
+ * `bash -lc "…"` wrappers, redact secrets, and truncate.
106
+ */
107
+ function shortCommand(raw, max = COMMAND_MAX) {
108
+ let cmd;
109
+ if (Array.isArray(raw)) {
110
+ const parts = raw.filter((x) => typeof x === 'string');
111
+ // Unwrap ["bash", "-lc", "<script>"] style argv.
112
+ const shellIdx = parts.findIndex((p) => p === '-lc' || p === '-c');
113
+ cmd = shellIdx >= 0 && parts[shellIdx + 1] ? parts[shellIdx + 1] : parts.join(' ');
114
+ }
115
+ else if (typeof raw === 'string') {
116
+ cmd = raw;
117
+ }
118
+ else {
119
+ return '';
120
+ }
121
+ cmd = cmd.trim();
122
+ // Unwrap a string-form shell wrapper: bash -lc 'pnpm test'
123
+ const wrapped = cmd.match(/^(?:\/\S*\/)?(?:ba|z)?sh\s+-l?c\s+(['"])([\s\S]*)\1$/);
124
+ if (wrapped)
125
+ cmd = wrapped[2].trim();
126
+ cmd = cmd.split('\n')[0].trim();
127
+ // Drop leading "cd <dir> &&" / "cd <dir>;" hops.
128
+ cmd = cmd.replace(/^(?:cd\s+("[^"]*"|'[^']*'|\S+)\s*(?:&&|;)\s*)+/, '');
129
+ // Drop leading env assignments.
130
+ cmd = cmd.replace(/^(?:[A-Za-z_][A-Za-z0-9_]*=("[^"]*"|'[^']*'|\S*)\s+)+/, '');
131
+ cmd = redactSecrets(cmd).replace(/\s+/g, ' ').trim();
132
+ return (0, text_js_1.truncate)(cmd, max);
133
+ }
134
+ function quote(s, max = PATTERN_MAX) {
135
+ return `'${(0, text_js_1.truncate)(s.replace(/\s+/g, ' '), max)}'`;
136
+ }
137
+ function hostOf(url) {
138
+ try {
139
+ return new URL(url).hostname.replace(/^www\./, '');
140
+ }
141
+ catch {
142
+ return (0, text_js_1.truncate)(url, PATTERN_MAX);
143
+ }
144
+ }
145
+ /** Files touched by an `apply_patch` envelope ("*** Update File: path"). */
146
+ function patchFiles(patch) {
147
+ const files = [];
148
+ const re = /^\*\*\* (?:Update|Add|Delete) File:\s*(.+)$/gm;
149
+ let m;
150
+ while ((m = re.exec(patch)) !== null) {
151
+ const f = m[1].trim();
152
+ if (f && !files.includes(f))
153
+ files.push(f);
154
+ }
155
+ return files;
156
+ }
157
+ /** "Editing a.ts" / "Editing a.ts +2 more" for a list of files. */
158
+ function editingFiles(files, cwd) {
159
+ if (files.length === 0)
160
+ return 'Editing files';
161
+ const first = shortPath(files[0], cwd);
162
+ return files.length === 1 ? `Editing ${first}` : `Editing ${first} +${files.length - 1} more`;
163
+ }
164
+ /**
165
+ * Describe a tool invocation in a few words. Covers Claude Code tool names and
166
+ * Codex tool names (Bash/shell/exec_command, apply_patch, update_plan, …);
167
+ * unknown tools fall back to "Using <tool>". Never includes file contents,
168
+ * edit strings, or prompts.
169
+ */
170
+ function describeToolUse(toolName, rawInput, cwd) {
171
+ const name = (toolName ?? '').trim();
172
+ const input = asInput(rawInput);
173
+ const key = name.toLowerCase();
174
+ // MCP tools: mcp__server__tool → "Using server (tool)"
175
+ if (key.startsWith('mcp__')) {
176
+ const [, server = 'mcp', tool = ''] = name.split('__');
177
+ return (0, text_js_1.truncate)(tool ? `Using ${server} (${tool})` : `Using ${server}`, exports.ACTIVITY_MAX);
178
+ }
179
+ switch (key) {
180
+ case 'replace':
181
+ case 'write_file':
182
+ case 'edit':
183
+ case 'multiedit':
184
+ case 'write':
185
+ case 'notebookedit': {
186
+ const file = str(input, 'file_path', 'absolute_path', 'notebook_path', 'path');
187
+ if (file)
188
+ return (0, text_js_1.truncate)(`Editing ${shortPath(file, cwd)}`, exports.ACTIVITY_MAX);
189
+ // Codex aliases Edit/Write to apply_patch; fall through to patch parsing.
190
+ const patch = str(input, 'command', 'input', 'patch');
191
+ return (0, text_js_1.truncate)(editingFiles(patch ? patchFiles(patch) : [], cwd), exports.ACTIVITY_MAX);
192
+ }
193
+ case 'delete': {
194
+ const file = str(input, 'file_path', 'path');
195
+ return file ? (0, text_js_1.truncate)(`Deleting ${shortPath(file, cwd)}`, exports.ACTIVITY_MAX) : 'Deleting a file';
196
+ }
197
+ case 'apply_patch':
198
+ case 'applypatch': {
199
+ const patch = str(input, 'command', 'input', 'patch') ?? '';
200
+ return (0, text_js_1.truncate)(editingFiles(patchFiles(patch), cwd), exports.ACTIVITY_MAX);
201
+ }
202
+ case 'run_shell_command':
203
+ case 'bash':
204
+ case 'shell':
205
+ case 'local_shell':
206
+ case 'exec_command':
207
+ case 'container.exec':
208
+ case 'unified_exec': {
209
+ const cmd = shortCommand(input['command'] ?? input['cmd']);
210
+ return cmd ? `Running ${cmd}` : 'Running a command';
211
+ }
212
+ case 'bashoutput':
213
+ case 'write_stdin':
214
+ return 'Checking a running command';
215
+ case 'killshell':
216
+ case 'killbash':
217
+ return 'Stopping a command';
218
+ case 'read_file':
219
+ case 'read':
220
+ case 'notebookread':
221
+ case 'view': {
222
+ const file = str(input, 'file_path', 'absolute_path', 'notebook_path', 'path');
223
+ return file ? (0, text_js_1.truncate)(`Reading ${shortPath(file, cwd)}`, exports.ACTIVITY_MAX) : 'Reading files';
224
+ }
225
+ case 'view_image': {
226
+ const file = str(input, 'path', 'file_path');
227
+ return file ? (0, text_js_1.truncate)(`Viewing ${shortPath(file, cwd)}`, exports.ACTIVITY_MAX) : 'Viewing an image';
228
+ }
229
+ case 'ls': {
230
+ const dir = str(input, 'path');
231
+ return dir ? (0, text_js_1.truncate)(`Listing ${shortPath(dir, cwd)}`, exports.ACTIVITY_MAX) : 'Listing files';
232
+ }
233
+ case 'grep': {
234
+ const pattern = str(input, 'pattern', 'query');
235
+ return pattern ? `Searching for ${quote(pattern)}` : 'Searching the code';
236
+ }
237
+ case 'glob': {
238
+ const pattern = str(input, 'pattern');
239
+ return pattern ? `Finding files ${quote(pattern)}` : 'Finding files';
240
+ }
241
+ case 'toolsearch':
242
+ return 'Looking up tools';
243
+ case 'webfetch': {
244
+ const url = str(input, 'url');
245
+ return url ? `Browsing ${hostOf(url)}` : 'Browsing the web';
246
+ }
247
+ case 'websearch':
248
+ case 'web_search':
249
+ case 'web_search_preview': {
250
+ const q = str(input, 'query', 'q');
251
+ return q ? `Searching the web for ${quote(q)}` : 'Searching the web';
252
+ }
253
+ case 'task':
254
+ case 'agent':
255
+ case 'spawn_agent':
256
+ return 'Delegating to a subagent';
257
+ case 'todowrite':
258
+ case 'update_plan':
259
+ case 'taskcreate':
260
+ case 'taskupdate':
261
+ return 'Planning';
262
+ case 'exitplanmode':
263
+ return 'Plan ready for review';
264
+ case 'askuserquestion':
265
+ case 'request_user_input':
266
+ return 'Has a question for you';
267
+ case 'skill': {
268
+ const skill = str(input, 'skill', 'name');
269
+ return skill ? (0, text_js_1.truncate)(`Using skill ${skill}`, exports.ACTIVITY_MAX) : 'Using a skill';
270
+ }
271
+ case '':
272
+ return 'Working';
273
+ default:
274
+ return (0, text_js_1.truncate)(`Using ${name}`, exports.ACTIVITY_MAX);
275
+ }
276
+ }
277
+ /** Tools whose PreToolUse means the agent is now waiting on the human. */
278
+ function isQuestionTool(toolName) {
279
+ const k = (toolName ?? '').toLowerCase();
280
+ return k === 'askuserquestion' || k === 'exitplanmode' || k === 'request_user_input';
281
+ }
282
+ /** Short failure label: "A command failed", "Edit failed". */
283
+ function failureText(toolName) {
284
+ const k = (toolName ?? '').toLowerCase();
285
+ if (k === 'bash' || k === 'shell' || k === 'exec_command')
286
+ return 'A command failed';
287
+ if (!toolName)
288
+ return 'Hit an error';
289
+ return (0, text_js_1.truncate)(`${toolName} failed`, exports.ACTIVITY_MAX);
290
+ }
291
+ //# sourceMappingURL=activity.js.map
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseNumstat = parseNumstat;
4
+ exports.computeGitStats = computeGitStats;
5
+ const node_child_process_1 = require("node:child_process");
6
+ const node_path_1 = require("node:path");
7
+ const node_perf_hooks_1 = require("node:perf_hooks");
8
+ /** Parse NUL-delimited numstat, including binary files and rename path pairs. */
9
+ function parseNumstat(raw) {
10
+ const fields = raw.split('\0'), files = [];
11
+ for (let i = 0; i < fields.length; i++) {
12
+ const record = fields[i];
13
+ if (!record)
14
+ continue;
15
+ const match = /^(\d+|-)\t(\d+|-)\t([\s\S]*)$/.exec(record);
16
+ if (!match)
17
+ continue;
18
+ let path = match[3];
19
+ if (!path) {
20
+ i++;
21
+ path = fields[++i] ?? '';
22
+ }
23
+ if (path)
24
+ files.push({
25
+ path,
26
+ insertions: match[1] === '-' ? 0 : Number(match[1]),
27
+ deletions: match[2] === '-' ? 0 : Number(match[2]),
28
+ });
29
+ }
30
+ return files;
31
+ }
32
+ /** Both commands share one wall-clock budget; call only from detached flushes. */
33
+ function computeGitStats(cwd, timeoutMs = 1500) {
34
+ const deadline = node_perf_hooks_1.performance.now() + Math.max(1, Math.min(1500, timeoutMs));
35
+ const git = (args) => {
36
+ const remaining = Math.floor(deadline - node_perf_hooks_1.performance.now());
37
+ if (remaining <= 0)
38
+ return null;
39
+ const result = (0, node_child_process_1.spawnSync)('git', ['--no-optional-locks', '-c', 'core.fsmonitor=false', '-C', cwd, ...args], {
40
+ encoding: 'utf8',
41
+ timeout: remaining,
42
+ killSignal: 'SIGKILL',
43
+ maxBuffer: 1 << 20,
44
+ windowsHide: true,
45
+ });
46
+ return result.status === 0 && !result.error ? result.stdout : null;
47
+ };
48
+ const diff = git(['diff', '--no-ext-diff', '--no-textconv', '--numstat', '-z', 'HEAD', '--']);
49
+ if (diff === null)
50
+ return null;
51
+ const untracked = git(['ls-files', '--others', '--exclude-standard', '-z']);
52
+ if (untracked === null)
53
+ return null;
54
+ const files = parseNumstat(diff);
55
+ for (const path of untracked.split('\0'))
56
+ if (path)
57
+ files.push({ path, insertions: 0, deletions: 0 });
58
+ if (files.length > 100_000)
59
+ return null;
60
+ files.sort((a, b) => b.insertions + b.deletions - (a.insertions + a.deletions) || a.path.localeCompare(b.path));
61
+ return {
62
+ filesChanged: files.length,
63
+ insertions: files.reduce((n, file) => n + file.insertions, 0),
64
+ deletions: files.reduce((n, file) => n + file.deletions, 0),
65
+ lastFiles: files.slice(0, 5).map((file) => (0, node_path_1.basename)(file.path)
66
+ // eslint-disable-next-line no-control-regex -- Strip display controls from Git filenames.
67
+ .replace(/[\u0000-\u001f\u007f-\u009f\u061c\u200e\u200f\u202a-\u202e\u2066-\u2069]/g, '')
68
+ .slice(0, 120)),
69
+ };
70
+ }
71
+ //# sourceMappingURL=git-stats.js.map