121 Commits

Author SHA1 Message Date
Cameron
8143af47ee fix: Windows TTY crash and LETTA_HOME shell expansion
#47: Skip /dev/tty entirely on Windows — it resolves to C:\dev\tty
which doesn't exist. The .on('error') handler from v2.1.1 catches the
async error on Linux, but on Windows we shouldn't even attempt it.

#48: Expand common shell syntax ($HOME, ${HOME}, ~) in LETTA_HOME.
When set via Claude Code settings.json, env vars aren't shell-expanded,
so "$HOME" becomes a literal directory name. expandPath() now resolves
these to os.homedir(). Fixes both getDurableStateDir() call sites and
the splash screen display.

Fixes #47, fixes #48.

Written by Cameron ◯ Letta Code

"Defensive programming is the art of expecting the unexpected." - Unknown
2026-04-15 17:13:09 -07:00
Cameron
382a2832e5 feat: add letta/auto and minimax/MiniMax-M2.7 to model fallback list
Written by Cameron ◯ Letta Code

"Variety is the spice of life." - William Cowper
2026-03-30 18:11:14 -07:00
Cameron
063f9ebc25 chore: bump version to 2.1.1
Written by Cameron ◯ Letta Code

"Ship early, ship often." - Eric S. Raymond
v2.1.1
2026-03-30 15:07:17 -07:00
Cameron
7c57b13683 fix: three bugs — silent worker resolution, TTY crash, plugin root fallback
#42: spawnSilentWorker on macOS/Linux now uses the plugin's local tsx
CLI (node_modules/tsx/dist/cli.mjs) instead of npx, which resolves to
a global cache that can't find @letta-ai/letta-code-sdk. Same pattern
Windows already used.

#41: Add error handler on /dev/tty WriteStream in session_start.ts.
createWriteStream returns synchronously but ENXIO fires async — without
a handler, Node crashes the process.

#34: Partial workaround for CLAUDE_PLUGIN_ROOT being empty on Linux.
hooks.json now uses ${CLAUDE_PLUGIN_ROOT:-.} fallback. silent-npx.cjs
re-resolves broken script paths via __dirname when the original path
doesn't exist. Note: this is primarily a Claude Code framework bug.

Fixes #42, fixes #41, partially addresses #34.

Written by Cameron ◯ Letta Code

"First, do no harm." - Hippocrates
2026-03-30 13:43:11 -07:00
Cameron
62a5606ff5 chore: bump version to 2.1.0
Written by Cameron ◯ Letta Code

"Progress is not in enhancing what is, but in advancing toward what will be." - Khalil Gibran
v2.1.0
2026-03-30 12:53:48 -07:00
Charles Packer
075e920f64 Update README.md 2026-03-28 11:46:09 -07:00
Charles Packer
b85c847e90 Update README.md 2026-03-28 11:41:35 -07:00
cpacker
9d5a7e9c27 fix: tag Subconscious agents with origin marker
Ensure imported and existing Subconscious agents always include origin:claude-subconcious for tracking, and keep git-memory-enabled tagging in the same idempotent path.

👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta Code <noreply@letta.com>
2026-03-23 22:38:49 -07:00
Cameron
fc2e50fc9d feat: migrate Subconscious to memfs (git-backed memory filesystem)
- Enable memfs on import: adds `git-memory-enabled` tag after importing
  the bundled agent, which triggers the server to create a git-backed
  memory repo and sync blocks as files
- Update system prompt: "memory blocks" → "files in a git-backed
  filesystem (memfs)"
- Update self_improvement: reference memfs conventions, file management
  instead of raw block management
- Update core_directives: "memory files" instead of "memory blocks"

Existing users' agents will get memfs when Letta Code enables it on
their cloud agent. New users get it automatically on import.

Closes #32

Written by Cameron ◯ Letta Code

"Simplicity is the ultimate sophistication." - Leonardo da Vinci
2026-03-18 04:33:15 -07:00
Cameron
5be36dd1e9 fix: enforce memory limits to prevent context window overflow
A production user (51 blocks, 115k tokens) hit compaction loops because
the system prompt alone exceeded the context window. Root cause: no
limits on block count or total memory size.

Changes to bundled agent:
- Hard cap: 12 blocks max, 30k chars total across all blocks
- Per-block limits reduced: 5k for system blocks, 3k for user blocks
  (down from 20k each — 160k theoretical max was dangerous)
- self_improvement rewritten: consolidate-first policy, aggressive
  trimming, explicit "every line must earn its place"
- core_directives: memory limit reminder near the top

Worst case with these limits: ~10.5k tokens of system prompt.
Previously: unbounded (observed 115k tokens in production).

Written by Cameron ◯ Letta Code

"Constraints inspire creativity." - Biz Stone
2026-03-17 17:14:43 -07:00
Cameron
04c342327e fix(api): normalize Letta URLs and avoid self-hosted conversations redirect (#31)
Use a shared URL builder across scripts and update createConversation to call /v1/conversations/ with query params to avoid HTTPS->HTTP redirect failures behind reverse proxies. This also deduplicates LETTA_API_BASE handling and adds regression tests for trailing-slash behavior.

👾 Generated with [Letta Code](https://letta.com)

Co-authored-by: Letta Code <noreply@letta.com>
2026-03-17 10:21:03 -07:00
Cameron
6346094a0d chore: bump version to 2.0.2
Written by Cameron ◯ Letta Code

"Done is better than perfect." - Sheryl Sandberg
v2.0.2
2026-03-13 18:49:19 -07:00
Cameron
3419f8027d fix: guidance policy + docs for Task tool and model selection
- Guidance block is now general-purpose, not session-specific. Do NOT
  clear on session start — multiple CC sessions share the same block.
- Call out Task tool / sub-agent spawning in full mode
- Note that glm-5 is free but users can pick any model via the ADE

Written by Cameron ◯ Letta Code

"The whole is greater than the sum of its parts." - Aristotle
2026-03-13 18:47:50 -07:00
Cameron
f2a3e0bfd2 chore: bump version to 2.0.1
Written by Cameron ◯ Letta Code

"Ship it." - Every engineer, eventually
v2.0.1
2026-03-13 18:42:16 -07:00
Cameron
a14635dbc8 chore: remove dead countTranscriptLines function
Written by Cameron ◯ Letta Code

"Dead code is a liability, not an asset." - Ward Cunningham
2026-03-13 18:39:36 -07:00
Cameron
ab7b3432c7 feat: tell both Sub and Claude about SDK tools mode at init
- Session start message to Sub now includes sdk_tools_mode and
  describes what tools are available (read-only, full, or off)
- letta_context header to Claude describes Sub's capabilities
  ("can read files, search your codebase" vs "listen-only mode")
- Updated core_directives in bundled agent to reflect tool access
- Updated system prompt and description to "Subconscious" framing

Written by Cameron ◯ Letta Code

"Know thyself." - Socrates
2026-03-13 18:37:49 -07:00
Cameron
fcc0681275 docs: minor README fixups — tool_guidelines label, first run copy
Written by Cameron ◯ Letta Code

"Almost there." - Lando Calrissian
2026-03-13 18:29:54 -07:00
Cameron
c3d42be26c docs: lighten the README tone — whispers, not enterprise
Written by Cameron ◯ Letta Code

"Brevity is the soul of wit." - William Shakespeare
2026-03-13 18:27:04 -07:00
Cameron
9a20b38819 docs: rewrite README pitch for v2 — background agent, not just memory
The top-level framing now reflects that Sub is a full background agent
with client-side tool access (Read, Grep, Glob, web search), not just
a passive memory layer. Updated architecture diagram, use cases, agent
description, and API notes.

Written by Cameron ◯ Letta Code

"If you can't explain it simply, you don't understand it well enough." - Albert Einstein
2026-03-13 18:26:03 -07:00
Cameron
7247275714 Merge pull request #30 from letta-ai/feat/sdk-only-breaking-change
feat!: SDK-only transport — remove legacy API path
v2.0.0
2026-03-13 18:23:06 -07:00
Cameron
4193d25d40 fix: replace checkpoint mode with SDK tools in startup splash
Written by Cameron ◯ Letta Code

"Clean code always looks like it was written by someone who cares." - Robert C. Martin
2026-03-13 18:22:52 -07:00
Cameron
36a078ae5a fix: update debug log filename in README
send_worker.log → send_worker_sdk.log

Written by Cameron ◯ Letta Code

"The devil is in the details." - Proverb
2026-03-13 18:21:11 -07:00
Cameron
792cd99f52 feat: restore LETTA_SDK_TOOLS=off as listen-only mode
off now means "no client-side tools" — Sub still receives transcripts
via the SDK transport but can only use memory operations. Useful for
listen-only agents that observe without filesystem access.

Written by Cameron ◯ Letta Code

"Listening is an art that requires attention over talent." - Dean Jackson
2026-03-13 18:19:47 -07:00
Cameron
8329de34a2 chore: clean up for v2.0.0 — README, logging, version bump
- Remove checkpoint docs, legacy `off` mode, and stale log file refs from README
- Clean up verbose per-message stream logging in SDK worker (keep tool calls + errors)
- Bump version to 2.0.0 in package.json and plugin.json

Written by Cameron ◯ Letta Code

"Less is more." - Ludwig Mies van der Rohe
2026-03-13 18:16:39 -07:00
Cameron
9e0602a4fc feat!: remove legacy API path, require Letta Code SDK
BREAKING CHANGE: The `LETTA_SDK_TOOLS=off` option is removed. All
message delivery to Sub now goes through the Letta Code SDK. Users
who need the old behavior should pin to a pre-SDK tag.

Deleted:
- scripts/send_worker.ts (legacy raw API worker)
- scripts/plan_checkpoint.ts (was no-op in SDK mode)

Removed:
- Legacy branch in send_messages_to_letta.ts
- Early prompt notification in sync_letta_memory.ts
- sendMessageToConversation from conversation_utils.ts
- Checkpoint hook from hooks.json

Written by Cameron ◯ Letta Code

"Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away." - Antoine de Saint-Exupéry
2026-03-13 17:23:22 -07:00
Cameron
901a9d7c32 chore: update bundled agent tool_guidelines with SDK tools
Add Read, Glob, Grep to tool_guidelines so Sub knows it has
filesystem access via the Letta Code SDK transport.

Written by Cameron ◯ Letta Code

"Know thyself." - Socrates
2026-03-13 17:06:01 -07:00
Cameron
732e39599c fix: prevent conversation conflicts between SDK and legacy paths
In SDK mode, sync_letta_memory.ts and plan_checkpoint.ts were still
spawning legacy send_worker.ts — racing the SDK worker on the same
conversation and causing 409 CONFLICT errors (0 chars response).

- sync_letta_memory: skip early prompt notification in SDK mode
- plan_checkpoint: skip entirely in SDK mode (Stop hook handles it)

Written by Cameron ◯ Letta Code

"Two threads enter, one thread leaves." - Mad Max, concurrent edition
2026-03-13 16:41:12 -07:00
Cameron
3acd22f9d9 fix: restore conversationId + add verbose stream logging
Revert to resumeSession(conversationId) and log every stream message
type to diagnose why the session returns 0 chars.

Written by Cameron ◯ Letta Code

"Debugging is twice as hard as writing the code." - Brian Kernighan
2026-03-13 16:35:52 -07:00
Cameron
e71fc2f976 fix: revert to resumeSession(agentId) — API conversations incompatible with SDK
resumeSession(conversationId) silently fails (0 chars response) when the
conversation was created via the raw Letta API. The SDK needs to manage
its own conversation. Revert to agentId for now.

Written by Cameron ◯ Letta Code

"Move fast and fix things." - Unknown
2026-03-13 16:34:49 -07:00
Cameron
4c3c457f7a fix: use conversationId in SDK worker so messages appear in same thread
resumeSession(conversationId) instead of resumeSession(agentId) so that
SDK-routed messages show up in the same conversation on app.letta.com.

Written by Cameron ◯ Letta Code

"All problems in computer science can be solved by another level of indirection." - David Wheeler
2026-03-13 16:29:19 -07:00
Cameron
3f1076c092 Merge pull request #29 from letta-ai/feat/sdk-tools
feat: Letta Code SDK transport for client-side tool access
2026-03-13 16:08:58 -07:00
Cameron
13b454bf00 feat: add Letta Code SDK transport for client-side tool access (#19)
Give the Subconscious agent client-side tool access (Read, Grep, Glob,
web_search) via the Letta Code SDK. Instead of being limited to memory
operations, Sub can now read files and search the web while processing
transcripts.

Architecture:
- New send_worker_sdk.ts uses resumeSession() from @letta-ai/letta-code-sdk
- send_messages_to_letta.ts routes to SDK or legacy worker based on
  LETTA_SDK_TOOLS env var (read-only | full | off)
- Stop hook is now async (won't block Claude Code)
- Legacy raw API path preserved for LETTA_SDK_TOOLS=off

New env var: LETTA_SDK_TOOLS
- read-only (default): Read, Grep, Glob, web_search, fetch_webpage
- full: all tools
- off: legacy memory-only behavior

Closes #19

Written by Cameron ◯ Letta Code

"The best interface is no interface." - Golden Krishna
2026-03-13 16:07:42 -07:00
Cameron
9af486be68 chore: sync plugin.json version to 1.5.1
👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta Code <noreply@letta.com>
2026-03-06 09:34:11 -08:00
Cameron
ebf87b15f6 chore: bump version to 1.5.1 v1.5.1 2026-03-04 13:18:02 -08:00
Cameron
98a5dbdf0b fix: improve splash screen mascot and link display order
- Simplified spider mascot with red eyes
- Print Discord/agent links before blocking network call
- Ensures links display even if session message times out
2026-03-04 13:17:41 -08:00
Cameron
246dd065b6 chore: bump version to 1.5.0 v1.5.0 2026-03-04 12:41:31 -08:00
Cameron
314b54be01 chore: update model reference to glm-5 2026-03-04 12:37:20 -08:00
Cameron
890872368c feat: add checkpoint hooks and startup splash screen
- Add PreToolUse hooks for AskUserQuestion and ExitPlanMode to send
  transcripts to Letta at natural pause points (plan_checkpoint.ts)
- Extract shared transcript utilities into transcript_utils.ts
- Add LETTA_CHECKPOINT_MODE env var (blocking/async/off)
- Add startup splash screen with agent info, settings, and links
- Write to /dev/tty to show splash in terminal (bypasses Claude capture)
- Update README with checkpoint hooks documentation
2026-03-04 12:36:01 -08:00
Cameron
2e93f2aff1 chore: bump version to 1.4.2
Written by Cameron ◯ Letta Code

"One more patch." - Every release engineer
v1.4.2
2026-02-26 14:33:25 -08:00
Cameron
465f4dcce3 Merge pull request #26 from letta-ai/fix/multi-user-temp-dir
fix: use per-user temp dir to avoid EACCES on shared machines
2026-02-26 14:33:08 -08:00
Cameron
f8cae38805 fix: use per-user temp dir to avoid EACCES on shared machines (#25)
The hardcoded /tmp/letta-claude-sync/ path caused EACCES errors when
multiple OS users shared the same machine — the first user to create
the directory owned it, blocking all others.

Now uses os.tmpdir() with a UID suffix (e.g. /tmp/letta-claude-sync-501/)
so each user gets their own log/payload directory.

Fixes #25

Written by Cameron ◯ Letta Code

"Sharing is caring, except for /tmp directories." - Unknown
2026-02-26 14:32:35 -08:00
Cameron
bf783b7cc2 chore: bump version to 1.4.1
Written by Cameron ◯ Letta Code

"Keep moving." - Unknown
v1.4.1
2026-02-24 10:29:45 -08:00
Cameron
20518f73d6 Update default agent model to glm-5
Written by Cameron ◯ Letta Code

"Upgrade your dependencies before they upgrade you." - Anonymous
2026-02-24 10:19:24 -08:00
Cameron
bdb532ea08 chore: bump version to 1.4.0
Written by Cameron ◯ Letta Code

"Ship it." - Every engineer ever
v1.4.0
2026-02-24 10:13:46 -08:00
Cameron
141194716f Merge pull request #22 from scrossle/fix/windows-pseudoconsole
fix(windows): eliminate console window flashes using PseudoConsole
2026-02-24 10:12:56 -08:00
Cameron
b80d7621f4 Merge pull request #24 from 24601/fix/model-patch-preserves-context-window
fix: use llm_config PATCH to preserve context_window during model updates
2026-02-24 10:12:53 -08:00
Basit Mustafa
a794a66dda fix: use llm_config PATCH to preserve context_window during model updates
The top-level `{ model: "..." }` PATCH on the Letta API resets
context_window to a server-side default (32K), even when both fields
are sent in the same request. This means every LETTA_MODEL override
silently drops the agent's context_window back to 32K.

Switch updateAgentModel() to use `{ llm_config: {...} }` PATCH format
which preserves context_window and other settings. Add buildLlmConfig()
helper that constructs the full config from available model metadata and
the agent's current settings.

Also adds LETTA_CONTEXT_WINDOW environment variable so users can
explicitly set their desired context window size.

Changes:
- Extract findModel() from isModelAvailable() for reuse
- Add LlmConfig interface with full llm_config fields
- Add buildLlmConfig() to construct config from model handle + metadata
- Update updateAgentModel() to PATCH via llm_config instead of model
- Add LETTA_CONTEXT_WINDOW env var support
- Document LETTA_CONTEXT_WINDOW in README
- Add 13 tests for findModel() and buildLlmConfig()
2026-02-19 09:18:04 -08:00
scrossle
36898f1318 fix(windows): add Win10 compat and deduplicate worker spawn logic
- Add dual P/Invoke for UpdateProcThreadAttribute (Win11 26300+) vs
  UpdateProcThreadAttributeList (Win10/older) with EntryPointNotFoundException
  fallback in SilentLauncher.cs
- Extract shared spawnSilentWorker() utility into conversation_utils.ts,
  replacing ~50 duplicated lines in send_messages_to_letta.ts and
  sync_letta_memory.ts
- Add build.ps1 for reproducible silent-launcher.exe builds
- Rebuild silent-launcher.exe with updated source

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 21:28:23 -08:00
scrossle
8adae7cdbb fix(windows): eliminate console window flashes using PseudoConsole
On Windows 11 / Windows Terminal, hook execution caused visible console
window popups. This replaces the simple npx wrapper (silent-npx.js) with
a PseudoConsole (ConPTY) + CREATE_NO_WINDOW approach that runs scripts
in a headless console session.

New files:
- SilentLauncher.cs: C# launcher creating a PseudoConsole with
  CREATE_NO_WINDOW, stdin/stdout via temp files, and --import tsx/esm
  for single-process execution
- silent-launcher.exe: Compiled as AnyCPU winexe (works on x64 and ARM64)
- stdio-preload.cjs: Node.js --require script for temp file I/O
- silent-npx.cjs: Cross-platform shim that delegates to
  silent-launcher.exe on Windows, runs tsx directly elsewhere

Also fixes:
- Letta API message sync: bumped limit from 50 to 300 and added date
  sorting (API does not guarantee newest-first ordering)
- Background workers on Windows: spawn through silent-launcher.exe with
  detached:true so workers survive PseudoConsole closure

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 21:16:02 -08:00
Cameron
c94353f0bc chore: bump version to 1.3.2 v1.3.2 2026-02-09 17:07:31 -08:00