@letta-ai/letta-code 0.26.3 → 0.26.5
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 +12 -0
- package/letta.js +20977 -18072
- package/package.json +1 -1
- package/skills/creating-extensions/SKILL.md +2 -1
- package/skills/creating-extensions/references/events.md +43 -6
package/package.json
CHANGED
|
@@ -44,7 +44,7 @@ Default to a **tool** when the model should decide when to use the capability. D
|
|
|
44
44
|
5. Write a single-file extension unless the user asks for something larger.
|
|
45
45
|
6. Return disposers for registered commands/tools/events, timers, subscriptions, and panels that should close on reload.
|
|
46
46
|
7. Do a basic review: valid names, descriptions present, schemas are object schemas, optional capabilities guarded, scoped APIs used, cleanup returned.
|
|
47
|
-
8. Tell the user the absolute file path changed and to run `/reload`.
|
|
47
|
+
8. Tell the user the absolute file path changed and to run `/reload`. If an extension breaks startup or command handling, recover with `letta --no-extensions` or `LETTA_DISABLE_EXTENSIONS=1 letta`.
|
|
48
48
|
|
|
49
49
|
## Core extension shape
|
|
50
50
|
|
|
@@ -72,6 +72,7 @@ Use `letta.capabilities` for optional behavior:
|
|
|
72
72
|
letta.capabilities.tools
|
|
73
73
|
letta.capabilities.commands
|
|
74
74
|
letta.capabilities.events.lifecycle
|
|
75
|
+
letta.capabilities.events.tools
|
|
75
76
|
letta.capabilities.events.turns
|
|
76
77
|
letta.capabilities.ui.panels
|
|
77
78
|
letta.capabilities.ui.statusValues
|
|
@@ -8,6 +8,7 @@ This is the first slice of the hooks-v2 direction. The long-term goal is for typ
|
|
|
8
8
|
|
|
9
9
|
```ts
|
|
10
10
|
letta.capabilities.events.lifecycle
|
|
11
|
+
letta.capabilities.events.tools
|
|
11
12
|
letta.capabilities.events.turns
|
|
12
13
|
```
|
|
13
14
|
|
|
@@ -33,26 +34,27 @@ letta.events.on("event_name", (event, ctx) => {
|
|
|
33
34
|
});
|
|
34
35
|
```
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
Tool events use this same API. Existing settings-based hooks still own blocking decisions and model feedback injection until those contracts are explicitly added to extension events.
|
|
37
38
|
|
|
38
39
|
```ts
|
|
39
|
-
letta.events.on("
|
|
40
|
+
letta.events.on("tool_start", (event, ctx) => {
|
|
40
41
|
if (event.toolName !== "Bash") return;
|
|
41
|
-
if (String(event.
|
|
42
|
-
return {
|
|
42
|
+
if (String(event.args.command).startsWith("npm test")) {
|
|
43
|
+
return { args: { ...event.args, command: "bun test" } };
|
|
43
44
|
}
|
|
44
45
|
});
|
|
45
46
|
```
|
|
46
47
|
|
|
47
|
-
Lifecycle and
|
|
48
|
+
Lifecycle, turn-start, and tool-start events are wired today.
|
|
48
49
|
|
|
49
|
-
Lifecycle handlers are notification-only and should not return values. `turn_start` handlers can transform the outbound input for the next model turn.
|
|
50
|
+
Lifecycle handlers are notification-only and should not return values. `turn_start` handlers can transform the outbound input for the next model turn. `tool_start` handlers can transform the tool arguments before execution.
|
|
50
51
|
|
|
51
52
|
## Supported events
|
|
52
53
|
|
|
53
54
|
```ts
|
|
54
55
|
"conversation_open"
|
|
55
56
|
"conversation_close"
|
|
57
|
+
"tool_start"
|
|
56
58
|
"turn_start"
|
|
57
59
|
```
|
|
58
60
|
|
|
@@ -91,6 +93,41 @@ Lifecycle handlers are notification-only and should not return values. `turn_sta
|
|
|
91
93
|
}
|
|
92
94
|
```
|
|
93
95
|
|
|
96
|
+
`tool_start` event:
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
{
|
|
100
|
+
agentId: string | null;
|
|
101
|
+
conversationId: string | null;
|
|
102
|
+
toolCallId: string | null;
|
|
103
|
+
toolName: string;
|
|
104
|
+
args: Record<string, unknown>;
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
`tool_start` fires immediately before a client-side tool executes. This includes built-in tools, extension tools, and external tools executed through the local tool manager. It runs after permission/approval classification and before `PreToolUse` hooks, so trusted local extensions can change the actual executed arguments after the approval UI has already classified the original request.
|
|
109
|
+
|
|
110
|
+
Handlers can inspect `event.args`, mutate it directly, or return replacement args:
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
letta.events.on("tool_start", (event) => {
|
|
114
|
+
if (event.toolName !== "Bash") return;
|
|
115
|
+
event.args = {
|
|
116
|
+
...event.args,
|
|
117
|
+
command: String(event.args.command).replaceAll("npm test", "bun test"),
|
|
118
|
+
};
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
letta.events.on("tool_start", (event) => {
|
|
122
|
+
if (event.toolName !== "Read") return;
|
|
123
|
+
return { args: { ...event.args, limit: 200 } };
|
|
124
|
+
});
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Handlers run in registration order. Later handlers see the current args after earlier mutations/returns. If a handler throws, its partial `event.args` mutation is rolled back and the error is recorded as an extension diagnostic.
|
|
128
|
+
|
|
129
|
+
`tool_start` is intentionally a trusted local extension point: it can rewrite commands, file paths, and other tool inputs before execution. Keep transforms focused and unsurprising. It does not support blocking; use existing hooks for blocking safety decisions.
|
|
130
|
+
|
|
94
131
|
`turn_start` fires before outbound turns that include a user message. In the TUI this includes normal submits and prompt-style command turns. In headless it includes one-shot prompts and bidirectional user turns.
|
|
95
132
|
|
|
96
133
|
Handlers can mutate `event.input` directly or return replacement input:
|