@cryptiklemur/lattice 5.10.0 → 5.11.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 (142) hide show
  1. package/dist/client/assets/{angular-html-BDIcxkJq.js → angular-html-BoFzmWT8.js} +1 -1
  2. package/dist/client/assets/{angular-ts-Bt22ouNH.js → angular-ts-DZnI8rKE.js} +1 -1
  3. package/dist/client/assets/{apl-p8qkxzEK.js → apl-DstVmncE.js} +1 -1
  4. package/dist/client/assets/{astro-CIaMc49M.js → astro-DTPCjzEx.js} +1 -1
  5. package/dist/client/assets/{blade-BR56EAMD.js → blade-6q42Ss3F.js} +1 -1
  6. package/dist/client/assets/{c-Dli0HzAh.js → c-BQDGJ-nQ.js} +1 -1
  7. package/dist/client/assets/{cobol-Cad15ECy.js → cobol-Dlh0WvsZ.js} +1 -1
  8. package/dist/client/assets/{coffee-DpyATEbF.js → coffee-DdQv129j.js} +1 -1
  9. package/dist/client/assets/{cpp-KN8_NFsf.js → cpp-DhbQJIv4.js} +1 -1
  10. package/dist/client/assets/{crystal-CuyGv0kh.js → crystal-C22kERUB.js} +1 -1
  11. package/dist/client/assets/{css-Cm3q4bxn.js → css-n31O5kHj.js} +1 -1
  12. package/dist/client/assets/{dist-BjxsMc4u.js → dist-D8okl7lw.js} +2 -2
  13. package/dist/client/assets/{edge-B6S7CSbx.js → edge-Cgwx-o_7.js} +1 -1
  14. package/dist/client/assets/{elixir-CNUy9H8T.js → elixir-DAGM2WKD.js} +1 -1
  15. package/dist/client/assets/{elm-CNfcWmb9.js → elm-BLw_7oO9.js} +1 -1
  16. package/dist/client/assets/{erb-DWebzDaI.js → erb-DCaNhYa7.js} +1 -1
  17. package/dist/client/assets/{git-rebase-B_Pt2ZBK.js → git-rebase-CNNhb8-g.js} +1 -1
  18. package/dist/client/assets/{glimmer-js-CVwoOd72.js → glimmer-js-BnZd88Wi.js} +1 -1
  19. package/dist/client/assets/{glimmer-ts-CjtFSxjz.js → glimmer-ts-DvFNbZu-.js} +1 -1
  20. package/dist/client/assets/{glsl-CP4rggAA.js → glsl-Dnrk_Jnx.js} +1 -1
  21. package/dist/client/assets/{graphql-Dbm6sAtp.js → graphql-DlWTPvCG.js} +1 -1
  22. package/dist/client/assets/{hack-Bj9y3SGf.js → hack-DQg1Ek33.js} +1 -1
  23. package/dist/client/assets/{haml-DRGrdf3f.js → haml-DSk45qIE.js} +1 -1
  24. package/dist/client/assets/{handlebars-CFKjcBMg.js → handlebars-DuLvATB2.js} +1 -1
  25. package/dist/client/assets/{html-Vcd4eHHg.js → html-D4DiUnLg.js} +1 -1
  26. package/dist/client/assets/{html-derivative-BF0YbD4L.js → html-derivative-CS5MZ6d9.js} +1 -1
  27. package/dist/client/assets/{http-CGVTa2NT.js → http-CkDncfer.js} +1 -1
  28. package/dist/client/assets/{hurl-B0GrsGqd.js → hurl-DU39oO3U.js} +1 -1
  29. package/dist/client/assets/{index-CX1tudsF.js → index-CHPfE1Zl.js} +129 -129
  30. package/dist/client/assets/index-DHUKmLLC.css +2 -0
  31. package/dist/client/assets/{java-BJHQqHsm.js → java-lntACKEu.js} +1 -1
  32. package/dist/client/assets/{javascript-CmuMsKrc.js → javascript-CxkFc6nV.js} +1 -1
  33. package/dist/client/assets/{jinja-JxCLeq1j.js → jinja-DolO2zO7.js} +1 -1
  34. package/dist/client/assets/{jison-BdgAUhei.js → jison-Cok5FPev.js} +1 -1
  35. package/dist/client/assets/{json-DtPissHL.js → json-BebuQPrq.js} +1 -1
  36. package/dist/client/assets/{jsx-DUAxxDkP.js → jsx-iLBaUyXr.js} +1 -1
  37. package/dist/client/assets/{julia-DxDlbL6e.js → julia-C5Dsc7cH.js} +1 -1
  38. package/dist/client/assets/{just-CVmAAx2R.js → just-DJYqq_9R.js} +1 -1
  39. package/dist/client/assets/{latex-uwxggTWA.js → latex-BTTYiKj1.js} +1 -1
  40. package/dist/client/assets/{liquid-xsETAJJy.js → liquid-DpAKCrOB.js} +1 -1
  41. package/dist/client/assets/{lua-B2Hh8PgD.js → lua-BZ6b1hko.js} +1 -1
  42. package/dist/client/assets/{marko-yDeGxD87.js → marko-D8VK6iGt.js} +1 -1
  43. package/dist/client/assets/{mdc-QMp4ieYR.js → mdc-Paa3XzwY.js} +1 -1
  44. package/dist/client/assets/{nginx-7gmRmcqz.js → nginx-C5k9mWtJ.js} +1 -1
  45. package/dist/client/assets/{nim-CA8SNY_7.js → nim-Dst6YSnE.js} +1 -1
  46. package/dist/client/assets/{perl-lx5nW4VC.js → perl-XhiCjgBp.js} +1 -1
  47. package/dist/client/assets/{php-DgHiW953.js → php-BcsPLnLU.js} +1 -1
  48. package/dist/client/assets/{pug-CbbB1vwb.js → pug-GLH9-eAJ.js} +1 -1
  49. package/dist/client/assets/{qml-COrzwCIh.js → qml-Cj_lJioE.js} +1 -1
  50. package/dist/client/assets/{r-Dv7pZJDH.js → r-B70aGYK5.js} +1 -1
  51. package/dist/client/assets/{razor-D2m8EDP5.js → razor-R3gub_zy.js} +1 -1
  52. package/dist/client/assets/{regexp-BXLT-jPc.js → regexp-itC0dIUJ.js} +1 -1
  53. package/dist/client/assets/{rst-_S6rrUYh.js → rst-DdyoV8E2.js} +1 -1
  54. package/dist/client/assets/{ruby-C3XO7tYY.js → ruby-BYBZsv66.js} +1 -1
  55. package/dist/client/assets/{sas-DP2k4iuN.js → sas-fqfqXqj1.js} +1 -1
  56. package/dist/client/assets/{scss-lhLFMXGn.js → scss-B-ELv6mu.js} +1 -1
  57. package/dist/client/assets/{shellscript-BYlBPHen.js → shellscript-BgB8TNw6.js} +1 -1
  58. package/dist/client/assets/{shellsession-CbVyQKWZ.js → shellsession-BLK2Dgkm.js} +1 -1
  59. package/dist/client/assets/{soy-Be8a0lHq.js → soy-C7_RmNrp.js} +1 -1
  60. package/dist/client/assets/{sql-2KxvU9YS.js → sql-AUgbUJq4.js} +1 -1
  61. package/dist/client/assets/{stata-BxlWftTS.js → stata-CIVqSIOr.js} +1 -1
  62. package/dist/client/assets/{surrealql-CJ-q86nR.js → surrealql-BzRQzc5S.js} +1 -1
  63. package/dist/client/assets/{svelte-Q1ml0OiY.js → svelte-BCIwEwtb.js} +1 -1
  64. package/dist/client/assets/{templ-BbfPZhtu.js → templ-C1hbwe4u.js} +1 -1
  65. package/dist/client/assets/{tex-Dcth4Gi6.js → tex-CI4tIsaP.js} +1 -1
  66. package/dist/client/assets/{ts-tags-BKhSOXI3.js → ts-tags-SUeikhEp.js} +1 -1
  67. package/dist/client/assets/{tsx-CS6iQ0XH.js → tsx-xkp7aIZs.js} +1 -1
  68. package/dist/client/assets/{twig-BHp31ZxS.js → twig-CGgBSAyc.js} +1 -1
  69. package/dist/client/assets/{typescript-16YJBTaO.js → typescript-O2YMTl_s.js} +1 -1
  70. package/dist/client/assets/{vue-CMKwTi4r.js → vue-DsNRxos1.js} +1 -1
  71. package/dist/client/assets/{vue-html-Dr8VUA2G.js → vue-html-CuY3t7bs.js} +1 -1
  72. package/dist/client/assets/{vue-vine-DZUqDerl.js → vue-vine-C6kSCKwY.js} +1 -1
  73. package/dist/client/assets/{xml-CBbBKKDC.js → xml-DafwzOLY.js} +1 -1
  74. package/dist/client/assets/{xsl-DWEX6PKX.js → xsl-1SGGZibr.js} +1 -1
  75. package/dist/client/assets/{yaml-DvKvvh3X.js → yaml-DSVhzmhr.js} +1 -1
  76. package/dist/client/index.html +2 -2
  77. package/dist/client/sw.js +1 -1
  78. package/dist/server/analytics/engine.js +241 -241
  79. package/dist/server/assets.js +4 -4
  80. package/dist/server/auth/passphrase.js +13 -13
  81. package/dist/server/config.js +7 -7
  82. package/dist/server/daemon.js +93 -93
  83. package/dist/server/features/brainstorm.js +42 -42
  84. package/dist/server/features/ralph-loop.js +33 -33
  85. package/dist/server/features/scheduler.js +53 -53
  86. package/dist/server/features/specs.js +54 -54
  87. package/dist/server/features/sticky-notes.js +17 -17
  88. package/dist/server/features/superpowers.js +24 -24
  89. package/dist/server/handlers/analytics.js +1 -1
  90. package/dist/server/handlers/attachment.js +32 -32
  91. package/dist/server/handlers/bookmarks.js +4 -4
  92. package/dist/server/handlers/brainstorm.js +4 -4
  93. package/dist/server/handlers/chat.js +54 -54
  94. package/dist/server/handlers/editor.js +13 -13
  95. package/dist/server/handlers/fs.js +51 -51
  96. package/dist/server/handlers/hooks.js +20 -20
  97. package/dist/server/handlers/loop.js +6 -6
  98. package/dist/server/handlers/memory.js +44 -44
  99. package/dist/server/handlers/mesh.js +60 -60
  100. package/dist/server/handlers/notes.js +7 -7
  101. package/dist/server/handlers/plugins.js +174 -174
  102. package/dist/server/handlers/project-settings.js +26 -26
  103. package/dist/server/handlers/scheduler.js +6 -6
  104. package/dist/server/handlers/session.js +24 -24
  105. package/dist/server/handlers/settings.js +21 -21
  106. package/dist/server/handlers/skills.js +91 -91
  107. package/dist/server/handlers/specs.js +51 -28
  108. package/dist/server/handlers/terminal.js +13 -13
  109. package/dist/server/handlers/themes.js +21 -21
  110. package/dist/server/handlers/update.js +17 -17
  111. package/dist/server/hooks/event_forward.sh +34 -0
  112. package/dist/server/hooks/post_tool_use.sh +26 -0
  113. package/dist/server/hooks/statusline.sh +26 -0
  114. package/dist/server/identity.js +6 -6
  115. package/dist/server/index.js +111 -111
  116. package/dist/server/logger.js +1 -1
  117. package/dist/server/mesh/connector.js +78 -78
  118. package/dist/server/mesh/crypto.js +20 -20
  119. package/dist/server/mesh/discovery.js +14 -14
  120. package/dist/server/mesh/pairing.js +30 -30
  121. package/dist/server/mesh/peers.js +10 -10
  122. package/dist/server/mesh/proxy.js +14 -14
  123. package/dist/server/mesh/session-sync.js +23 -23
  124. package/dist/server/project/bookmarks.js +11 -11
  125. package/dist/server/project/context-breakdown.js +70 -70
  126. package/dist/server/project/file-browser.js +17 -17
  127. package/dist/server/project/project-files.js +68 -68
  128. package/dist/server/project/registry.js +10 -10
  129. package/dist/server/project/sdk-bridge.js +157 -157
  130. package/dist/server/project/session.js +201 -199
  131. package/dist/server/project/terminal.js +15 -15
  132. package/dist/server/project/warmup.js +37 -37
  133. package/dist/server/push.js +11 -11
  134. package/dist/server/runtime.js +1 -1
  135. package/dist/server/tls.js +15 -15
  136. package/dist/server/tui.js +15 -15
  137. package/dist/server/update-checker.js +21 -21
  138. package/dist/server/ws/broadcast.js +18 -18
  139. package/dist/server/ws/router.js +17 -17
  140. package/dist/shared/constants.js +8 -8
  141. package/package.json +2 -2
  142. package/dist/client/assets/index-DlfI20Gn.css +0 -2
@@ -3,9 +3,9 @@ import { join } from "node:path";
3
3
  import { loadConfig } from "../config.js";
4
4
  import { broadcast } from "../ws/broadcast.js";
5
5
  import { log } from "../logger.js";
6
- var activeBrainstorms = {};
7
- var watchers = [];
8
- var debounceTimers = {};
6
+ let activeBrainstorms = {};
7
+ let watchers = [];
8
+ let debounceTimers = {};
9
9
  function debounce(key, fn, ms) {
10
10
  if (debounceTimers[key]) {
11
11
  clearTimeout(debounceTimers[key]);
@@ -19,13 +19,13 @@ function getMostRecentSessionDir(brainstormDir) {
19
19
  if (!existsSync(brainstormDir)) {
20
20
  return null;
21
21
  }
22
- var entries = [];
22
+ const entries = [];
23
23
  try {
24
- var names = readdirSync(brainstormDir);
25
- for (var i = 0; i < names.length; i++) {
26
- var fullPath = join(brainstormDir, names[i]);
24
+ const names = readdirSync(brainstormDir);
25
+ for (let i = 0; i < names.length; i++) {
26
+ const fullPath = join(brainstormDir, names[i]);
27
27
  try {
28
- var stat = statSync(fullPath);
28
+ const stat = statSync(fullPath);
29
29
  if (stat.isDirectory()) {
30
30
  entries.push({ name: names[i], mtime: stat.mtimeMs });
31
31
  }
@@ -59,11 +59,11 @@ function handleContentFile(projectSlug, contentDir, sessionDir, filename) {
59
59
  broadcast({ type: "brainstorm:cleared" });
60
60
  return;
61
61
  }
62
- var filePath = join(contentDir, filename);
62
+ const filePath = join(contentDir, filename);
63
63
  if (!existsSync(filePath)) {
64
64
  return;
65
65
  }
66
- var html;
66
+ let html;
67
67
  try {
68
68
  html = readFileSync(filePath, "utf-8");
69
69
  }
@@ -83,32 +83,32 @@ function handleStateFile(projectSlug, filename) {
83
83
  }
84
84
  }
85
85
  function watchSessionDir(projectSlug, sessionDir) {
86
- var contentDir = join(sessionDir, "content");
87
- var stateDir = join(sessionDir, "state");
86
+ const contentDir = join(sessionDir, "content");
87
+ const stateDir = join(sessionDir, "state");
88
88
  if (!existsSync(contentDir)) {
89
89
  mkdirSync(contentDir, { recursive: true });
90
90
  }
91
91
  if (!existsSync(stateDir)) {
92
92
  mkdirSync(stateDir, { recursive: true });
93
93
  }
94
- var alreadyStopped = existsSync(join(stateDir, "server-stopped"));
94
+ const alreadyStopped = existsSync(join(stateDir, "server-stopped"));
95
95
  if (!alreadyStopped) {
96
- var existingFiles = [];
96
+ let existingFiles = [];
97
97
  try {
98
98
  existingFiles = readdirSync(contentDir);
99
99
  }
100
100
  catch {
101
101
  // ok
102
102
  }
103
- for (var i = 0; i < existingFiles.length; i++) {
104
- var fname = existingFiles[i];
103
+ for (let i = 0; i < existingFiles.length; i++) {
104
+ const fname = existingFiles[i];
105
105
  if (fname.endsWith(".html") && !isWaitingFile(fname)) {
106
106
  handleContentFile(projectSlug, contentDir, sessionDir, fname);
107
107
  }
108
108
  }
109
109
  }
110
110
  try {
111
- var contentWatcher = watch(contentDir, function (eventType, filename) {
111
+ const contentWatcher = watch(contentDir, function (eventType, filename) {
112
112
  if (!filename) {
113
113
  return;
114
114
  }
@@ -122,7 +122,7 @@ function watchSessionDir(projectSlug, sessionDir) {
122
122
  log.server("[brainstorm] failed to watch content dir %s: %s", contentDir, err);
123
123
  }
124
124
  try {
125
- var stateWatcher = watch(stateDir, function (eventType, filename) {
125
+ const stateWatcher = watch(stateDir, function (eventType, filename) {
126
126
  if (!filename) {
127
127
  return;
128
128
  }
@@ -137,19 +137,19 @@ function watchSessionDir(projectSlug, sessionDir) {
137
137
  }
138
138
  }
139
139
  function watchBrainstormDir(projectSlug, brainstormDir) {
140
- var recentSession = getMostRecentSessionDir(brainstormDir);
140
+ const recentSession = getMostRecentSessionDir(brainstormDir);
141
141
  if (recentSession) {
142
142
  watchSessionDir(projectSlug, recentSession);
143
143
  }
144
144
  try {
145
- var dirWatcher = watch(brainstormDir, function (eventType, filename) {
145
+ const dirWatcher = watch(brainstormDir, function (eventType, filename) {
146
146
  if (!filename) {
147
147
  return;
148
148
  }
149
149
  debounce("brainstorm:" + brainstormDir + ":" + filename, function () {
150
- var candidate = join(brainstormDir, filename);
150
+ const candidate = join(brainstormDir, filename);
151
151
  try {
152
- var stat = statSync(candidate);
152
+ const stat = statSync(candidate);
153
153
  if (stat.isDirectory()) {
154
154
  log.server("[brainstorm] new session dir detected: %s", candidate);
155
155
  watchSessionDir(projectSlug, candidate);
@@ -167,8 +167,8 @@ function watchBrainstormDir(projectSlug, brainstormDir) {
167
167
  }
168
168
  }
169
169
  function watchProjectRoot(projectSlug, projectPath) {
170
- var superpowersDir = join(projectPath, ".superpowers");
171
- var brainstormDir = join(superpowersDir, "brainstorm");
170
+ const superpowersDir = join(projectPath, ".superpowers");
171
+ const brainstormDir = join(superpowersDir, "brainstorm");
172
172
  if (existsSync(brainstormDir)) {
173
173
  watchBrainstormDir(projectSlug, brainstormDir);
174
174
  return;
@@ -178,7 +178,7 @@ function watchProjectRoot(projectSlug, projectPath) {
178
178
  return;
179
179
  }
180
180
  try {
181
- var rootWatcher = watch(projectPath, function (eventType, filename) {
181
+ const rootWatcher = watch(projectPath, function (eventType, filename) {
182
182
  if (filename !== ".superpowers") {
183
183
  return;
184
184
  }
@@ -199,7 +199,7 @@ function watchForBrainstormDir(projectSlug, superpowersDir, brainstormDir) {
199
199
  return;
200
200
  }
201
201
  try {
202
- var spWatcher = watch(superpowersDir, function (eventType, filename) {
202
+ const spWatcher = watch(superpowersDir, function (eventType, filename) {
203
203
  if (filename !== "brainstorm") {
204
204
  return;
205
205
  }
@@ -215,10 +215,10 @@ function watchForBrainstormDir(projectSlug, superpowersDir, brainstormDir) {
215
215
  }
216
216
  }
217
217
  export function startBrainstormWatchers() {
218
- var config = loadConfig();
219
- var projects = config.projects;
220
- for (var i = 0; i < projects.length; i++) {
221
- var project = projects[i];
218
+ const config = loadConfig();
219
+ const projects = config.projects;
220
+ for (let i = 0; i < projects.length; i++) {
221
+ const project = projects[i];
222
222
  if (!project.path || !project.slug) {
223
223
  continue;
224
224
  }
@@ -230,7 +230,7 @@ export function startBrainstormWatchers() {
230
230
  }
231
231
  }
232
232
  export function stopBrainstormWatchers() {
233
- for (var i = 0; i < watchers.length; i++) {
233
+ for (let i = 0; i < watchers.length; i++) {
234
234
  try {
235
235
  watchers[i].close();
236
236
  }
@@ -240,8 +240,8 @@ export function stopBrainstormWatchers() {
240
240
  }
241
241
  watchers = [];
242
242
  activeBrainstorms = {};
243
- var keys = Object.keys(debounceTimers);
244
- for (var i = 0; i < keys.length; i++) {
243
+ const keys = Object.keys(debounceTimers);
244
+ for (let i = 0; i < keys.length; i++) {
245
245
  clearTimeout(debounceTimers[keys[i]]);
246
246
  }
247
247
  debounceTimers = {};
@@ -250,23 +250,23 @@ export function getActiveBrainstorm(projectSlug) {
250
250
  return activeBrainstorms[projectSlug] || null;
251
251
  }
252
252
  export function getAnyActiveBrainstorm() {
253
- var keys = Object.keys(activeBrainstorms);
253
+ const keys = Object.keys(activeBrainstorms);
254
254
  if (keys.length === 0)
255
255
  return null;
256
256
  return activeBrainstorms[keys[0]];
257
257
  }
258
258
  export function stopBrainstorm(projectSlug) {
259
- var slugs = projectSlug ? [projectSlug] : Object.keys(activeBrainstorms);
260
- for (var i = 0; i < slugs.length; i++) {
261
- var slug = slugs[i];
262
- var active = activeBrainstorms[slug];
259
+ const slugs = projectSlug ? [projectSlug] : Object.keys(activeBrainstorms);
260
+ for (let i = 0; i < slugs.length; i++) {
261
+ const slug = slugs[i];
262
+ const active = activeBrainstorms[slug];
263
263
  if (!active)
264
264
  continue;
265
- var stateDir = join(active.sessionDir, "state");
265
+ const stateDir = join(active.sessionDir, "state");
266
266
  if (!existsSync(stateDir)) {
267
267
  mkdirSync(stateDir, { recursive: true });
268
268
  }
269
- var stoppedPath = join(stateDir, "server-stopped");
269
+ const stoppedPath = join(stateDir, "server-stopped");
270
270
  if (!existsSync(stoppedPath)) {
271
271
  try {
272
272
  writeFileSync(stoppedPath, String(Date.now()));
@@ -281,11 +281,11 @@ export function stopBrainstorm(projectSlug) {
281
281
  broadcast({ type: "brainstorm:cleared" });
282
282
  }
283
283
  export function writeBrainstormEvent(sessionDir, event) {
284
- var stateDir = join(sessionDir, "state");
284
+ const stateDir = join(sessionDir, "state");
285
285
  if (!existsSync(stateDir)) {
286
286
  mkdirSync(stateDir, { recursive: true });
287
287
  }
288
- var eventsFile = join(stateDir, "events");
288
+ const eventsFile = join(stateDir, "events");
289
289
  try {
290
290
  appendFileSync(eventsFile, JSON.stringify(event) + "\n", "utf-8");
291
291
  }
@@ -4,25 +4,25 @@ import { randomBytes } from "node:crypto";
4
4
  import { query } from "@anthropic-ai/claude-agent-sdk";
5
5
  import { broadcast } from "../ws/broadcast.js";
6
6
  import { getProjectBySlug } from "../project/registry.js";
7
- var activeLoops = new Map();
7
+ const activeLoops = new Map();
8
8
  function readLoopFile(projectPath, filename) {
9
- var loopsDir = join(projectPath, ".claude", "loops");
10
- var filePath = join(loopsDir, filename);
9
+ const loopsDir = join(projectPath, ".claude", "loops");
10
+ const filePath = join(loopsDir, filename);
11
11
  if (!existsSync(filePath)) {
12
12
  return null;
13
13
  }
14
14
  return readFileSync(filePath, "utf-8");
15
15
  }
16
16
  async function runIteration(loopId, prompt, cwd, iterationNum) {
17
- var accumulated = "";
18
- var stream = query({ prompt, options: { cwd, allowedTools: ["*"], permissionMode: "acceptEdits" } });
19
- for await (var msg of stream) {
20
- var typedMsg = msg;
17
+ let accumulated = "";
18
+ const stream = query({ prompt, options: { cwd, allowedTools: ["*"], permissionMode: "acceptEdits" } });
19
+ for await (const msg of stream) {
20
+ const typedMsg = msg;
21
21
  if (typedMsg.type === "stream_event") {
22
- var partial = typedMsg;
23
- var evt = partial.event;
22
+ const partial = typedMsg;
23
+ const evt = partial.event;
24
24
  if (evt.type === "content_block_delta") {
25
- var deltaEvt = evt;
25
+ const deltaEvt = evt;
26
26
  if (deltaEvt.delta.type === "text_delta" && typeof deltaEvt.delta.text === "string") {
27
27
  accumulated += deltaEvt.delta.text;
28
28
  broadcast({ type: "loop:delta", loopId, iteration: iterationNum, text: deltaEvt.delta.text });
@@ -33,38 +33,38 @@ async function runIteration(loopId, prompt, cwd, iterationNum) {
33
33
  return accumulated;
34
34
  }
35
35
  async function runJudge(judgePrompt, iterationResult, cwd) {
36
- var fullPrompt = `${judgePrompt}\n\n<iteration_result>\n${iterationResult}\n</iteration_result>\n\nRespond with PASS or FAIL on the first line, followed by a brief reason.`;
37
- var accumulated = "";
38
- var stream = query({ prompt: fullPrompt, options: { cwd, allowedTools: [], permissionMode: "acceptEdits" } });
39
- for await (var msg of stream) {
40
- var typedMsg = msg;
36
+ const fullPrompt = `${judgePrompt}\n\n<iteration_result>\n${iterationResult}\n</iteration_result>\n\nRespond with PASS or FAIL on the first line, followed by a brief reason.`;
37
+ let accumulated = "";
38
+ const stream = query({ prompt: fullPrompt, options: { cwd, allowedTools: [], permissionMode: "acceptEdits" } });
39
+ for await (const msg of stream) {
40
+ const typedMsg = msg;
41
41
  if (typedMsg.type === "stream_event") {
42
- var partial = typedMsg;
43
- var evt = partial.event;
42
+ const partial = typedMsg;
43
+ const evt = partial.event;
44
44
  if (evt.type === "content_block_delta") {
45
- var deltaEvt = evt;
45
+ const deltaEvt = evt;
46
46
  if (deltaEvt.delta.type === "text_delta" && typeof deltaEvt.delta.text === "string") {
47
47
  accumulated += deltaEvt.delta.text;
48
48
  }
49
49
  }
50
50
  }
51
51
  }
52
- var firstLine = accumulated.trim().split("\n")[0].toUpperCase();
53
- var pass = firstLine.startsWith("PASS");
54
- var reason = accumulated.trim().split("\n").slice(1).join("\n").trim() || accumulated.trim();
52
+ const firstLine = accumulated.trim().split("\n")[0].toUpperCase();
53
+ const pass = firstLine.startsWith("PASS");
54
+ const reason = accumulated.trim().split("\n").slice(1).join("\n").trim() || accumulated.trim();
55
55
  return { pass, reason };
56
56
  }
57
57
  export function startLoop(projectSlug) {
58
- var project = getProjectBySlug(projectSlug);
58
+ const project = getProjectBySlug(projectSlug);
59
59
  if (!project) {
60
60
  return null;
61
61
  }
62
- var prompt = readLoopFile(project.path, "PROMPT.md");
62
+ const prompt = readLoopFile(project.path, "PROMPT.md");
63
63
  if (!prompt) {
64
64
  return null;
65
65
  }
66
- var loopId = "loop_" + Date.now() + "_" + randomBytes(3).toString("hex");
67
- var loopStatus = {
66
+ const loopId = "loop_" + Date.now() + "_" + randomBytes(3).toString("hex");
67
+ const loopStatus = {
68
68
  id: loopId,
69
69
  projectSlug,
70
70
  status: "running",
@@ -77,9 +77,9 @@ export function startLoop(projectSlug) {
77
77
  activeLoops.set(loopId, loopStatus);
78
78
  broadcast({ type: "loop:started", loop: loopStatus });
79
79
  void (async function () {
80
- var judgePrompt = readLoopFile(project.path, "JUDGE.md");
81
- for (var i = 1; i <= loopStatus.maxIterations; i++) {
82
- var current = activeLoops.get(loopId);
80
+ const judgePrompt = readLoopFile(project.path, "JUDGE.md");
81
+ for (let i = 1; i <= loopStatus.maxIterations; i++) {
82
+ const current = activeLoops.get(loopId);
83
83
  if (!current || current.status === "stopped") {
84
84
  break;
85
85
  }
@@ -87,9 +87,9 @@ export function startLoop(projectSlug) {
87
87
  activeLoops.set(loopId, current);
88
88
  broadcast({ type: "loop:status_update", loop: { ...current } });
89
89
  try {
90
- var result = await runIteration(loopId, prompt, project.path, i);
90
+ const result = await runIteration(loopId, prompt, project.path, i);
91
91
  if (judgePrompt) {
92
- var judgment = await runJudge(judgePrompt, result, project.path);
92
+ const judgment = await runJudge(judgePrompt, result, project.path);
93
93
  current.judgeReason = judgment.reason;
94
94
  activeLoops.set(loopId, current);
95
95
  if (judgment.pass) {
@@ -102,7 +102,7 @@ export function startLoop(projectSlug) {
102
102
  }
103
103
  }
104
104
  catch (err) {
105
- var errMsg = err instanceof Error ? err.message : String(err);
105
+ const errMsg = err instanceof Error ? err.message : String(err);
106
106
  console.error(`[ralph-loop] Iteration ${i} error:`, errMsg);
107
107
  current.status = "error";
108
108
  current.judgeReason = errMsg;
@@ -112,7 +112,7 @@ export function startLoop(projectSlug) {
112
112
  return;
113
113
  }
114
114
  }
115
- var final = activeLoops.get(loopId);
115
+ const final = activeLoops.get(loopId);
116
116
  if (final && final.status === "running") {
117
117
  final.status = "done";
118
118
  final.finishedAt = Date.now();
@@ -123,7 +123,7 @@ export function startLoop(projectSlug) {
123
123
  return loopStatus;
124
124
  }
125
125
  export function stopLoop(loopId) {
126
- var loop = activeLoops.get(loopId);
126
+ const loop = activeLoops.get(loopId);
127
127
  if (!loop || loop.status !== "running") {
128
128
  return false;
129
129
  }
@@ -3,11 +3,11 @@ import { join } from "node:path";
3
3
  import { randomBytes } from "node:crypto";
4
4
  import { getLatticeHome } from "../config.js";
5
5
  import { broadcast } from "../ws/broadcast.js";
6
- var schedulesFile = "";
7
- var tasks = [];
8
- var timerId = null;
9
- var lastTriggeredMinute = {};
10
- var CHECK_INTERVAL = 30 * 1000;
6
+ let schedulesFile = "";
7
+ let tasks = [];
8
+ let timerId = null;
9
+ const lastTriggeredMinute = {};
10
+ const CHECK_INTERVAL = 30 * 1000;
11
11
  function getSchedulesPath() {
12
12
  if (!schedulesFile) {
13
13
  schedulesFile = join(getLatticeHome(), "schedules.json");
@@ -15,37 +15,37 @@ function getSchedulesPath() {
15
15
  return schedulesFile;
16
16
  }
17
17
  function parseCronField(field, min, max) {
18
- var values = [];
19
- var parts = field.split(",");
20
- for (var i = 0; i < parts.length; i++) {
21
- var part = parts[i].trim();
18
+ const values = [];
19
+ const parts = field.split(",");
20
+ for (let i = 0; i < parts.length; i++) {
21
+ const part = parts[i].trim();
22
22
  if (part.indexOf("/") !== -1) {
23
- var slashParts = part.split("/");
24
- var step = parseInt(slashParts[1], 10);
25
- var rangeStr = slashParts[0];
26
- var rangeMin = min;
27
- var rangeMax = max;
23
+ const slashParts = part.split("/");
24
+ const step = parseInt(slashParts[1], 10);
25
+ const rangeStr = slashParts[0];
26
+ let rangeMin = min;
27
+ let rangeMax = max;
28
28
  if (rangeStr !== "*") {
29
- var rp = rangeStr.split("-");
29
+ const rp = rangeStr.split("-");
30
30
  rangeMin = parseInt(rp[0], 10);
31
31
  rangeMax = rp.length > 1 ? parseInt(rp[1], 10) : rangeMin;
32
32
  }
33
- for (var v = rangeMin; v <= rangeMax; v += step) {
33
+ for (let v = rangeMin; v <= rangeMax; v += step) {
34
34
  values.push(v);
35
35
  }
36
36
  continue;
37
37
  }
38
38
  if (part === "*") {
39
- for (var v = min; v <= max; v++) {
39
+ for (let v = min; v <= max; v++) {
40
40
  values.push(v);
41
41
  }
42
42
  continue;
43
43
  }
44
44
  if (part.indexOf("-") !== -1) {
45
- var rangeParts = part.split("-");
46
- var from = parseInt(rangeParts[0], 10);
47
- var to = parseInt(rangeParts[1], 10);
48
- for (var v = from; v <= to; v++) {
45
+ const rangeParts = part.split("-");
46
+ const from = parseInt(rangeParts[0], 10);
47
+ const to = parseInt(rangeParts[1], 10);
48
+ for (let v = from; v <= to; v++) {
49
49
  values.push(v);
50
50
  }
51
51
  continue;
@@ -55,7 +55,7 @@ function parseCronField(field, min, max) {
55
55
  return values;
56
56
  }
57
57
  function parseCron(expr) {
58
- var fields = expr.trim().split(/\s+/);
58
+ const fields = expr.trim().split(/\s+/);
59
59
  if (fields.length !== 5) {
60
60
  return null;
61
61
  }
@@ -75,15 +75,15 @@ function cronMatches(parsed, date) {
75
75
  parsed.daysOfWeek.indexOf(date.getDay()) !== -1);
76
76
  }
77
77
  function nextRunTime(cronExpr, after) {
78
- var parsed = parseCron(cronExpr);
78
+ const parsed = parseCron(cronExpr);
79
79
  if (!parsed) {
80
80
  return null;
81
81
  }
82
- var d = new Date(after || Date.now());
82
+ const d = new Date(after || Date.now());
83
83
  d.setSeconds(0, 0);
84
84
  d.setMinutes(d.getMinutes() + 1);
85
- var limit = 366 * 24 * 60;
86
- for (var i = 0; i < limit; i++) {
85
+ const limit = 366 * 24 * 60;
86
+ for (let i = 0; i < limit; i++) {
87
87
  if (cronMatches(parsed, d)) {
88
88
  return d.getTime();
89
89
  }
@@ -92,17 +92,17 @@ function nextRunTime(cronExpr, after) {
92
92
  return null;
93
93
  }
94
94
  export function loadSchedules() {
95
- var path = getSchedulesPath();
95
+ const path = getSchedulesPath();
96
96
  if (!existsSync(path)) {
97
97
  tasks = [];
98
98
  return;
99
99
  }
100
100
  try {
101
- var raw = readFileSync(path, "utf-8");
102
- var parsed = JSON.parse(raw);
101
+ const raw = readFileSync(path, "utf-8");
102
+ const parsed = JSON.parse(raw);
103
103
  tasks = parsed.tasks || [];
104
- for (var i = 0; i < tasks.length; i++) {
105
- var task = tasks[i];
104
+ for (let i = 0; i < tasks.length; i++) {
105
+ const task = tasks[i];
106
106
  if (task.enabled && task.cron) {
107
107
  task.nextRunAt = nextRunTime(task.cron);
108
108
  }
@@ -114,12 +114,12 @@ export function loadSchedules() {
114
114
  }
115
115
  }
116
116
  function saveSchedules() {
117
- var path = getSchedulesPath();
118
- var dir = join(path, "..");
117
+ const path = getSchedulesPath();
118
+ const dir = join(path, "..");
119
119
  if (!existsSync(dir)) {
120
120
  mkdirSync(dir, { recursive: true });
121
121
  }
122
- var tmp = path + ".tmp";
122
+ const tmp = path + ".tmp";
123
123
  try {
124
124
  writeFileSync(tmp, JSON.stringify({ tasks }, null, 2));
125
125
  renameSync(tmp, path);
@@ -129,25 +129,25 @@ function saveSchedules() {
129
129
  }
130
130
  }
131
131
  function tick() {
132
- var now = Date.now();
133
- var nowMinuteKey = Math.floor(now / 60000);
134
- for (var i = 0; i < tasks.length; i++) {
135
- var task = tasks[i];
132
+ const now = Date.now();
133
+ const nowMinuteKey = Math.floor(now / 60000);
134
+ for (let i = 0; i < tasks.length; i++) {
135
+ const task = tasks[i];
136
136
  if (!task.enabled || !task.nextRunAt) {
137
137
  continue;
138
138
  }
139
139
  if (task.nextRunAt > now) {
140
140
  continue;
141
141
  }
142
- var triggerKey = task.id + "_" + nowMinuteKey;
142
+ const triggerKey = task.id + "_" + nowMinuteKey;
143
143
  if (lastTriggeredMinute[triggerKey]) {
144
144
  continue;
145
145
  }
146
146
  lastTriggeredMinute[triggerKey] = true;
147
- var keys = Object.keys(lastTriggeredMinute);
148
- for (var k = 0; k < keys.length; k++) {
149
- var keyParts = keys[k].split("_");
150
- var keyMinute = parseInt(keyParts[keyParts.length - 1], 10);
147
+ const keys = Object.keys(lastTriggeredMinute);
148
+ for (let k = 0; k < keys.length; k++) {
149
+ const keyParts = keys[k].split("_");
150
+ const keyMinute = parseInt(keyParts[keyParts.length - 1], 10);
151
151
  if (keyMinute < nowMinuteKey - 1) {
152
152
  delete lastTriggeredMinute[keys[k]];
153
153
  }
@@ -180,12 +180,12 @@ export function listTasks() {
180
180
  return tasks.slice();
181
181
  }
182
182
  export function createTask(data) {
183
- var parsed = parseCron(data.cron);
183
+ const parsed = parseCron(data.cron);
184
184
  if (!parsed) {
185
185
  return null;
186
186
  }
187
- var now = Date.now();
188
- var task = {
187
+ const now = Date.now();
188
+ const task = {
189
189
  id: "task_" + now + "_" + randomBytes(3).toString("hex"),
190
190
  name: data.name,
191
191
  prompt: data.prompt,
@@ -202,8 +202,8 @@ export function createTask(data) {
202
202
  return task;
203
203
  }
204
204
  export function updateTask(taskId, data) {
205
- var task = null;
206
- for (var i = 0; i < tasks.length; i++) {
205
+ let task = null;
206
+ for (let i = 0; i < tasks.length; i++) {
207
207
  if (tasks[i].id === taskId) {
208
208
  task = tasks[i];
209
209
  break;
@@ -212,7 +212,7 @@ export function updateTask(taskId, data) {
212
212
  if (!task)
213
213
  return null;
214
214
  if (data.cron && data.cron !== task.cron) {
215
- var parsed = parseCron(data.cron);
215
+ const parsed = parseCron(data.cron);
216
216
  if (!parsed)
217
217
  return null;
218
218
  task.cron = data.cron;
@@ -227,8 +227,8 @@ export function updateTask(taskId, data) {
227
227
  return task;
228
228
  }
229
229
  export function deleteTask(taskId) {
230
- var idx = -1;
231
- for (var i = 0; i < tasks.length; i++) {
230
+ let idx = -1;
231
+ for (let i = 0; i < tasks.length; i++) {
232
232
  if (tasks[i].id === taskId) {
233
233
  idx = i;
234
234
  break;
@@ -242,8 +242,8 @@ export function deleteTask(taskId) {
242
242
  return true;
243
243
  }
244
244
  export function toggleTask(taskId) {
245
- var task = null;
246
- for (var i = 0; i < tasks.length; i++) {
245
+ let task = null;
246
+ for (let i = 0; i < tasks.length; i++) {
247
247
  if (tasks[i].id === taskId) {
248
248
  task = tasks[i];
249
249
  break;