@letta-ai/letta-agent-sdk 0.6.1 → 0.6.2

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.
@@ -17,6 +17,7 @@ export declare abstract class RemoteClientSessionCore implements LettaCodeSessio
17
17
  private readonly requestTimeoutMs;
18
18
  private initializePromise;
19
19
  private removeMessageHandler;
20
+ private detachTransportDisconnect;
20
21
  private readonly turns;
21
22
  private toolNames;
22
23
  private deviceStatusListeners;
@@ -63,6 +64,25 @@ export declare abstract class RemoteClientSessionCore implements LettaCodeSessio
63
64
  changeDeviceState(updates: ChangeDeviceStateOptions): Promise<void>;
64
65
  updateToolset(toolsetPreference: string): Promise<void>;
65
66
  protected abstract initializeRuntimeController(): Promise<RuntimeSessionInit>;
67
+ /**
68
+ * Fail the session when its transport drops unexpectedly.
69
+ *
70
+ * Without this an in-flight turn parks forever: nextMessage() only settles
71
+ * through the coordinator, and the socket's own pending-request rejection
72
+ * covers request/response commands, not streaming turns.
73
+ *
74
+ * The session is not revived — the runtime lived on the dead socket. The
75
+ * caller observes the error and rebuilds via resumeSession().
76
+ *
77
+ * Subclasses call this only once their runtime is live: a drop before that
78
+ * already surfaces as a rejected connect or runtime-start, and failing the
79
+ * session there would defeat initialize()'s retry path. Explicit closes do
80
+ * not notify, so this fires for faults only. Detaching stays here so every
81
+ * teardown path — clean close and failed initialize alike — covers it.
82
+ */
83
+ protected watchTransportDisconnect(client: {
84
+ onDisconnect(handler: () => void): () => void;
85
+ }): void;
66
86
  protected afterRuntimeInitialized(): Promise<void>;
67
87
  protected beforeTurn(): Promise<void>;
68
88
  protected onCoreClose(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"remote-client-session-core.d.ts","sourceRoot":"","sources":["../src/remote-client-session-core.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"remote-client-session-core.d.ts","sourceRoot":"","sources":["../src/remote-client-session-core.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EACrB,oBAAoB,EACpB,wBAAwB,EACxB,kBAAkB,EAClB,sBAAsB,EACtB,6BAA6B,EAC7B,gBAAgB,EAEhB,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,8BAA8B,EAC9B,6BAA6B,EAC7B,yBAAyB,EACzB,cAAc,EACd,UAAU,EACV,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,aAAa,EACb,4BAA4B,EAC5B,iBAAiB,EACjB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAWL,KAAK,6BAA6B,EAClC,KAAK,6BAA6B,EAClC,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EAExB,MAAM,8BAA8B,CAAC;AACtC,YAAY,EACV,eAAe,EACf,6BAA6B,EAC7B,qBAAqB,EACrB,YAAY,EACZ,sBAAsB,EACtB,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,8BAA8B,CAAC;AAEtC,8BAAsB,uBAAwB,YAAW,gBAAgB;IAsBrE,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,kBAAkB;IArB7C,SAAS,CAAC,UAAU,EAAE,6BAA6B,GAAG,IAAI,CAAQ;IAClE,SAAS,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAAQ;IAC9C,SAAS,CAAC,WAAW,UAAS;IAC9B,SAAS,CAAC,MAAM,UAAS;IACzB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IACzC,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC3C,SAAS,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAQ;IAChD,SAAS,CAAC,MAAM,SAAM;IACtB,SAAS,CAAC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAQ;IAEhE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAqB;IACtD,OAAO,CAAC,iBAAiB,CAAwC;IACjE,OAAO,CAAC,oBAAoB,CAA6B;IACzD,OAAO,CAAC,yBAAyB,CAA6B;IAC9D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAwB;IAC9C,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,qBAAqB,CAAoD;IACjF,OAAO,CAAC,0BAA0B,CAAqC;IAEvE,SAAS,aACY,IAAI,EAAE,kBAAkB,EAC3C,MAAM,EAAE,6BAA6B;IAavC;;;;;;;;;OASG;IACG,UAAU,IAAI,OAAO,CAAC,cAAc,CAAC;YA+B7B,iBAAiB;IA2C/B;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAoBzB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBzC,oBAAoB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAwBpE,MAAM,IAAI,cAAc,CAAC,UAAU,CAAC;IASrC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAOtB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IACvD,WAAW,CAAC,SAAS,SAAS,kBAAkB,GAAG,kBAAkB,EACzE,OAAO,EAAE,kBAAkB,EAC3B,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,SAAS,CAAC;IAmCf,UAAU,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAUvC,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC;YAUpE,gBAAgB;IAuBxB,uBAAuB,CAC3B,OAAO,GAAE,8BAAmC,GAC3C,OAAO,CAAC,6BAA6B,CAAC;IAUnC,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC;IAkCvE,eAAe,CACnB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,mBAAmB,CAAC;IAgB/B,cAAc,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,GAAG,MAAM,IAAI;IAU3E,OAAO,CAAC,mBAAmB;IA2ErB,YAAY,CAAC,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAc5E,cAAc,CAClB,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,oBAAoB,CAAC;IA2BhC,KAAK,IAAI,IAAI;IAkBb,IAAI,OAAO,IAAI,MAAM,GAAG,IAAI,CAE3B;IAED,IAAI,SAAS,IAAI,MAAM,GAAG,IAAI,CAE7B;IAED,IAAI,cAAc,IAAI,MAAM,GAAG,IAAI,CAElC;IAEK,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC;IAKtC,iBAAiB,CACrB,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,IAAI,CAAC;IA0BV,aAAa,CAAC,iBAAiB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB7D,SAAS,CAAC,QAAQ,CAAC,2BAA2B,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAE7E;;;;;;;;;;;;;;;OAeG;IACH,SAAS,CAAC,wBAAwB,CAAC,MAAM,EAAE;QACzC,YAAY,CAAC,OAAO,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;KAC/C,GAAG,IAAI;cAWQ,uBAAuB,IAAI,OAAO,CAAC,IAAI,CAAC;cAIxC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3C,SAAS,CAAC,WAAW,IAAI,IAAI;cAIb,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAI/C,SAAS,CAAC,cAAc,IAAI,6BAA6B,GAAG,kBAAkB;IAI9E,SAAS,CAAC,iBAAiB,CAAC,OAAO,EAAE,6BAA6B,GAAG,kBAAkB,GAAG,OAAO;IAKjG,SAAS,CAAC,eAAe,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAKpD,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;YAIzB,yBAAyB;cAuEvB,0BAA0B,IAAI,OAAO,CAAC,IAAI,CAAC;IAqD3D,OAAO,CAAC,gBAAgB;CASzB"}
@@ -35,6 +35,16 @@ export declare class RemoteTurnCoordinator {
35
35
  markAbortRequested(): void;
36
36
  handleProtocolMessage(message: ProtocolMessage, runtime: RuntimeScope): void;
37
37
  nextMessage(): Promise<SDKMessage | null>;
38
+ /**
39
+ * Close after the transport dropped, surfacing the failure to stream
40
+ * consumers first.
41
+ *
42
+ * A plain close() resolves waiting consumers with `null`, which is
43
+ * indistinguishable from a conversation ending normally. A dead socket
44
+ * cannot deliver a turn-scoped failure of its own, so the error is
45
+ * synthesized here before the queue drains.
46
+ */
47
+ closeWithError(detail: string): void;
38
48
  close(): void;
39
49
  private activateTurn;
40
50
  private activateNextTurnFromProtocol;
@@ -1 +1 @@
1
- {"version":3,"file":"remote-turn-coordinator.d.ts","sourceRoot":"","sources":["../src/remote-turn-coordinator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,UAAU,EAIV,mBAAmB,EACpB,MAAM,YAAY,CAAC;AACpB,OAAO,EAoBL,KAAK,eAAe,EACpB,KAAK,YAAY,EAEjB,KAAK,WAAW,EACjB,MAAM,8BAA8B,CAAC;AAEtC,KAAK,2BAA2B,GAAG;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,cAAc,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAAC;CACnD,CAAC;AAEF;;;;;;GAMG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAqB;IACtD,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAU;IACnD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAwC;IACvE,OAAO,CAAC,WAAW,CAAoB;IACvC,OAAO,CAAC,eAAe,CAAmD;IAC1E,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,oBAAoB,CAAK;IACjC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,oBAAoB,CAAK;gBAErB,MAAM,EAAE,2BAA2B;IAO/C,IAAI,mBAAmB,IAAI,MAAM,CAEhC;IAED,eAAe,IAAI,OAAO;IAI1B,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,WAAW;IAuBjD,iBAAiB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI;IAU1C,kBAAkB,IAAI,IAAI;IAI1B,qBAAqB,CAAC,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI;IAsC5E,WAAW,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IASzC,KAAK,IAAI,IAAI;IAYb,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,4BAA4B;IAQpC,OAAO,CAAC,QAAQ;IAoBhB,OAAO,CAAC,kBAAkB;IAW1B,OAAO,CAAC,uBAAuB;IAiD/B,OAAO,CAAC,uBAAuB;IAiC/B,OAAO,CAAC,oBAAoB;IA0K5B,OAAO,CAAC,cAAc;IAqCtB,OAAO,CAAC,OAAO;IASf,OAAO,CAAC,UAAU;CAKnB"}
1
+ {"version":3,"file":"remote-turn-coordinator.d.ts","sourceRoot":"","sources":["../src/remote-turn-coordinator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,UAAU,EAIV,mBAAmB,EACpB,MAAM,YAAY,CAAC;AACpB,OAAO,EAoBL,KAAK,eAAe,EACpB,KAAK,YAAY,EAEjB,KAAK,WAAW,EACjB,MAAM,8BAA8B,CAAC;AAEtC,KAAK,2BAA2B,GAAG;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,cAAc,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAAC;CACnD,CAAC;AAEF;;;;;;GAMG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAqB;IACtD,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAU;IACnD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAwC;IACvE,OAAO,CAAC,WAAW,CAAoB;IACvC,OAAO,CAAC,eAAe,CAAmD;IAC1E,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,oBAAoB,CAAK;IACjC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,oBAAoB,CAAK;gBAErB,MAAM,EAAE,2BAA2B;IAO/C,IAAI,mBAAmB,IAAI,MAAM,CAEhC;IAED,eAAe,IAAI,OAAO;IAI1B,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,WAAW;IAuBjD,iBAAiB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI;IAU1C,kBAAkB,IAAI,IAAI;IAI1B,qBAAqB,CAAC,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI;IAsC5E,WAAW,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IASzC;;;;;;;;OAQG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAkBpC,KAAK,IAAI,IAAI;IAYb,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,4BAA4B;IAQpC,OAAO,CAAC,QAAQ;IAoBhB,OAAO,CAAC,kBAAkB;IAW1B,OAAO,CAAC,uBAAuB;IAiD/B,OAAO,CAAC,uBAAuB;IAiC/B,OAAO,CAAC,oBAAoB;IA0K5B,OAAO,CAAC,cAAc;IAqCtB,OAAO,CAAC,OAAO;IASf,OAAO,CAAC,UAAU;CAKnB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letta-ai/letta-agent-sdk",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "packageManager": "bun@1.3.0",
5
5
  "description": "SDK for programmatic control of Letta agents",
6
6
  "type": "module",
@@ -40,7 +40,7 @@
40
40
  },
41
41
  "dependencies": {
42
42
  "@letta-ai/letta-client": "^1.12.1",
43
- "@letta-ai/letta-code": "0.30.0"
43
+ "@letta-ai/letta-code": "0.30.5"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@modelcontextprotocol/server-everything": "^2026.7.4",
@@ -1,66 +1,104 @@
1
1
  import {
2
- buildCreatedAgentTags,
3
- buildCreateAgentRequestForPersonality,
4
- buildSystemPrompt,
5
- LETTA_CODE_AGENT_TYPE,
6
- MODEL_PRESETS,
2
+ buildCreateAgentRequest,
3
+ type CreateAgentMemoryBlock,
4
+ type CreateAgentRequest,
7
5
  } from "@letta-ai/letta-code/agent-presets";
8
6
  import type { CreateAgentOptions } from "./types.js";
9
7
 
10
- const DEFAULT_MODEL_ID = "auto";
11
- const DEFAULT_SUMMARIZATION_MODEL = "letta/auto";
12
-
13
- function resolveModel(modelIdentifier: string): string {
14
- const preset = MODEL_PRESETS.find(
15
- (model) =>
16
- model.id === modelIdentifier || model.handle === modelIdentifier,
17
- );
18
- if (preset) return preset.handle;
19
-
20
- // Preserve support for model handles supplied by self-hosted servers even
21
- // when they are not present in the bundled catalog.
22
- if (modelIdentifier.includes("/")) return modelIdentifier;
8
+ function isPresetSystemPrompt(value: string): boolean {
9
+ return [
10
+ "default",
11
+ "letta-claude",
12
+ "letta-codex",
13
+ "letta-gemini",
14
+ "claude",
15
+ "codex",
16
+ "gemini",
17
+ ].includes(value);
18
+ }
23
19
 
24
- throw new Error(`Unknown model: ${modelIdentifier}`);
20
+ function assertCreateAgentOptionsSupported(options: CreateAgentOptions): void {
21
+ if (
22
+ options.allowedTools !== undefined ||
23
+ options.disallowedTools !== undefined
24
+ ) {
25
+ throw new Error(
26
+ "App-server createAgent() does not yet support allowedTools/disallowedTools.",
27
+ );
28
+ }
29
+ if (options.canUseTool !== undefined) {
30
+ throw new Error(
31
+ "App-server createAgent() does not yet support canUseTool callbacks.",
32
+ );
33
+ }
34
+ if (options.systemInfoReminder !== undefined) {
35
+ throw new Error(
36
+ "App-server createAgent() does not yet support systemInfoReminder overrides.",
37
+ );
38
+ }
39
+ if (options.dreaming?.behavior !== undefined) {
40
+ throw new Error(
41
+ "App-server createAgent() does not yet support dreaming.behavior overrides.",
42
+ );
43
+ }
25
44
  }
26
45
 
27
- /**
28
- * Build the standard harness portion of a create-agent request.
29
- *
30
- * Personality presets are explicit opt-ins. Without one, the SDK builds a
31
- * generic agent and lets the caller's memory blocks define its identity.
32
- */
33
- export async function buildInitialAgentBody(
46
+ /** Translate SDK convenience options into the canonical Letta Code request. */
47
+ export async function createAgentBody(
34
48
  options: CreateAgentOptions,
35
- ): Promise<Record<string, unknown>> {
36
- if (options.personality !== undefined) {
37
- return {
38
- ...(await buildCreateAgentRequestForPersonality({
39
- personalityId: options.personality,
40
- ...(options.name !== undefined ? { name: options.name } : {}),
41
- ...(options.description !== undefined
42
- ? { description: options.description }
43
- : {}),
44
- ...(options.model !== undefined ? { model: options.model } : {}),
45
- ...(options.tags !== undefined ? { extraTags: options.tags } : {}),
46
- })),
47
- };
49
+ ): Promise<CreateAgentRequest> {
50
+ assertCreateAgentOptionsSupported(options);
51
+
52
+ let system: string | undefined;
53
+ if (options.systemPrompt !== undefined) {
54
+ if (
55
+ typeof options.systemPrompt !== "string" ||
56
+ isPresetSystemPrompt(options.systemPrompt)
57
+ ) {
58
+ throw new Error(
59
+ "createAgent() does not yet support system prompt presets for this backend.",
60
+ );
61
+ }
62
+ system = options.systemPrompt;
63
+ }
64
+
65
+ const memoryBlocks: CreateAgentMemoryBlock[] = [];
66
+ const blockIds: string[] = [];
67
+ for (const item of options.memory ?? []) {
68
+ if (typeof item === "string") {
69
+ throw new Error(
70
+ "App-server createAgent() does not yet support memory preset names.",
71
+ );
72
+ }
73
+ if ("blockId" in item) {
74
+ blockIds.push(item.blockId);
75
+ } else {
76
+ memoryBlocks.push({ ...item });
77
+ }
78
+ }
79
+ if (options.persona !== undefined) {
80
+ memoryBlocks.push({ label: "persona", value: options.persona });
81
+ }
82
+ if (options.human !== undefined) {
83
+ memoryBlocks.push({ label: "human", value: options.human });
48
84
  }
85
+ const hasMemoryConfiguration =
86
+ options.memory !== undefined ||
87
+ options.persona !== undefined ||
88
+ options.human !== undefined;
49
89
 
50
- return {
51
- agent_type: LETTA_CODE_AGENT_TYPE,
52
- ...(options.name !== undefined ? { name: options.name } : {}),
53
- ...(options.description !== undefined
54
- ? { description: options.description }
55
- : {}),
56
- model: resolveModel(options.model ?? DEFAULT_MODEL_ID),
57
- system: buildSystemPrompt("default", "memfs"),
58
- tags: buildCreatedAgentTags({
59
- enableMemfs: true,
60
- tags: options.tags ?? [],
61
- }),
62
- initial_message_sequence: [],
63
- parallel_tool_calls: true,
64
- compaction_settings: { model: DEFAULT_SUMMARIZATION_MODEL },
65
- };
90
+ return buildCreateAgentRequest({
91
+ personalityId: options.personality,
92
+ name: options.name,
93
+ description: options.description,
94
+ model: options.model,
95
+ system,
96
+ memoryBlocks: hasMemoryConfiguration ? memoryBlocks : undefined,
97
+ blockIds,
98
+ extraTags: options.tags,
99
+ enableMemfs: options.memfs ?? true,
100
+ baseTools: options.baseTools,
101
+ embedding: options.embedding,
102
+ hidden: options.hidden,
103
+ });
66
104
  }
@@ -11,12 +11,7 @@ import type {
11
11
  RuntimeStartResponseMessage,
12
12
  UpdateModelResponseMessage,
13
13
  } from "@letta-ai/letta-code/app-server-protocol";
14
- import {
15
- buildSystemPrompt,
16
- GIT_MEMORY_ENABLED_TAG,
17
- LETTA_CODE_ORIGIN_TAG,
18
- } from "@letta-ai/letta-code/agent-presets";
19
- import { buildInitialAgentBody } from "./agent-creation.js";
14
+ import { createAgentBody } from "./agent-creation.js";
20
15
  import { normalizeAppServerModels } from "./app-server-models.js";
21
16
  import {
22
17
  buildCanUseToolContext,
@@ -99,152 +94,10 @@ export type AppServerSessionOptions = Partial<LettaCodeRemoteClientOptions> & {
99
94
  connect?: (
100
95
  sessionEnv?: Record<string, string>,
101
96
  ) => Promise<{ url: string; close(): void }>;
102
- /** Whether SDK create-agent payloads should add the origin tag automatically. */
103
- includeSdkOriginTag?: boolean;
104
97
  };
105
98
 
106
99
  export type AppServerSessionMode = RuntimeSessionMode;
107
100
 
108
- function isPresetSystemPrompt(value: string): boolean {
109
- return [
110
- "default",
111
- "letta-claude",
112
- "letta-codex",
113
- "letta-gemini",
114
- "claude",
115
- "codex",
116
- "gemini",
117
- ].includes(value);
118
- }
119
-
120
- function assertRemoteCreateAgentOptionsSupported(options: CreateAgentOptions): void {
121
- if (options.allowedTools !== undefined || options.disallowedTools !== undefined) {
122
- throw new Error("App-server createAgent() does not yet support allowedTools/disallowedTools.");
123
- }
124
- if (options.canUseTool !== undefined) {
125
- throw new Error("App-server createAgent() does not yet support canUseTool callbacks.");
126
- }
127
- if (options.systemInfoReminder !== undefined) {
128
- throw new Error("App-server createAgent() does not yet support systemInfoReminder overrides.");
129
- }
130
- if (options.dreaming?.behavior !== undefined) {
131
- throw new Error("App-server createAgent() does not yet support dreaming.behavior overrides.");
132
- }
133
- }
134
-
135
- function normalizeMemoryBlock(block: Record<string, unknown>): Record<string, unknown> {
136
- const normalized = { ...block };
137
- if (normalized.value === undefined && typeof normalized.content === "string") {
138
- normalized.value = normalized.content;
139
- }
140
- return normalized;
141
- }
142
-
143
- function upsertMemoryBlock(
144
- blocks: Array<Record<string, unknown>>,
145
- block: Record<string, unknown>,
146
- ): void {
147
- const label = block.label;
148
- if (typeof label === "string") {
149
- const existingIndex = blocks.findIndex((candidate) => candidate.label === label);
150
- if (existingIndex >= 0) {
151
- blocks[existingIndex] = block;
152
- return;
153
- }
154
- }
155
- blocks.push(block);
156
- }
157
-
158
- export async function createAgentBody(
159
- options: CreateAgentOptions,
160
- settings: { includeSdkOriginTag?: boolean } = {},
161
- ): Promise<Record<string, unknown>> {
162
- assertRemoteCreateAgentOptionsSupported(options);
163
-
164
- const includeOriginTag = settings.includeSdkOriginTag ?? true;
165
- const body = await buildInitialAgentBody(options);
166
-
167
- if (Array.isArray(body.tags)) {
168
- body.tags = body.tags.filter(
169
- (tag) =>
170
- (includeOriginTag || tag !== LETTA_CODE_ORIGIN_TAG) &&
171
- (options.memfs !== false || tag !== GIT_MEMORY_ENABLED_TAG),
172
- );
173
- }
174
-
175
- if (options.embedding !== undefined) body.embedding = options.embedding;
176
- if (options.hidden !== undefined) body.hidden = options.hidden;
177
- // When baseTools is omitted, the harness applies its created-agent
178
- // defaults (web_search, fetch_webpage). An explicit list is pinned exactly:
179
- // `tools` alone does not suppress the Letta agent type's defaults, so both
180
- // default tool attachment and its default tool rules are disabled here.
181
- if (options.baseTools === undefined) {
182
- delete body.tools;
183
- delete body.include_base_tools;
184
- delete body.include_base_tool_rules;
185
- } else {
186
- body.tools = options.baseTools;
187
- body.include_base_tools = false;
188
- body.include_base_tool_rules = false;
189
- }
190
-
191
- if (options.systemPrompt === undefined) {
192
- if (options.memfs === false) {
193
- body.system = buildSystemPrompt("default", "standard");
194
- }
195
- } else {
196
- if (typeof options.systemPrompt === "string") {
197
- if (isPresetSystemPrompt(options.systemPrompt)) {
198
- throw new Error("createAgent() does not yet support system prompt presets for this backend.");
199
- }
200
- body.system = options.systemPrompt;
201
- } else {
202
- throw new Error("createAgent() does not yet support system prompt preset objects for this backend.");
203
- }
204
- }
205
-
206
- const hasMemoryConfiguration =
207
- Array.isArray(body.memory_blocks) ||
208
- options.memory !== undefined ||
209
- options.persona !== undefined ||
210
- options.human !== undefined;
211
- const memoryBlocks = Array.isArray(body.memory_blocks)
212
- ? body.memory_blocks
213
- .filter(
214
- (block): block is Record<string, unknown> =>
215
- block !== null && typeof block === "object",
216
- )
217
- .map((block) => ({ ...block }))
218
- : [];
219
- const blockIds: string[] = [];
220
- for (const item of options.memory ?? []) {
221
- if (typeof item === "string") {
222
- throw new Error("App-server createAgent() does not yet support memory preset names.");
223
- }
224
- if ("blockId" in item) {
225
- blockIds.push(item.blockId);
226
- } else {
227
- upsertMemoryBlock(
228
- memoryBlocks,
229
- normalizeMemoryBlock(item as unknown as Record<string, unknown>),
230
- );
231
- }
232
- }
233
- if (options.persona !== undefined) {
234
- upsertMemoryBlock(memoryBlocks, {
235
- label: "persona",
236
- value: options.persona,
237
- });
238
- }
239
- if (options.human !== undefined) {
240
- upsertMemoryBlock(memoryBlocks, { label: "human", value: options.human });
241
- }
242
- if (hasMemoryConfiguration) body.memory_blocks = memoryBlocks;
243
- if (blockIds.length > 0) body.block_ids = blockIds;
244
-
245
- return body;
246
- }
247
-
248
101
  export function externalToolGroups(tools: AnyAgentTool[] | undefined): Array<Record<string, unknown>> | undefined {
249
102
  if (!tools || tools.length === 0) return undefined;
250
103
  return [
@@ -779,6 +632,8 @@ export class AppServerSession extends RemoteClientSessionCore {
779
632
  throw new Error(response.error ?? "Failed to start app-server runtime");
780
633
  }
781
634
 
635
+ this.watchTransportDisconnect(client);
636
+
782
637
  const tools = agentToolNames(response.agent);
783
638
  const skillSources = options.skillSources;
784
639
  const clientToolset = "toolset" in options ? options.toolset : undefined;
@@ -883,9 +738,7 @@ export class AppServerSession extends RemoteClientSessionCore {
883
738
 
884
739
  if (this.mode.kind === "create-agent") {
885
740
  command.create_agent = {
886
- body: await createAgentBody(this.mode.options, {
887
- includeSdkOriginTag: this.remoteOptions.includeSdkOriginTag,
888
- }),
741
+ body: await createAgentBody(this.mode.options),
889
742
  // Hidden (worker-style) agents default to unpinned.
890
743
  pin_global:
891
744
  this.remoteOptions.pinGlobalAgent ??
@@ -5,10 +5,10 @@ import {
5
5
  createAppServerClient,
6
6
  type AppServerClient,
7
7
  } from "@letta-ai/letta-code/app-server-client";
8
+ import { createAgentBody } from "./agent-creation.js";
8
9
  import {
9
10
  AppServerRuntimeController,
10
11
  agentToolNames,
11
- createAgentBody,
12
12
  createExternalToolCallHandler,
13
13
  externalToolGroups,
14
14
  registerAppServerControlRequestHandler,
@@ -398,6 +398,8 @@ export class CloudEnvironmentSession extends RemoteClientSessionCore {
398
398
  throw new Error(response.error ?? "Failed to start Cloud status runtime");
399
399
  }
400
400
 
401
+ this.watchTransportDisconnect(client);
402
+
401
403
  const tools = agentToolNames(response.agent);
402
404
  const skillSources = options.skillSources;
403
405
  const clientToolset = "toolset" in options ? options.toolset : undefined;
@@ -77,6 +77,7 @@ export abstract class RemoteClientSessionCore implements LettaCodeSession {
77
77
  private readonly requestTimeoutMs: number | undefined;
78
78
  private initializePromise: Promise<SDKInitMessage> | null = null;
79
79
  private removeMessageHandler: (() => void) | null = null;
80
+ private detachTransportDisconnect: (() => void) | null = null;
80
81
  private readonly turns: RemoteTurnCoordinator;
81
82
  private toolNames: string[] | undefined;
82
83
  private deviceStatusListeners = new Set<(status: SessionDeviceStatus) => void>();
@@ -188,6 +189,8 @@ export abstract class RemoteClientSessionCore implements LettaCodeSession {
188
189
  private cleanupFailedInitialize(): void {
189
190
  this.removeMessageHandler?.();
190
191
  this.removeMessageHandler = null;
192
+ this.detachTransportDisconnect?.();
193
+ this.detachTransportDisconnect = null;
191
194
  this.controller?.close();
192
195
  this.controller = null;
193
196
  // Subclass-owned resources (spawned connections, sandboxes, handlers)
@@ -543,6 +546,8 @@ export abstract class RemoteClientSessionCore implements LettaCodeSession {
543
546
  this.closed = true;
544
547
  this.removeMessageHandler?.();
545
548
  this.removeMessageHandler = null;
549
+ this.detachTransportDisconnect?.();
550
+ this.detachTransportDisconnect = null;
546
551
  this.turns.close();
547
552
  for (const cancel of [...this.deviceStatusRefreshCancels]) {
548
553
  cancel(new Error(`Session closed while waiting for ${this.label} device status`));
@@ -619,6 +624,35 @@ export abstract class RemoteClientSessionCore implements LettaCodeSession {
619
624
 
620
625
  protected abstract initializeRuntimeController(): Promise<RuntimeSessionInit>;
621
626
 
627
+ /**
628
+ * Fail the session when its transport drops unexpectedly.
629
+ *
630
+ * Without this an in-flight turn parks forever: nextMessage() only settles
631
+ * through the coordinator, and the socket's own pending-request rejection
632
+ * covers request/response commands, not streaming turns.
633
+ *
634
+ * The session is not revived — the runtime lived on the dead socket. The
635
+ * caller observes the error and rebuilds via resumeSession().
636
+ *
637
+ * Subclasses call this only once their runtime is live: a drop before that
638
+ * already surfaces as a rejected connect or runtime-start, and failing the
639
+ * session there would defeat initialize()'s retry path. Explicit closes do
640
+ * not notify, so this fires for faults only. Detaching stays here so every
641
+ * teardown path — clean close and failed initialize alike — covers it.
642
+ */
643
+ protected watchTransportDisconnect(client: {
644
+ onDisconnect(handler: () => void): () => void;
645
+ }): void {
646
+ this.detachTransportDisconnect?.();
647
+ this.detachTransportDisconnect = client.onDisconnect(() => {
648
+ if (this.closed) return;
649
+ this.turns.closeWithError(
650
+ `The ${this.label} connection closed unexpectedly; resume the conversation to continue.`,
651
+ );
652
+ this.close();
653
+ });
654
+ }
655
+
622
656
  protected async afterRuntimeInitialized(): Promise<void> {
623
657
  // Optional hook for subclasses to send transport-specific startup frames.
624
658
  }
@@ -160,6 +160,33 @@ export class RemoteTurnCoordinator {
160
160
  });
161
161
  }
162
162
 
163
+ /**
164
+ * Close after the transport dropped, surfacing the failure to stream
165
+ * consumers first.
166
+ *
167
+ * A plain close() resolves waiting consumers with `null`, which is
168
+ * indistinguishable from a conversation ending normally. A dead socket
169
+ * cannot deliver a turn-scoped failure of its own, so the error is
170
+ * synthesized here before the queue drains.
171
+ */
172
+ closeWithError(detail: string): void {
173
+ if (this.closed) return;
174
+ const active = this.activeTurn;
175
+ if (active) {
176
+ this.failTurn(active, detail);
177
+ } else {
178
+ this.enqueue({
179
+ type: "error",
180
+ message: detail,
181
+ errorCode: "error",
182
+ stopReason: "error",
183
+ errorDetail: detail,
184
+ recoverable: false,
185
+ });
186
+ }
187
+ this.close();
188
+ }
189
+
163
190
  close(): void {
164
191
  if (this.closed) return;
165
192
  this.closed = true;