Commit graph

13 commits

Author SHA1 Message Date
Richard McCorkle
8eb95a25ce refactor: remove broken watch-page/ANDROID/MWEB/WEB transcript methods
Delete the four obsolete local transcript methods, their six helper
methods, the YouTubeConfig interface, and the now-unused statics. The
iOS player method added earlier is the sole local fallback.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 14:28:30 +02:00
Richard McCorkle
314a737437 feat: route transcript fallback through the iOS player method
fetchTranscript now uses a three-rung ladder (ScrapeCreators, iOS
player, Supadata). getVideoMetadata is sourced from the iOS player
response instead of the watch-page HTML scrape.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 14:20:40 +02:00
Richard McCorkle
45b2baa4ba feat: add iOS InnerTube player transcript method
Add fetchIosPlayerData and fetchViaIosPlayer, built from the YouTube
iOS player approach. Not yet wired into the fallback ladder.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 14:13:58 +02:00
Richard McCorkle
10dea4d04e feat: add collectUnder folder-walk helper 2026-05-17 21:08:52 +02:00
Richard McCorkle
800bbee770 refactor: remove dead class members flagged by fallow
Fallow dead-code analysis flagged 13 issues. Removed the 10 that are
genuinely unreferenced:
- LLMFactory.getBestProvider, LLMFactory.updateSettings
- GeminiClient.isAvailable, OllamaClient.isAvailable
- ProcessingSpinner.setLabel, plus the now-dead callCount field and its
  '#N' suffix in the spinner text (setLabel was callCount's only writer,
  so the counter had been stuck at 0 already)
- YouTubeTranscriptExtractor.fetchTranscriptSegments, combineTranscript,
  clearConfigCache, parseJsonCaptions
- dropped the unused 'export' on the CaptionTrack interface (still used
  locally in the file, just never imported elsewhere)

Kept OllamaClient.validateConnection and createChatCompletion: fallow
flagged them, but transcript-summarizer.ts calls them via a loosely
typed 'client' variable that fallow cannot statically resolve.

Build and lint pass clean.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 20:20:37 +02:00
Richard McCorkle
8311ee1fb8 chore: upgrade eslint-plugin-obsidianmd to 0.3.0, fix resulting lint errors
Bump eslint-plugin-obsidianmd 0.2.9 -> 0.3.0 and typescript-eslint
8.58.2 -> 8.59.3. ESLint stays at 9.39.4: obsidianmd 0.3.0 peer-pins
@eslint/js ^9 and @eslint/json 0.14.0, so ESLint 10 is not yet
cleanly supported.

obsidianmd 0.3.0 adds two new rules. Fixes for the errors they raise:
- no-unnecessary-type-assertion: remove 4 redundant type assertions
  (main.ts x3, fetch-shim.ts x1) - all compile-time-only, tsc confirms.
- prefer-window-timers: switch 11 activeWindow timer calls to window
  (main.ts, form-utils.ts, processing-spinner.ts). TubeSage has no
  popout-window feature, so window === activeWindow at every call site.

Note: obsidianmd 0.3.0's prefer-active-doc rule (warning) now flags
window.* as preferring activeWindow, directly contradicting the
error-level prefer-window-timers rule. window.* is kept because it
satisfies the error-level rule; the 11 advisory warnings are an
upstream rule conflict and cannot be resolved without suppression.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 07:38:12 +02:00
Richard McCorkle
185372a25e feat: add platform-aware ProcessingSpinner (Braille status-bar / in-modal) 2026-05-16 22:51:00 +02:00
Richard McCorkle
8aa1406ffe fix: remove unnecessary type assertion in fetch-shim 2026-05-16 21:19:15 +02:00
Richard McCorkle
2e5e2aefa8 feat: add OpenRouter as a fifth LLM provider for summary and timestamps
OpenRouter exposes an OpenAI-compatible Chat Completions API, so reuse the
existing @langchain/openai ChatOpenAI client with a custom baseURL —
no new SDK required. The obsidianFetch shim continues to apply through
getLangChainConfiguration, preserving cross-platform (mobile) support.

Changes:
- model-limits-registry: add 'openrouter' to Provider union; seed registry
  with curated namespaced models (openai/gpt-4o, anthropic/claude-3.5-sonnet,
  google/gemini-2.5-flash, meta-llama/llama-3.1-70b-instruct, etc.)
- langchain-client: new 'openrouter' switch case mirroring the OpenAI path
  but routing to https://openrouter.ai/api/v1 with the recommended
  HTTP-Referer and X-Title attribution headers
- main.ts: wire openrouter into DEFAULT_SETTINGS (apiKey, selectedModel,
  fetchedModels), getModelForProvider fallback, provider dropdown, and the
  providerCatalog UI block with the same shape as the other providers

Both the summary pass and the timestamp-linking pass dispatch through the
same LangChainClient, so OpenRouter is available for both automatically.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 21:23:49 +02:00
Richard McCorkle
1b043d0723 fix: improve timeout error message and detect Gemini DEADLINE_EXCEEDED
Root cause: for 2hr+ transcripts, the Gemini API returns a server-side
DEADLINE_EXCEEDED (504) — not a client-side timeout. The error was being
categorised as a generic timeout and the message told the user to "try again",
which is misleading since retrying the same large transcript will fail again.

Changes:
- error-utils: catch DEADLINE_EXCEEDED/deadline exceeded as Timeout category
- error-utils: replace "try again" timeout message with actionable advice
  (try shorter video, reduce max tokens, or switch model)
- gemini-client: log full error body for easier debugging; surface gRPC
  status code in error message; throw DEADLINE_EXCEEDED prefix on 504 so
  upstream categorisation is unambiguous

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 13:37:09 +02:00
Richard McCorkle
a953c56e04 chore: clean up lint errors and warnings post-fallow audit
Lint now passes with 0 errors / 0 warnings.

ESLint config:
- Ignore graphify-out/, .fallowrc.json, .mcp.json, .fallow/
  (eliminates 69 phantom JSON-parse errors)

main.ts:
- Sentence-case fixes per obsidianmd/ui/sentence-case (4 errors):
  'YouTube data API key', 'Scrapecreators API key', 'Supadata API key',
  and the Google Cloud console description string
- Prefix unused args with underscore: _contentType, _headingPositions, _index

src/utils/:
- Delete dead function bodies left after fallow's export-removal pass:
  form-utils.ts: validateCustom, validateInputField, showNotice, filterItems,
    createListKeyHandler (and the now-unused Notice import)
  logger.ts: configureLogger, setCategoryLogLevel, getLogEntries,
    getLogsAsString, plus 5 unused module-level logger consts
  model-limits-registry.ts: getProviderFromModel, getModelsForProvider,
    getLegacyMaxTokens
  path-utils.ts: getParentFolder
- timestamp-utils.ts: prefix unused _headings arg

src/youtube-transcript.ts:
- Prefix unused _options arg in fetchViaWebScrapeCreators

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 22:00:17 +02:00
Richard McCorkle
e81d711749 chore: remove dead exports and unused dependencies (fallow audit)
Auto-removed via fallow fix_apply after manual verification:
- 25 unused exports in logger, form-utils, model-limits-registry,
  error-utils, path-utils, timestamp-utils, langchain-fetcher
- 10 unused deps (@langchain/anthropic, @langchain/google-genai,
  langchain, openai, parse-duration, node-html-parser,
  @anthropic-ai/tokenizer, @typescript-eslint/eslint-plugin,
  @typescript-eslint/parser, adm-zip)

Kept tslib because tsconfig has importHelpers:true. Added
.fallowrc.json with project entry points and ignoreDependencies,
and .mcp.json registering the fallow MCP server at project scope.

Build verified: tsc -noEmit clean; esbuild produces main.js (1.67 MB).
Health score: 57.2 → 73.0 (C → B). Dead-export rate: 30.7% → 1.6%.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 21:44:06 +02:00
Richard McCorkle
d551490a6d TubeSage 1.2.21
Collapsed history snapshot — represents the cumulative state of TubeSage
through 1.2.21. Earlier commit history (covering versions 1.2.0 through
1.2.20) was rewritten into this single root commit to remove tracking
of a personal deploy script that referenced local filesystem paths.

The current release content is unchanged. See manifest.json for the
plugin version. Older tags (1.2.0 through 1.2.20) have been retired.

Features in this release line:
- YouTube transcript extraction (ScrapeCreators API + local fallbacks)
- LLM-driven summarisation (OpenAI, Anthropic, Google, Ollama)
- Per-provider always-visible API key rows
- Selected-provider model controls with registry-aware overrides
- Custom-model parameter overrides with synchronous panel refresh
- Max tokens field with blur-commit and reset-on-blank
- Settings de-pollution migration on plugin load
- Summary-callout split for multi-section model output
- Security patches: fast-xml-parser >=5.7.0, uuid >=14.0.0
2026-05-01 15:30:50 +02:00