@letta-ai/letta-code 0.30.32 → 0.31.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.
Files changed (61) hide show
  1. package/dist/agent-presets-agent-presets.js +11 -0
  2. package/dist/agent-presets-agent-presets.js.map +9 -0
  3. package/dist/agent-presets-personality-asset-content.js +42 -0
  4. package/dist/agent-presets-personality-asset-content.js.map +10 -0
  5. package/dist/agent-presets.js +17 -2
  6. package/dist/agent-presets.js.map +3 -3
  7. package/dist/channels-public.js +16 -1
  8. package/dist/channels-public.js.map +5 -4
  9. package/dist/gateway-core.js +5 -4
  10. package/dist/gateway-core.js.map +3 -3
  11. package/dist/mcp-client.js +2 -2
  12. package/dist/mcp-client.js.map +1 -1
  13. package/dist/types/agent/create-agent-request.d.ts +3 -0
  14. package/dist/types/agent/create-agent-request.d.ts.map +1 -1
  15. package/dist/types/agent/model.d.ts.map +1 -1
  16. package/dist/types/agent/personality-asset-content.d.ts +3 -0
  17. package/dist/types/agent/personality-asset-content.d.ts.map +1 -0
  18. package/dist/types/agent/skills.d.ts.map +1 -1
  19. package/dist/types/channels/gateway-core.d.ts.map +1 -1
  20. package/dist/types/channels/route-thread-key.d.ts +20 -0
  21. package/dist/types/channels/route-thread-key.d.ts.map +1 -0
  22. package/dist/types/channels-public.d.ts +1 -0
  23. package/dist/types/channels-public.d.ts.map +1 -1
  24. package/dist/types/tools/impl/skill.d.ts.map +1 -1
  25. package/dist/types/types/protocol_v2.d.ts +3 -144
  26. package/dist/types/types/protocol_v2.d.ts.map +1 -1
  27. package/dist/types/types/schedule-protocol.d.ts +151 -1
  28. package/dist/types/types/schedule-protocol.d.ts.map +1 -1
  29. package/dist/types/utils/frontmatter.d.ts.map +1 -1
  30. package/dist/types/websocket/listener/cwd-change.d.ts.map +1 -1
  31. package/letta.js +238 -86
  32. package/package.json +4 -2
  33. package/scripts/builtin-skills-watch/agent-watch.test.ts +104 -0
  34. package/scripts/builtin-skills-watch/agent-watch.ts +337 -0
  35. package/scripts/builtin-skills-watch/aggregate-results.test.ts +79 -0
  36. package/scripts/builtin-skills-watch/aggregate-results.ts +326 -0
  37. package/scripts/builtin-skills-watch/analysis.test.ts +70 -0
  38. package/scripts/builtin-skills-watch/analysis.ts +228 -0
  39. package/scripts/builtin-skills-watch/evidence.test.ts +114 -0
  40. package/scripts/builtin-skills-watch/evidence.ts +145 -0
  41. package/scripts/builtin-skills-watch/github.ts +161 -0
  42. package/scripts/builtin-skills-watch/tracker.test.ts +249 -0
  43. package/scripts/builtin-skills-watch/tracker.ts +506 -0
  44. package/scripts/builtin-skills-watch/update-tracker.test.ts +234 -0
  45. package/scripts/builtin-skills-watch/update-tracker.ts +508 -0
  46. package/scripts/claude-watch/release-source.test.ts +16 -4
  47. package/scripts/claude-watch/release-source.ts +41 -2
  48. package/scripts/codex-watch/agent-watch.ts +8 -5
  49. package/scripts/codex-watch/release-analysis.test.ts +18 -16
  50. package/scripts/codex-watch/release-analysis.ts +31 -9
  51. package/scripts/codex-watch/tracker.test.ts +5 -5
  52. package/scripts/codex-watch/tracker.ts +7 -8
  53. package/scripts/pi-ai-watch/agent-watch.ts +9 -14
  54. package/scripts/pi-ai-watch/release-analysis.test.ts +24 -18
  55. package/scripts/pi-ai-watch/release-analysis.ts +85 -45
  56. package/scripts/pi-ai-watch/tracker.test.ts +25 -18
  57. package/scripts/pi-ai-watch/tracker.ts +7 -19
  58. package/scripts/pi-ai-watch/update-tracker.ts +2 -2
  59. package/scripts/source-file-size-baseline.json +2 -2
  60. package/skills/dispatching-coding-agents/SKILL.md +16 -7
  61. package/skills/syncing-memory-filesystem/SKILL.md +118 -226
@@ -1,7 +1,6 @@
1
1
  import { describe, expect, test } from "bun:test";
2
2
  import type { PiAiWatchAnalysis } from "./release-analysis.ts";
3
3
  import {
4
- advanceMergedPr,
5
4
  getPendingPrForCursor,
6
5
  hasCompletedRange,
7
6
  hasRecordedOutcome,
@@ -19,17 +18,18 @@ describe("pi-ai watch tracker", () => {
19
18
 
20
19
  test("advances after a no-upgrade decision", () => {
21
20
  const state = recordAnalysis(initialTrackerState("0.82.1"), {
22
- analysis: analysis("0.82.1", "0.83.0"),
21
+ analysis: analysis("0.82.1", "0.84.0"),
23
22
  outcome: "no_upgrade",
24
23
  notes: "upstream-only provider change",
25
24
  processedAt: "2026-08-21T00:00:00Z",
26
25
  });
27
- expect(state.audit_cursor_version).toBe("0.83.0");
28
- expect(hasCompletedRange(state, "0.82.1", "0.83.0")).toBe(true);
29
- expect(hasRecordedOutcome(state, "0.82.1", "0.83.0")).toBe(true);
26
+ expect(state.audit_cursor_version).toBe("0.84.0");
27
+ expect(hasCompletedRange(state, "0.82.1", "0.84.0")).toBe(true);
28
+ expect(hasRecordedOutcome(state, "0.82.1", "0.84.0")).toBe(true);
29
+ expect(renderTrackerBody(state)).toContain("[0.82.1...0.84.0]");
30
30
  });
31
31
 
32
- test("keeps a created PR pending until it merges", () => {
32
+ test("advances a created PR and keeps it pending at the cursor", () => {
33
33
  const pending = recordAnalysis(initialTrackerState("0.82.1"), {
34
34
  analysis: analysis("0.82.1", "0.83.0"),
35
35
  outcome: "pr_created",
@@ -37,14 +37,18 @@ describe("pi-ai watch tracker", () => {
37
37
  prUrl: "https://github.com/letta-ai/letta-code/pull/123",
38
38
  processedAt: "2026-08-21T00:00:00Z",
39
39
  });
40
- expect(pending.audit_cursor_version).toBe("0.82.1");
40
+ expect(pending.audit_cursor_version).toBe("0.83.0");
41
41
  expect(getPendingPrForCursor(pending)?.version).toBe("0.83.0");
42
- expect(hasCompletedRange(pending, "0.82.1", "0.83.0")).toBe(false);
42
+ expect(hasCompletedRange(pending, "0.82.1", "0.83.0")).toBe(true);
43
43
  expect(hasRecordedOutcome(pending, "0.82.1", "0.83.0")).toBe(true);
44
44
 
45
- const merged = advanceMergedPr(pending, "0.83.0");
46
- expect(merged.audit_cursor_version).toBe("0.83.0");
47
- expect(getPendingPrForCursor(merged)).toBeNull();
45
+ const later = recordAnalysis(pending, {
46
+ analysis: analysis("0.83.0", "0.84.0"),
47
+ outcome: "no_upgrade",
48
+ notes: "later release range",
49
+ });
50
+ expect(later.audit_cursor_version).toBe("0.84.0");
51
+ expect(getPendingPrForCursor(later)).toBeNull();
48
52
  });
49
53
 
50
54
  test("keeps errors retryable and replaces them with a later outcome", () => {
@@ -68,16 +72,16 @@ describe("pi-ai watch tracker", () => {
68
72
  expect(retried.processed[0]?.outcome).toBe("no_upgrade");
69
73
  });
70
74
 
71
- test("advances uncertain releases but not explicit non-adjacent replays", () => {
75
+ test("advances cumulative reviews but not replays behind the cursor", () => {
72
76
  const human = recordAnalysis(initialTrackerState("0.82.1"), {
73
- analysis: analysis("0.82.1", "0.83.0"),
77
+ analysis: analysis("0.82.1", "0.84.0"),
74
78
  outcome: "needs_human_review",
75
79
  notes: "product decision",
76
80
  });
77
- expect(human.audit_cursor_version).toBe("0.83.0");
81
+ expect(human.audit_cursor_version).toBe("0.84.0");
78
82
 
79
83
  const replay = recordAnalysis(initialTrackerState("0.82.1"), {
80
- analysis: analysis("0.82.1", "0.84.0", false),
84
+ analysis: analysis("0.82.1", "0.83.0", false),
81
85
  outcome: "no_upgrade",
82
86
  notes: "explicit replay",
83
87
  });
@@ -101,7 +105,7 @@ describe("pi-ai watch tracker", () => {
101
105
  const previous = `0.${index}.0`;
102
106
  const current = `0.${index}.1`;
103
107
  state = recordAnalysis(state, {
104
- analysis: analysis(previous, current, false),
108
+ analysis: analysis(previous, current),
105
109
  outcome: "error",
106
110
  notes: `attempt ${index}`,
107
111
  processedAt: `2026-08-21T00:${String(index).padStart(2, "0")}:00Z`,
@@ -115,18 +119,21 @@ describe("pi-ai watch tracker", () => {
115
119
  function analysis(
116
120
  previousVersion: string,
117
121
  currentVersion: string,
118
- adjacent = true,
122
+ isLatestRelease = true,
119
123
  ): PiAiWatchAnalysis {
120
124
  return {
121
125
  package: "@earendil-works/pi-ai",
122
126
  installed_version: "0.82.1",
123
127
  previous_version: previousVersion,
124
128
  current_version: currentVersion,
125
- is_adjacent_release: adjacent,
129
+ is_latest_release: isLatestRelease,
126
130
  published_at: "2026-08-14T00:00:00Z",
127
131
  integrity: "sha512-test",
128
132
  tarball_url: "https://example.test/pi-ai.tgz",
133
+ previous_git_head: "previous123",
129
134
  git_head: "abc123",
135
+ previous_tag_commit: "previous123",
136
+ current_tag_commit: "abc123",
130
137
  release_url: `https://github.com/earendil-works/pi/releases/tag/v${currentVersion}`,
131
138
  compare_url: `https://github.com/earendil-works/pi/compare/v${previousVersion}...v${currentVersion}`,
132
139
  changelog_md: "## Added",
@@ -87,9 +87,9 @@ export function recordAnalysis(
87
87
  ].slice(0, HISTORY_LIMIT);
88
88
 
89
89
  const advancesCursor =
90
- options.analysis.is_adjacent_release &&
90
+ options.analysis.is_latest_release &&
91
91
  entry.previous_version === state.audit_cursor_version &&
92
- (entry.outcome === "no_upgrade" || entry.outcome === "needs_human_review");
92
+ entry.outcome !== "error";
93
93
 
94
94
  return {
95
95
  audit_cursor_version: advancesCursor
@@ -123,8 +123,7 @@ export function hasCompletedRange(
123
123
  (entry) =>
124
124
  entry.previous_version === previousVersion &&
125
125
  entry.version === currentVersion &&
126
- (entry.outcome === "no_upgrade" ||
127
- entry.outcome === "needs_human_review"),
126
+ entry.outcome !== "error",
128
127
  );
129
128
  }
130
129
 
@@ -134,24 +133,13 @@ export function getPendingPrForCursor(
134
133
  return (
135
134
  state.processed.find(
136
135
  (entry) =>
137
- entry.previous_version === state.audit_cursor_version &&
136
+ entry.version === state.audit_cursor_version &&
138
137
  entry.outcome === "pr_created" &&
139
138
  entry.pr_url,
140
139
  ) ?? null
141
140
  );
142
141
  }
143
142
 
144
- export function advanceMergedPr(
145
- state: TrackerState,
146
- currentVersion: string,
147
- ): TrackerState {
148
- const pending = getPendingPrForCursor(state);
149
- if (!pending || pending.version !== currentVersion) {
150
- throw new Error(`No pending pi-ai PR for ${currentVersion}`);
151
- }
152
- return { ...state, audit_cursor_version: currentVersion };
153
- }
154
-
155
143
  export function renderTrackerBody(state: TrackerState): string {
156
144
  const normalized = normalizeState(state);
157
145
  return `${[
@@ -166,7 +154,7 @@ export function renderTrackerBody(state: TrackerState): string {
166
154
  "",
167
155
  "## Hidden state",
168
156
  "",
169
- "The workflow uses the hidden JSON block below for ordered release processing and dedupe.",
157
+ "The workflow uses the hidden JSON block below for cumulative release processing and dedupe.",
170
158
  "",
171
159
  serializeTrackerState(normalized),
172
160
  ].join("\n")}\n`;
@@ -193,12 +181,12 @@ function renderTable(state: TrackerState): string {
193
181
  if (entries.length === 0) return "_No pi-ai releases reviewed yet._";
194
182
 
195
183
  const rows = [
196
- "| Release | Installed | Outcome | PR | Notes |",
184
+ "| Range | Installed | Outcome | PR | Notes |",
197
185
  "|---|---|---|---|---|",
198
186
  ];
199
187
  for (const entry of entries) {
200
188
  rows.push(
201
- `| [${entry.version}](${entry.compare_url}) | ${entry.installed_version} | ${entry.outcome} | ${renderPr(entry.pr_url)} | ${escapeTable(entry.notes)} |`,
189
+ `| [${entry.previous_version}...${entry.version}](${entry.compare_url}) | ${entry.installed_version} | ${entry.outcome} | ${renderPr(entry.pr_url)} | ${escapeTable(entry.notes)} |`,
202
190
  );
203
191
  }
204
192
  return rows.join("\n");
@@ -202,13 +202,13 @@ function parseOutcome(value: string | undefined): TrackerOutcome {
202
202
  function defaultNotes(outcome: TrackerOutcome): string {
203
203
  switch (outcome) {
204
204
  case "no_upgrade":
205
- return "reviewed; no upgrade needed for this release";
205
+ return "reviewed; no upgrade needed for this release range";
206
206
  case "pr_created":
207
207
  return "opened pi-ai dependency upgrade PR";
208
208
  case "needs_human_review":
209
209
  return "needs human review";
210
210
  case "error":
211
- return "automation hit an error; retry this release";
211
+ return "automation hit an error; retry this release range";
212
212
  }
213
213
  }
214
214
 
@@ -37,13 +37,13 @@
37
37
  "src/settings-manager.ts": 2102,
38
38
  "src/tools/manager.ts": 2993,
39
39
  "src/tools/tool-execution-context.test.ts": 1138,
40
- "src/types/protocol_v2.ts": 2834,
40
+ "src/types/protocol_v2.ts": 2666,
41
41
  "src/websocket/listen-client-concurrency.test.ts": 2686,
42
42
  "src/websocket/listen-client-protocol.test.ts": 5819,
43
43
  "src/websocket/listener/commands/memory.ts": 1114,
44
44
  "src/websocket/listener/file-commands.ts": 1053,
45
45
  "src/websocket/listener/lifecycle.ts": 1048,
46
- "src/websocket/listener/protocol-inbound.ts": 2237,
46
+ "src/websocket/listener/protocol-inbound.ts": 2227,
47
47
  "src/websocket/listener/protocol-outbound.ts": 1047,
48
48
  "src/websocket/listener/turn.ts": 1058
49
49
  }
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: dispatching-coding-agents
3
- description: Dispatch stateless coding agents (Claude Code or Codex) via Bash. Use when you're stuck, need a second opinion, or need parallel research on a hard problem. They have no memory you must provide all context.
3
+ description: Dispatch stateless coding agents through Claude Code or Codex. Model catalog checked 2026-08-25: Claude Code includes Sonnet 5, Opus 5, and Fable 5; Codex includes GPT-5.6 Luna, Terra, and Sol. Use when you're stuck, need a second opinion, or need parallel research on a hard problem. They have no memory, so you must provide all context.
4
4
  ---
5
5
 
6
6
  # Dispatching Coding Agents
@@ -43,14 +43,23 @@ Different agents have different strengths. Track what works in your memory over
43
43
 
44
44
  ### Categories
45
45
 
46
- **Codex:**
47
- - Use the configured default model. Model catalogs and account access change frequently, so only pass `--model` when the user explicitly requests one.
46
+ **Codex (catalog checked 2026-08-25):**
47
+ - `gpt-5.6-luna`: high-throughput, lower-latency work
48
+ - `gpt-5.6-terra`: strong performance with a balance of intelligence and cost
49
+ - `gpt-5.6-sol`: quality-first flagship for difficult coding and reasoning
50
+ - Use the configured default unless the user requests a model. Pass a requested model with `-m`, for example `codex exec "YOUR PROMPT" -m gpt-5.6-sol --sandbox workspace-write`.
48
51
  - If a requested model is rejected, inspect the installed CLI and account configuration rather than guessing another model name.
49
52
 
50
- **Claude Code:**
51
- - `opus` Excellent writer. Best for docs, refactors, open-ended tasks, and vague instructions.
52
- - Strengths: Excellent writer, understands vague instructions, excellent for coding but also general-purpose
53
- - Weaknesses: Tends to generate "slop", writing excessive quantities of code unnecessarily. Can hang on large repos.
53
+ **Claude Code (catalog checked 2026-08-25):**
54
+ - The current flagship models are Sonnet 5, Opus 5, and Fable 5. Use the configured default unless the user requests a model.
55
+ - Claude Code's stable aliases follow its current catalog:
56
+ - `best`: highest-capability model available to the account, using Fable 5 when available
57
+ - `fable`: Fable 5 for the hardest, longest-running tasks
58
+ - `opus`: Opus 5 for complex reasoning, docs, refactors, and open-ended tasks
59
+ - `sonnet`: Sonnet 5 for everyday coding
60
+ - `haiku`: fast, simple tasks
61
+ - Pass an alias with `--model`, for example `claude -p "YOUR PROMPT" --model fable --dangerously-skip-permissions`.
62
+ - Aliases update as Claude Code's catalog changes. If an alias is rejected, inspect the installed CLI version and account access rather than guessing a versioned model name.
54
63
 
55
64
  ### Cost and speed tradeoffs
56
65
  - Use each CLI's configured default model unless the task requires a model the user explicitly requested