@rithien/comfy_adapter 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,20 @@
1
+ # Changelog
2
+
3
+ ## v0.1.2 — 2026-05-18
4
+
5
+ - **Bug fix**: `buildSingleCallback` wysyłał `pcall(Token.get(<n>)(d)); pcall(Server.raise_data_set(d))` (dual-path). Gdy backend nie miał record dla zapytanego key (świeży gracz), `d.value=nil`, a handler `on_data_set_changed` w `scenario/lib/sessions.lua` interpretował to jako DELETE i nullował `storage.sessions[name]` + `storage.trusted[name]` świeżo ustawione przez `try_upload_data_token`. Effect runtime: gracz online > threshold, ale `/sessionsstatus` pokazywał `sessions=0, trusted=false`. Pozostawiono tylko Token callback path; `Server.raise_data_set` nadal wywoływany w `broadcastDataSet` (cross-instance push, intencjonalny). Anuluje decyzję dual-path z [2026-05-17][22:54].
6
+
7
+ ## v0.1.1 — 2026-05-18
8
+
9
+ - **Bug fix**: `/cc` RCON callbacks (`buildSingleCallback`, `buildAllCallback`, `broadcastDataSet`) used `require('lib.token')` / `require('lib.server')` to access scenario modules. Factorio disables `require` outside of `control.lua` parsing — runtime calls raised `"Require can't be used outside of control.lua parsing"` and dropped the DATA-GET response, leaving `storage.sessions` empty. Switched to `_G.Token` / `_G.Server` (globals exposed by `scenario/control.lua` from v0.1.1+). **Requires** `factorio-polska` scenario v0.1.1 or newer.
10
+
11
+ ## v0.1.0 — 2026-05-17
12
+
13
+ - Initial release. Parses tagged stdout from the `factorio-polska` scenario:
14
+ - `[DISCORD*]` → Discord channel (via `@rithien/discord_bridge` channel routing)
15
+ - `[ANTIGRIEF-LOG]{category, action}` → color-coded Discord embed
16
+ - `[DATA-SET]{data_set, key, value?}` → JSON datastore upsert (debounced)
17
+ - `[DATA-GET]<token>{data_set, key}` → JSON read + RCON callback (dual-path: `Token.get` + `Server.raise_data_set`)
18
+ - Cross-instance broadcast for shared datasets (`comfy_adapter.broadcast_data_sets`, default `sessions`) — enables cross-server trust propagation.
19
+ - Shared Discord client with `@rithien/discord_bridge` (no separate bot login).
20
+ - JSON storage with atomic write (tmp + rename) and configurable write debounce.
package/controller.js CHANGED
@@ -329,6 +329,7 @@ class ControllerPlugin extends BaseControllerPlugin {
329
329
  async broadcastDataSet(sourceInstanceId, dataSet, key, value) {
330
330
  // Buduje pojedyncze /cc per instancja docelowa. Tylko raise_data_set
331
331
  // (nie Token.get — żaden token nie został wygenerowany dla tego data set u odbiorcy).
332
+ // Używa globalu `Server` z scenario/control.lua (require wyłączone w runtime).
332
333
  const fields = [`data_set=${luaString(dataSet)}`, `key=${luaString(key)}`];
333
334
  if (value !== null && value !== undefined) {
334
335
  fields.push(`value=${luaLiteral(value)}`);
@@ -336,7 +337,7 @@ class ControllerPlugin extends BaseControllerPlugin {
336
337
  const data = `{${fields.join(",")}}`;
337
338
  const cmd =
338
339
  `/cc local d=${data} ` +
339
- `local ok,err=pcall(function() require('lib.server').raise_data_set(d) end) ` +
340
+ `local ok,err=pcall(function() Server.raise_data_set(d) end) ` +
340
341
  `if not ok then log('[comfy_adapter broadcast] '..tostring(err)) end`;
341
342
 
342
343
  const targets = [];
@@ -374,8 +375,20 @@ class ControllerPlugin extends BaseControllerPlugin {
374
375
  }
375
376
 
376
377
  /**
377
- * Buduje `/cc local d={...}; require('lib.token').get(<token>)(d); require('lib.server').raise_data_set(d)`.
378
- * Oba paths są wywoływane: per-request closure (Token) i broadcast (raise_data_set).
378
+ * Buduje `/cc local d={...}; Token.get(<token>)(d)`.
379
+ *
380
+ * Single-path: tylko per-request closure (Token callback). NIE wywołujemy
381
+ * `Server.raise_data_set(d)` na DATA-GET response — to powodowało race condition
382
+ * w `scenario/lib/sessions.lua`: gdy backend nie ma record (świeży gracz),
383
+ * `d.value=nil`, a handler `on_data_set_changed` interpretuje to jako DELETE
384
+ * i nuluje `storage.sessions[name]` + `storage.trusted[name]` świeżo ustawione
385
+ * przez Token callback (try_upload_data_token). Cross-instance broadcast
386
+ * pozostaje w `broadcastDataSet` (wywoływany z `handleDataSet`, nie z odpowiedzi
387
+ * na DATA-GET). Patrz DECISIONS.md [2026-05-18] (anuluje dual-path z [2026-05-17][22:54]).
388
+ *
389
+ * Używa globala `Token` eksponowanego przez scenario/control.lua —
390
+ * `require` jest wyłączone w runtime Factorio ("Require can't be used outside of
391
+ * control.lua parsing"). Wymaga scenariusza factorio-polska v0.1.1+.
379
392
  */
380
393
  buildSingleCallback(token, dataSet, key, value, toPrint = null) {
381
394
  const fields = [
@@ -391,22 +404,21 @@ class ControllerPlugin extends BaseControllerPlugin {
391
404
  const data = `{${fields.join(",")}}`;
392
405
  return (
393
406
  `/cc local d=${data} ` +
394
- `local ok1,err1=pcall(function() require('lib.token').get(${token})(d) end) ` +
395
- `local ok2,err2=pcall(function() require('lib.server').raise_data_set(d) end) ` +
396
- `if not ok1 then log('[comfy_adapter Token callback] '..tostring(err1)) end ` +
397
- `if not ok2 then log('[comfy_adapter raise_data_set] '..tostring(err2)) end`
407
+ `local ok,err=pcall(function() Token.get(${token})(d) end) ` +
408
+ `if not ok then log('[comfy_adapter Token callback] '..tostring(err)) end`
398
409
  );
399
410
  }
400
411
 
401
412
  /**
402
413
  * DATA-GET-ALL response: pojedyncze callback z `entries` jako tabela {key=value,...}.
403
414
  * Format kompatybilny z Comfy try_get_all_data callback signature.
415
+ * Wymaga _G.Token (scenario v0.1.1+).
404
416
  */
405
417
  buildAllCallback(token, dataSet, dataset) {
406
418
  const data = `{data_set=${luaString(dataSet)},entries=${luaLiteral(dataset)}}`;
407
419
  return (
408
420
  `/cc local d=${data} ` +
409
- `local ok,err=pcall(function() require('lib.token').get(${token})(d) end) ` +
421
+ `local ok,err=pcall(function() Token.get(${token})(d) end) ` +
410
422
  `if not ok then log('[comfy_adapter Token all callback] '..tostring(err)) end`
411
423
  );
412
424
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "main.js": "static/main.761df12d5815fb8e02fa.js",
3
- "comfy_adapter.js": "static/comfy_adapter.1ca70d5b170a77bb6963.js",
3
+ "comfy_adapter.js": "static/comfy_adapter.e593ec53fe47f48d8273.js",
4
4
  "static/info_js.js": "static/info_js.9ad5f016be3454c1a255.js",
5
- "static/package_json.js": "static/package_json.b88ad27d58c1784bb20f.js"
5
+ "static/package_json.js": "static/package_json.e650ba10073abbad50e8.js"
6
6
  }
@@ -123,7 +123,7 @@ __webpack_require__.d(exports, {
123
123
  /******/ // This function allow to reference async chunks
124
124
  /******/ __webpack_require__.u = (chunkId) => {
125
125
  /******/ // return url for filenames based on template
126
- /******/ return "static/" + chunkId + "." + {"info_js":"9ad5f016be3454c1a255","package_json":"b88ad27d58c1784bb20f"}[chunkId] + ".js";
126
+ /******/ return "static/" + chunkId + "." + {"info_js":"9ad5f016be3454c1a255","package_json":"e650ba10073abbad50e8"}[chunkId] + ".js";
127
127
  /******/ };
128
128
  /******/ })();
129
129
  /******/
@@ -15,7 +15,7 @@
15
15
  \**********************/
16
16
  (module) {
17
17
 
18
- module.exports = /*#__PURE__*/JSON.parse('{"name":"@rithien/comfy_adapter","version":"0.1.0","description":"Clusterio plugin: parses Comfy/factorio-polska scenario stdout tags ([DISCORD*], [ANTIGRIEF-LOG], [DATA-SET/GET]) and bridges to Discord + JSON datastore","main":"info.js","scripts":{"test":"echo \\"Error: no test specified\\" && exit 1","prepare":"webpack-cli --env production"},"keywords":["clusterio","clusterio-plugin","factorio","factorio-polska","discord","comfyfactorio"],"author":"rithien <jacek@zaluzje.bialystok.pl>","license":"MIT","peerDependencies":{"@clusterio/lib":"^2.0.0-alpha.14"},"devDependencies":{"@clusterio/lib":"^2.0.0-alpha.14","@clusterio/web_ui":"^2.0.0-alpha.14","webpack":"^5.88.2","webpack-cli":"^5.1.4","webpack-merge":"^5.9.0"},"publishConfig":{"access":"public"}}');
18
+ module.exports = /*#__PURE__*/JSON.parse('{"name":"@rithien/comfy_adapter","version":"0.1.2","description":"Clusterio plugin: parses Comfy/factorio-polska scenario stdout tags ([DISCORD*], [ANTIGRIEF-LOG], [DATA-SET/GET]) and bridges to Discord + JSON datastore","main":"info.js","scripts":{"test":"echo \\"Error: no test specified\\" && exit 1","prepare":"webpack-cli --env production"},"keywords":["clusterio","clusterio-plugin","factorio","factorio-polska","discord","comfyfactorio"],"author":"rithien <jacek@zaluzje.bialystok.pl>","license":"MIT","peerDependencies":{"@clusterio/lib":"^2.0.0-alpha.14"},"devDependencies":{"@clusterio/lib":"^2.0.0-alpha.14","@clusterio/web_ui":"^2.0.0-alpha.14","webpack":"^5.88.2","webpack-cli":"^5.1.4","webpack-merge":"^5.9.0"},"publishConfig":{"access":"public"}}');
19
19
 
20
20
  /***/ }
21
21
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rithien/comfy_adapter",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Clusterio plugin: parses Comfy/factorio-polska scenario stdout tags ([DISCORD*], [ANTIGRIEF-LOG], [DATA-SET/GET]) and bridges to Discord + JSON datastore",
5
5
  "main": "info.js",
6
6
  "scripts": {