Skip to main content

Skype

@magistr/skypev2026.08.19.1· 23d agoMODELS
01README

Skype SQLite database reader — conversations, contacts, messages, search, Obsidian export

02Models1
@magistr/skypev2026.08.19.1extensions/models/skype.ts

Global Arguments

ArgumentTypeDescription
basePathstringPath to Skype data directory (contains profile subdirectories)
profilestringProfile directory name (e.g. your-skype-name)
queryTimeoutMsnumberMax milliseconds to wait for a single sqlite3 subprocess query before aborting it
fn listProfiles()
List available Skype profiles in the data directory
fn listConversations(minMessages: number)
List all conversations with message counts, ordered by activity
ArgumentTypeDescription
minMessagesnumberMinimum messages to include
fn listContacts()
List all contacts
fn readConversation(conversation: string, limit: number, offset: number)
Read messages from a specific conversation
ArgumentTypeDescription
conversationstringConversation identity or display name
limitnumberMax messages
offsetnumberSkip first N messages
fn searchBySender(sender: string, limit: number)
Search all conversations for messages from a specific sender
ArgumentTypeDescription
senderstringSender skypename or display name (partial match)
limitnumberMax results
fn exportToObsidian(folder: string, minMessages: number, maxNotesPerResource: number)
Export all conversations as Obsidian notes — one note per conversation with full chat log
ArgumentTypeDescription
folderstringObsidian base folder
minMessagesnumberSkip conversations with fewer messages
maxNotesPerResourcenumberFlush accumulated notes to a new data resource after this many conversations, bounding both in-memory growth and per-resource size for large profiles
fn importToObsidian(folder: string, vaultPath: string, minMessages: number)
Export all conversations and write to Obsidian vault via CLI — handles large conversations
ArgumentTypeDescription
folderstringObsidian base folder
vaultPathstringAbsolute path to Obsidian vault directory
minMessagesnumberSkip conversations with fewer messages
fn searchByText(text: string, limit: number)
Search all messages for text content
ArgumentTypeDescription
textstringText to search for
limitnumberMax results

Resources

conversations(infinite)— List of Skype conversations
messages(1h)— Messages from a conversation or search
contacts(infinite)— Contacts list
03Previous Versions4
2026.08.02.1

2026.08.02.1

The remaining seven of the nine latent bugs pinned in 2026.07.16.2's test backfill (all MEDIUM/LOW) are now real-fixed. Tracked end-to-end in the LOCAL skype-latent-bugs issue-lifecycle model (never a Lab issue). Every adversarial pin proving each bug now asserts the FIXED behavior instead of the bug; no benign/frozen contract, methods, or coverage assertion changed byte for byte, and both 2026.08.01.1 fixes (LB1/LB2) stay green and untouched.

  1. Resource-name/note-filename collision (MEDIUM), FIXEDreadConversation's conv_<safeKey> (50-char truncation) and exportToObsidian/importToObsidian's 80-char-truncated filename both collided for two distinct conversations sharing a long common prefix, silently clobbering one's data with the other's. Fixed with a new truncKey(s, n) helper: a string that already fits within n CODE POINTS is returned completely unchanged (so every existing short name stays byte-identical); once truncation actually removes something, a short deterministic hash (shortHash, FNV-1a 32-bit, base36-encoded) of the FULL original string is appended, so two names sharing the same truncated prefix no longer collide.
  2. exportToObsidian unbounded memory + single-blob resource (MEDIUM), FIXED — every conversation's full chat log used to accumulate into one in-memory array and write as exactly one writeResource call, regardless of profile size. A new maxNotesPerResource method argument (default 500, backward-compatible) now flushes the accumulated notes to their own data resource every N conversations: page 0 keeps the original obsidian_<profile> name, overflow pages are obsidian_<profile>_p<N>, and the method now returns one dataHandles entry per page. An empty export still writes exactly one (empty) page 0, never zero resources. Any profile within the default 500-conversation budget — every fixture in this test suite — still writes exactly one byte-identical resource.
  3. No subprocess timeout (MEDIUM), FIXEDqueryDb's Deno.Command carried no signal/timeout option; a wedged sqlite3 process (e.g. a locked/corrupt main.db) would hold the caller, and the swamp model lock, forever. Fixed with a new queryTimeoutMs global argument (default 30000ms, backward-compatible) threaded through every queryDb call site; queryDb now wraps its Deno.Command in an AbortController + setTimeout(() => ac.abort(), timeoutMs), clearing the timer in a finally block on every path (success or failure). Deliberately NOT AbortSignal.timeout(ms): that built-in's internal timer has no handle the caller can clear, so a query finishing well within budget would still leave a live timer running — under Deno's test resource sanitizer that shows up as a leaked timer.
  4. Lone-surrogate slice truncation (MEDIUM), FIXEDimportToObsidian's (and exportToObsidian's) 80-char filename slice could cut an astral-emoji surrogate pair in half; Deno.writeTextFile silently tolerated this, replacing the lone surrogate with U+FFFD on disk rather than erroring or skipping the write. Folded into the same truncKey fix as #1 above: truncation now happens by CODE POINT via Array.from, so a surrogate pair landing at the cut boundary is kept whole rather than split. searchByText's textKey slicing was fixed the same way for consistency, though it was never observed to corrupt an on-disk file (it only feeds a resource name).
  5. YAML frontmatter injection via a raw line-break in the display name (MEDIUM), FIXED — the frontmatter title:/identity:/profile: template only ever escaped ", never a line-break; a display name (or identity, or profile) carrying a raw \r (a real newline character that, unlike \n, survives queryDb's row split intact) could inject arbitrary additional YAML-shaped lines into the frontmatter block. Fixed with a new yamlDq(s) helper — backslash and double-quote are backslash-escaped, and every C0 control character (including a raw CR/LF) is replaced with its escape sequence — applied to title/identity/profile in both exportToObsidian and importToObsidian. Byte-identical for every benign (control-character-free) value.
  6. Emoji numeric-entity mis-decode (LOW), FIXEDstripXml's &#(\d+); decoder used String.fromCharCode, correct for BMP code points but silently wrong for any astral (>0xFFFF) code point — e.g. &#128512; (grinning face) decoded to an unrelated BMP character instead of the intended emoji. Fixed by switching to String.fromCodePoint, guarded so an out-of-range code point (impossible for \d+ to produce negative, but fromCodePoint throws above 0x10FFFF) leaves the original entity text
2026.07.16.2

Release 2026.07.16.2 — align model versions with manifests

Maintenance release across the @magistr extensions. For most packages this carries no functional change: the only edit is the model's version: field, brought back in line with its manifest version so the published model type version and the package version no longer drift.

Functional changes in this release are limited to:

  • anime-cron: normalizeTitle now strips a ": subtitle" suffix and a trailing parenthesized year before comparison, fixing dedup false-misses where the torrent title carries a subtitle or year that the AniList romaji does not.

  • arckit: first publish. Standalone ArcKit port — a 12-phase architecture governance state machine with 65 bundled templates, driven by a bundled skill.

Also tracks three extensions (kaiten, observability-agent, music-library) that previously existed only as untracked working-tree directories, recovered from stashes.

Added 1, removed 1 models

2026.05.25.1

Merge pull request #4 from umag/extensions/magistr-grade-a-workspace

extensions: stage 15 @magistr extensions as Grade A workspace dirs + wire CI

2026.03.29.1
04Stats
A
100 / 100
Downloads
2
Archive size
21.5 KB
  • Has README or module doc2/2earned
  • README has a code example1/1earned
  • README is substantive1/1earned
  • Most symbols documented1/1earned
  • No slow types (deprecated)1/1earned
  • Dependencies pass trust audit2/2earned
  • Has description1/1earned
  • Platform support declared (or universal)2/2earned
  • License declared1/1earned
  • Verified public repository2/2earned
05Platforms
06Labels