@letta-ai/letta-code 0.34.35 → 0.34.36
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/dist/agent-presets.js.map +1 -1
- package/dist/mcp-client.js +2 -2
- package/dist/mcp-client.js.map +1 -1
- package/dist/mcp-oauth.js +2 -2
- package/dist/mcp-oauth.js.map +1 -1
- package/dist/types/agent/agent-tags.d.ts +2 -0
- package/dist/types/agent/agent-tags.d.ts.map +1 -1
- package/dist/types/agent/memory-filesystem.d.ts.map +1 -1
- package/dist/types/backend/local/local-store.d.ts.map +1 -1
- package/dist/types/reminders/catalog.d.ts +1 -1
- package/dist/types/reminders/catalog.d.ts.map +1 -1
- package/dist/types/reminders/engine.d.ts.map +1 -1
- package/dist/types/reminders/state.d.ts +0 -5
- package/dist/types/reminders/state.d.ts.map +1 -1
- package/dist/types/tools/impl/bash.d.ts +4 -0
- package/dist/types/tools/impl/bash.d.ts.map +1 -1
- package/dist/types/tools/impl/monitor-script.d.ts.map +1 -1
- package/dist/types/tools/workflow/workflow-engine.d.ts +2 -2
- package/dist/types/tools/workflow/workflow-engine.d.ts.map +1 -1
- package/dist/types/websocket/listener/connection.d.ts.map +1 -1
- package/letta.js +156 -145
- package/npm-shrinkwrap.json +16 -16
- package/package.json +2 -2
- package/scripts/source-file-size-baseline.json +3 -3
package/letta.js
CHANGED
|
@@ -380,6 +380,39 @@ var init_error = __esm(() => {
|
|
|
380
380
|
};
|
|
381
381
|
});
|
|
382
382
|
|
|
383
|
+
// src/agent/agent-tags.ts
|
|
384
|
+
var exports_agent_tags = {};
|
|
385
|
+
__export(exports_agent_tags, {
|
|
386
|
+
isStatelessSubagentTags: () => isStatelessSubagentTags,
|
|
387
|
+
isMemfsOptOutCreateTags: () => isMemfsOptOutCreateTags,
|
|
388
|
+
buildCreatedAgentTags: () => buildCreatedAgentTags,
|
|
389
|
+
ONBOARDING_ORIGIN_TAG: () => ONBOARDING_ORIGIN_TAG,
|
|
390
|
+
MEMFS_DISABLED_TAG: () => MEMFS_DISABLED_TAG,
|
|
391
|
+
LETTA_CODE_SUBAGENT_TAG: () => LETTA_CODE_SUBAGENT_TAG,
|
|
392
|
+
LETTA_CODE_ORIGIN_TAG: () => LETTA_CODE_ORIGIN_TAG,
|
|
393
|
+
GIT_MEMORY_ENABLED_TAG: () => GIT_MEMORY_ENABLED_TAG
|
|
394
|
+
});
|
|
395
|
+
function buildCreatedAgentTags(options = {}) {
|
|
396
|
+
const tags = [LETTA_CODE_ORIGIN_TAG];
|
|
397
|
+
if (options.isSubagent) {
|
|
398
|
+
tags.push(LETTA_CODE_SUBAGENT_TAG);
|
|
399
|
+
}
|
|
400
|
+
if (options.enableMemfs) {
|
|
401
|
+
tags.push(GIT_MEMORY_ENABLED_TAG);
|
|
402
|
+
}
|
|
403
|
+
if (options.tags && Array.isArray(options.tags)) {
|
|
404
|
+
tags.push(...options.tags);
|
|
405
|
+
}
|
|
406
|
+
return Array.from(new Set(tags));
|
|
407
|
+
}
|
|
408
|
+
function isStatelessSubagentTags(tags) {
|
|
409
|
+
return Boolean(tags?.includes(LETTA_CODE_SUBAGENT_TAG) && !tags.includes(GIT_MEMORY_ENABLED_TAG));
|
|
410
|
+
}
|
|
411
|
+
function isMemfsOptOutCreateTags(tags) {
|
|
412
|
+
return Array.isArray(tags) && tags.includes(MEMFS_DISABLED_TAG);
|
|
413
|
+
}
|
|
414
|
+
var LETTA_CODE_ORIGIN_TAG = "origin:letta-code", ONBOARDING_ORIGIN_TAG = "origin:onboarding", LETTA_CODE_SUBAGENT_TAG = "role:subagent", GIT_MEMORY_ENABLED_TAG = "git-memory-enabled", MEMFS_DISABLED_TAG = "memfs:disabled";
|
|
415
|
+
|
|
383
416
|
// node_modules/@letta-ai/letta-client/internal/tslib.mjs
|
|
384
417
|
function __classPrivateFieldSet(receiver, state, value, kind, f) {
|
|
385
418
|
if (kind === "m")
|
|
@@ -6044,7 +6077,7 @@ var package_default;
|
|
|
6044
6077
|
var init_package = __esm(() => {
|
|
6045
6078
|
package_default = {
|
|
6046
6079
|
name: "@letta-ai/letta-code",
|
|
6047
|
-
version: "0.34.
|
|
6080
|
+
version: "0.34.36",
|
|
6048
6081
|
lettaStartupLogProtocol: 1,
|
|
6049
6082
|
lettaConfigDirProtocol: 1,
|
|
6050
6083
|
description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
|
|
@@ -6322,7 +6355,7 @@ var init_package = __esm(() => {
|
|
|
6322
6355
|
},
|
|
6323
6356
|
lettaLifecycleProtocol: 1,
|
|
6324
6357
|
lettaRuntimeGraphProtocol: 1,
|
|
6325
|
-
lettaRuntimeGraphSha512: "sha512-
|
|
6358
|
+
lettaRuntimeGraphSha512: "sha512-tPPjQGBLt5+vA9W+Mv4yvHjYDOzBSNPnlU8rxk0g42xKGYf9HCuWpRA2cR5XvB6ETJFjJmcjMOcHZmQVjiwNuA==",
|
|
6326
6359
|
patchedDependencies: {
|
|
6327
6360
|
"@earendil-works/pi-ai@0.99.1": "patches/@earendil-works%2Fpi-ai@0.99.1.patch"
|
|
6328
6361
|
}
|
|
@@ -99024,35 +99057,6 @@ var init_backend_mode = __esm(() => {
|
|
|
99024
99057
|
init_paths();
|
|
99025
99058
|
});
|
|
99026
99059
|
|
|
99027
|
-
// src/agent/agent-tags.ts
|
|
99028
|
-
var exports_agent_tags = {};
|
|
99029
|
-
__export(exports_agent_tags, {
|
|
99030
|
-
isMemfsOptOutCreateTags: () => isMemfsOptOutCreateTags,
|
|
99031
|
-
buildCreatedAgentTags: () => buildCreatedAgentTags,
|
|
99032
|
-
ONBOARDING_ORIGIN_TAG: () => ONBOARDING_ORIGIN_TAG,
|
|
99033
|
-
MEMFS_DISABLED_TAG: () => MEMFS_DISABLED_TAG,
|
|
99034
|
-
LETTA_CODE_SUBAGENT_TAG: () => LETTA_CODE_SUBAGENT_TAG,
|
|
99035
|
-
LETTA_CODE_ORIGIN_TAG: () => LETTA_CODE_ORIGIN_TAG,
|
|
99036
|
-
GIT_MEMORY_ENABLED_TAG: () => GIT_MEMORY_ENABLED_TAG
|
|
99037
|
-
});
|
|
99038
|
-
function buildCreatedAgentTags(options = {}) {
|
|
99039
|
-
const tags = [LETTA_CODE_ORIGIN_TAG];
|
|
99040
|
-
if (options.isSubagent) {
|
|
99041
|
-
tags.push(LETTA_CODE_SUBAGENT_TAG);
|
|
99042
|
-
}
|
|
99043
|
-
if (options.enableMemfs) {
|
|
99044
|
-
tags.push(GIT_MEMORY_ENABLED_TAG);
|
|
99045
|
-
}
|
|
99046
|
-
if (options.tags && Array.isArray(options.tags)) {
|
|
99047
|
-
tags.push(...options.tags);
|
|
99048
|
-
}
|
|
99049
|
-
return Array.from(new Set(tags));
|
|
99050
|
-
}
|
|
99051
|
-
function isMemfsOptOutCreateTags(tags) {
|
|
99052
|
-
return Array.isArray(tags) && tags.includes(MEMFS_DISABLED_TAG);
|
|
99053
|
-
}
|
|
99054
|
-
var LETTA_CODE_ORIGIN_TAG = "origin:letta-code", ONBOARDING_ORIGIN_TAG = "origin:onboarding", LETTA_CODE_SUBAGENT_TAG = "role:subagent", GIT_MEMORY_ENABLED_TAG = "git-memory-enabled", MEMFS_DISABLED_TAG = "memfs:disabled";
|
|
99055
|
-
|
|
99056
99060
|
// src/utils/directory-limits.ts
|
|
99057
99061
|
function parsePositiveIntEnv(value, fallback, min, max) {
|
|
99058
99062
|
if (!value || value.trim() === "") {
|
|
@@ -109111,6 +109115,12 @@ async function applyMemfsFlags(agentId, memfsFlag, options) {
|
|
|
109111
109115
|
const { settingsManager: settingsManager2 } = await Promise.resolve().then(() => (init_settings_manager(), exports_settings_manager));
|
|
109112
109116
|
const { getBackend: getBackend2 } = await Promise.resolve().then(() => (init_backend2(), exports_backend));
|
|
109113
109117
|
const backend = getBackend2();
|
|
109118
|
+
const { GIT_MEMORY_ENABLED_TAG: GIT_MEMORY_ENABLED_TAG2, isStatelessSubagentTags: isStatelessSubagentTags2 } = await Promise.resolve().then(() => exports_agent_tags);
|
|
109119
|
+
const tags = options?.agentTags ?? (await backend.retrieveAgent(agentId, { include: ["agent.tags"] })).tags;
|
|
109120
|
+
if (isStatelessSubagentTags2(tags)) {
|
|
109121
|
+
debugLog("memfs", `Not enabling MemFS for stateless subagent ${agentId}`);
|
|
109122
|
+
return { action: "unchanged" };
|
|
109123
|
+
}
|
|
109114
109124
|
if (backend.capabilities.localMemfs) {
|
|
109115
109125
|
const memoryDir = getScopedMemoryFilesystemRoot(agentId);
|
|
109116
109126
|
const { initializeLocalMemoryRepo: initializeLocalMemoryRepo2 } = await Promise.resolve().then(() => (init_memory_git(), exports_memory_git));
|
|
@@ -109133,7 +109143,6 @@ async function applyMemfsFlags(agentId, memfsFlag, options) {
|
|
|
109133
109143
|
throw new Error(await getMemfsSyncUnavailableMessage());
|
|
109134
109144
|
}
|
|
109135
109145
|
const localMemfsEnabled = settingsManager2.isMemfsEnabled(agentId);
|
|
109136
|
-
const { GIT_MEMORY_ENABLED_TAG: GIT_MEMORY_ENABLED_TAG2 } = await Promise.resolve().then(() => exports_agent_tags);
|
|
109137
109146
|
const shouldAutoEnableFromTag = !memfsFlag && !localMemfsEnabled && Boolean(options?.agentTags?.includes(GIT_MEMORY_ENABLED_TAG2));
|
|
109138
109147
|
const enabling = Boolean(memfsFlag || shouldAutoEnableFromTag);
|
|
109139
109148
|
if (enabling) {
|
|
@@ -109217,6 +109226,7 @@ async function enableMemfsIfCloud(agentId, options = {}) {
|
|
|
109217
109226
|
var MEMORY_FS_ROOT = ".letta", MEMORY_FS_AGENTS_DIR = "agents", MEMORY_FS_MEMORY_DIR = "memory", MEMORY_SYSTEM_DIR = "system", MEMORY_TREE_MAX_LINES, MEMORY_TREE_MAX_CHARS, MEMORY_TREE_MAX_CHILDREN_PER_DIR;
|
|
109218
109227
|
var init_memory_filesystem2 = __esm(() => {
|
|
109219
109228
|
init_paths();
|
|
109229
|
+
init_debug();
|
|
109220
109230
|
init_directory_limits();
|
|
109221
109231
|
init_settings_path();
|
|
109222
109232
|
init_context();
|
|
@@ -110796,11 +110806,15 @@ class LocalStore {
|
|
|
110796
110806
|
listAgents(body) {
|
|
110797
110807
|
this.refreshLoadedAgentRecordsFromStorage();
|
|
110798
110808
|
const bodyRecord = body ?? {};
|
|
110809
|
+
const name = optionalString3(bodyRecord.name);
|
|
110799
110810
|
const queryText = optionalString3(bodyRecord.query_text)?.toLowerCase();
|
|
110800
110811
|
const tags = isStringArray2(bodyRecord.tags) ? bodyRecord.tags : [];
|
|
110801
110812
|
const after = optionalString3(bodyRecord.after);
|
|
110802
110813
|
const limit4 = typeof bodyRecord.limit === "number" ? bodyRecord.limit : 20;
|
|
110803
110814
|
let agents = [...this.agents.values()].filter((agent) => !isHiddenLocalAgentRecord(agent)).map((agent) => this.projectAgent(agent));
|
|
110815
|
+
if (name) {
|
|
110816
|
+
agents = agents.filter((agent) => agent.name === name);
|
|
110817
|
+
}
|
|
110804
110818
|
if (tags.length > 0) {
|
|
110805
110819
|
agents = agents.filter((agent) => tags.every((tag) => agent.tags?.includes(tag)));
|
|
110806
110820
|
}
|
|
@@ -110811,11 +110825,7 @@ class LocalStore {
|
|
|
110811
110825
|
return haystack.includes(queryText);
|
|
110812
110826
|
});
|
|
110813
110827
|
}
|
|
110814
|
-
agents.sort((a, b) =>
|
|
110815
|
-
const aDate = a.last_run_completion ?? "";
|
|
110816
|
-
const bDate = b.last_run_completion ?? "";
|
|
110817
|
-
return bDate.localeCompare(aDate);
|
|
110818
|
-
});
|
|
110828
|
+
agents.sort((a, b) => (b.last_run_completion ?? "").localeCompare(a.last_run_completion ?? ""));
|
|
110819
110829
|
if (after) {
|
|
110820
110830
|
const afterIndex = agents.findIndex((agent) => agent.id === after);
|
|
110821
110831
|
if (afterIndex >= 0)
|
|
@@ -211680,7 +211690,7 @@ var init_mcp_client = __esm(() => {
|
|
|
211680
211690
|
init_streamableHttp();
|
|
211681
211691
|
DEFAULT_CLIENT_INFO = {
|
|
211682
211692
|
name: "letta-code",
|
|
211683
|
-
version: "0.34.
|
|
211693
|
+
version: "0.34.36"
|
|
211684
211694
|
};
|
|
211685
211695
|
});
|
|
211686
211696
|
|
|
@@ -213668,7 +213678,6 @@ function createSharedReminderState() {
|
|
|
213668
213678
|
lastNotifiedPermissionMode: null,
|
|
213669
213679
|
turnCount: 0,
|
|
213670
213680
|
pendingReflectionTrigger: false,
|
|
213671
|
-
pendingMemoryGitSyncReminders: [],
|
|
213672
213681
|
pendingCommandIoReminders: [],
|
|
213673
213682
|
pendingToolsetChangeReminders: [],
|
|
213674
213683
|
hasNotifiedLowDiskSpace: false
|
|
@@ -213704,9 +213713,6 @@ function pushBounded(items3, entry) {
|
|
|
213704
213713
|
function enqueueCommandIoReminder(state2, reminder) {
|
|
213705
213714
|
pushBounded(state2.pendingCommandIoReminders, reminder);
|
|
213706
213715
|
}
|
|
213707
|
-
function enqueueMemoryGitSyncReminder(state2, reminder) {
|
|
213708
|
-
pushBounded(state2.pendingMemoryGitSyncReminders, reminder);
|
|
213709
|
-
}
|
|
213710
213716
|
function enqueueToolsetChangeReminder(state2, reminder) {
|
|
213711
213717
|
pushBounded(state2.pendingToolsetChangeReminders, reminder);
|
|
213712
213718
|
}
|
|
@@ -215641,7 +215647,7 @@ Before executing the command, please follow these steps:
|
|
|
215641
215647
|
|
|
215642
215648
|
Usage notes:
|
|
215643
215649
|
- The command and description arguments are required.
|
|
215644
|
-
-
|
|
215650
|
+
- Commands run until they exit unless you pass a timeout in milliseconds. Foreground timeouts have a maximum of 600000ms.
|
|
215645
215651
|
- Write a clear, concise user-facing description of what this command does. This description may be shown directly in chat as part of a status row like \`Running command: <description>\` or \`Ran command: <description>\`. Describe the command's purpose, not its shell syntax. For simple commands, keep it brief (5-10 words). For complex commands (piped commands, obscure flags, or anything hard to understand at a glance), add enough context to clarify what it does.
|
|
215646
215652
|
- If the output exceeds 30000 characters, you receive only the first 2000 characters plus the path of a file containing the full output. A failed command whose output exceeds 10000 characters returns a head-and-tail excerpt plus that file path. Read or search that file when you need the rest instead of re-running the command.
|
|
215647
215653
|
- Ordinary commands wait briefly for a result, then automatically continue in the background if they are still running. You will receive a task ID and one completion notification, so do not predict command duration, set \`run_in_background\` merely because a command may be slow, or poll for completion.
|
|
@@ -215744,7 +215750,7 @@ Important:
|
|
|
215744
215750
|
var init_Bash = () => {};
|
|
215745
215751
|
|
|
215746
215752
|
// src/tools/descriptions/CodeMode.md
|
|
215747
|
-
var CodeMode_default = "Run a JavaScript async function body that calls tools and returns only the results you need.\n\nCall built-in and server-side tools with `await tools.<name>(args)` and MCP tools with `await tools.mcp__server__tool(args)`; `listTools()` and `describeTool(name)` list tools and their schemas. Failed calls throw. `args` holds optional input, `process.env` holds the variables a Bash command sees plus the agent's secrets, and `console.log()` output is captured.\n\nReturns `{ result, output }`. Like Bash, a script still running after a brief wait continues in the background and its result arrives as a task notification; `run_in_background: true` returns the task ID immediately. TaskStop aborts it.\n\nNested calls follow permission rules; calls that need approval fail, so call those tools directly. This is not a security sandbox.\n\nExample:\n\n const texts = await Promise.all(args.paths.map(file_path => tools.Read({ file_path })));\n return texts.map((text, i) => ({ path: args.paths[i], lines: text.split('\\n').length }));\n";
|
|
215753
|
+
var CodeMode_default = "Run a JavaScript async function body that calls tools and returns only the results you need.\n\nCall built-in and server-side tools with `await tools.<name>(args)` and MCP tools with `await tools.mcp__server__tool(args)`; `listTools()` and `describeTool(name)` list tools and their schemas. Failed calls throw. `args` holds optional input, `process.env` holds the variables a Bash command sees plus the agent's secrets, and `console.log()` output is captured.\n\n`await decide(state, questions, options?)` makes one typed model decision. `questions` is an object of id → `{ type, instructions, criteria }`: `choice` takes a criteria map of id → description, `score` a criteria array, `noul` no criteria. It resolves to `{ answers }` keyed by question id (`.choice`, `.score`, or `.noul` in 0–1), or `null` after an invalid answer.\n\nReturns `{ result, output }`. Like Bash, a script still running after a brief wait continues in the background and its result arrives as a task notification; `run_in_background: true` returns the task ID immediately. TaskStop aborts it.\n\nNested calls follow permission rules; calls that need approval fail, so call those tools directly. This is not a security sandbox.\n\nExample:\n\n const texts = await Promise.all(args.paths.map(file_path => tools.Read({ file_path })));\n return texts.map((text, i) => ({ path: args.paths[i], lines: text.split('\\n').length }));\n";
|
|
215748
215754
|
var init_CodeMode = () => {};
|
|
215749
215755
|
|
|
215750
215756
|
// src/tools/descriptions/Edit.md
|
|
@@ -215848,7 +215854,7 @@ Do not use this tool for root memory files (already loaded) or skills/ (use Skil
|
|
|
215848
215854
|
var init_Memory = () => {};
|
|
215849
215855
|
|
|
215850
215856
|
// src/tools/descriptions/Monitor.md
|
|
215851
|
-
var Monitor_default = 'Start a background monitor that streams events from a long-running script. Each stdout line is an event — you keep working and notifications arrive in the chat. Events arrive on their own schedule and are not replies from the user, even if one lands while you\'re waiting for the user to answer a question.\n\nPick by how many notifications you need:\n- **One** ("tell me when the server is ready / the build finishes") → use **Bash with `run_in_background`** and a command that exits when the condition is true, e.g. `until grep -q "Ready in" dev.log; do sleep 0.5; done`. You get a single completion notification when it exits.\n- **One per occurrence, indefinitely** ("tell me every time an ERROR line appears") → Monitor with an unbounded command (`tail -f`, `inotifywait -m`, `while true`).\n- **One per occurrence, until a known end** ("emit each CI step result, stop when the run completes") → Monitor with a command that emits lines and then exits.\n\nYour script\'s stdout is the event stream. Each line becomes a notification. Exit ends the watch.\n # Each matching log line is an event\n tail -f /var/log/app.log | grep --line-buffered "ERROR"\n # Each file change is an event\n inotifywait -m --format \'%e %f\' /watched/dir\n # Node script that emits events as they arrive (e.g. WebSocket listener)\n node watch-for-events.js\n\nFor open github.com pull requests, use WatchPR instead. It covers the whole PR surface and keeps watching after CI finishes. Use Monitor only when WatchPR does not apply.\n\n**Don\'t use an unbounded command for a single notification.** `tail -f`, `inotifywait -m`, and `while true` never exit on their own, so the monitor stays armed until timeout even after the event has fired. For "tell me when X is ready," use Bash `run_in_background` with an `until` loop instead (one notification, ends in seconds). Note that `tail -f log | grep -m 1 ...` does *not* fix this: if the log goes quiet after the match, `tail` never receives SIGPIPE and the pipeline hangs anyway.\n\n- Every pipe stage must flush per line or matches sit in its buffer unseen: `grep` needs `--line-buffered`, `awk` needs `fflush()`. `head` cannot flush at all — `| head -N` delivers nothing until N matches accumulate, then ends the stream.\n- In poll loops, handle transient failures (`curl ... || true`) — one failed request shouldn\'t kill the monitor.\n- Poll intervals: 30s+ for remote APIs (rate limits), 0.5–1s for local checks.\n- Write a specific `description` — it appears in every notification ("errors in deploy.log" not "watching logs").\n- Only stdout is the event stream. Stderr goes to the output file (readable via Read) but does not trigger notifications — for a command you run directly (e.g. `python train.py 2>&1 | grep --line-buffered ...`), merge stderr with `2>&1` so its failures reach your filter. (No effect on `tail -f` of an existing log — that file only contains what its writer redirected.)\n\n**Coverage — silence is not success.** When watching a job or process for an outcome, your filter must match every terminal state, not just the happy path. A monitor that greps only for the success marker stays silent through a crashloop, a hung process, or an unexpected exit — and silence looks identical to "still running." Before arming, ask: *if this process crashed right now, would my filter emit anything?* If not, widen it.\n # Wrong — silent on crash, hang, or any non-success exit\n tail -f run.log | grep --line-buffered "elapsed_steps="\n # Right — one alternation covering progress + the failure signatures you\'d act on\n tail -f run.log | grep -E --line-buffered "elapsed_steps=|Traceback|Error|FAILED|assert|Killed|OOM"\n\nFor poll loops checking job state, emit on every terminal status (`succeeded|failed|cancelled|timeout`), not just success. If you cannot confidently enumerate the failure signatures, broaden the grep alternation rather than narrow it — some extra noise is better than missing a crashloop.\n\n**Output volume**: Every stdout line is a conversation message, so the filter should be selective — but selective means "the lines you\'d act on," not "only good news." Never pipe raw logs; filter to exactly the success and failure signals you care about. Monitors that produce too many events are automatically stopped; restart with a tighter filter if this happens.\n\nStdout lines within 200ms are batched into a single notification, so multiline output from a single event groups naturally.\n\nThe script runs in the same shell environment as Bash. Exit ends the watch (exit code is reported). Timeout → killed. Set `persistent: true` for session-length watches (log tails, long-lived event streams). In managed Cloud sandboxes, every monitor stops at the per-sandbox cap configured by LETTA_MONITOR_MAX_TIMEOUT_MS (default 1 hour, clamped to 1 hour through 7 days), including persistent monitors; elsewhere persistent monitors run until TaskStop or session end. Call Monitor again to re-arm it if you still need to watch. For much longer Cloud waits, schedule a Wake or cron (which does not keep the sandbox running between turns) and combine it with shorter monitors. Use TaskStop to cancel early.\n\nWhen someone is waiting on the result, set `backup_after_seconds` (e.g. 900). If the monitor goes that long without an event, a durable Wake brings you back to check the real state, so a queued, hung, or dead watch can\'t leave them waiting in silence.\n\n**ws source** — open a WebSocket and stream each incoming text frame as an event. No shell, no polling: the server pushes, you get notified.\n ws: {url: \'wss://events.example.com/stream\', protocols: [\'v1\']},\n description: \'deploy events\',\n\nEach text frame becomes one notification (multiline frames stay as one event). Binary frames are reported as `[binary frame, N bytes]` rather than passed through. Socket close ends the watch with the close code surfaced; errors are surfaced before close. Same rate limiting as bash — a firehose will be suppressed and eventually stopped, so subscribe to a filtered feed where one exists.\n\nPrefer this over `command: \'websocat wss://…\'` — it avoids the extra process and line-buffering pitfalls. Use bash when you need to transform or filter frames with shell tools before they become events.\n\n**script source** — a JavaScript watch loop with the same globals as CodeMode, plus `emit(text)` (one event) and `sleep(ms)`. Returning or throwing ends the watch.\n';
|
|
215857
|
+
var Monitor_default = 'Start a background monitor that streams events from a long-running script. Each stdout line is an event — you keep working and notifications arrive in the chat. Events arrive on their own schedule and are not replies from the user, even if one lands while you\'re waiting for the user to answer a question.\n\nPick by how many notifications you need:\n- **One** ("tell me when the server is ready / the build finishes") → use **Bash with `run_in_background`** and a command that exits when the condition is true, e.g. `until grep -q "Ready in" dev.log; do sleep 0.5; done`. You get a single completion notification when it exits.\n- **One per occurrence, indefinitely** ("tell me every time an ERROR line appears") → Monitor with an unbounded command (`tail -f`, `inotifywait -m`, `while true`).\n- **One per occurrence, until a known end** ("emit each CI step result, stop when the run completes") → Monitor with a command that emits lines and then exits.\n\nYour script\'s stdout is the event stream. Each line becomes a notification. Exit ends the watch.\n # Each matching log line is an event\n tail -f /var/log/app.log | grep --line-buffered "ERROR"\n # Each file change is an event\n inotifywait -m --format \'%e %f\' /watched/dir\n # Node script that emits events as they arrive (e.g. WebSocket listener)\n node watch-for-events.js\n\nFor open github.com pull requests, use WatchPR instead. It covers the whole PR surface and keeps watching after CI finishes. Use Monitor only when WatchPR does not apply.\n\n**Don\'t use an unbounded command for a single notification.** `tail -f`, `inotifywait -m`, and `while true` never exit on their own, so the monitor stays armed until timeout even after the event has fired. For "tell me when X is ready," use Bash `run_in_background` with an `until` loop instead (one notification, ends in seconds). Note that `tail -f log | grep -m 1 ...` does *not* fix this: if the log goes quiet after the match, `tail` never receives SIGPIPE and the pipeline hangs anyway.\n\n- Every pipe stage must flush per line or matches sit in its buffer unseen: `grep` needs `--line-buffered`, `awk` needs `fflush()`. `head` cannot flush at all — `| head -N` delivers nothing until N matches accumulate, then ends the stream.\n- In poll loops, handle transient failures (`curl ... || true`) — one failed request shouldn\'t kill the monitor.\n- Poll intervals: 30s+ for remote APIs (rate limits), 0.5–1s for local checks.\n- Write a specific `description` — it appears in every notification ("errors in deploy.log" not "watching logs").\n- Only stdout is the event stream. Stderr goes to the output file (readable via Read) but does not trigger notifications — for a command you run directly (e.g. `python train.py 2>&1 | grep --line-buffered ...`), merge stderr with `2>&1` so its failures reach your filter. (No effect on `tail -f` of an existing log — that file only contains what its writer redirected.)\n\n**Coverage — silence is not success.** When watching a job or process for an outcome, your filter must match every terminal state, not just the happy path. A monitor that greps only for the success marker stays silent through a crashloop, a hung process, or an unexpected exit — and silence looks identical to "still running." Before arming, ask: *if this process crashed right now, would my filter emit anything?* If not, widen it.\n # Wrong — silent on crash, hang, or any non-success exit\n tail -f run.log | grep --line-buffered "elapsed_steps="\n # Right — one alternation covering progress + the failure signatures you\'d act on\n tail -f run.log | grep -E --line-buffered "elapsed_steps=|Traceback|Error|FAILED|assert|Killed|OOM"\n\nFor poll loops checking job state, emit on every terminal status (`succeeded|failed|cancelled|timeout`), not just success. If you cannot confidently enumerate the failure signatures, broaden the grep alternation rather than narrow it — some extra noise is better than missing a crashloop.\n\n**Output volume**: Every stdout line is a conversation message, so the filter should be selective — but selective means "the lines you\'d act on," not "only good news." Never pipe raw logs; filter to exactly the success and failure signals you care about. Monitors that produce too many events are automatically stopped; restart with a tighter filter if this happens.\n\nStdout lines within 200ms are batched into a single notification, so multiline output from a single event groups naturally.\n\nThe script runs in the same shell environment as Bash. Exit ends the watch (exit code is reported). Timeout → killed. Set `persistent: true` for session-length watches (log tails, long-lived event streams). In managed Cloud sandboxes, every monitor stops at the per-sandbox cap configured by LETTA_MONITOR_MAX_TIMEOUT_MS (default 1 hour, clamped to 1 hour through 7 days), including persistent monitors; elsewhere persistent monitors run until TaskStop or session end. Call Monitor again to re-arm it if you still need to watch. For much longer Cloud waits, schedule a Wake or cron (which does not keep the sandbox running between turns) and combine it with shorter monitors. Use TaskStop to cancel early.\n\nWhen someone is waiting on the result, set `backup_after_seconds` (e.g. 900). If the monitor goes that long without an event, a durable Wake brings you back to check the real state, so a queued, hung, or dead watch can\'t leave them waiting in silence.\n\n**ws source** — open a WebSocket and stream each incoming text frame as an event. No shell, no polling: the server pushes, you get notified.\n ws: {url: \'wss://events.example.com/stream\', protocols: [\'v1\']},\n description: \'deploy events\',\n\nEach text frame becomes one notification (multiline frames stay as one event). Binary frames are reported as `[binary frame, N bytes]` rather than passed through. Socket close ends the watch with the close code surfaced; errors are surfaced before close. Same rate limiting as bash — a firehose will be suppressed and eventually stopped, so subscribe to a filtered feed where one exists.\n\nPrefer this over `command: \'websocat wss://…\'` — it avoids the extra process and line-buffering pitfalls. Use bash when you need to transform or filter frames with shell tools before they become events.\n\n**script source** — a JavaScript watch loop with the same globals as CodeMode (including `decide()`), plus `emit(text)` (one event) and `sleep(ms)`. Tool calls and `decide()` share one rate limit; `decide()` spends money on every call, so call it only when an observed change needs judgment, not on every poll. Returning or throwing ends the watch.\n';
|
|
215852
215858
|
var init_Monitor = () => {};
|
|
215853
215859
|
|
|
215854
215860
|
// src/tools/descriptions/Read.md
|
|
@@ -221930,9 +221936,13 @@ var exports_bash = {};
|
|
|
221930
221936
|
__export(exports_bash, {
|
|
221931
221937
|
spawnCommand: () => spawnCommand,
|
|
221932
221938
|
getBackgroundLauncher: () => getBackgroundLauncher,
|
|
221933
|
-
bash: () => bash
|
|
221939
|
+
bash: () => bash,
|
|
221940
|
+
__setShellProcessStarterForTests: () => __setShellProcessStarterForTests
|
|
221934
221941
|
});
|
|
221935
221942
|
import { rmSync as rmSync13 } from "node:fs";
|
|
221943
|
+
function __setShellProcessStarterForTests(starter) {
|
|
221944
|
+
shellProcessStarter = starter ?? startShellProcess;
|
|
221945
|
+
}
|
|
221936
221946
|
function rebuildCachedLauncher(command, secretEnv) {
|
|
221937
221947
|
if (!cachedWorkingLauncher)
|
|
221938
221948
|
return null;
|
|
@@ -222078,7 +222088,7 @@ async function bash(args) {
|
|
|
222078
222088
|
validateRequiredParams(args, ["command"], "Bash");
|
|
222079
222089
|
const {
|
|
222080
222090
|
command,
|
|
222081
|
-
timeout
|
|
222091
|
+
timeout,
|
|
222082
222092
|
description,
|
|
222083
222093
|
run_in_background = false,
|
|
222084
222094
|
signal,
|
|
@@ -222156,8 +222166,8 @@ async function bash(args) {
|
|
|
222156
222166
|
let bgProcess;
|
|
222157
222167
|
let outputWriteFailed = false;
|
|
222158
222168
|
const foregroundOutput = { stdout: "", stderr: "" };
|
|
222159
|
-
const effectiveTimeout = run_in_background ? timeout > 0 ? timeout : 0 : Math.min(Math.max(timeout, 1), 600000);
|
|
222160
|
-
const runningProcess =
|
|
222169
|
+
const effectiveTimeout = run_in_background ? timeout !== undefined && timeout > 0 ? timeout : 0 : timeout === undefined ? 0 : Math.min(Math.max(timeout, 1), 600000);
|
|
222170
|
+
const runningProcess = shellProcessStarter(sandboxed.launcher, {
|
|
222161
222171
|
cwd: userCwd,
|
|
222162
222172
|
env: sandboxed.env,
|
|
222163
222173
|
timeoutMs: effectiveTimeout,
|
|
@@ -222225,11 +222235,11 @@ async function bash(args) {
|
|
|
222225
222235
|
}, (error5) => {
|
|
222226
222236
|
flushStreamScrubbers();
|
|
222227
222237
|
const err = error5;
|
|
222228
|
-
const message = sanitizeOutput(err.killed ? `Command timed out after ${
|
|
222238
|
+
const message = sanitizeOutput(err.killed ? `Command timed out after ${effectiveTimeout}ms` : err.message);
|
|
222229
222239
|
bgProcess.status = "failed";
|
|
222230
222240
|
appendBackgroundProcessOutput(bgProcess, "stderr", message);
|
|
222231
222241
|
appendToOutputFile(outputFile, err.killed ? `
|
|
222232
|
-
[timeout after ${
|
|
222242
|
+
[timeout after ${effectiveTimeout}ms]
|
|
222233
222243
|
` : `
|
|
222234
222244
|
[error] ${message}
|
|
222235
222245
|
`);
|
|
@@ -222324,7 +222334,7 @@ Output file: ${outputFile}`
|
|
|
222324
222334
|
status: "success"
|
|
222325
222335
|
};
|
|
222326
222336
|
}
|
|
222327
|
-
var cachedWorkingLauncher = null, DEFAULT_FOREGROUND_YIELD_MS = 1e4, NOTIFICATION_TAIL_LINES = 50;
|
|
222337
|
+
var cachedWorkingLauncher = null, DEFAULT_FOREGROUND_YIELD_MS = 1e4, shellProcessStarter, NOTIFICATION_TAIL_LINES = 50;
|
|
222328
222338
|
var init_bash = __esm(async () => {
|
|
222329
222339
|
init_constants2();
|
|
222330
222340
|
init_runtime_context();
|
|
@@ -222342,6 +222352,7 @@ var init_bash = __esm(async () => {
|
|
|
222342
222352
|
init_worktree_ownership(),
|
|
222343
222353
|
init_shell_runner()
|
|
222344
222354
|
]);
|
|
222355
|
+
shellProcessStarter = startShellProcess;
|
|
222345
222356
|
});
|
|
222346
222357
|
|
|
222347
222358
|
// src/tools/client-tool-serialization.ts
|
|
@@ -235685,7 +235696,8 @@ async function executeScript(spawner, options, meta2, extraGlobals) {
|
|
|
235685
235696
|
tools,
|
|
235686
235697
|
listTools,
|
|
235687
235698
|
describeTool,
|
|
235688
|
-
|
|
235699
|
+
decide,
|
|
235700
|
+
...spawner ? { agent, parallel, pipeline: pipeline7, phase, log: log3 } : {},
|
|
235689
235701
|
args: options.args,
|
|
235690
235702
|
console: { log: log3, warn: log3, error: log3, info: log3 },
|
|
235691
235703
|
process: Object.freeze({ env: Object.freeze({ ...options.env }) }),
|
|
@@ -242308,10 +242320,10 @@ var init_monitor_event_stream = __esm(() => {
|
|
|
242308
242320
|
});
|
|
242309
242321
|
|
|
242310
242322
|
// src/tools/impl/monitor-script.ts
|
|
242311
|
-
function
|
|
242323
|
+
function createCallLimiter(signal) {
|
|
242312
242324
|
let tokens = TOOL_CALL_BURST;
|
|
242313
242325
|
let refilledAt = Date.now();
|
|
242314
|
-
return (
|
|
242326
|
+
return (call2) => {
|
|
242315
242327
|
if (signal.aborted)
|
|
242316
242328
|
return new Promise(() => {});
|
|
242317
242329
|
const now2 = Date.now();
|
|
@@ -242321,10 +242333,10 @@ function rateLimitToolCalls(call2, signal) {
|
|
|
242321
242333
|
refilledAt += refill * TOOL_CALL_REFILL_MS;
|
|
242322
242334
|
}
|
|
242323
242335
|
if (tokens === 0) {
|
|
242324
|
-
throw new Error(`Monitor script exceeded ${1000 / TOOL_CALL_REFILL_MS}
|
|
242336
|
+
throw new Error(`Monitor script exceeded ${1000 / TOOL_CALL_REFILL_MS} calls per second; add sleep() between polls.`);
|
|
242325
242337
|
}
|
|
242326
242338
|
tokens -= 1;
|
|
242327
|
-
return call2(
|
|
242339
|
+
return call2();
|
|
242328
242340
|
};
|
|
242329
242341
|
}
|
|
242330
242342
|
function abortableSleep3(ms, signal) {
|
|
@@ -242467,16 +242479,25 @@ async function startScriptMonitor(args, hooks) {
|
|
|
242467
242479
|
const stopped = new Promise((_resolve, reject2) => {
|
|
242468
242480
|
controller.signal.addEventListener("abort", () => reject2(controller.signal.reason), { once: true });
|
|
242469
242481
|
});
|
|
242482
|
+
const limit4 = createCallLimiter(controller.signal);
|
|
242470
242483
|
const run = executeToolScript({
|
|
242471
242484
|
...toolScope,
|
|
242472
|
-
callTool:
|
|
242485
|
+
callTool: (toolName2, toolArgs) => limit4(() => toolScope.callTool(toolName2, toolArgs)),
|
|
242473
242486
|
maxTotalToolCalls: Number.POSITIVE_INFINITY,
|
|
242474
242487
|
script: args.script,
|
|
242475
242488
|
args: args.args,
|
|
242476
242489
|
signal: new AbortController().signal,
|
|
242477
242490
|
globals: {
|
|
242478
242491
|
emit,
|
|
242479
|
-
sleep: (ms) => abortableSleep3(ms, controller.signal)
|
|
242492
|
+
sleep: (ms) => abortableSleep3(ms, controller.signal),
|
|
242493
|
+
decide: (state2, questions, options) => {
|
|
242494
|
+
if (options !== undefined && (!options || typeof options !== "object" || Array.isArray(options))) {
|
|
242495
|
+
throw new Error("decide() options must be an object.");
|
|
242496
|
+
}
|
|
242497
|
+
const pending2 = limit4(() => submitWorkflowDecision({ ...options, state: state2, questions }, controller.signal));
|
|
242498
|
+
pending2.catch(() => {});
|
|
242499
|
+
return pending2;
|
|
242500
|
+
}
|
|
242480
242501
|
},
|
|
242481
242502
|
onProgress: (event) => {
|
|
242482
242503
|
if (event.kind === "log")
|
|
@@ -242517,6 +242538,7 @@ var init_monitor_script = __esm(() => {
|
|
|
242517
242538
|
init_script_tool_scope();
|
|
242518
242539
|
init_secret_substitution();
|
|
242519
242540
|
init_tool_context_retention();
|
|
242541
|
+
init_decide();
|
|
242520
242542
|
init_workflow_engine();
|
|
242521
242543
|
init_message_queue_bridge();
|
|
242522
242544
|
init_task_notifications();
|
|
@@ -245048,7 +245070,7 @@ class CodexAppServerClient {
|
|
|
245048
245070
|
await this.request("initialize", {
|
|
245049
245071
|
clientInfo: {
|
|
245050
245072
|
name: "letta-code",
|
|
245051
|
-
version: "0.34.
|
|
245073
|
+
version: "0.34.36"
|
|
245052
245074
|
},
|
|
245053
245075
|
capabilities: null
|
|
245054
245076
|
});
|
|
@@ -246262,16 +246284,6 @@ var init_catalog = __esm(() => {
|
|
|
246262
246284
|
"listen"
|
|
246263
246285
|
]
|
|
246264
246286
|
},
|
|
246265
|
-
{
|
|
246266
|
-
id: "memory-git-sync",
|
|
246267
|
-
description: "Queued post-turn memory git sync status",
|
|
246268
|
-
modes: [
|
|
246269
|
-
"interactive",
|
|
246270
|
-
"headless-one-shot",
|
|
246271
|
-
"headless-bidirectional",
|
|
246272
|
-
"listen"
|
|
246273
|
-
]
|
|
246274
|
-
},
|
|
246275
246287
|
{
|
|
246276
246288
|
id: "command-io",
|
|
246277
246289
|
description: "Recent slash command input/output context",
|
|
@@ -246514,14 +246526,6 @@ async function buildPermissionModeReminder(context3) {
|
|
|
246514
246526
|
|
|
246515
246527
|
`;
|
|
246516
246528
|
}
|
|
246517
|
-
async function buildMemoryGitSyncReminder(context3) {
|
|
246518
|
-
if (context3.state.pendingMemoryGitSyncReminders.length === 0) {
|
|
246519
|
-
return null;
|
|
246520
|
-
}
|
|
246521
|
-
return context3.state.pendingMemoryGitSyncReminders.splice(0).map((reminder) => reminder.text).join(`
|
|
246522
|
-
|
|
246523
|
-
`);
|
|
246524
|
-
}
|
|
246525
246529
|
function escapeXml2(value) {
|
|
246526
246530
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
246527
246531
|
}
|
|
@@ -246687,7 +246691,6 @@ var init_engine3 = __esm(() => {
|
|
|
246687
246691
|
"mcp-servers-info": buildMcpServersInfoReminder,
|
|
246688
246692
|
"session-context": buildSessionContextReminder,
|
|
246689
246693
|
"permission-mode": buildPermissionModeReminder,
|
|
246690
|
-
"memory-git-sync": buildMemoryGitSyncReminder,
|
|
246691
246694
|
"command-io": buildCommandIoReminder,
|
|
246692
246695
|
"toolset-change": buildToolsetChangeReminder,
|
|
246693
246696
|
"disk-space": buildDiskSpaceReminder
|
|
@@ -255545,7 +255548,7 @@ var init_Bash2 = __esm(() => {
|
|
|
255545
255548
|
},
|
|
255546
255549
|
timeout: {
|
|
255547
255550
|
type: "number",
|
|
255548
|
-
description: "
|
|
255551
|
+
description: "Commands run until they exit unless you pass a timeout in milliseconds. Foreground timeouts have a maximum of 600000."
|
|
255549
255552
|
},
|
|
255550
255553
|
description: {
|
|
255551
255554
|
type: "string",
|
|
@@ -259090,6 +259093,7 @@ var init_startup_ingress = __esm(() => {
|
|
|
259090
259093
|
});
|
|
259091
259094
|
|
|
259092
259095
|
// src/websocket/listener/connection.ts
|
|
259096
|
+
import WebSocket7 from "ws";
|
|
259093
259097
|
function toListenerConnection(connectionId) {
|
|
259094
259098
|
return { type: "ToConnection", connectionId };
|
|
259095
259099
|
}
|
|
@@ -259109,8 +259113,11 @@ function refreshLegacySingleConnection(runtime) {
|
|
|
259109
259113
|
const only = live.find(({ id: id2 }) => id2 === runtime.connectionId) ?? (live.length === 1 ? live[0] : null);
|
|
259110
259114
|
runtime.transport = runtime.processTransport ?? only?.writer ?? null;
|
|
259111
259115
|
runtime.streamTransport = only?.streamWriter ?? null;
|
|
259112
|
-
|
|
259113
|
-
|
|
259116
|
+
const pending2 = (socket) => socket != null && socket.readyState <= WebSocket7.OPEN && ![...runtime.connections.values()].some(({ writer, streamWriter }) => writer === socket || streamWriter === socket);
|
|
259117
|
+
if (only || !pending2(runtime.socket))
|
|
259118
|
+
runtime.socket = only ? socketForTransport(only.writer) : null;
|
|
259119
|
+
if (only || !pending2(runtime.streamSocket))
|
|
259120
|
+
runtime.streamSocket = only?.streamWriter ? socketForTransport(only.streamWriter) : null;
|
|
259114
259121
|
}
|
|
259115
259122
|
function createConnectionRequestKey(connectionId, requestId) {
|
|
259116
259123
|
return JSON.stringify([connectionId, requestId]);
|
|
@@ -441999,9 +442006,13 @@ async function syncMemfsForAgent(agentId) {
|
|
|
441999
442006
|
const agent = await getBackend2().retrieveAgent(agentId, {
|
|
442000
442007
|
include: ["agent.tags"]
|
|
442001
442008
|
});
|
|
442002
|
-
const { GIT_MEMORY_ENABLED_TAG: GIT_MEMORY_ENABLED_TAG2 } = await Promise.resolve().then(() => exports_agent_tags);
|
|
442009
|
+
const { GIT_MEMORY_ENABLED_TAG: GIT_MEMORY_ENABLED_TAG2, isStatelessSubagentTags: isStatelessSubagentTags2 } = await Promise.resolve().then(() => exports_agent_tags);
|
|
442003
442010
|
const { applyMemfsFlags: applyMemfsFlags2, isLettaCloud: isLettaCloud2 } = await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem));
|
|
442004
442011
|
if (!agent.tags?.includes(GIT_MEMORY_ENABLED_TAG2)) {
|
|
442012
|
+
if (isStatelessSubagentTags2(agent.tags)) {
|
|
442013
|
+
debugLog("memfs-sync", `Agent ${agentId} is a subagent, skipping repair`);
|
|
442014
|
+
return;
|
|
442015
|
+
}
|
|
442005
442016
|
if (!await isLettaCloud2()) {
|
|
442006
442017
|
debugLog("memfs-sync", `Agent ${agentId} does not have memfs tag (self-hosted), skipping`);
|
|
442007
442018
|
return;
|
|
@@ -445335,7 +445346,7 @@ var init_control_inputs = __esm(async () => {
|
|
|
445335
445346
|
// src/websocket/terminal-handler.ts
|
|
445336
445347
|
import { existsSync as existsSync58 } from "node:fs";
|
|
445337
445348
|
import * as os6 from "node:os";
|
|
445338
|
-
import
|
|
445349
|
+
import WebSocket8 from "ws";
|
|
445339
445350
|
function getTerminalKey(connectionId, terminalId) {
|
|
445340
445351
|
return JSON.stringify([connectionId, terminalId]);
|
|
445341
445352
|
}
|
|
@@ -445356,7 +445367,7 @@ function getDefaultShell() {
|
|
|
445356
445367
|
return "/bin/sh";
|
|
445357
445368
|
}
|
|
445358
445369
|
function sendTerminalMessage(socket, message2) {
|
|
445359
|
-
if (socket.readyState ===
|
|
445370
|
+
if (socket.readyState === WebSocket8.OPEN) {
|
|
445360
445371
|
socket.send(JSON.stringify(message2));
|
|
445361
445372
|
}
|
|
445362
445373
|
}
|
|
@@ -453909,7 +453920,7 @@ async function runPostTurnMemorySync(params, dependencies4 = {}) {
|
|
|
453909
453920
|
const repairInProgress = (result3.status === "conflict" || result3.status === "invalid") && await repairMemory({ ...params, result: result3 });
|
|
453910
453921
|
const reminder = repairInProgress ? formatMemoryRepairInProgressReminder(result3) : formatMemoryPostTurnSyncReminder(result3);
|
|
453911
453922
|
if (reminder) {
|
|
453912
|
-
|
|
453923
|
+
debugWarn("memfs-git", reminder);
|
|
453913
453924
|
await params.emitWarning?.(reminder);
|
|
453914
453925
|
}
|
|
453915
453926
|
} finally {
|
|
@@ -453923,7 +453934,7 @@ async function runPostTurnMemorySync(params, dependencies4 = {}) {
|
|
|
453923
453934
|
try {
|
|
453924
453935
|
const repositorySyncResult = await syncAttachedRepositories(params.agentId);
|
|
453925
453936
|
for (const reminder of formatAttachedRepositoriesPostTurnSyncReminders(repositorySyncResult)) {
|
|
453926
|
-
|
|
453937
|
+
debugWarn("memfs-git", reminder);
|
|
453927
453938
|
await params.emitWarning?.(reminder);
|
|
453928
453939
|
}
|
|
453929
453940
|
} catch (error5) {
|
|
@@ -454009,9 +454020,6 @@ async function runListenerTurnCleanup(params) {
|
|
|
454009
454020
|
affected_paths: ["*"],
|
|
454010
454021
|
timestamp: Date.now()
|
|
454011
454022
|
}, { agent_id: agentId, conversation_id: conversationId }, TO_SUBSCRIBERS);
|
|
454012
|
-
},
|
|
454013
|
-
enqueueReminder: (text3) => {
|
|
454014
|
-
enqueueMemoryGitSyncReminder(runtime.reminderState, { text: text3 });
|
|
454015
454023
|
}
|
|
454016
454024
|
});
|
|
454017
454025
|
}
|
|
@@ -461160,7 +461168,7 @@ var init_turn = __esm(async () => {
|
|
|
461160
461168
|
});
|
|
461161
461169
|
|
|
461162
461170
|
// src/websocket/listener/connection-lifecycle.ts
|
|
461163
|
-
import
|
|
461171
|
+
import WebSocket9 from "ws";
|
|
461164
461172
|
function createConnectionTurnProcessor(runtime) {
|
|
461165
461173
|
return async (queuedTurn, dequeuedBatch) => {
|
|
461166
461174
|
const scopedRuntime = getOrCreateScopedRuntime(runtime, queuedTurn.agentId, queuedTurn.conversationId);
|
|
@@ -461265,7 +461273,7 @@ function closeListenerRuntimeConnections(runtime, suppressCallbacks) {
|
|
|
461265
461273
|
for (const socket of socketsToClose) {
|
|
461266
461274
|
if (suppressCallbacks) {
|
|
461267
461275
|
socket.removeAllListeners();
|
|
461268
|
-
if (socket.readyState !==
|
|
461276
|
+
if (socket.readyState !== WebSocket9.CLOSED && typeof socket.on === "function" && typeof socket.once === "function" && typeof socket.removeListener === "function") {
|
|
461269
461277
|
const ignoreError = () => {};
|
|
461270
461278
|
socket.on("error", ignoreError);
|
|
461271
461279
|
socket.once("close", () => {
|
|
@@ -461273,7 +461281,7 @@ function closeListenerRuntimeConnections(runtime, suppressCallbacks) {
|
|
|
461273
461281
|
});
|
|
461274
461282
|
}
|
|
461275
461283
|
}
|
|
461276
|
-
if (socket.readyState ===
|
|
461284
|
+
if (socket.readyState === WebSocket9.OPEN || socket.readyState === WebSocket9.CONNECTING) {
|
|
461277
461285
|
socket.close();
|
|
461278
461286
|
}
|
|
461279
461287
|
}
|
|
@@ -462311,12 +462319,12 @@ var init_file_commands = __esm(async () => {
|
|
|
462311
462319
|
});
|
|
462312
462320
|
|
|
462313
462321
|
// src/websocket/listener/handshake-deadline.ts
|
|
462314
|
-
import
|
|
462322
|
+
import WebSocket10 from "ws";
|
|
462315
462323
|
function createListenerSocket(url2, apiKey) {
|
|
462316
462324
|
const options = getListenerSocketOptions(apiKey);
|
|
462317
|
-
const socket = new
|
|
462325
|
+
const socket = new WebSocket10(url2.toString(), options);
|
|
462318
462326
|
const timer = setTimeout(() => {
|
|
462319
|
-
if (socket.readyState ===
|
|
462327
|
+
if (socket.readyState === WebSocket10.CONNECTING)
|
|
462320
462328
|
socket.terminate();
|
|
462321
462329
|
}, options.handshakeTimeout);
|
|
462322
462330
|
timer.unref?.();
|
|
@@ -465695,7 +465703,7 @@ var init_input_frame_router = __esm(async () => {
|
|
|
465695
465703
|
});
|
|
465696
465704
|
|
|
465697
465705
|
// src/websocket/listener/split-stream-lifecycle.ts
|
|
465698
|
-
import { WebSocket as
|
|
465706
|
+
import { WebSocket as WebSocket11 } from "ws";
|
|
465699
465707
|
function createListenerPairIdentity(runtime) {
|
|
465700
465708
|
runtime.nextConnectionAttempt += 1;
|
|
465701
465709
|
return {
|
|
@@ -465717,7 +465725,7 @@ function parseListenerReadyMessage(data) {
|
|
|
465717
465725
|
return null;
|
|
465718
465726
|
}
|
|
465719
465727
|
function terminateSocketIfOpenOrConnecting(socket) {
|
|
465720
|
-
if (socket && (socket.readyState ===
|
|
465728
|
+
if (socket && (socket.readyState === WebSocket11.OPEN || socket.readyState === WebSocket11.CONNECTING)) {
|
|
465721
465729
|
socket.terminate();
|
|
465722
465730
|
}
|
|
465723
465731
|
}
|
|
@@ -465727,6 +465735,13 @@ function isCurrentSocketPair(runtime, controlSocket, streamSocket) {
|
|
|
465727
465735
|
function shouldHandleControlSocketClose(runtime, controlSocket, connectionId) {
|
|
465728
465736
|
return runtime === getActiveRuntime() && (runtime.socket === controlSocket || runtime.connections.get(connectionId)?.writer === controlSocket);
|
|
465729
465737
|
}
|
|
465738
|
+
function trackReconnectInFlight(runtime, reconnect) {
|
|
465739
|
+
reconnectsInFlight.add(runtime);
|
|
465740
|
+
return reconnect.finally(() => reconnectsInFlight.delete(runtime));
|
|
465741
|
+
}
|
|
465742
|
+
function shouldRecoverOrphanedControlClose(runtime) {
|
|
465743
|
+
return runtime === getActiveRuntime() && !runtime.intentionallyClosed && (!runtime.socket || runtime.socket.readyState === WebSocket11.CLOSED) && ![...runtime.connections.values()].some(({ writer }) => isListenerTransportOpen(writer)) && !runtime.reconnectTimeout && !reconnectsInFlight.has(runtime);
|
|
465744
|
+
}
|
|
465730
465745
|
function terminateCurrentSocketPair(runtime, controlSocket, streamSocket) {
|
|
465731
465746
|
if (!isCurrentSocketPair(runtime, controlSocket, streamSocket)) {
|
|
465732
465747
|
return;
|
|
@@ -465756,7 +465771,7 @@ function getStreamOpenTimeoutMs() {
|
|
|
465756
465771
|
return LISTENER_STREAM_OPEN_TIMEOUT_MS;
|
|
465757
465772
|
}
|
|
465758
465773
|
async function waitForPairedSocketAcceptance(socket, identity2) {
|
|
465759
|
-
if (socket.readyState ===
|
|
465774
|
+
if (socket.readyState === WebSocket11.CLOSING || socket.readyState === WebSocket11.CLOSED) {
|
|
465760
465775
|
return { status: "closed" };
|
|
465761
465776
|
}
|
|
465762
465777
|
const timeoutMs = getStreamOpenTimeoutMs();
|
|
@@ -465796,10 +465811,10 @@ async function waitForPairedSocketAcceptance(socket, identity2) {
|
|
|
465796
465811
|
});
|
|
465797
465812
|
}
|
|
465798
465813
|
async function waitForStreamSocketOpen(streamSocket) {
|
|
465799
|
-
if (streamSocket.readyState ===
|
|
465814
|
+
if (streamSocket.readyState === WebSocket11.OPEN) {
|
|
465800
465815
|
return { status: "open", transport: streamSocket };
|
|
465801
465816
|
}
|
|
465802
|
-
if (streamSocket.readyState ===
|
|
465817
|
+
if (streamSocket.readyState === WebSocket11.CLOSING || streamSocket.readyState === WebSocket11.CLOSED) {
|
|
465803
465818
|
return { status: "closed" };
|
|
465804
465819
|
}
|
|
465805
465820
|
const timeoutMs = getStreamOpenTimeoutMs();
|
|
@@ -465950,11 +465965,13 @@ function handleListenerSocketOpenFailure({
|
|
|
465950
465965
|
}
|
|
465951
465966
|
terminateCurrentSocketPair(runtime, controlSocket, streamSocket);
|
|
465952
465967
|
}
|
|
465953
|
-
var MAX_CLOSE_REASON_LENGTH = 120;
|
|
465968
|
+
var reconnectsInFlight, MAX_CLOSE_REASON_LENGTH = 120;
|
|
465954
465969
|
var init_split_stream_lifecycle = __esm(async () => {
|
|
465955
465970
|
init_debug();
|
|
465956
465971
|
init_constants3();
|
|
465972
|
+
init_transport2();
|
|
465957
465973
|
await init_runtime6();
|
|
465974
|
+
reconnectsInFlight = new WeakSet;
|
|
465958
465975
|
});
|
|
465959
465976
|
|
|
465960
465977
|
// src/websocket/listener/turn-finished-ack.ts
|
|
@@ -467685,9 +467702,9 @@ var init_restored_queue_pump = __esm(async () => {
|
|
|
467685
467702
|
});
|
|
467686
467703
|
|
|
467687
467704
|
// src/websocket/listener/socket-send.ts
|
|
467688
|
-
import
|
|
467705
|
+
import WebSocket12 from "ws";
|
|
467689
467706
|
function safeSocketSend(socket, payload, errorType, context3) {
|
|
467690
|
-
if (socket.readyState !==
|
|
467707
|
+
if (socket.readyState !== WebSocket12.OPEN)
|
|
467691
467708
|
return false;
|
|
467692
467709
|
try {
|
|
467693
467710
|
const serialized = typeof payload === "string" ? payload : JSON.stringify(payload);
|
|
@@ -467986,7 +468003,7 @@ var init_sync_replay = __esm(async () => {
|
|
|
467986
468003
|
});
|
|
467987
468004
|
|
|
467988
468005
|
// src/websocket/listener/lifecycle.ts
|
|
467989
|
-
import
|
|
468006
|
+
import WebSocket13 from "ws";
|
|
467990
468007
|
function createRuntime() {
|
|
467991
468008
|
const bootWorkingDirectory = getCurrentWorkingDirectory();
|
|
467992
468009
|
return {
|
|
@@ -468256,7 +468273,7 @@ async function attachOpenListenerSocket(runtime, socket, opts, options = {}) {
|
|
|
468256
468273
|
abortStartupIngress();
|
|
468257
468274
|
return;
|
|
468258
468275
|
}
|
|
468259
|
-
const streamTransport = streamSocket?.readyState ===
|
|
468276
|
+
const streamTransport = streamSocket?.readyState === WebSocket13.OPEN ? streamSocket : null;
|
|
468260
468277
|
await startConnectedListenerRuntime(runtime, transport3, opts, processQueuedTurn, {
|
|
468261
468278
|
startHeartbeat: options.startHeartbeat ?? false,
|
|
468262
468279
|
startCronScheduler: options.startCronScheduler ?? true,
|
|
@@ -468494,7 +468511,7 @@ async function connectWithRetry(runtime, opts, attempt2 = 0, startTime = Date.no
|
|
|
468494
468511
|
socket.on("close", (code2, reason) => {
|
|
468495
468512
|
lifecycleLog(formatListenerSocketClose("control", code2, reason));
|
|
468496
468513
|
abortStartupIngress();
|
|
468497
|
-
if (!shouldHandleControlSocketClose(runtime, socket, opts.connectionId)) {
|
|
468514
|
+
if (!shouldHandleControlSocketClose(runtime, socket, opts.connectionId) && !shouldRecoverOrphanedControlClose(runtime)) {
|
|
468498
468515
|
return;
|
|
468499
468516
|
}
|
|
468500
468517
|
safeEmitWsEvent("recv", "lifecycle", {
|
|
@@ -468527,7 +468544,7 @@ async function connectWithRetry(runtime, opts, attempt2 = 0, startTime = Date.no
|
|
|
468527
468544
|
streamSocket.removeAllListeners("message");
|
|
468528
468545
|
streamSocket.removeAllListeners("open");
|
|
468529
468546
|
streamSocket.removeAllListeners("close");
|
|
468530
|
-
if (streamSocket.readyState ===
|
|
468547
|
+
if (streamSocket.readyState === WebSocket13.OPEN || streamSocket.readyState === WebSocket13.CONNECTING) {
|
|
468531
468548
|
streamSocket.close();
|
|
468532
468549
|
}
|
|
468533
468550
|
}
|
|
@@ -468554,7 +468571,7 @@ async function connectWithRetry(runtime, opts, attempt2 = 0, startTime = Date.no
|
|
|
468554
468571
|
const nextAttempt = runtime.hasSuccessfulConnection ? 0 : attempt2 + 1;
|
|
468555
468572
|
const nextStartTime = runtime.hasSuccessfulConnection ? Date.now() : startTime;
|
|
468556
468573
|
runtime.hasSuccessfulConnection = false;
|
|
468557
|
-
connectWithRetry(runtime, opts, nextAttempt, nextStartTime).catch((error5) => {
|
|
468574
|
+
trackReconnectInFlight(runtime, connectWithRetry(runtime, opts, nextAttempt, nextStartTime)).catch((error5) => {
|
|
468558
468575
|
opts.onError(error5 instanceof Error ? error5 : new Error(String(error5)));
|
|
468559
468576
|
});
|
|
468560
468577
|
});
|
|
@@ -470933,7 +470950,7 @@ __export(exports_app_server, {
|
|
|
470933
470950
|
});
|
|
470934
470951
|
import { createServer as createServer6 } from "node:http";
|
|
470935
470952
|
import { hostname as hostname5 } from "node:os";
|
|
470936
|
-
import
|
|
470953
|
+
import WebSocket14, { WebSocketServer } from "ws";
|
|
470937
470954
|
function getRequiredAddressInfo(server2) {
|
|
470938
470955
|
const address = server2.address();
|
|
470939
470956
|
if (!address || typeof address === "string") {
|
|
@@ -470949,12 +470966,12 @@ function getWebSocketUrl(baseUrl, path47) {
|
|
|
470949
470966
|
function closeSocket(socket, code2 = 1001, reason = "closing") {
|
|
470950
470967
|
if (!socket)
|
|
470951
470968
|
return;
|
|
470952
|
-
if (socket.readyState ===
|
|
470969
|
+
if (socket.readyState === WebSocket14.OPEN || socket.readyState === WebSocket14.CONNECTING) {
|
|
470953
470970
|
socket.close(code2, reason);
|
|
470954
470971
|
}
|
|
470955
470972
|
}
|
|
470956
470973
|
function terminateSocket(socket) {
|
|
470957
|
-
if (!socket || socket.readyState ===
|
|
470974
|
+
if (!socket || socket.readyState === WebSocket14.CLOSED)
|
|
470958
470975
|
return;
|
|
470959
470976
|
socket.terminate();
|
|
470960
470977
|
}
|
|
@@ -471141,7 +471158,7 @@ async function startAppServer(options = {}) {
|
|
|
471141
471158
|
client.terminate();
|
|
471142
471159
|
continue;
|
|
471143
471160
|
}
|
|
471144
|
-
if (client.readyState ===
|
|
471161
|
+
if (client.readyState === WebSocket14.OPEN) {
|
|
471145
471162
|
const sentAt = Date.now();
|
|
471146
471163
|
client.ping();
|
|
471147
471164
|
watchdog?.recordPing(sentAt);
|
|
@@ -484690,7 +484707,7 @@ async function handleChannelsSlashCommand(runtime, args) {
|
|
|
484690
484707
|
|
|
484691
484708
|
// src/channels/gateway-local.ts
|
|
484692
484709
|
import { createHash as createHash21 } from "node:crypto";
|
|
484693
|
-
import
|
|
484710
|
+
import WebSocket15 from "ws";
|
|
484694
484711
|
async function executeChannelServiceCommand(command) {
|
|
484695
484712
|
if (!isDetachedChannelsCommand(command)) {
|
|
484696
484713
|
throw new Error(`Unsupported ChannelGateway command: ${command.type}`);
|
|
@@ -484761,7 +484778,7 @@ async function startLocalChannelGateway(options) {
|
|
|
484761
484778
|
await settingsManager.initialize();
|
|
484762
484779
|
const client = createAppServerClient({
|
|
484763
484780
|
url: options.appServerUrl,
|
|
484764
|
-
WebSocket:
|
|
484781
|
+
WebSocket: WebSocket15
|
|
484765
484782
|
});
|
|
484766
484783
|
await client.connect();
|
|
484767
484784
|
let serverInfo;
|
|
@@ -486449,9 +486466,10 @@ function resolveHeadlessMemfsPolicy(options) {
|
|
|
486449
486466
|
const isFreshStatelessSubagent = options.isSubagentRole && options.newAgentRequested;
|
|
486450
486467
|
return {
|
|
486451
486468
|
isFreshStatelessSubagent,
|
|
486452
|
-
isStatelessSession: options.statelessRequested || isFreshStatelessSubagent
|
|
486469
|
+
isStatelessSession: options.statelessRequested || isFreshStatelessSubagent || isStatelessSubagentTags(options.agentTags)
|
|
486453
486470
|
};
|
|
486454
486471
|
}
|
|
486472
|
+
var init_headless_memfs_policy = () => {};
|
|
486455
486473
|
|
|
486456
486474
|
// src/headless-mod-adapter.ts
|
|
486457
486475
|
import { join as join106 } from "node:path";
|
|
@@ -487235,18 +487253,17 @@ In headless mode, use:
|
|
|
487235
487253
|
const skillSourcesRaw = values4["skill-sources"];
|
|
487236
487254
|
const memfsFlag = values4.memfs;
|
|
487237
487255
|
const statelessFlag = values4.stateless;
|
|
487238
|
-
const
|
|
487239
|
-
const
|
|
487256
|
+
const isSubagent = process.env.LETTA_CODE_AGENT_ROLE === "subagent";
|
|
487257
|
+
const memfsPolicyFor = (agentTags) => resolveHeadlessMemfsPolicy({
|
|
487240
487258
|
statelessRequested: Boolean(statelessFlag),
|
|
487241
|
-
isSubagentRole,
|
|
487242
|
-
newAgentRequested: Boolean(forceNew)
|
|
487243
|
-
|
|
487244
|
-
|
|
487245
|
-
const
|
|
487246
|
-
|
|
487247
|
-
|
|
487248
|
-
|
|
487249
|
-
}
|
|
487259
|
+
isSubagentRole: isSubagent,
|
|
487260
|
+
newAgentRequested: Boolean(forceNew),
|
|
487261
|
+
agentTags
|
|
487262
|
+
});
|
|
487263
|
+
const memfsPolicy = memfsPolicyFor();
|
|
487264
|
+
let isStatelessSession = Boolean(ephemeralFlag) || memfsPolicy.isStatelessSession;
|
|
487265
|
+
if (isStatelessSession && backend3.capabilities.localMemfs)
|
|
487266
|
+
disableLocalBackendMemfsForProcess();
|
|
487250
487267
|
const memfsStartupRaw = values4["memfs-startup"];
|
|
487251
487268
|
const memfsStartupPolicy = memfsStartupRaw === "background" || memfsStartupRaw === "skip" ? memfsStartupRaw : "blocking";
|
|
487252
487269
|
const requestedMemoryPromptMode = memfsFlag ? "memfs" : undefined;
|
|
@@ -487437,7 +487454,7 @@ Use --new-agent to create a local agent, or pass --agent <local-agent-id> to cho
|
|
|
487437
487454
|
if (!agent && forceNew) {
|
|
487438
487455
|
const { isLettaCloud: isLettaCloud2 } = await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem));
|
|
487439
487456
|
const willAutoEnableMemfs = backend3.capabilities.remoteMemfs && shouldAutoEnableMemfsForNewAgent && await isLettaCloud2();
|
|
487440
|
-
const effectiveMemoryMode = backend3.capabilities.localMemfs ? isFreshStatelessSubagent ? "standard" : "local-memfs" : requestedMemoryPromptMode ?? (willAutoEnableMemfs ? "memfs" : undefined);
|
|
487457
|
+
const effectiveMemoryMode = backend3.capabilities.localMemfs ? memfsPolicy.isFreshStatelessSubagent ? "standard" : "local-memfs" : requestedMemoryPromptMode ?? (willAutoEnableMemfs ? "memfs" : undefined);
|
|
487441
487458
|
const personalityOptions = personality ? await buildCreateAgentOptionsForPersonality({
|
|
487442
487459
|
personalityId: personality,
|
|
487443
487460
|
model,
|
|
@@ -487534,7 +487551,9 @@ Current session AGENT_ID=${process.env.AGENT_ID}; --backend local switches to a
|
|
|
487534
487551
|
let conversationId;
|
|
487535
487552
|
let conversationOpenReason = "startup";
|
|
487536
487553
|
let effectiveReflectionSettings;
|
|
487537
|
-
|
|
487554
|
+
isStatelessSession ||= memfsPolicyFor(agent.tags).isStatelessSession;
|
|
487555
|
+
if (isStatelessSession && backend3.capabilities.localMemfs)
|
|
487556
|
+
disableLocalBackendMemfsForProcess();
|
|
487538
487557
|
let startupMemfsFlag = autoEnableMemfsForFreshAgent ? true : memfsFlag;
|
|
487539
487558
|
if (!isStatelessSession && !isDetached && backend3.capabilities.remoteMemfs && !autoEnableMemfsForFreshAgent) {
|
|
487540
487559
|
const { hydrateMemfsSettingFromAgent: hydrateMemfsSettingFromAgent2, isLettaCloud: isLettaCloud2 } = await Promise.resolve().then(() => (init_memory_filesystem2(), exports_memory_filesystem));
|
|
@@ -489877,13 +489896,7 @@ async function runBidirectionalMode(agent, conversationId, effectiveModel, _outp
|
|
|
489877
489896
|
conversationId,
|
|
489878
489897
|
agentId: agent.id,
|
|
489879
489898
|
isEnabled: (id2) => settingsManager.isMemfsEnabled(id2),
|
|
489880
|
-
debugLabel: "Post-turn headless memory sync"
|
|
489881
|
-
enqueueReminder: (text3) => {
|
|
489882
|
-
enqueueMemoryGitSyncReminder(sharedReminderState, { text: text3 });
|
|
489883
|
-
},
|
|
489884
|
-
emitWarning: (text3) => {
|
|
489885
|
-
debugWarn("memfs-git", text3);
|
|
489886
|
-
}
|
|
489899
|
+
debugLabel: "Post-turn headless memory sync"
|
|
489887
489900
|
});
|
|
489888
489901
|
turnInProgress = false;
|
|
489889
489902
|
blockedEmittedThisTurn = false;
|
|
@@ -489908,6 +489921,7 @@ var LLM_API_ERROR_MAX_RETRIES2 = 3, EMPTY_RESPONSE_MAX_RETRIES2 = 2, HEADLESS_ST
|
|
|
489908
489921
|
var init_headless = __esm(async () => {
|
|
489909
489922
|
init_error();
|
|
489910
489923
|
init_preloaded_skills();
|
|
489924
|
+
init_paths();
|
|
489911
489925
|
init_constants2();
|
|
489912
489926
|
init_headless_message_sender();
|
|
489913
489927
|
init_headless_response_state();
|
|
@@ -489941,6 +489955,7 @@ var init_headless = __esm(async () => {
|
|
|
489941
489955
|
init_headless_cloud_send();
|
|
489942
489956
|
init_headless_environment_response();
|
|
489943
489957
|
init_headless_listener_launch();
|
|
489958
|
+
init_headless_memfs_policy();
|
|
489944
489959
|
init_headless_reflection_settings();
|
|
489945
489960
|
init_diff_preview();
|
|
489946
489961
|
init_mcp_runtime();
|
|
@@ -532155,12 +532170,7 @@ ${SYSTEM_REMINDER_CLOSE}
|
|
|
532155
532170
|
await runPostTurnMemorySync({
|
|
532156
532171
|
conversationId,
|
|
532157
532172
|
agentId,
|
|
532158
|
-
isEnabled: isActiveMemfsEnabled
|
|
532159
|
-
enqueueReminder: (text3) => {
|
|
532160
|
-
enqueueMemoryGitSyncReminder(sharedReminderStateRef.current, {
|
|
532161
|
-
text: text3
|
|
532162
|
-
});
|
|
532163
|
-
}
|
|
532173
|
+
isEnabled: isActiveMemfsEnabled
|
|
532164
532174
|
});
|
|
532165
532175
|
clearPlaceholdersInText(msg);
|
|
532166
532176
|
return { submitted: true };
|
|
@@ -537017,8 +537027,9 @@ Error: ${message2}`);
|
|
|
537017
537027
|
skipPromptUpdate: shouldCreateNew
|
|
537018
537028
|
})) : Promise.resolve().then(() => {
|
|
537019
537029
|
if (backend3.capabilities.localMemfs) {
|
|
537020
|
-
|
|
537021
|
-
|
|
537030
|
+
const enabled = !isStatelessSubagentTags(agentTags);
|
|
537031
|
+
settingsManager.setMemfsEnabled(agentId2, enabled);
|
|
537032
|
+
return { action: enabled ? "enabled" : "unchanged" };
|
|
537022
537033
|
}
|
|
537023
537034
|
if (memfsFlag) {
|
|
537024
537035
|
throw new Error("MemFS is not supported by the active backend.");
|
|
@@ -539725,4 +539736,4 @@ function registerBunOAuthFlows() {
|
|
|
539725
539736
|
registerBunOAuthFlows();
|
|
539726
539737
|
await init_src5().then(() => exports_src2);
|
|
539727
539738
|
|
|
539728
|
-
//# debugId=
|
|
539739
|
+
//# debugId=69C4BA5DCB08F6E364756E2164756E21
|