') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); chore(main): release 1.1.0 by github-actions[bot] · Pull Request #116 · ApocDev/pyops · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
{
".": "1.0.0"
".": "1.1.0"
}
52 changes: 52 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,57 @@
# Changelog

## [1.1.0](https://github.com/ApocDev/pyops/compare/v1.0.0...v1.1.0) (2026-07-07)


### ⚠ BREAKING CHANGES

* **planner:** modules are no longer applied automatically. Rows that relied on ambient auto-fill show empty fills (with the hint) until applied — the block toolbar's sparkle button restores them in one click. The `autofill` setting now only controls hint visibility.
* **planner:** the payback-window setting is gone; module auto-fill is now a plain on/off toggle (meta key `autofill`, ON by default — previously payback 0 meant off). The old `autofill_payback` key is ignored. `chooseModuleFill` is replaced by the pure `pickAutoModules`.

### Features

* add support for Vitest in Vite config and enhance AI assistant documentation ([0e40a08](https://github.com/ApocDev/pyops/commit/0e40a08b3f777fd517609b2b2562d7f6ae5f71a0))
* **agent:** add blockBuildStatus tool for built-vs-required machines ([334cdde](https://github.com/ApocDev/pyops/commit/334cddeacb8a06043bc481703edc8ec39144f8ee)), closes [#123](https://github.com/ApocDev/pyops/issues/123)
* **agent:** add factory-wide power rollup tool ([e3dad05](https://github.com/ApocDev/pyops/commit/e3dad059ec9cdbe21b2a7188d8f4e971e78ecaeb)), closes [#129](https://github.com/ApocDev/pyops/issues/129)
* **agent:** add logisticsFor tool for belts/inserters at a rate ([34bac86](https://github.com/ApocDev/pyops/commit/34bac862a076db1e9601b4e769c5b8c222932159)), closes [#126](https://github.com/ApocDev/pyops/issues/126)
* **agent:** add productionStats tool for synced production stats ([d9fa963](https://github.com/ApocDev/pyops/commit/d9fa9631f3e69fa77580a6120a28c57069c757b9)), closes [#124](https://github.com/ApocDev/pyops/issues/124)
* **agent:** add read-only listNotes tool for planning context ([53c8173](https://github.com/ApocDev/pyops/commit/53c8173b7cd1ae9941e9b65b583ee25b6d68a070)), closes [#128](https://github.com/ApocDev/pyops/issues/128)
* **agent:** add researchPath tool for prerequisite closure + science cost ([bf0b407](https://github.com/ApocDev/pyops/commit/bf0b4078207b8fb38b6806452c0f2537a555e6bb)), closes [#125](https://github.com/ApocDev/pyops/issues/125)
* **agent:** chip technology names too; steer the assistant off Lua for recipe data ([0949f01](https://github.com/ApocDev/pyops/commit/0949f014e980161beb37e761e25f5136a24d17d2))
* **agent:** expose factoryWhatIf as a whatIf tool ([f8e7655](https://github.com/ApocDev/pyops/commit/f8e7655ef6ee3dd37483ace82412042fd62b1406)), closes [#127](https://github.com/ApocDev/pyops/issues/127)
* **agent:** implement building counts in draft and aggregate machine requirements ([00d6b32](https://github.com/ApocDev/pyops/commit/00d6b3271fdbb8d8e4b0b92d4c0d27b6406ce652))
* **agent:** multi-goal + keep-in-stock goals, and module-fill the building bill ([b8f7102](https://github.com/ApocDev/pyops/commit/b8f710206b39f80251dcc25a6d60267a227530da))
* **agent:** resolve recipeOptions' machine to the actual draft pick ([86bdc36](https://github.com/ApocDev/pyops/commit/86bdc366beee5e4c5ac39c4088e02f5846b18cc1)), closes [#130](https://github.com/ApocDev/pyops/issues/130)
* **app:** inline click-to-fix building count with color tint, no badge ([3fc1e8f](https://github.com/ApocDev/pyops/commit/3fc1e8f9d02f7f44dd9a66fdf6364a6de3285733)), closes [#121](https://github.com/ApocDev/pyops/issues/121)
* **app:** show the heat draw (MW) on heat-powered rows, not just a label ([16057f9](https://github.com/ApocDev/pyops/commit/16057f9e986ceb7c0dece3fe7a36f82e8560ff30))
* **planner:** count pin on a goal's producer supply-pushes instead of fighting the goal ([e2ff2ab](https://github.com/ApocDev/pyops/commit/e2ff2ab658a9ce1eb12baccda352fb3361b86188)), closes [#121](https://github.com/ApocDev/pyops/issues/121)
* **planner:** module auto-fill becomes suggest + explicit apply ([fdd43ca](https://github.com/ApocDev/pyops/commit/fdd43ca64ff345ac358f4201e1fa14330b107b46))
* **planner:** replace payback-economy module auto-fill with the direct algorithm ([37b47ba](https://github.com/ApocDev/pyops/commit/37b47ba1d0489a93fcbc514b41ac87b17c4e9ef9))
* **ui:** add styled Tooltip primitive, replace native title for explanatory text ([6197c83](https://github.com/ApocDev/pyops/commit/6197c83d1275862ff43c9b0e5632e879e6e69491))


### Bug Fixes

* **agent:** address review findings in assistant tool batch ([7fca79c](https://github.com/ApocDev/pyops/commit/7fca79c1d20550ba2d3df7cccb1c3ed718b2cf1d))
* **app:** a sink goal caches the consumed good once, not a duplicate import ([e9bd2fb](https://github.com/ApocDev/pyops/commit/e9bd2fb200a26d1b2e3e39d872f6da3949cc69e0))
* **app:** a sink goal is met by a consumer, not a producer — no false 'no recipe' warning ([46d3d95](https://github.com/ApocDev/pyops/commit/46d3d95d1bd654da7792f933aabdb118107febca))
* **app:** classify factory imbalances by a relative floor, not an absolute epsilon ([cc4774a](https://github.com/ApocDev/pyops/commit/cc4774aa9296e847f206de3790aaed9be4cc62ff))
* **app:** gate recipe availability on a tech's full prerequisite closure, not its own cost ([e18679d](https://github.com/ApocDev/pyops/commit/e18679db0ed0e3b8de7139c320391dbc7cc8d17a))
* **app:** size row inserters per built machine, not per fractional machine ([cce110a](https://github.com/ApocDev/pyops/commit/cce110a1e37f25bd07ff26cb51b91197f296000b)), closes [#21](https://github.com/ApocDev/pyops/issues/21)
* **bridge:** stop gating the in-game logistics readout on web display prefs ([8d4fc4f](https://github.com/ApocDev/pyops/commit/8d4fc4fdddf1d16d44d1fe2e102da81c45b99fd0)), closes [#21](https://github.com/ApocDev/pyops/issues/21)
* **mod:** make the summary panel's blueprint a temporary cursor stack ([ecc5292](https://github.com/ApocDev/pyops/commit/ecc5292b44fd1de7e28ce0ad3eb4bf6c1c47ac98))
* **planner:** drain a byproduct when its consumer is a terminal sink ([278edb1](https://github.com/ApocDev/pyops/commit/278edb192487de5186ccd62c2e647b678ba130ce)), closes [#91](https://github.com/ApocDev/pyops/issues/91)
* **planner:** hold module suggestions steady near whole-count boundaries ([b1881c7](https://github.com/ApocDev/pyops/commit/b1881c73498bb19b3a90cf5c66397ca88e9f87fe)), closes [#117](https://github.com/ApocDev/pyops/issues/117)
* **planner:** module auto-fill considers ZERO speed modules ([c112097](https://github.com/ApocDev/pyops/commit/c112097a81e81f522ce91626193f0e02c48b2649))
* **solver:** byproduct consumers no longer let the plan import-and-restructure ([138c27e](https://github.com/ApocDev/pyops/commit/138c27e2ab26fac83b42a62c000e04844ee6315c)), closes [#91](https://github.com/ApocDev/pyops/issues/91)
* **test:** type the sink-goal test's block data as saveBlockRow expects ([62f990d](https://github.com/ApocDev/pyops/commit/62f990db8ec7927e65961df0443fe43b5637e141))


### Performance Improvements

* **app:** bound the solve query cache to 30s ([bc46cfe](https://github.com/ApocDev/pyops/commit/bc46cfed1bd684fa956098e9c7c8f59de2a5e3c0))
* **planner:** batch the module-suggestion pool to one scan per solve ([60d49d5](https://github.com/ApocDev/pyops/commit/60d49d53f5f77b9e892845099154c57b902388ff)), closes [#117](https://github.com/ApocDev/pyops/issues/117)

## [1.0.0](https://github.com/ApocDev/pyops/compare/v0.5.0...v1.0.0) (2026-07-04)


Expand Down
2 changes: 1 addition & 1 deletion app/package.json
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
{
"name": "app",
"version": "1.0.0",
"version": "1.1.0",
"private": true,
"type": "module",
"imports": {
Expand Down
2 changes: 1 addition & 1 deletion app/src-tauri/Cargo.toml
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
[package]
name = "app"
version = "1.0.0"
version = "1.1.0"
description = "A Tauri App"
authors = ["you"]
license = ""
Expand Down
2 changes: 1 addition & 1 deletion app/src-tauri/tauri.conf.json
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "PyOps",
"version": "1.0.0",
"version": "1.1.0",
"identifier": "com.apocdev.pyops",
"build": {
"beforeDevCommand": "PORT=34115 HOST=127.0.0.1 node .output/server/index.mjs",
Expand Down
2 changes: 1 addition & 1 deletion mod/info.json
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
{
"name": "pyops",
"version": "1.0.0",
"version": "1.1.0",
"title": "PyOps",
"author": "ApocDev",
"factorio_version": "2.0",
Expand Down
2 changes: 1 addition & 1 deletion version.txt
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1.0.0
1.1.0