@letta-ai/letta-code 0.25.10 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +108 -28
- package/dist/types/protocol.d.ts +2 -2
- package/docs/nix.md +105 -0
- package/docs/plans/discord-channel-policy-consolidation.md +35 -0
- package/letta.js +250244 -247360
- package/package.json +11 -4
- package/scripts/check-exported-functions.js +58 -0
- package/scripts/check-filename-casing.js +70 -0
- package/scripts/check-layer-boundaries.js +113 -0
- package/scripts/check-test-mock-isolation.js +19 -19
- package/scripts/check.js +64 -44
- package/scripts/codex-watch/check-release.ts +426 -0
- package/scripts/codex-watch/diff-models-json.test.ts +151 -0
- package/scripts/codex-watch/diff-models-json.ts +207 -0
- package/scripts/codex-watch/render-issue.ts +273 -0
- package/scripts/rename-to-kebab.js +59 -0
- package/scripts/run-unit-tests.cjs +78 -0
- package/scripts/update-kebab-imports.js +93 -0
- package/skills/initializing-memory/SKILL.md +1 -2
- package/skills/working-in-parallel/SKILL.md +0 -90
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Updates import paths after renaming .ts files to kebab-case.
|
|
4
|
+
*
|
|
5
|
+
* Builds an exact old-basename → new-basename mapping from `git diff --cached`
|
|
6
|
+
* so only paths that were actually renamed get updated.
|
|
7
|
+
* .tsx component imports are NOT touched (those files weren't renamed).
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { execSync } from "node:child_process";
|
|
11
|
+
import { readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
12
|
+
import { basename, dirname, join } from "node:path";
|
|
13
|
+
|
|
14
|
+
// Build exact mapping from git staged renames: oldBase -> newBase (no extension)
|
|
15
|
+
const renameMap = new Map(); // "OldName" -> "new-name"
|
|
16
|
+
|
|
17
|
+
const gitStatus = execSync("git diff --cached --name-status", {
|
|
18
|
+
encoding: "utf-8",
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
for (const line of gitStatus.split("\n")) {
|
|
22
|
+
const m = line.match(/^R\d*\t(.+)\t(.+)$/);
|
|
23
|
+
if (!m) continue;
|
|
24
|
+
const [, oldPath, newPath] = m;
|
|
25
|
+
const oldBase = basename(oldPath);
|
|
26
|
+
const newBase = basename(newPath);
|
|
27
|
+
if (oldBase === newBase) continue;
|
|
28
|
+
|
|
29
|
+
// Strip only the last extension (e.g. "FooBar.shared.ts" -> "FooBar.shared")
|
|
30
|
+
// so dotted names like imageResize.shared are looked up correctly.
|
|
31
|
+
const oldStem = oldBase.replace(/\.[^.]+$/, "");
|
|
32
|
+
const newStem = newBase.replace(/\.[^.]+$/, "");
|
|
33
|
+
renameMap.set(oldStem, newStem);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
console.log(`Built rename map: ${renameMap.size} entries`);
|
|
37
|
+
|
|
38
|
+
function* walkSrc(dir) {
|
|
39
|
+
for (const entry of readdirSync(dir)) {
|
|
40
|
+
const full = join(dir, entry);
|
|
41
|
+
if (statSync(full).isDirectory()) yield* walkSrc(full);
|
|
42
|
+
else if (entry.endsWith(".ts") || entry.endsWith(".tsx")) yield full;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Replace the last path segment of an import path if it's in the rename map
|
|
47
|
+
function updatePath(importPath) {
|
|
48
|
+
const lastSlash = importPath.lastIndexOf("/");
|
|
49
|
+
const dir = lastSlash >= 0 ? importPath.slice(0, lastSlash + 1) : "";
|
|
50
|
+
let file = lastSlash >= 0 ? importPath.slice(lastSlash + 1) : importPath;
|
|
51
|
+
|
|
52
|
+
// Strip explicit .ts/.js extension for lookup (imports usually have no ext)
|
|
53
|
+
let ext = "";
|
|
54
|
+
if (file.endsWith(".ts") || file.endsWith(".js")) {
|
|
55
|
+
ext = file.slice(file.lastIndexOf("."));
|
|
56
|
+
file = file.slice(0, file.lastIndexOf("."));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const newFile = renameMap.get(file);
|
|
60
|
+
if (!newFile) return importPath;
|
|
61
|
+
return dir + newFile + ext;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let totalFiles = 0;
|
|
65
|
+
let totalChanged = 0;
|
|
66
|
+
|
|
67
|
+
// Matches from/import()/require() string literals and new URL() path strings
|
|
68
|
+
const IMPORT_RE =
|
|
69
|
+
/(?:(?:from|import)\s*\(?\s*|require\s*\()(["'`])([^"'`\n]+)\1/g;
|
|
70
|
+
const URL_RE = /new\s+URL\s*\(\s*(["'`])([^"'`\n]+\.ts)\1/g;
|
|
71
|
+
|
|
72
|
+
for (const file of walkSrc("src")) {
|
|
73
|
+
const src = readFileSync(file, "utf-8");
|
|
74
|
+
let result = src;
|
|
75
|
+
|
|
76
|
+
result = result.replace(IMPORT_RE, (match, quote, path) => {
|
|
77
|
+
const updated = updatePath(path);
|
|
78
|
+
return updated === path ? match : match.replace(path, updated);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
result = result.replace(URL_RE, (match, quote, path) => {
|
|
82
|
+
const updated = updatePath(path);
|
|
83
|
+
return updated === path ? match : match.replace(path, updated);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
if (result !== src) {
|
|
87
|
+
writeFileSync(file, result, "utf-8");
|
|
88
|
+
totalChanged++;
|
|
89
|
+
}
|
|
90
|
+
totalFiles++;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
console.log(`Scanned ${totalFiles} files, updated ${totalChanged} files.`);
|
|
@@ -50,7 +50,7 @@ You should determine what the users goals and motivations are, to help yourself
|
|
|
50
50
|
Understanding the user's personality and other attributes about them will help contextualize their interactions and allow you to engage with them more effectively. Can you pattern match them to common personas? Do they have unique attributes, quirks, or linguistic patterns? How would you describe them as a person?
|
|
51
51
|
|
|
52
52
|
**Understanding their preferences**:
|
|
53
|
-
You should learn how the user wants work to be done, and how they want to collaborate with AIs like yourself. Examples of this can include coding preferences (e.g. "Prefer functional components over class components", "Use early returns instead of nested conditionals"), but also higher-level preferences such as when to
|
|
53
|
+
You should learn how the user wants work to be done, and how they want to collaborate with AIs like yourself. Examples of this can include coding preferences (e.g. "Prefer functional components over class components", "Use early returns instead of nested conditionals"), but also higher-level preferences such as when to ask before planning or implementing, the scope of changes, how to communicate in different scenarios, etc.
|
|
54
54
|
|
|
55
55
|
### Understanding the codebase and existing work
|
|
56
56
|
You should also learn as much as possible about the existing codebase and work. Think of this as your onboarding period - an opportunity to maximize your performance for future tasks. Learn things like:
|
|
@@ -718,4 +718,3 @@ git push
|
|
|
718
718
|
**Write findings to memory as you go** — don't wait until the end.
|
|
719
719
|
**Edit memory files directly via the filesystem** — memory is projected to `$MEMORY_DIR` specifically for ease of bulk modification. Use standard file tools (Read, Write, Edit) and git to manage changes during initialization.
|
|
720
720
|
|
|
721
|
-
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: working-in-parallel
|
|
3
|
-
description: Guide for working in parallel with other agents. Use when another agent is already working in the same directory, or when you need to work on multiple features simultaneously. Covers git worktrees as the recommended approach.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Working in Parallel
|
|
7
|
-
|
|
8
|
-
Use **git worktrees** to work in parallel when another agent is in the same directory.
|
|
9
|
-
|
|
10
|
-
Git worktrees let you check out multiple branches into separate directories. Each worktree has its own isolated files while sharing the same Git history and remote connections. Changes in one worktree won't affect others, so parallel agents can't interfere with each other.
|
|
11
|
-
|
|
12
|
-
Learn more: [Git worktree documentation](https://git-scm.com/docs/git-worktree)
|
|
13
|
-
|
|
14
|
-
## IMPORTANT: Worktree Location
|
|
15
|
-
|
|
16
|
-
**All worktrees MUST be created under `.letta/worktrees/` in the repo root.** This keeps worktrees organized, gitignored, and out of the user's project directory.
|
|
17
|
-
|
|
18
|
-
Before creating the first worktree, ensure `.letta/worktrees` is in the repo's `.gitignore`:
|
|
19
|
-
|
|
20
|
-
```bash
|
|
21
|
-
# Add to .gitignore if not already present
|
|
22
|
-
grep -q '.letta/worktrees' .gitignore 2>/dev/null || echo '.letta/worktrees' >> .gitignore
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
## IMPORTANT: Check Project Setup First
|
|
26
|
-
|
|
27
|
-
Before running ANY commands in a new worktree, check the project's setup instructions:
|
|
28
|
-
|
|
29
|
-
1. **Read the README** - Usually has install/build commands
|
|
30
|
-
2. **Check `claude.md` or `AGENT.md`** - Agent-specific guidance if present
|
|
31
|
-
3. **Review your `project` memory block** - Contains learned project preferences
|
|
32
|
-
|
|
33
|
-
Don't assume `npm` vs `bun` vs `pnpm` - **check the project first!**
|
|
34
|
-
|
|
35
|
-
## Quick Start
|
|
36
|
-
|
|
37
|
-
```bash
|
|
38
|
-
# Ensure .letta/worktrees is gitignored
|
|
39
|
-
grep -q '.letta/worktrees' .gitignore 2>/dev/null || echo '.letta/worktrees' >> .gitignore
|
|
40
|
-
|
|
41
|
-
# Create worktree with new branch (from repo root)
|
|
42
|
-
git worktree add -b fix/my-feature .letta/worktrees/my-feature main
|
|
43
|
-
|
|
44
|
-
# Work in the worktree
|
|
45
|
-
cd .letta/worktrees/my-feature
|
|
46
|
-
|
|
47
|
-
# CHECK PROJECT SETUP FIRST - then install dependencies
|
|
48
|
-
# Read README.md or check project memory block for correct command
|
|
49
|
-
bun install # Example - verify this is correct for YOUR project!
|
|
50
|
-
|
|
51
|
-
# Make changes, commit, push, PR
|
|
52
|
-
git add <files>
|
|
53
|
-
git commit -m "fix: description"
|
|
54
|
-
git push -u origin fix/my-feature
|
|
55
|
-
gh pr create --title "Fix: description" --body "## Summary..."
|
|
56
|
-
|
|
57
|
-
# Clean up when done (from repo root)
|
|
58
|
-
git worktree remove .letta/worktrees/my-feature
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
## Key Commands
|
|
62
|
-
|
|
63
|
-
```bash
|
|
64
|
-
git worktree add -b <branch> .letta/worktrees/<name> main # Create with new branch
|
|
65
|
-
git worktree add .letta/worktrees/<name> <existing-branch> # Use existing branch
|
|
66
|
-
git worktree list # Show all worktrees
|
|
67
|
-
git worktree remove .letta/worktrees/<name> # Remove worktree
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
## When to Use
|
|
71
|
-
|
|
72
|
-
- Another agent is working in the current directory
|
|
73
|
-
- Long-running task in one session, quick fix needed in another
|
|
74
|
-
- User wants to continue development while an agent works on a separate feature
|
|
75
|
-
|
|
76
|
-
## Pre-commit Hooks in Worktrees
|
|
77
|
-
|
|
78
|
-
Worktrees share `.git`, but pre-commit hooks may need initialization depending on project setup. After creating a worktree and installing dependencies, verify hooks are active before committing. Check project docs or run the project's hook setup command if needed.
|
|
79
|
-
|
|
80
|
-
## Tips
|
|
81
|
-
|
|
82
|
-
- **Always use `.letta/worktrees/`** - never create worktrees outside this directory
|
|
83
|
-
- **Check project setup docs before installing** - README, claude.md, project memory block
|
|
84
|
-
- Name worktrees clearly: `.letta/worktrees/feature-auth`, `.letta/worktrees/bugfix-123`
|
|
85
|
-
- Install dependencies using the project's package manager (check first!)
|
|
86
|
-
- Push changes before removing worktrees
|
|
87
|
-
|
|
88
|
-
## Alternative: Repo Clones
|
|
89
|
-
|
|
90
|
-
Some users prefer cloning the repo multiple times (`gh repo clone owner/repo project-01`) for simpler mental model. This uses more disk space but provides complete isolation. If the user expresses confusion about worktrees or explicitly prefers clones, use that approach instead.
|