Skip to content

Add SwiftMiner integration, recipe wizard, and dashboard polish#8

Merged
johnwatso merged 41 commits into
mainfrom
SwiftMiner-Intergraton
May 11, 2026
Merged

Add SwiftMiner integration, recipe wizard, and dashboard polish#8
johnwatso merged 41 commits into
mainfrom
SwiftMiner-Intergraton

Conversation

@johnwatso
Copy link
Copy Markdown
Owner

@johnwatso johnwatso commented May 11, 2026

Summary

  • SwiftMiner integration end-to-end — pairing server, typed DM pipeline (router, sender, embed builders, theme), onboarding state, frequency gate, persistent dedup, Discord linking, webhook delivery. Settings tab restyled to match SwiftMiner's grouped-Form look with status card + pairing section.
  • Recipe wizard + templates — new guided flow for building action rules from reusable templates.
  • Overview & Analytics dashboards redesigned — operational status metrics, attention items, voice analytics card, rebalanced layouts. Memory metric now reports a rolling 3-minute average in whole MB; the noisy "Event flow stalled" alert is reworked to an info-level "Runtime feed quiet" notice that only fires after 4h of silence with a healthy heartbeat.
  • Admin web UI — HTTP keep-alive, OAuth refinements, recordings playback streaming, refreshed dashboard HTML.
  • Misc — event/cluster alerts, sidebar polish, prefix-command removal, debug stream toggle, security policy, README/license refresh, expanded test coverage for the SwiftMiner DM pipeline.

Test plan

  • Build the app target: xcodebuild -project SwiftBot.xcodeproj -scheme SwiftBot -configuration Debug build
  • Run the test target: xcodebuild -project SwiftBot.xcodeproj -scheme SwiftBot -configuration Debug test
  • Launch the app and walk through Preferences › Integrations: pair with SwiftMiner via paste-bundle, confirm status card flips to "Paired".
  • Trigger a SwiftMiner event (or replay one) and confirm the DM is delivered to a linked Discord account.
  • Open Overview: confirm the Memory metric shows whole MB and updates on a ~5s cadence; confirm no false "Event flow stalled" alert during normal idle.
  • Open Analytics › Voice Analytics: confirm the chart and insights column share width sensibly when the window is resized.
  • Run the Recipe Wizard from a template and verify the generated rule is created and enabled.

johnwatso added 30 commits May 6, 2026 11:24
Introduce SwiftMiner support: add a SwiftMiner client service (Services/SwiftMinerClient.swift) and AppModel helpers (AppModel+SwiftMiner.swift) to handle pairing tokens, activation, projections, webhook handling and signature validation. Wire up admin web UI and API: add a webhook endpoint in AdminWebServer, expose a pairing UI in AdvancedPreferencesView, register commands and slash options in CommandProcessor and SlashCommandHelpers, and add a help entry in HelpEngine. Add settings and pairing bundle types to BotSettings, update tests to include the new dependency, and update the Xcode project to include the new sources. Also includes small project metadata changes (CURRENT_PROJECT_VERSION and MARKETING_VERSION).
- Switch analytics line chart to monotone interpolation and add y-axis
  headroom so peak markers no longer overshoot the panel bounds.
- Bundle pending updates across media export, admin web, Patchy, and
  SwiftMiner integration paths.
Replace assets/readme/ui-preview.png with an updated binary to refresh the README UI preview. No code changes included; only the image asset was modified.
- MARKETING_VERSION 1.9.9 -> 1.10, CURRENT_PROJECT_VERSION 196000 -> 1100000.
- Add docs/release-notes/1.10.html and a new 1.10 entry in docs/appcast.xml
  (enclosure length and edSignature still need to be filled in once the
  signed zip is built).
- Pin ENABLE_USER_SCRIPT_SANDBOXING=NO in project.yml so xcodegen stops
  flipping it back on and breaking the SwiftLint build phase.
- Remove a stray AnalyticsView 2.swift Finder duplicate that xcodegen
  was picking up as a redeclaration of AnalyticsView.
- Switch CURRENT_PROJECT_VERSION to the same yyyyMMddHH timestamp
  scheme SwiftMiner uses (1100000 -> 2026050813) across project.yml,
  pbxproj, appcast, and release-note copy.
- Update AGENTS.md to document the timestamp convention so future
  build bumps stay consistent.
- Expand docs/release-notes/1.10.html with a dedicated Media Export
  section covering the move off FFmpeg onto AVFoundation, and reflect
  that shift in the intro.
- Drop the per-range chunk cap from 256 MB to 8 MB in
  localMediaStreamResponse so each /api/media/stream request returns
  in milliseconds instead of stalling while hundreds of MB are read
  into RAM. This is the likely cause of the ~20-30s buffering pauses
  seen on higher-bitrate recordings.
- Add a SWIFTBOT_DEBUG_STREAM env flag (MediaStreamDebug.swift) that
  logs offset/length/status/elapsedMs for every range request so we
  can verify the diagnosis from logs.
- Add a low-bitrate transcode fallback (MediaTranscodeCache.swift)
  served via /api/media/stream?quality=low. Variants are generated
  on demand with AVAssetExportSession (medium-quality preset) and
  cached under ~/Library/Caches/SwiftBot/MediaTranscodes/, keyed by
  item id + source mtime. Concurrent requests share a single in-flight
  transcode task.
- Wire a quality toggle into the admin web player that flips the
  video src between original and ?quality=low and resumes playback
  at the same timestamp.
Range-based recordings playback was forcing the browser to open a
new TCP+TLS connection for every 8 MB chunk because every response
sent Connection: close. Once playback drained the per-host
connection cap (~6 in Chrome/Firefox), follow-up audio range
requests stalled, leaving video playing while audio went silent
~30 s in.

- Switch the default response Connection header to keep-alive and
  honour either side's explicit Connection: close.
- Rework AdminWebNIOHTTPHandler to consume a single HTTP request
  out of its read buffer (preserving any pipelined remainder),
  process it, then reset state and process the next request on the
  same channel instead of closing.
- Detect HTTP/1.0 (which defaults to close) and explicit close
  headers from either client or response so legacy callers still
  get the old behaviour.
Stream debug lines were only going to OSLog, so they were invisible
in the SwiftBot Logs panel. Add a StreamDebug.inAppSink hook wired
from AppModel.init that forwards each line through LogStore so it
shows up alongside the rest of the runtime log when the env flag
is on.
The env-var-only flag was unusable when SwiftBot is launched from
Finder or LaunchServices, since neither inherits the shell env.
Read UserDefaults["SwiftBotDebugStream"] first and fall back to the
env var, so the flag can be flipped at runtime with `defaults write
com.example.swiftbot SwiftBotDebugStream -bool YES` without
relaunching from Xcode.
…ilders

- Add SwiftMinerDMTypes, SwiftMinerDMRouter, SwiftMinerDMSender
- Add SwiftMinerDMEmbedBuilders with per-type embed construction
- Add SwiftMinerDMTheme for centralized copy and help URL support
- Add SwiftMinerDMStyle for semantic notification styles
- Add onboarding state tracking (welcomeMessageSentUserIds, completedInitialDMFlowUserIds)
- Update AdminWebServer /dm/test to decode full SwiftMinerDMRequest
- Update AppModel+SwiftMiner with typed DM wrappers
- Add SwiftBotTests for router, sender, REST client DM, state round-trip
- Fix Swift 6 concurrency in DM dependency closures
johnwatso and others added 11 commits May 9, 2026 21:08
- Add SwiftMinerDMFrequencyConfig to SwiftMinerSettings (Codable, persisted)
- Add SwiftMinerDMFrequencyGate actor with per-type and global cooldowns
- Wire frequency gate into SwiftMinerDMSender
- Onboarding messages (welcome, discordLinked, setup, linked) bypass gate
- Default cooldowns: dropClaimed=5min, campaignComplete=10min,
  welcomeBack=1hr, connectionExpired=5min, global=1min
- Config can be adjusted via settings JSON without code changes
- Add 'Limit how often event DMs are sent' master toggle
- Add pickers for drop claimed, campaign complete, and global cooldowns
- Bind directly to SwiftMinerSettings.frequencyConfig
- Onboarding messages bypass gate regardless of settings
- Replace SwiftMinerDMFrequencyConfig with SwiftMinerDMNotificationPreferences
- Rename SwiftMinerDMFrequencyGate to SwiftMinerDMNotificationFilter
- Filter checks which event DM types are enabled instead of cooldowns
- Onboarding messages (welcome, discordLinked, setup, linked) always pass
- Add 7 toggle switches in SwiftMinerPreferencesView for each event type
- All event types default to enabled
- Simplify SwiftMinerPreferencesView to single Integrations card with
  Discord Integration section shown when paired. Fixes card not appearing.
- Add eventId field to SwiftMinerDMRequest for cross-launch dedup.
- Add sentEventSignatures to SwiftMinerSettings (persisted to disk).
- Update SwiftMinerDMSender to check and record event signatures.
- Update tests for new hasEventBeenSent/markEventSent dependencies.
- Add dedup tests: duplicate skip, different IDs pass, debug bypass.
- Simplify SwiftMinerPreferencesView back to pairing UI only.
- Remove SwiftMinerDMNotificationFilter from sender; SwiftBot now
  sends all DMs it receives (dedup still applies).
- Keep notificationPreferences in BotSettings for backward compat.
- Add activationURL field to SwiftMinerDMRequest and mock data.
- Update buildSetupEmbed to show a clickable [Click here to link Twitch]
  markdown link when activationURL is present, falling back to manual
  steps + code block when absent.
- Add setupLinkTitle/setupLinkLabel to theme.
- Update /miner action:setup command response to include a clickable
  activation link with code pre-filled (verificationUri?code=userCode).
- Router passes activationURL through to embed builder.
Introduce an IFTTT-style recipe wizard and reusable recipe templates to speed up creating automations. Adds RecipeTemplates.swift (templates, RecipeFieldValues, RecipeBuilder) and RecipeWizardView.swift (3-step UI) and wires them into VoiceActionsView to present the wizard and append created rules via a new RuleStore.addRule(_:). Update project.pbxproj to include the new files. Also adjust SwiftMiner DM copy and styling: add emojis to several embed titles, improve greeting/newline handling, and always surface activation codes alongside CTA links; update SwiftMinerDMTheme labels to include emoji and clearer helper labels.
Overview: add new attention items — an "Event flow stalled" alert when the newest runtime event is older than 15 minutes (escalates to critical at 30 minutes), and a "Cluster primary unreachable" alert for worker/standby modes when worker state is degraded/failed (uses configured leader address or the configured primary). Removed the previous runtime queue-load alert. Remote UI: remove the sidebar toggle toolbar item by calling .toolbar(removing: .sidebarToggle).
- Restyle Integrations tab with grouped Form + status card to match SwiftMiner.
- Rebalance Voice Analytics row so the insights column gets a fairer share of width.
- Soften 'Event flow stalled' attention item: now an info-level 'Runtime feed quiet' notice that only fires after 4h of silence and requires a healthy heartbeat.
- Memory metric now averages a rolling 3-minute window and renders whole MB.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@johnwatso johnwatso merged commit 5a8dd13 into main May 11, 2026
1 check failed
@johnwatso johnwatso deleted the SwiftMiner-Intergraton branch May 11, 2026 03:46
johnwatso added a commit that referenced this pull request May 11, 2026
Add SwiftMiner integration, recipe wizard, and dashboard polish
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant